diff --git a/arch/arm/src/lpc313x/Make.defs b/arch/arm/src/lpc313x/Make.defs index b60209fefb..9d9a7dd49a 100755 --- a/arch/arm/src/lpc313x/Make.defs +++ b/arch/arm/src/lpc313x/Make.defs @@ -46,7 +46,7 @@ CMN_CSRCS = up_assert.c up_blocktask.c up_copystate.c up_createstack.c \ up_undefinedinsn.c up_usestack.c CGU_ASRCS = -CGU_CSRCS = lpc313x_clkdomain.c +CGU_CSRCS = lpc313x_clkdomain.c lpc313x_fdcndx.c lpc313x_esrndx.c -CHIP_ASRCS = +CHIP_ASRCS = $(CGU_ASRCS) CHIP_CSRCS = lpc313x_irq.c lpc313x_allocateheap.c $(CGU_CSRCS) diff --git a/arch/arm/src/lpc313x/lpc313x_cgudrvr.h b/arch/arm/src/lpc313x/lpc313x_cgudrvr.h index 4d222e35b5..631581124e 100755 --- a/arch/arm/src/lpc313x/lpc313x_cgudrvr.h +++ b/arch/arm/src/lpc313x/lpc313x_cgudrvr.h @@ -105,68 +105,69 @@ #define CLKID_SYSCLKO_LAST CLKID_SYSCLKO #define _D11B(id) _RBIT(id,CLKID_SYSCLKO_FIRST) -#define CGU_NDOMAINS 12 -#define CLKID_INVALIDCLK -1 -#define CLKID_INVALIDDOMAIN -1 +#define CGU_NDOMAINS 12 /* The number of clock domains */ +#define CLKID_INVALIDCLK -1 /* Indicates and invalid clock ID */ +#define DOMAINID_INVALID -1 /* Indicates an invalid domain ID */ +#define ESRNDX_INVALID -1 /* Indicates an invalid ESR register index */ -/* The number of fractional dividers available for each base frequency, - * their bit widths and extractions for sub elements from the fractional - * divider configuration register +/* There are 24 fractional dividers, indexed 0 to 23. The following definitions + * provide (1) the number of fractional dividers available for each base frequency, + * (2) start and end indices, and (3) extraction info for sub elements from the + * fractional divider configuration register */ -#define FRACDIV_BASE0_CNT 7 -#define FRACDIV_BASE0_LOW 0 -#define FRACDIV_BASE0_HIGH 6 +#define FRACDIV_BASE0_CNT 7 /* 7 fractional dividers available */ +#define FRACDIV_BASE0_LOW 0 /* First is index 0 */ +#define FRACDIV_BASE0_HIGH 6 /* Last is index 6 */ #define FRACDIV_BASE0_FDIV0W 8 -#define FRACDIV_BASE1_CNT 2 -#define FRACDIV_BASE1_LOW 7 -#define FRACDIV_BASE1_HIGH 8 +#define FRACDIV_BASE1_CNT 2 /* 2 fractional dividers available */ +#define FRACDIV_BASE1_LOW 7 /* First is index 7 */ +#define FRACDIV_BASE1_HIGH 8 /* Last is index 8 */ #define FRACDIV_BASE1_FDIV0W 8 -#define FRACDIV_BASE2_CNT 2 -#define FRACDIV_BASE2_LOW 9 -#define FRACDIV_BASE2_HIGH 10 +#define FRACDIV_BASE2_CNT 2 /* 2 fractional dividers available */ +#define FRACDIV_BASE2_LOW 9 /* First is index 9 */ +#define FRACDIV_BASE2_HIGH 10 /* Last is index 10 */ #define FRACDIV_BASE2_FDIV0W 8 -#define FRACDIV_BASE3_CNT 3 -#define FRACDIV_BASE3_LOW 11 -#define FRACDIV_BASE3_HIGH 13 +#define FRACDIV_BASE3_CNT 3 /* 3 fractional dividers available */ +#define FRACDIV_BASE3_LOW 11 /* First is index 11 */ +#define FRACDIV_BASE3_HIGH 13 /* Last is index 12 */ #define FRACDIV_BASE3_FDIV0W 8 -#define FRACDIV_BASE4_CNT 1 -#define FRACDIV_BASE4_LOW 14 -#define FRACDIV_BASE4_HIGH 14 +#define FRACDIV_BASE4_CNT 1 /* 1 fractional divider available */ +#define FRACDIV_BASE4_LOW 14 /* First is index 14 */ +#define FRACDIV_BASE4_HIGH 14 /* Last is index 14 */ #define FRACDIV_BASE4_FDIV0W 8 -#define FRACDIV_BASE5_CNT 1 -#define FRACDIV_BASE5_LOW 15 -#define FRACDIV_BASE5_HIGH 15 +#define FRACDIV_BASE5_CNT 1 /* 1 fractional divider available */ +#define FRACDIV_BASE5_LOW 15 /* First is index 15 */ +#define FRACDIV_BASE5_HIGH 15 /* Last is index 15 */ #define FRACDIV_BASE5_FDIV0W 8 -#define FRACDIV_BASE6_CNT 1 -#define FRACDIV_BASE6_LOW 16 -#define FRACDIV_BASE6_HIGH 16 +#define FRACDIV_BASE6_CNT 1 /* 1 fractional divider available */ +#define FRACDIV_BASE6_LOW 16 /* First is index 16 */ +#define FRACDIV_BASE6_HIGH 16 /* Last is index 16 */ #define FRACDIV_BASE6_FDIV0W 8 -#define FRACDIV_BASE7_CNT 6 -#define FRACDIV_BASE7_LOW 17 -#define FRACDIV_BASE7_HIGH 22 +#define FRACDIV_BASE7_CNT 6 /* 6 fractional dividers available */ +#define FRACDIV_BASE7_LOW 17 /* First is index 17 */ +#define FRACDIV_BASE7_HIGH 22 /* Last is index 22 */ #define FRACDIV_BASE7_FDIV0W 13 -#define FRACDIV_BASE8_CNT 0 -#define FRACDIV_BASE9_CNT 0 +#define FRACDIV_BASE8_CNT 0 /* No fractional divider available */ +#define FRACDIV_BASE9_CNT 0 /* No fractional divider available */ -#define FRACDIV_BASE10_CNT 1 -#define FRACDIV_BASE10_LOW 23 -#define FRACDIV_BASE10_HIGH 23 +#define FRACDIV_BASE10_CNT 1 /* 1 fractional divider available */ +#define FRACDIV_BASE10_LOW 23 /* First is index 23 */ +#define FRACDIV_BASE10_HIGH 23 /* Last is index 23 */ #define FRACDIV_BASE10_FDIV0W 8 -#define FRACDIV_BASE11_CNT 0 +#define FRACDIV_BASE11_CNT 0 /* No fractional divider available */ -#define CGU_NDOMAINS 12 -#define CLKID_INVALIDCLK -1 -#define CLKID_INVALIDDOMAIN -1 +#define FDCNDX_INVALID -1 /* Indicates an invalid fractional + * divider index */ /************************************************************************ * Public Types @@ -376,6 +377,41 @@ static inline void lpc313x_disableclock(enum lpc313x_clockid_e clkid) EXTERN enum lpc313x_domainid_e lpc313x_clkdomain(enum lpc313x_clockid_e clkid); +/************************************************************************ + * Name: lp313x_esrndx + * + * Description: + * Given a clock ID, return the index of the corresponding ESR + * register (or ESRNDX_INVALID if there is no ESR associated with + * this clock ID). Indexing of ESRs differs slightly from the clock + * ID: There are 92 clock IDs but only 89 ESR regisers. There are no + * ESR registers for : + * + * + * CLKID_I2SRXBCK0 Clock ID 87: I2SRX_BCK0 + * CLKID_I2SRXBCK1, Clock ID 88: I2SRX_BCK1 + * + * and + * + * CLKID_SYSCLKO Clock ID 91: SYSCLK_O + * + ************************************************************************/ + +EXTERN int lp313x_esrndx(enum lpc313x_clockid_e clkid); + +/************************************************************************ + * Name: lpc313x_fdcndx + * + * Description: + * Given a clock ID and its domain ID, return the index of the + * corresponding fractional divider register (or FDCNDX_INVALID if + * there is no fractional divider associated with this clock). + * + ************************************************************************/ + +EXTERN int lpc313x_fdcndx(enum lpc313x_clockid_e clkid, + enum lpc313x_domainid_e dmnid); + #undef EXTERN #ifdef __cplusplus } diff --git a/arch/arm/src/lpc313x/lpc313x_esrndx.c b/arch/arm/src/lpc313x/lpc313x_esrndx.c new file mode 100755 index 0000000000..040edd51c2 --- /dev/null +++ b/arch/arm/src/lpc313x/lpc313x_esrndx.c @@ -0,0 +1,134 @@ +/************************************************************************ + * arch/arm/src/lpc313x/lpc313x_esrndx.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * - UM10314 LPC3130/31 User manual Rev. 1.01 — 9 September 2009 + * - lpc313x.cdl.drivers.zip example driver code + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#include "up_arch.h" +#include "lpc313x_cgudrvr.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/************************************************************************ + * Private Data + ************************************************************************/ + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: lp313x_esrndx + * + * Description: + * Given a clock ID, return the index of the corresponding ESR + * register (or ESRNDX_INVALID if there is no ESR associated with + * this clock ID). Indexing of ESRs differs slightly from the clock + * ID: There are 92 clock IDs but only 89 ESR regisers. There are no + * ESR registers for : + * + * + * CLKID_I2SRXBCK0 Clock ID 87: I2SRX_BCK0 + * CLKID_I2SRXBCK1, Clock ID 88: I2SRX_BCK1 + * + * and + * + * CLKID_SYSCLKO Clock ID 91: SYSCLK_O + * + ************************************************************************/ + +int lp313x_esrndx(enum lpc313x_clockid_e clkid) +{ + int esrndx = (int)clkid; + + /* There ar 89 Enable Select Registers (ESR). Indexing for these + * registers is identical to indexing to other registers (like PCR), + * except that there are no ESR registers for + * + * + * CLKID_I2SRXBCK0 Clock ID 87: I2SRX_BCK0 + * CLKID_I2SRXBCK1, Clock ID 88: I2SRX_BCK1 + * + * and + * + * CLKID_SYSCLKO Clock ID 91: SYSCLK_O + */ + + switch (clkid) + { + /* There are no ESR registers corresponding to the following + * three clocks: + */ + + case CLKID_I2SRXBCK0: + case CLKID_I2SRXBCK1: + case CLKID_SYSCLKO: + esrndx = ESRNDX_INVALID; + break; + + /* These clock IDs are a special case and need to be adjusted + * by two: + * + * CLKID_SPICLK Clock ID 89, ESR index 87 + * CLKID_SPICLKGATED Clock ID 90, ESR index 88 + */ + + case CLKID_SPICLK: + case CLKID_SPICLKGATED: + esrndx = esrndx - 2; + break; + + /* The rest of the indices match up and we don't have to do anything. */ + + default: + break; + } + + return esrndx; +} diff --git a/arch/arm/src/lpc313x/lpc313x_fdcndx.c b/arch/arm/src/lpc313x/lpc313x_fdcndx.c new file mode 100755 index 0000000000..128f321db5 --- /dev/null +++ b/arch/arm/src/lpc313x/lpc313x_fdcndx.c @@ -0,0 +1,127 @@ +/************************************************************************ + * arch/arm/src/lpc313x/lpc313x_fdcndx.c + * + * Copyright (C) 2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * References: + * - UM10314 LPC3130/31 User manual Rev. 1.01 — 9 September 2009 + * - lpc313x.cdl.drivers.zip example driver code + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ************************************************************************/ + +/************************************************************************ + * Included Files + ************************************************************************/ + +#include +#include + +#include "up_arch.h" +#include "lpc313x_cgudrvr.h" + +/************************************************************************ + * Pre-processor Definitions + ************************************************************************/ + +/* The select register in the ESR registers vary in width from 1-3 bits. + * Below is a macro to select the widest case (which is OK because the + * undefined bits will be read as zero). Within the field, bits 0-7 to + * indicate the offset from the base FDC index. + */ + +#define CGU_ESRSEL(n) (((n)>>1)&7) + +/************************************************************************ + * Private Data + ************************************************************************/ + +static const uint8_t g_fdcbase[CGU_NDOMAINS] = +{ + FRACDIV_BASE0_LOW, /* Domain 0: SYS_BASE */ + FRACDIV_BASE1_LOW, /* Domain 1: AHB0APB0_BASE */ + FRACDIV_BASE2_LOW, /* Domain 2: AHB0APB1_BASE */ + FRACDIV_BASE3_LOW, /* Domain 3: AHB0APB2_BASE */ + FRACDIV_BASE4_LOW, /* Domain 4: AHB0APB3_BASE */ + FRACDIV_BASE5_LOW, /* Domain 5: PCM_BASE */ + FRACDIV_BASE6_LOW, /* Domain 6: UART_BASE */ + FRACDIV_BASE7_LOW, /* Domain 7: CLK1024FS_BASE */ + 0, /* Domain 8: BCK0_BASE (no ESR register) */ + 0, /* Domain 9: BCK1_BASE (no ESR register) */ + FRACDIV_BASE10_LOW, /* Domain 10: SPI_BASE */ + 0, /* Domain 11: SYSCLKO_BASE (no ESR register) */ +}; + +/************************************************************************ + * Private Functions + ************************************************************************/ + +/************************************************************************ + * Public Functions + ************************************************************************/ + +/************************************************************************ + * Name: lpc313x_fdcndx + * + * Description: + * Given a clock ID and its domain ID, return the index of the + * corresponding fractional divider register (or FDCNDX_INVALID if + * there is no fractional divider associated with this clock). + * + ************************************************************************/ + +int lpc313x_fdcndx(enum lpc313x_clockid_e clkid, enum lpc313x_domainid_e dmnid) +{ + int esrndx; + int fdcndx = FDCNDX_INVALID; + + /* Check if there is an ESR register associate with this clock ID */ + + esrndx = lp313x_esrndx(clkid); + if (esrndx != ESRNDX_INVALID) + { + /* Read the clock's ESR to get the fractional divider */ + + uint32_t regval = getreg32(LPC313X_CGU_ESR_OFFSET(esrndx)); + + /* Check if any fractional divider is enabled for this clock. */ + + if ((regval & CGU_ESR_ESREN) != 0) + { + /* Yes.. The FDC index is an offset from this fractional + * divider base for this domain. + */ + + fdcndx = CGU_ESRSEL(regval) + (int)g_fdcbase[dmnid]; + } + } + return fdcndx; +} +