arch/arm/src/samd5e5/: Combine some duplicated GCLK configuration logic

This commit is contained in:
Gregory Nutt
2018-08-31 13:34:09 -06:00
parent b699bdef3b
commit 25dce66483
7 changed files with 185 additions and 290 deletions
+2 -2
View File
@@ -110,10 +110,10 @@
#define GCLK_GENCTRL_OE (1 << 11) /* Bit 11: Clock output enable */
#define GCLK_GENCTRL_DIVSEL (1 << 12) /* Bit 12: Clock source divider */
#define GCLK_GENCTRL_RUNSTDBY (1 << 13) /* Bit 13: Run in standby */
#define GCLK_GENCTRL_DIV_SHIFT (16) /* Bits 16-31: Generator 0,2-11 Division factor */
#define GCLK_GENCTRL_DIV_SHIFT (16) /* Bits 16-23: Generator 0,2-11 Division factor */
#define GCLK_GENCTRL_DIV_MASK (0xff << GCLK_GENCTRL_DIV_SHIFT)
# define GCLK_GENCTRL_DIV(n) ((uint32_t)(n) << GCLK_GENCTRL_DIV_SHIFT)
#define GCLK_GENCTRL1_DIV_SHIFT (16) /* Bits 16-23: Generator 1 Division factor **/
#define GCLK_GENCTRL1_DIV_SHIFT (16) /* Bits 16-31: Generator 1 Division factor **/
#define GCLK_GENCTRL1_DIV_MASK (0xffff << GCLK_GENCTRL1_DIV_SHIFT)
# define GCLK_GENCTRL1_DIV(n) ((uint32_t)(n) << GCLK_GENCTRL1_DIV_SHIFT)
+74 -157
View File
@@ -149,7 +149,7 @@ static const struct sam_clockconfig_s g_initial_clocking =
.gclk = BOARD_DFLL_GCLK,
.mul = BOARD_DFLL_MUL
},
.dpll =
.dpll =
{
{
.enable = BOARD_DPLL0_ENABLE,
@@ -189,124 +189,100 @@ static const struct sam_clockconfig_s g_initial_clocking =
.gclk =
{
{
.enable = BOARD_GCLK0_ENABLE,
.idc = BOARD_GCLK0_IDC,
.oov = BOARD_GCLK0_OOV,
.oe = BOARD_GCLK0_OE,
.divsel = BOARD_GCLK0_DIVSEL,
.runstdby = BOARD_GCLK0_RUNSTDBY,
.source = BOARD_GCLK0_SOURCE,
.div = BOARD_GCLK0_DIV
.enable = BOARD_GCLK0_ENABLE,
.oov = BOARD_GCLK0_OOV,
.oe = BOARD_GCLK0_OE,
.runstdby = BOARD_GCLK0_RUNSTDBY,
.source = BOARD_GCLK0_SOURCE,
.div = BOARD_GCLK0_DIV
},
{
.enable = BOARD_GCLK1_ENABLE,
.idc = BOARD_GCLK1_IDC,
.oov = BOARD_GCLK1_OOV,
.oe = BOARD_GCLK1_OE,
.divsel = BOARD_GCLK1_DIVSEL,
.runstdby = BOARD_GCLK1_RUNSTDBY,
.source = BOARD_GCLK1_SOURCE,
.div = BOARD_GCLK1_DIV
.enable = BOARD_GCLK1_ENABLE,
.oov = BOARD_GCLK1_OOV,
.oe = BOARD_GCLK1_OE,
.runstdby = BOARD_GCLK1_RUNSTDBY,
.source = BOARD_GCLK1_SOURCE,
.div = BOARD_GCLK1_DIV
},
{
.enable = BOARD_GCLK2_ENABLE,
.idc = BOARD_GCLK2_IDC,
.oov = BOARD_GCLK2_OOV,
.oe = BOARD_GCLK2_OE,
.divsel = BOARD_GCLK2_DIVSEL,
.runstdby = BOARD_GCLK2_RUNSTDBY,
.source = BOARD_GCLK2_SOURCE,
.div = BOARD_GCLK2_DIV
.enable = BOARD_GCLK2_ENABLE,
.oov = BOARD_GCLK2_OOV,
.oe = BOARD_GCLK2_OE,
.runstdby = BOARD_GCLK2_RUNSTDBY,
.source = BOARD_GCLK2_SOURCE,
.div = BOARD_GCLK2_DIV
},
{
.enable = BOARD_GCLK3_ENABLE,
.idc = BOARD_GCLK3_IDC,
.oov = BOARD_GCLK3_OOV,
.oe = BOARD_GCLK3_OE,
.divsel = BOARD_GCLK3_DIVSEL,
.runstdby = BOARD_GCLK3_RUNSTDBY,
.source = BOARD_GCLK3_SOURCE,
.div = BOARD_GCLK3_DIV
.enable = BOARD_GCLK3_ENABLE,
.oov = BOARD_GCLK3_OOV,
.oe = BOARD_GCLK3_OE,
.runstdby = BOARD_GCLK3_RUNSTDBY,
.source = BOARD_GCLK3_SOURCE,
.div = BOARD_GCLK3_DIV
},
{
.enable = BOARD_GCLK4_ENABLE,
.idc = BOARD_GCLK4_IDC,
.oov = BOARD_GCLK4_OOV,
.oe = BOARD_GCLK4_OE,
.divsel = BOARD_GCLK4_DIVSEL,
.runstdby = BOARD_GCLK4_RUNSTDBY,
.source = BOARD_GCLK4_SOURCE,
.div = BOARD_GCLK4_DIV
.enable = BOARD_GCLK4_ENABLE,
.oov = BOARD_GCLK4_OOV,
.oe = BOARD_GCLK4_OE,
.runstdby = BOARD_GCLK4_RUNSTDBY,
.source = BOARD_GCLK4_SOURCE,
.div = BOARD_GCLK4_DIV
},
{
.enable = BOARD_GCLK5_ENABLE,
.idc = BOARD_GCLK5_IDC,
.oov = BOARD_GCLK5_OOV,
.oe = BOARD_GCLK5_OE,
.divsel = BOARD_GCLK5_DIVSEL,
.runstdby = BOARD_GCLK5_RUNSTDBY,
.source = BOARD_GCLK5_SOURCE,
.div = BOARD_GCLK5_DIV
.enable = BOARD_GCLK5_ENABLE,
.oov = BOARD_GCLK5_OOV,
.oe = BOARD_GCLK5_OE,
.runstdby = BOARD_GCLK5_RUNSTDBY,
.source = BOARD_GCLK5_SOURCE,
.div = BOARD_GCLK5_DIV
},
{
.enable = BOARD_GCLK6_ENABLE,
.idc = BOARD_GCLK6_IDC,
.oov = BOARD_GCLK6_OOV,
.oe = BOARD_GCLK6_OE,
.divsel = BOARD_GCLK6_DIVSEL,
.runstdby = BOARD_GCLK6_RUNSTDBY,
.source = BOARD_GCLK6_SOURCE,
.div = BOARD_GCLK6_DIV
.enable = BOARD_GCLK6_ENABLE,
.oov = BOARD_GCLK6_OOV,
.oe = BOARD_GCLK6_OE,
.runstdby = BOARD_GCLK6_RUNSTDBY,
.source = BOARD_GCLK6_SOURCE,
.div = BOARD_GCLK6_DIV
},
{
.enable = BOARD_GCLK7_ENABLE,
.idc = BOARD_GCLK7_IDC,
.oov = BOARD_GCLK7_OOV,
.oe = BOARD_GCLK7_OE,
.divsel = BOARD_GCLK7_DIVSEL,
.runstdby = BOARD_GCLK7_RUNSTDBY,
.source = BOARD_GCLK7_SOURCE,
.div = BOARD_GCLK7_DIV
.enable = BOARD_GCLK7_ENABLE,
.oov = BOARD_GCLK7_OOV,
.oe = BOARD_GCLK7_OE,
.runstdby = BOARD_GCLK7_RUNSTDBY,
.source = BOARD_GCLK7_SOURCE,
.div = BOARD_GCLK7_DIV
},
{
.enable = BOARD_GCLK8_ENABLE,
.idc = BOARD_GCLK8_IDC,
.oov = BOARD_GCLK8_OOV,
.oe = BOARD_GCLK8_OE,
.divsel = BOARD_GCLK8_DIVSEL,
.runstdby = BOARD_GCLK8_RUNSTDBY,
.source = BOARD_GCLK8_SOURCE,
.div = BOARD_GCLK8_DIV
.enable = BOARD_GCLK8_ENABLE,
.oov = BOARD_GCLK8_OOV,
.oe = BOARD_GCLK8_OE,
.runstdby = BOARD_GCLK8_RUNSTDBY,
.source = BOARD_GCLK8_SOURCE,
.div = BOARD_GCLK8_DIV
},
{
.enable = BOARD_GCLK9_ENABLE,
.idc = BOARD_GCLK9_IDC,
.oov = BOARD_GCLK9_OOV,
.oe = BOARD_GCLK9_OE,
.divsel = BOARD_GCLK9_DIVSEL,
.runstdby = BOARD_GCLK9_RUNSTDBY,
.source = BOARD_GCLK9_SOURCE,
.div = BOARD_GCLK9_DIV
.enable = BOARD_GCLK9_ENABLE,
.oov = BOARD_GCLK9_OOV,
.oe = BOARD_GCLK9_OE,
.runstdby = BOARD_GCLK9_RUNSTDBY,
.source = BOARD_GCLK9_SOURCE,
.div = BOARD_GCLK9_DIV
},
{
.enable = BOARD_GCLK10_ENABLE,
.idc = BOARD_GCLK10_IDC,
.oov = BOARD_GCLK10_OOV,
.oe = BOARD_GCLK10_OE,
.divsel = BOARD_GCLK10_DIVSEL,
.runstdby = BOARD_GCLK10_RUNSTDBY,
.source = BOARD_GCLK10_SOURCE,
.div = BOARD_GCLK10_DIV
.enable = BOARD_GCLK10_ENABLE,
.oov = BOARD_GCLK10_OOV,
.oe = BOARD_GCLK10_OE,
.runstdby = BOARD_GCLK10_RUNSTDBY,
.source = BOARD_GCLK10_SOURCE,
.div = BOARD_GCLK10_DIV
},
{
.enable = BOARD_GCLK11_ENABLE,
.idc = BOARD_GCLK11_IDC,
.oov = BOARD_GCLK11_OOV,
.oe = BOARD_GCLK11_OE,
.divsel = BOARD_GCLK11_DIVSEL,
.runstdby = BOARD_GCLK11_RUNSTDBY,
.source = BOARD_GCLK11_SOURCE,
.div = BOARD_GCLK11_DIV
.enable = BOARD_GCLK11_ENABLE,
.oov = BOARD_GCLK11_OOV,
.oe = BOARD_GCLK11_OE,
.runstdby = BOARD_GCLK11_RUNSTDBY,
.source = BOARD_GCLK11_SOURCE,
.div = BOARD_GCLK11_DIV
}
}
};
@@ -608,65 +584,6 @@ static inline void sam_mclk_configure(uint8_t cpudiv)
putreg8(cpudiv, SAM_MCLK_CPUDIV);
}
/****************************************************************************
* Name: sam_gclk_configure
*
* Description:
* Configure one GCLK
*
****************************************************************************/
static void sam_gclk_configure(uintptr_t regaddr,
const struct sam_gclk_config_s *config)
{
uint32_t regval;
/* Are we enabling or disabling the GCLK? */
if (config->enable)
{
/* Get the GCLK configuration */
regval = GCLK_GENCTRL_SRC(config->source) | GCLK_GENCTRL_GENEN |
GCLK_GENCTRL1_DIV(config->div);
if (config->idc)
{
regval |= GCLK_GENCTRL_IDC;
}
if (config->oov)
{
regval |= GCLK_GENCTRL_OOV;
}
if (config->oe)
{
regval |= GCLK_GENCTRL_OE;
}
if (config->divsel)
{
regval |= GCLK_GENCTRL_DIVSEL;
}
if (config->runstdby)
{
regval |= GCLK_GENCTRL_RUNSTDBY;
}
}
else
{
/* Disable the GCLK */
regval = 0;
}
/* Write the GCLK configuration */
putreg32(regval, regaddr);
}
/****************************************************************************
* Name: sam_gclkset_configure
*
@@ -693,7 +610,7 @@ static void sam_gclkset_configure(uint16_t gclkset,
/* Yes.. Remove it from the set and configure it */
gclkset &= ~mask;
sam_gclk_configure(SAM_GCLK_GENCTRL(gclk), &config[gclk]);
sam_gclk_configure(gclk, &config[gclk]);
}
}
}
+1 -23
View File
@@ -41,6 +41,7 @@
************************************************************************************/
#include <nuttx/config.h>
#include "sam_gclk.h"
/************************************************************************************
* Pre-processor Definitions
@@ -182,29 +183,6 @@ struct sam_dpll_config_s
uint16_t div; /* Clock divider */
};
/* This structure defines the configuration of a GCLK */
struct sam_gclk_config_s
{
uint8_t enable : 1; /* True: Enable GCLK */
uint8_t idc : 1; /* True: Improve duty cycle */
uint8_t oov : 1; /* True: Clock output selection */
uint8_t oe : 1; /* True: Output enable */
uint8_t divsel : 1; /* True: Clock source divider */
uint8_t runstdby : 1; /* Run in standby */
uint8_t source; /* GCLK clock source:
* 0 XOSC 0 oscillator input
* 1 XOSC 1 oscillator input
* 2 Generator input pad
* 3 Generic clock generator 1 output
* 4 OSCULP32K oscillator output
* 5 XOSC32K oscillator output
* 6 DFLL oscillator output
* 7 DPLL0 output
* 8 DPLL1 output */
uint16_t div; /* Division factor: 8-bits for all but GCLK1 */
};
/* This structure defines the configuration of the clock sus-system */
struct sam_clockconfig_s
+80 -74
View File
@@ -71,7 +71,9 @@
static void sam_gclck_waitsyncbusy(uint8_t gclk)
{
uintptr_t gclkbit = GCLK_SYNCHBUSY_GENCTRL(gclk);
while ((getreg8(SAM_GCLK_SYNCHBUSY) & gclkbit) != 0);
while ((getreg8(SAM_GCLK_SYNCHBUSY) & gclkbit) != 0)
{
}
}
/****************************************************************************
@@ -79,12 +81,13 @@ static void sam_gclck_waitsyncbusy(uint8_t gclk)
****************************************************************************/
/****************************************************************************
* Name: sam_gclk_config
* Name: sam_gclk_configure
*
* Description:
* Configure a single GCLK(s) based on settings in the config structure.
*
* Input Parameters:
* gclk - GCLK index
* config - An instance of struct sam_gclkconfig describing the GCLK
* configuration.
*
@@ -93,111 +96,114 @@ static void sam_gclck_waitsyncbusy(uint8_t gclk)
*
****************************************************************************/
void sam_gclk_config(FAR const struct sam_gclkconfig_s *config)
void sam_gclk_configure(int gclk, FAR const struct sam_gclk_config_s *config)
{
irqstate_t flags;
uintptr_t regaddr;
uint32_t regval;
uint32_t genctrl;
/* Select the requested source clock for the generator */
/* Are we enabling or disabling the GCLK? */
genctrl = ((uint32_t)config->clksrc << GCLK_GENCTRL_SRC_SHIFT);
regval = 0;
regaddr = SAM_GCLK_GENCTRL(gclk);
#if 0 /* Not yet supported */
/* Configure the clock to be either high or low when disabled */
if (config->level)
if (config->enable)
{
genctrl |= GCLK_GENCTRL_OOV;
}
#endif
/* Select the requested source clock for the generator */
/* Configure if the clock output to I/O pin should be enabled */
regval = GCLK_GENCTRL_SRC(config->source);
if (config->output)
{
genctrl |= GCLK_GENCTRL_OE;
}
/* Clock output selection */
/* Set the prescaler division factor */
if (config->prescaler > 1)
{
/* Check if division is a power of two */
if (((config->prescaler & (config->prescaler - 1)) == 0))
if (config->oov)
{
/* Determine the index of the highest bit set to get the
* division factor that must be loaded into the division
* register.
*/
regval |= GCLK_GENCTRL_OOV;
}
uint32_t count = 0;
uint32_t mask;
/* Output enable */
for (mask = 2; mask < (uint32_t)config->prescaler; mask <<= 1)
if (config->oe)
{
regval |= GCLK_GENCTRL_OE;
}
/* Run in standby */
if (config->runstdby)
{
regval |= GCLK_GENCTRL_RUNSTDBY;
}
/* Set the prescaler division factor */
if (config->div > 1)
{
/* Check if division is a power of two */
if (((config->div & (config->div - 1)) == 0))
{
count++;
/* Determine the index of the highest bit set to get the
* division factor that must be loaded into the division
* register.
*/
uint32_t count = 0;
uint32_t mask;
for (mask = 2; mask < (uint32_t)config->div; mask <<= 1)
{
count++;
}
/* Set binary divider power of 2 division factor */
regval |= GCLK_GENCTRL1_DIV(count);
regval |= GCLK_GENCTRL_DIVSEL;
}
else
{
/* Set integer division factor */
/* Set binary divider power of 2 division factor */
regval |= GCLK_GENCTRL1_DIV((uint32_t)config->div);
genctrl |= count << GCLK_GENCTRL_DIV_SHIFT;
genctrl |= GCLK_GENCTRL_DIVSEL;
/* Enable non-binary division with increased duty cycle accuracy */
regval |= GCLK_GENCTRL_IDC;
}
}
else
/* Don't disable GCLK0 */
if (gclk == 0)
{
/* Set integer division factor */
genctrl |= GCLK_GENCTRL_DIV((uint32_t)config->prescaler);
/* Enable non-binary division with increased duty cycle accuracy */
genctrl |= GCLK_GENCTRL_IDC;
regval |= GCLK_GENCTRL_GENEN;
}
}
/* Enable or disable the clock in standby mode */
if (config->runstandby)
{
genctrl |= GCLK_GENCTRL_RUNSTDBY;
}
/* Wait for synchronization */
sam_gclck_waitsyncbusy(config->gclk);
/* Preserve the GENEN bit */
regaddr = SAM_GCLK_GENCTRL(config->gclk);
flags = enter_critical_section();
regval = getreg32(regaddr);
regval &= GCLK_GENCTRL_GENEN;
genctrl |= regval;
/* Configure the generator */
putreg32(genctrl, regaddr);
flags = enter_critical_section();
putreg32(regval, regaddr);
/* Wait for synchronization */
sam_gclck_waitsyncbusy(config->gclk);
sam_gclck_waitsyncbusy(gclk);
leave_critical_section(flags);
sam_gclck_waitsyncbusy(config->gclk);
sam_gclck_waitsyncbusy(gclk);
/* Enable the clock generator */
if (config->enable)
{
/* Enable the clock generator */
flags = enter_critical_section();
genctrl |= GCLK_GENCTRL_GENEN;
putreg32(genctrl, regaddr);
flags = enter_critical_section();
regval |= GCLK_GENCTRL_GENEN;
putreg32(regval, regaddr);
/* Wait for synchronization */
/* Wait for synchronization */
sam_gclck_waitsyncbusy(config->gclk);
leave_critical_section(flags);
sam_gclck_waitsyncbusy(gclk);
leave_critical_section(flags);
}
}
/****************************************************************************
+19 -8
View File
@@ -61,13 +61,23 @@
/* This structure describes the configuration of one GCLK */
struct sam_gclkconfig_s
struct sam_gclk_config_s
{
uint8_t gclk; /* Clock generator */
bool runstandby; /* Run clock in standby */
bool output; /* Output enable */
uint8_t clksrc; /* Encoded clock source */
uint16_t prescaler; /* Prescaler value */
uint8_t enable : 1; /* True: Enable GCLK */
uint8_t oov : 1; /* True: Clock output selection */
uint8_t oe : 1; /* True: Output enable */
uint8_t runstdby : 1; /* True: Run in standby */
uint8_t source; /* GCLK clock source:
* 0 XOSC 0 oscillator input
* 1 XOSC 1 oscillator input
* 2 Generator input pad
* 3 Generic clock generator 1 output
* 4 OSCULP32K oscillator output
* 5 XOSC32K oscillator output
* 6 DFLL oscillator output
* 7 DPLL0 output
* 8 DPLL1 output */
uint16_t div; /* Division factor: 8-bits for all but GCLK1 */
};
/****************************************************************************
@@ -92,12 +102,13 @@ extern "C"
****************************************************************************/
/****************************************************************************
* Name: sam_gclk_config
* Name: sam_gclk_configure
*
* Description:
* Configure a single GCLK(s) based on settings in the config structure.
*
* Input Parameters:
* gclk - GCLK index
* config - An instance of struct sam_gclkconfig describing the GCLK
* configuration.
*
@@ -106,7 +117,7 @@ extern "C"
*
****************************************************************************/
void sam_gclk_config(FAR const struct sam_gclkconfig_s *config);
void sam_gclk_configure(int gclk, FAR const struct sam_gclk_config_s *config);
/****************************************************************************
* Name: sam_gclk_chan_enable