Commit 72e40b68 authored by Alexander Potashev's avatar Alexander Potashev

RT75747. ea-lpc1788: USB clock configuration

* The USB clock configuration code is disabled by default
* PLL1 will be configured only if the USB clock is enabled by defining
    the CONFIG_LPC178X_USB_DIV option in the board configuration file.
parent b1277b2a
......@@ -48,6 +48,20 @@
*/
#define CONFIG_LPC178X_PLL0_ENABLE
/*
* Set CONFIG_LPC178X_PLL1_ENABLE to enable PLL1. If PLL1 is enabled,
* the values of CONFIG_LPC178X_PLL1_M and CONFIG_LPC178X_PLL1_PSEL must also
* be set to configure the PLL1 rate based on the selected input clock.
* See the LCP178x/7x User's Manual for information on setting these
* values correctly. SYSCLK is used as the PLL1 input clock.
*
* We only enable the PLL1 if the USB clock configuration is enabled, because
* only the USB clock uses the PLL1 output.
*/
#ifdef CONFIG_LPC178X_USB_DIV
#define CONFIG_LPC178X_PLL1_ENABLE
#endif /* CONFIG_LPC178X_USB_DIV */
/*
* Use the output of PLL0 for CPU clock.
*/
......@@ -103,16 +117,35 @@ static u32 clock_val[CLOCK_END];
*/
#define LPC178X_SCC_EMCCLKSEL_HALFCPU_MSK (1 << 0)
/*
* USB Clock Selection register
*/
/* Selects the divide value for creating the USB clock */
#define LPC178X_SCC_USBCLKSEL_USBDIV_BITS 0
/* The mask for all bits of USBCLKSEL[USBDIV] */
#define LPC178X_SCC_USBCLKSEL_USBDIV_MSK \
(((1 << 5) - 1) << LPC178X_SCC_USBCLKSEL_USBDIV_BITS)
/* Selects the input clock for the USB clock divider */
#define LPC178X_SCC_USBCLKSEL_USBSEL_BITS 8
/* The mask for all bits of USBCLKSEL[USBSEL] */
#define LPC178X_SCC_USBCLKSEL_USBSEL_MSK \
(3 << LPC178X_SCC_USBCLKSEL_USBSEL_BITS)
/* The output of the Alt PLL is used as the input to the USB clock divider */
#define LPC178X_SCC_USBCLKSEL_USBSEL_PLL1_MSK \
(2 << LPC178X_SCC_USBCLKSEL_USBSEL_BITS)
/*
* Calculate clock rates
*/
/*
* Set LPC178X_PLL0_P to the PLL divider value.
* The same for PLL1.
*
* P (PPL divider value) = 2 in the power of PSEL
* P can be 1, 2, 4 or 8.
*/
#define LPC178X_PLL0_P (1 << CONFIG_LPC178X_PLL0_PSEL)
#define LPC178X_PLL1_P (1 << CONFIG_LPC178X_PLL1_PSEL)
/*
* Set LPC178X_OSC_RATE to the rate of the oscillator actually used.
......@@ -132,6 +165,15 @@ static u32 clock_val[CLOCK_END];
#define LPC178X_PLL0_CLK_OUT 0
#endif
/*
* Set LPC178X_PLL1_CLK_OUT to the output rate of PLL1.
*/
#ifdef CONFIG_LPC178X_PLL1_ENABLE
#define LPC178X_PLL1_CLK_OUT (LPC178X_OSC_RATE * CONFIG_LPC178X_PLL1_M)
#else
#define LPC178X_PLL1_CLK_OUT 0
#endif
/*
* Clock at the output of CPU clock selector
*
......@@ -218,6 +260,18 @@ static u32 clock_val[CLOCK_END];
#endif
#endif /* CONFIG_LPC178X_PLL0_ENABLE */
/*
* Verify that PLL1 FCCO fits the range of 156 MHz to 320 MHz
*/
#ifdef CONFIG_LPC178X_PLL1_ENABLE
#if (LPC178X_PLL1_CLK_OUT * 2 * LPC178X_PLL1_P) < 156000000
#error PLL1 FCCO rate is too low
#endif
#if (LPC178X_PLL1_CLK_OUT * 2 * LPC178X_PLL1_P) > 320000000
#error PLL1 FCCO rate is too high
#endif
#endif /* CONFIG_LPC178X_PLL1_ENABLE */
/*
* Feed sequence values for pll_latch()
*/
......@@ -323,6 +377,21 @@ static inline void pll_latch(volatile struct lpc178x_pll_regs *pll_regs)
pll_regs->feed = LPC178X_PLL_FEED_KEY2;
}
/*
* PLLn setup
*/
#define PLL_CONFIG(idx) do { \
LPC178X_SCC->pll##idx.cfg = \
((CONFIG_LPC178X_PLL## idx ##_M - 1) << \
LPC178X_SCC_PLLCFG_MSEL_BITS) | \
(CONFIG_LPC178X_PLL## idx ##_PSEL << \
LPC178X_SCC_PLLCFG_PSEL_BITS); \
pll_latch(&LPC178X_SCC->pll##idx); \
/* Wait for lock */ \
while (!(LPC178X_SCC->pll##idx.stat & \
LPC178X_SCC_PLLSTAT_PLOCK_MSK)); \
} while (0)
/*
* Set-up the main oscillator, PLL0 and CPU clock (if necessary)
*/
......@@ -347,22 +416,15 @@ static void clock_setup(void)
#endif /* !CONFIG_LPC178X_SYS_CLK_IRC */
#ifdef CONFIG_LPC178X_PLL0_ENABLE
/*
* PLL0 setup.
*
* Only MSEL and PSEL bit groups used in PLL0CFG,
* therefore not using |=
*/
LPC178X_SCC->pll0.cfg =
((CONFIG_LPC178X_PLL0_M - 1) << LPC178X_SCC_PLLCFG_MSEL_BITS) |
(CONFIG_LPC178X_PLL0_PSEL << LPC178X_SCC_PLLCFG_PSEL_BITS);
pll_latch(&LPC178X_SCC->pll0);
/* Wait for lock */
while (!(LPC178X_SCC->pll0.stat & LPC178X_SCC_PLLSTAT_PLOCK_MSK));
PLL_CONFIG(0);
#endif /* CONFIG_LPC178X_PLL0_ENABLE */
/* TBD: enable PLL1 (necessary only for USB?) */
#ifdef CONFIG_LPC178X_PLL1_ENABLE
/*
* PLL1 is necessary for USB
*/
PLL_CONFIG(1);
#endif /* CONFIG_LPC178X_PLL1_ENABLE */
/*
* CPU clock
......@@ -391,6 +453,15 @@ static void clock_setup(void)
LPC178X_SCC->emcclksel = 0;
#endif /* CONFIG_LPC178X_EMC_HALFCPU */
#endif /* CONFIG_NR_DRAM_BANKS */
#ifdef CONFIG_LPC178X_USB_DIV
/*
* USB clock
*/
LPC178X_SCC->usbclksel =
(CONFIG_LPC178X_USB_DIV << LPC178X_SCC_USBCLKSEL_USBDIV_BITS) |
LPC178X_SCC_USBCLKSEL_USBSEL_PLL1_MSK;
#endif /* CONFIG_LPC178X_USB_DIV */
}
/*
......
......@@ -59,6 +59,7 @@
#define LPC178X_SCC_PCONP_PCUART2_MSK (1 << 24)
#define LPC178X_SCC_PCONP_PCUART3_MSK (1 << 25)
#define LPC178X_SCC_PCONP_PCENET_MSK (1 << 30)
#define LPC178X_SCC_PCONP_PCUSB_MSK (1 << 31)
/*
* PLL register map
......
......@@ -98,7 +98,7 @@
* PLL0_CLK_OUT must be between 9.75MHz and 160MHz
*/
/*
* PLL Multiplier value (1..32)
* PLL0 Multiplier value (1..32)
*/
/* TODO: change M to 10 in order to reach 120 MHz CPU clock */
#define CONFIG_LPC178X_PLL0_M 9 /* 12 MHz * 9 = 108 MHz */
......@@ -109,6 +109,17 @@
*/
#define CONFIG_LPC178X_PLL0_PSEL 0 /* P = 1 */
/*
* PLL1 Multiplier value (1..32)
*/
#define CONFIG_LPC178X_PLL1_M 8 /* 12 MHz * 8 = 96 MHz */
/*
* PSEL (a 0..3 code for PLL Divider value)
* P (PPL divider value) = 2 in the power of PSEL
* PSEL = 0..3 make P = 1, 2, 4 or 8.
*/
#define CONFIG_LPC178X_PLL1_PSEL 0 /* P = 1 */
/*
* CCLKDIV value. Selects the divide value for creating the CPU clock (CCLK)
* from the selected clock source.
......@@ -117,6 +128,23 @@
*/
#define CONFIG_LPC178X_CPU_DIV 1
/*
* USB clock divider value
*
* The PLL1 is confugured to produce a 96 MHz clock: 12*8 = 96 MHz.
* For the USB controller, we need a 48 Mhz clock, therefore we have to divide
* the PLL1 clock by 2.
*
* The LPC178x/7x User Manual claims that this divider value should be 4 or 6,
* but that statement is wrong.
*
* If you do not want to configure the USB clock, you should not set
* the `CONFIG_LPC178X_USB_DIV` option.
*/
#define CONFIG_LPC178X_USB_DIV 2
/* Disable USB clock configuration */
#undef CONFIG_LPC178X_USB_DIV
/*
* Peripheral clock selector. This divider, between 1 and 31, is used to
* generate the clock to the peripherals. The rate is divided from the
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment