123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /*
- * Copyright (c) 2011-2012, Freescale Semiconductor, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- *
- * o Redistributions of source code must retain the above copyright notice, this list
- * of conditions and the following disclaimer.
- *
- * o 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.
- *
- * o Neither the name of Freescale Semiconductor, Inc. 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 HOLDER 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.
- */
- #include "sdk.h"
- #include "registers/regsccm.h"
- #include "registers/regsccmanalog.h"
- #include "registers/regsuart.h"
- #include "registers/regsepit.h"
- #include "registers/regsspba.h"
- #include "registers/regssdmaarm.h"
- #include "registers/regsgpt.h"
- #include "registers/regsi2c.h"
- #include "registers/regsecspi.h"
- #include "ccm_pll.h"
- //#include "hardware.h"
- //#include "soc_memory_map.h"
- #define HW_ANADIG_REG_CORE (ANATOP_IPS_BASE_ADDR + 0x140)
- #define HW_ANADIG_PLL_SYS_RW (ANATOP_IPS_BASE_ADDR + 0x000)
- #define HW_ANADIG_REG_CORE_V_CORE_VALUE_mv(x) ((((x)-700)/25) << 0)
- #define HW_ANADIG_REG_CORE_V_SOC_VALUE_mv(x) ((((x)-700)/25) << 18)
- #define HW_ANADIG_REG_CORE_V_CORE_MSK 0x1F
- #define HW_ANADIG_REG_CORE_V_SOC_MSK (0x1F << 18)
- uint32_t g_arm_clk = 528000000;
- const uint32_t PLL2_OUTPUT[] = { 528000000, 396000000, 352000000, 198000000 };
- const uint32_t PLL3_OUTPUT[] = { 480000000, 720000000, 540000000, 508235294, 454736842 };
- const uint32_t PLL4_OUTPUT = 650000000;
- const uint32_t PLL5_OUTPUT = 650000000;
- ////////////////////////////////////////////////////////////////////////////////
- // Code
- ////////////////////////////////////////////////////////////////////////////////
- void set_soc_core_voltage(unsigned int v_core_mv, unsigned int v_soc_mv)
- {
- unsigned int val, val_v_core, val_v_soc;
- val = reg32_read(HW_ANADIG_REG_CORE);
- val &= ~HW_ANADIG_REG_CORE_V_CORE_MSK;
- val &= ~HW_ANADIG_REG_CORE_V_SOC_MSK;
- val_v_core = HW_ANADIG_REG_CORE_V_CORE_VALUE_mv(v_core_mv);
- val_v_soc = HW_ANADIG_REG_CORE_V_SOC_VALUE_mv(v_soc_mv);
- val |= val_v_core | val_v_soc;
- reg32_write(HW_ANADIG_REG_CORE, val);
- }
- void setup_clk(void)
- {
- uint32_t div_select;
- uint32_t temp;
- uint32_t arm_clk = g_arm_clk/1000000;
-
- switch(arm_clk)
- {
- case 400:
- div_select = 33;
- set_soc_core_voltage(1150, 1175);
- return;
- case 528:
- div_select = 44;
- set_soc_core_voltage(1250, 1250);
- break;
- case 756:
- div_select = 63;
- set_soc_core_voltage(1250, 1250);
- printf("ARM Clock set to 756MHz\r\n");
- break;
- default:
- return;
- }
-
- // first, make sure ARM_PODF is clear
- HW_CCM_CACRR_WR(0);
- // write the div_select value into HW_ANADIG_PLL_SYS_RW
- // this will re-program the PLL to the new freq
- temp = readl(HW_ANADIG_PLL_SYS_RW);
- temp |= 0x10000;// set BYBASS
- writel(temp, HW_ANADIG_PLL_SYS_RW);
- temp = readl(HW_ANADIG_PLL_SYS_RW);
- temp &= ~(0x0000007F);
- temp |= div_select; // Update div
- writel(temp, HW_ANADIG_PLL_SYS_RW);
- /* Wait for PLL to lock */
- while(!(readl(HW_ANADIG_PLL_SYS_RW) & 0x80000000));
- /*disable BYPASS*/
- temp = readl(HW_ANADIG_PLL_SYS_RW);
- temp &= ~0x10000;
- writel(temp, HW_ANADIG_PLL_SYS_RW);
- }
- void ccm_init(void)
- {
- HW_CCM_CCGR0_WR(0xffffffff);
- HW_CCM_CCGR1_WR(0xffffffff); // EPIT, ESAI, GPT enabled by driver
- HW_CCM_CCGR2_WR(0xffffffff); // I2C enabled by driver
- HW_CCM_CCGR3_WR(0xffffffff);
- HW_CCM_CCGR4_WR(0xffffffff); // GPMI, Perfmon enabled by driver
- HW_CCM_CCGR5_WR(0xffffffff); // UART, SATA enabled by driver
- HW_CCM_CCGR6_WR(0xffffffff);
- /*
- * Keep default settings at reset.
- * pre_periph_clk_sel is by default at 0, so the selected output
- * of PLL2 is the main output at 528MHz.
- * => by default, ahb_podf divides by 4 => AHB_CLK@132MHz.
- * => by default, ipg_podf divides by 2 => IPG_CLK@66MHz.
- */
- HW_CCM_CBCDR.U = BF_CCM_CBCDR_AHB_PODF(3)
- | BF_CCM_CBCDR_AXI_PODF(1)
- | BF_CCM_CBCDR_IPG_PODF(1);
-
- setup_clk();
- /* Power up 480MHz PLL */
- reg32_write_mask(HW_CCM_ANALOG_PLL_USB1_ADDR, 0x00001000, 0x00001000);
- /* Enable 480MHz PLL */
- reg32_write_mask(HW_CCM_ANALOG_PLL_USB1_ADDR, 0x00002000, 0x00002000);
-
- reg32_write_mask(HW_CCM_CSCDR1_ADDR, 0x00000000, 0x0000003F);
- }
- uint32_t get_main_clock(main_clocks_t clock)
- {
- uint32_t ret_val = 0;
- uint32_t pre_periph_clk_sel = HW_CCM_CBCMR.B.PRE_PERIPH_CLK_SEL;
- switch (clock) {
- case CPU_CLK:
- ret_val = g_arm_clk;
- break;
- case AXI_CLK:
- ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AXI_PODF + 1);
- break;
- case MMDC_CH0_AXI_CLK:
- ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.MMDC_CH0_AXI_PODF + 1);
- break;
- case AHB_CLK:
- ret_val = PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AHB_PODF + 1);
- break;
- case IPG_CLK:
- ret_val =
- PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AHB_PODF +
- 1) / (HW_CCM_CBCDR.B.IPG_PODF + 1);
- break;
- case IPG_PER_CLK:
- ret_val =
- PLL2_OUTPUT[pre_periph_clk_sel] / (HW_CCM_CBCDR.B.AHB_PODF +
- 1) / (HW_CCM_CBCDR.B.IPG_PODF +
- 1) / (HW_CCM_CSCMR1.B.PERCLK_PODF + 1);
- break;
- default:
- break;
- }
- return ret_val;
- }
- uint32_t get_peri_clock(peri_clocks_t clock)
- {
- uint32_t ret_val = 0;
- switch (clock)
- {
- case UART1_MODULE_CLK:
- case UART2_MODULE_CLK:
- case UART3_MODULE_CLK:
- case UART4_MODULE_CLK:
- case UART5_MODULE_CLK:
- case UART6_MODULE_CLK:
- case UART7_MODULE_CLK:
- case UART8_MODULE_CLK:
- // UART source clock is a fixed PLL3 / 6
- ret_val = PLL3_OUTPUT[0] / 6 / (HW_CCM_CSCDR1.B.UART_CLK_PODF + 1);
- break;
- case SPI_CLK:
- ret_val = PLL3_OUTPUT[0] / 8 / (HW_CCM_CSCDR2.B.ECSPI_CLK_PODF + 1);
- break;
- case RAWNAND_CLK:
- ret_val =
- PLL3_OUTPUT[0] / (HW_CCM_CS2CDR.B.ENFC_CLK_PRED + 1) / (HW_CCM_CS2CDR.B.ENFC_CLK_PODF +
- 1);
- break;
- case CAN_CLK:
- // For i.mx6dq/sdl CAN source clock is a fixed PLL3 / 8
- ret_val = PLL3_OUTPUT[0] / 8 / (HW_CCM_CSCMR2.B.CAN_CLK_PODF + 1);
- break;
- default:
- break;
- }
- return ret_val;
- }
- void ccm_ccgr_config(uint32_t ccm_ccgrx, uint32_t cgx_offset, uint32_t gating_mode)
- {
- if (gating_mode == CLOCK_ON)
- {
- *(volatile uint32_t *)(ccm_ccgrx) |= cgx_offset;
- }
- else
- {
- *(volatile uint32_t *)(ccm_ccgrx) &= ~cgx_offset;
- }
- }
- void clock_gating_config(uint32_t base_address, uint32_t gating_mode)
- {
- uint32_t ccm_ccgrx = 0;
- uint32_t cgx_offset = 0;
- switch (base_address)
- {
- case REGS_UART1_BASE:
- ccm_ccgrx = HW_CCM_CCGR5_ADDR;
- cgx_offset = CG(12);
- break;
- case REGS_UART2_BASE:
- ccm_ccgrx = HW_CCM_CCGR0_ADDR;
- cgx_offset = CG(14);
- break;
- case REGS_UART3_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(5);
- break;
- case REGS_UART4_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(12);
- break;
- case REGS_UART5_BASE:
- ccm_ccgrx = HW_CCM_CCGR3_ADDR;
- cgx_offset = CG(1);
- break;
- case REGS_UART6_BASE:
- ccm_ccgrx = HW_CCM_CCGR3_ADDR;
- cgx_offset = CG(3);
- break;
- case REGS_UART7_BASE:
- ccm_ccgrx = HW_CCM_CCGR5_ADDR;
- cgx_offset = CG(13);
- break;
- case REGS_UART8_BASE:
- ccm_ccgrx = HW_CCM_CCGR6_ADDR;
- cgx_offset = CG(7);
- break;
- case REGS_SPBA_BASE:
- ccm_ccgrx = HW_CCM_CCGR5_ADDR;
- cgx_offset = CG(6);
- break;
- case REGS_SDMAARM_BASE:
- ccm_ccgrx = HW_CCM_CCGR5_ADDR;
- cgx_offset = CG(3);
- break;
- case REGS_EPIT1_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(6);
- break;
- case REGS_EPIT2_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(7);
- break;
- case REGS_GPT1_BASE:
- case REGS_GPT2_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(10)|CG(11);
- break;
- case REGS_I2C1_BASE:
- ccm_ccgrx = HW_CCM_CCGR2_ADDR;
- cgx_offset = CG(3);
- break;
- case REGS_I2C2_BASE:
- ccm_ccgrx = HW_CCM_CCGR2_ADDR;
- cgx_offset = CG(4);
- break;
- case REGS_I2C3_BASE:
- ccm_ccgrx = HW_CCM_CCGR2_ADDR;
- cgx_offset = CG(5);
- break;
- case REGS_ECSPI1_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(0);
- break;
- case REGS_ECSPI2_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(1);
- break;
- case REGS_ECSPI3_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(2);
- break;
- case REGS_ECSPI4_BASE:
- ccm_ccgrx = HW_CCM_CCGR1_ADDR;
- cgx_offset = CG(3);
- break;
- default:
- break;
- }
- // apply changes only if a valid address was found
- if (ccm_ccgrx != 0)
- {
- ccm_ccgr_config(ccm_ccgrx, cgx_offset, gating_mode);
- }
- }
- ////////////////////////////////////////////////////////////////////////////////
- // End of file
- ////////////////////////////////////////////////////////////////////////////////
|