Created
June 5, 2012 18:43
-
-
Save jboone/2876843 to your computer and use it in GitHub Desktop.
LPC43xx code for configuring Si5351 and internal clock tree.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
volatile uint_fast8_t* peripheral_bitband_address(volatile void* const address, const uint_fast8_t bit_number) { | |
const uint32_t bit_band_base = 0x42000000; | |
const uint32_t byte_offset = (uint32_t)address - 0x40000000; | |
const uint32_t bit_word_offset = (byte_offset * 32) + (bit_number * 4); | |
const uint32_t bit_word_address = bit_band_base + bit_word_offset; | |
return (volatile uint_fast8_t*)bit_word_address; | |
} | |
void peripheral_bitband_set(volatile void* const peripheral_address, const uint_fast8_t bit_number) { | |
volatile uint_fast8_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); | |
*bitband_address = 1; | |
} | |
void peripheral_bitband_clear(volatile void* const peripheral_address, const uint_fast8_t bit_number) { | |
volatile uint_fast8_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); | |
*bitband_address = 0; | |
} | |
uint_fast8_t peripheral_bitband_get(volatile void* const peripheral_address, const uint_fast8_t bit_number) { | |
volatile uint_fast8_t* const bitband_address = peripheral_bitband_address(peripheral_address, bit_number); | |
return *bitband_address; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define CLOCKGEN_I2C LPC_I2C0 | |
#define CLOCKGEN_SLAVE_ADDRESS 0x60 | |
int clockgen_write( | |
uint8_t* const data, | |
const uint_fast8_t data_count) { | |
I2C_M_SETUP_Type setup; | |
Status status; | |
setup.sl_addr7bit = CLOCKGEN_SLAVE_ADDRESS; | |
setup.tx_data = data; | |
setup.tx_length = data_count; | |
setup.rx_data = NULL; | |
setup.rx_length = 0; | |
setup.retransmissions_max = 0; | |
status = I2C_MasterTransferData(CLOCKGEN_I2C, &setup, I2C_TRANSFER_POLLING); | |
return (status != SUCCESS); | |
} | |
int clockgen_disable_all_outputs() { | |
/* Disable all CLKx outputs. */ | |
uint8_t data[] = { 3, 0xFF }; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_disable_oeb_pin_control() { | |
/* Turn off OEB pin control for all CLKx */ | |
uint8_t data[] = { 9, 0xFF }; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_power_down_all_clocks() { | |
/* Power down all CLKx */ | |
uint8_t data[] = { 16, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_set_crystal_configuration() { | |
/* Register 183: Crystal Internal Load Capacitance | |
* Reads as 0xE4 on power-up | |
* Set to 10pF (until I find out what loading the crystal/PCB likes best) | |
*/ | |
uint8_t data[] = { 183, 0xE4 }; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_enable_xo_and_ms_fanout() { | |
/* Register 187: Fanout Enable | |
* Turn on XO and MultiSynth fanout only. | |
*/ | |
uint8_t data[] = { 187, 0x50 }; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_configure_pll_sources_for_xtal() { | |
/* Register 15: PLL Input Source | |
* CLKIN_DIV=0 (Divide by 1) | |
* PLLB_SRC=0 (XTAL input) | |
* PLLA_SRC=0 (XTAL input) | |
*/ | |
uint8_t data[] = { 15, 0x00 }; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_configure_pll1_multisynth() { | |
/* MultiSynth NA (PLL1) */ | |
uint8_t data[] = { 26, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00 }; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_configure_multisynth( | |
const uint_fast8_t ms_number, | |
const uint32_t p1, | |
const uint32_t p2, | |
const uint32_t p3 | |
) { | |
// TODO: Check for p3 > 0? 0 has no meaning in fractional mode? | |
// And it makes for more jitter in integer mode. | |
const uint_fast8_t register_number = 42 + (ms_number * 8); | |
uint8_t data[] = { | |
register_number, | |
(p3 >> 8) & 0xFF, | |
(p3 >> 0) & 0xFF, | |
(0 << 4) | (0 << 2) | ((p1 >> 16) & 0x3), | |
(p1 >> 8) & 0xFF, | |
(p1 >> 0) & 0xFF, | |
(((p3 >> 16) & 0xF) << 4) | (((p2 >> 16) & 0xF) << 0), | |
(p2 >> 8) & 0xFF, | |
(p2 >> 0) & 0xFF | |
}; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_configure_clock_control() { | |
/* Registers 16 through 23: CLKx Control | |
* CLK0: | |
* CLK0_PDN=0 (powered up) | |
* MS0_INT=1 (integer mode) | |
* MS0_SRC=0 (PLLA as source for MultiSynth 0) | |
* CLK0_INV=0 (not inverted) | |
* CLK0_SRC=3 (MS0 as input source) | |
* CLK0_IDRV=3 (8mA) | |
* CLK1: | |
* CLK1_PDN=0 (powered up) | |
* MS1_INT=1 (integer mode) | |
* MS1_SRC=0 (PLLA as source for MultiSynth 1) | |
* CLK1_INV=0 (not inverted) | |
* CLK1_SRC=3 (MS1 as input source) | |
* CLK1_IDRV=3 (8mA) | |
* CLK4: | |
* CLK4_PDN=0 (powered up) | |
* MS4_INT=0 (fractional mode -- to support 12MHz to LPC for USB DFU) | |
* MS4_SRC=0 (PLLA as source for MultiSynth 4) | |
* CLK4_INV=0 (not inverted) | |
* CLK4_SRC=3 (MS4 as input source) | |
* CLK4_IDRV=3 (8mA) | |
*/ | |
uint8_t data[] = { | |
16, | |
0x4F, 0x4F, 0x80, 0x80, 0x0F, 0x80, 0x80, 0x80 | |
}; | |
return clockgen_write(data, sizeof(data)); | |
} | |
int clockgen_enable_clock_outputs() { | |
/* Enable CLK outputs 0, 1, 4 only. */ | |
uint8_t data[] = { | |
3, 0xEC | |
}; | |
return clockgen_write(data, sizeof(data)); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void SetupHardware() { | |
SystemInit(); | |
// Running on internal RC at this point. | |
// Configure I2C to bring up Si5351C, as clock for the | |
// LPC. | |
// Not calling I2C_Init, because it's written to use PLL1, and we're | |
// not in a position to fuss with PLL1 yet. | |
// | |
//I2C_Init(CLOCKGEN_I2C, 400000); | |
CGU_EntityConnect(CGU_CLKSRC_IRC, CGU_BASE_APB1); | |
LPC_SCU->SFSI2C0 = (1<<3 | 1<<11); | |
const uint32_t clockrate = 400000; | |
const uint32_t tem = CGU_GetPCLKFrequency(CGU_PERIPHERAL_M4CORE) / clockrate; | |
CLOCKGEN_I2C->SCLH = (uint32_t)(tem / 2); | |
CLOCKGEN_I2C->SCLL = (uint32_t)(tem - CLOCKGEN_I2C->SCLH); | |
CLOCKGEN_I2C->CONCLR = (I2C_I2CONCLR_AAC |I2C_I2CONCLR_SIC | I2C_I2CONCLR_STAC | I2C_I2CONCLR_I2ENC); | |
I2C_Cmd(CLOCKGEN_I2C, ENABLE); | |
clockgen_disable_all_outputs(); | |
clockgen_disable_oeb_pin_control(); | |
clockgen_power_down_all_clocks(); | |
clockgen_set_crystal_configuration(); | |
clockgen_enable_xo_and_ms_fanout(); | |
clockgen_configure_pll_sources_for_xtal(); | |
clockgen_configure_pll1_multisynth(); | |
// MS0/CLK0 is the source for the MAX2837 clock input. | |
clockgen_configure_multisynth(0, 2048, 0, 1); // 40MHz | |
// MS1/CLK1 is the source for the MAX5864 codec. | |
clockgen_configure_multisynth(1, 4608, 0, 1); // 20MHz | |
// MS4/CLK4 is the source for the LPC43xx microcontroller. | |
clockgen_configure_multisynth(4, 8021, 1, 3); // 12MHz | |
clockgen_configure_clock_control(); | |
clockgen_enable_clock_outputs(); | |
I2C_Cmd(CLOCKGEN_I2C, DISABLE); | |
I2C_DeInit(CLOCKGEN_I2C); | |
// 12MHz clock is entering LPC XTAL1/OSC input now. | |
// Set up PLL1 to run from XTAL1 input. | |
CGU_SetXTALOSC(12000000); | |
CGU_EnableEntity(CGU_CLKSRC_XTAL_OSC, ENABLE); | |
CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_BASE_M4); | |
CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_BASE_APB1); | |
CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL1); | |
CGU_SetPLL1(1); | |
CGU_EnableEntity(CGU_CLKSRC_PLL1, ENABLE); | |
CGU_UpdateClock(); | |
CGU_SetPLL1(9); | |
CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_M4); | |
wait_count(1000000); | |
CGU_SetPLL1(17); | |
wait_count(1000000); | |
CGU_UpdateClock(); | |
CGU_EntityConnect(CGU_CLKSRC_XTAL_OSC, CGU_CLKSRC_PLL0); | |
CGU_SetPLL0(); | |
CGU_EnableEntity(CGU_CLKSRC_PLL0, ENABLE); | |
CGU_EntityConnect(CGU_CLKSRC_PLL0, CGU_BASE_USB0); | |
/*CGU_EnableEntity(CGU_BASE_PERIPH, ENABLE); | |
CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_PERIPH); | |
CGU_EntityConnect(CGU_CLKSRC_PLL1, CGU_BASE_APB1);*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment