Path: blob/master/arch/arm/mach-mx5/clock-mx51-mx53.c
10817 views
/*1* Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.2* Copyright (C) 2009-2010 Amit Kucheria <[email protected]>3*4* The code contained herein is licensed under the GNU General Public5* License. You may obtain a copy of the GNU General Public License6* Version 2 or later at the following locations:7*8* http://www.opensource.org/licenses/gpl-license.html9* http://www.gnu.org/copyleft/gpl.html10*/1112#include <linux/mm.h>13#include <linux/delay.h>14#include <linux/clk.h>15#include <linux/io.h>16#include <linux/clkdev.h>1718#include <asm/div64.h>1920#include <mach/hardware.h>21#include <mach/common.h>22#include <mach/clock.h>2324#include "crm_regs.h"2526/* External clock values passed-in by the board code */27static unsigned long external_high_reference, external_low_reference;28static unsigned long oscillator_reference, ckih2_reference;2930static struct clk osc_clk;31static struct clk pll1_main_clk;32static struct clk pll1_sw_clk;33static struct clk pll2_sw_clk;34static struct clk pll3_sw_clk;35static struct clk mx53_pll4_sw_clk;36static struct clk lp_apm_clk;37static struct clk periph_apm_clk;38static struct clk ahb_clk;39static struct clk ipg_clk;40static struct clk usboh3_clk;41static struct clk emi_fast_clk;42static struct clk ipu_clk;43static struct clk mipi_hsc1_clk;44static struct clk esdhc1_clk;45static struct clk esdhc2_clk;46static struct clk esdhc3_mx53_clk;4748#define MAX_DPLL_WAIT_TRIES 1000 /* 1000 * udelay(1) = 1ms */4950/* calculate best pre and post dividers to get the required divider */51static void __calc_pre_post_dividers(u32 div, u32 *pre, u32 *post,52u32 max_pre, u32 max_post)53{54if (div >= max_pre * max_post) {55*pre = max_pre;56*post = max_post;57} else if (div >= max_pre) {58u32 min_pre, temp_pre, old_err, err;59min_pre = DIV_ROUND_UP(div, max_post);60old_err = max_pre;61for (temp_pre = max_pre; temp_pre >= min_pre; temp_pre--) {62err = div % temp_pre;63if (err == 0) {64*pre = temp_pre;65break;66}67err = temp_pre - err;68if (err < old_err) {69old_err = err;70*pre = temp_pre;71}72}73*post = DIV_ROUND_UP(div, *pre);74} else {75*pre = div;76*post = 1;77}78}7980static void _clk_ccgr_setclk(struct clk *clk, unsigned mode)81{82u32 reg = __raw_readl(clk->enable_reg);8384reg &= ~(MXC_CCM_CCGRx_CG_MASK << clk->enable_shift);85reg |= mode << clk->enable_shift;8687__raw_writel(reg, clk->enable_reg);88}8990static int _clk_ccgr_enable(struct clk *clk)91{92_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_ON);93return 0;94}9596static void _clk_ccgr_disable(struct clk *clk)97{98_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_OFF);99}100101static int _clk_ccgr_enable_inrun(struct clk *clk)102{103_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);104return 0;105}106107static void _clk_ccgr_disable_inwait(struct clk *clk)108{109_clk_ccgr_setclk(clk, MXC_CCM_CCGRx_MOD_IDLE);110}111112/*113* For the 4-to-1 muxed input clock114*/115static inline u32 _get_mux(struct clk *parent, struct clk *m0,116struct clk *m1, struct clk *m2, struct clk *m3)117{118if (parent == m0)119return 0;120else if (parent == m1)121return 1;122else if (parent == m2)123return 2;124else if (parent == m3)125return 3;126else127BUG();128129return -EINVAL;130}131132static inline void __iomem *_mx51_get_pll_base(struct clk *pll)133{134if (pll == &pll1_main_clk)135return MX51_DPLL1_BASE;136else if (pll == &pll2_sw_clk)137return MX51_DPLL2_BASE;138else if (pll == &pll3_sw_clk)139return MX51_DPLL3_BASE;140else141BUG();142143return NULL;144}145146static inline void __iomem *_mx53_get_pll_base(struct clk *pll)147{148if (pll == &pll1_main_clk)149return MX53_DPLL1_BASE;150else if (pll == &pll2_sw_clk)151return MX53_DPLL2_BASE;152else if (pll == &pll3_sw_clk)153return MX53_DPLL3_BASE;154else if (pll == &mx53_pll4_sw_clk)155return MX53_DPLL4_BASE;156else157BUG();158159return NULL;160}161162static inline void __iomem *_get_pll_base(struct clk *pll)163{164if (cpu_is_mx51())165return _mx51_get_pll_base(pll);166else167return _mx53_get_pll_base(pll);168}169170static unsigned long clk_pll_get_rate(struct clk *clk)171{172long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;173unsigned long dp_op, dp_mfd, dp_mfn, dp_ctl, pll_hfsm, dbl;174void __iomem *pllbase;175s64 temp;176unsigned long parent_rate;177178parent_rate = clk_get_rate(clk->parent);179180pllbase = _get_pll_base(clk);181182dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);183pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;184dbl = dp_ctl & MXC_PLL_DP_CTL_DPDCK0_2_EN;185186if (pll_hfsm == 0) {187dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);188dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);189dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);190} else {191dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);192dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);193dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);194}195pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;196mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;197mfi = (mfi <= 5) ? 5 : mfi;198mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;199mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;200/* Sign extend to 32-bits */201if (mfn >= 0x04000000) {202mfn |= 0xFC000000;203mfn_abs = -mfn;204}205206ref_clk = 2 * parent_rate;207if (dbl != 0)208ref_clk *= 2;209210ref_clk /= (pdf + 1);211temp = (u64) ref_clk * mfn_abs;212do_div(temp, mfd + 1);213if (mfn < 0)214temp = -temp;215temp = (ref_clk * mfi) + temp;216217return temp;218}219220static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)221{222u32 reg;223void __iomem *pllbase;224225long mfi, pdf, mfn, mfd = 999999;226s64 temp64;227unsigned long quad_parent_rate;228unsigned long pll_hfsm, dp_ctl;229unsigned long parent_rate;230231parent_rate = clk_get_rate(clk->parent);232233pllbase = _get_pll_base(clk);234235quad_parent_rate = 4 * parent_rate;236pdf = mfi = -1;237while (++pdf < 16 && mfi < 5)238mfi = rate * (pdf+1) / quad_parent_rate;239if (mfi > 15)240return -EINVAL;241pdf--;242243temp64 = rate * (pdf+1) - quad_parent_rate * mfi;244do_div(temp64, quad_parent_rate/1000000);245mfn = (long)temp64;246247dp_ctl = __raw_readl(pllbase + MXC_PLL_DP_CTL);248/* use dpdck0_2 */249__raw_writel(dp_ctl | 0x1000L, pllbase + MXC_PLL_DP_CTL);250pll_hfsm = dp_ctl & MXC_PLL_DP_CTL_HFSM;251if (pll_hfsm == 0) {252reg = mfi << 4 | pdf;253__raw_writel(reg, pllbase + MXC_PLL_DP_OP);254__raw_writel(mfd, pllbase + MXC_PLL_DP_MFD);255__raw_writel(mfn, pllbase + MXC_PLL_DP_MFN);256} else {257reg = mfi << 4 | pdf;258__raw_writel(reg, pllbase + MXC_PLL_DP_HFS_OP);259__raw_writel(mfd, pllbase + MXC_PLL_DP_HFS_MFD);260__raw_writel(mfn, pllbase + MXC_PLL_DP_HFS_MFN);261}262263return 0;264}265266static int _clk_pll_enable(struct clk *clk)267{268u32 reg;269void __iomem *pllbase;270int i = 0;271272pllbase = _get_pll_base(clk);273reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) | MXC_PLL_DP_CTL_UPEN;274__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);275276/* Wait for lock */277do {278reg = __raw_readl(pllbase + MXC_PLL_DP_CTL);279if (reg & MXC_PLL_DP_CTL_LRF)280break;281282udelay(1);283} while (++i < MAX_DPLL_WAIT_TRIES);284285if (i == MAX_DPLL_WAIT_TRIES) {286pr_err("MX5: pll locking failed\n");287return -EINVAL;288}289290return 0;291}292293static void _clk_pll_disable(struct clk *clk)294{295u32 reg;296void __iomem *pllbase;297298pllbase = _get_pll_base(clk);299reg = __raw_readl(pllbase + MXC_PLL_DP_CTL) & ~MXC_PLL_DP_CTL_UPEN;300__raw_writel(reg, pllbase + MXC_PLL_DP_CTL);301}302303static int _clk_pll1_sw_set_parent(struct clk *clk, struct clk *parent)304{305u32 reg, step;306307reg = __raw_readl(MXC_CCM_CCSR);308309/* When switching from pll_main_clk to a bypass clock, first select a310* multiplexed clock in 'step_sel', then shift the glitchless mux311* 'pll1_sw_clk_sel'.312*313* When switching back, do it in reverse order314*/315if (parent == &pll1_main_clk) {316/* Switch to pll1_main_clk */317reg &= ~MXC_CCM_CCSR_PLL1_SW_CLK_SEL;318__raw_writel(reg, MXC_CCM_CCSR);319/* step_clk mux switched to lp_apm, to save power. */320reg = __raw_readl(MXC_CCM_CCSR);321reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;322reg |= (MXC_CCM_CCSR_STEP_SEL_LP_APM <<323MXC_CCM_CCSR_STEP_SEL_OFFSET);324} else {325if (parent == &lp_apm_clk) {326step = MXC_CCM_CCSR_STEP_SEL_LP_APM;327} else if (parent == &pll2_sw_clk) {328step = MXC_CCM_CCSR_STEP_SEL_PLL2_DIVIDED;329} else if (parent == &pll3_sw_clk) {330step = MXC_CCM_CCSR_STEP_SEL_PLL3_DIVIDED;331} else332return -EINVAL;333334reg &= ~MXC_CCM_CCSR_STEP_SEL_MASK;335reg |= (step << MXC_CCM_CCSR_STEP_SEL_OFFSET);336337__raw_writel(reg, MXC_CCM_CCSR);338/* Switch to step_clk */339reg = __raw_readl(MXC_CCM_CCSR);340reg |= MXC_CCM_CCSR_PLL1_SW_CLK_SEL;341}342__raw_writel(reg, MXC_CCM_CCSR);343return 0;344}345346static unsigned long clk_pll1_sw_get_rate(struct clk *clk)347{348u32 reg, div;349unsigned long parent_rate;350351parent_rate = clk_get_rate(clk->parent);352353reg = __raw_readl(MXC_CCM_CCSR);354355if (clk->parent == &pll2_sw_clk) {356div = ((reg & MXC_CCM_CCSR_PLL2_PODF_MASK) >>357MXC_CCM_CCSR_PLL2_PODF_OFFSET) + 1;358} else if (clk->parent == &pll3_sw_clk) {359div = ((reg & MXC_CCM_CCSR_PLL3_PODF_MASK) >>360MXC_CCM_CCSR_PLL3_PODF_OFFSET) + 1;361} else362div = 1;363return parent_rate / div;364}365366static int _clk_pll2_sw_set_parent(struct clk *clk, struct clk *parent)367{368u32 reg;369370reg = __raw_readl(MXC_CCM_CCSR);371372if (parent == &pll2_sw_clk)373reg &= ~MXC_CCM_CCSR_PLL2_SW_CLK_SEL;374else375reg |= MXC_CCM_CCSR_PLL2_SW_CLK_SEL;376377__raw_writel(reg, MXC_CCM_CCSR);378return 0;379}380381static int _clk_lp_apm_set_parent(struct clk *clk, struct clk *parent)382{383u32 reg;384385if (parent == &osc_clk)386reg = __raw_readl(MXC_CCM_CCSR) & ~MXC_CCM_CCSR_LP_APM_SEL;387else388return -EINVAL;389390__raw_writel(reg, MXC_CCM_CCSR);391392return 0;393}394395static unsigned long clk_cpu_get_rate(struct clk *clk)396{397u32 cacrr, div;398unsigned long parent_rate;399400parent_rate = clk_get_rate(clk->parent);401cacrr = __raw_readl(MXC_CCM_CACRR);402div = (cacrr & MXC_CCM_CACRR_ARM_PODF_MASK) + 1;403404return parent_rate / div;405}406407static int clk_cpu_set_rate(struct clk *clk, unsigned long rate)408{409u32 reg, cpu_podf;410unsigned long parent_rate;411412parent_rate = clk_get_rate(clk->parent);413cpu_podf = parent_rate / rate - 1;414/* use post divider to change freq */415reg = __raw_readl(MXC_CCM_CACRR);416reg &= ~MXC_CCM_CACRR_ARM_PODF_MASK;417reg |= cpu_podf << MXC_CCM_CACRR_ARM_PODF_OFFSET;418__raw_writel(reg, MXC_CCM_CACRR);419420return 0;421}422423static int _clk_periph_apm_set_parent(struct clk *clk, struct clk *parent)424{425u32 reg, mux;426int i = 0;427428mux = _get_mux(parent, &pll1_sw_clk, &pll3_sw_clk, &lp_apm_clk, NULL);429430reg = __raw_readl(MXC_CCM_CBCMR) & ~MXC_CCM_CBCMR_PERIPH_CLK_SEL_MASK;431reg |= mux << MXC_CCM_CBCMR_PERIPH_CLK_SEL_OFFSET;432__raw_writel(reg, MXC_CCM_CBCMR);433434/* Wait for lock */435do {436reg = __raw_readl(MXC_CCM_CDHIPR);437if (!(reg & MXC_CCM_CDHIPR_PERIPH_CLK_SEL_BUSY))438break;439440udelay(1);441} while (++i < MAX_DPLL_WAIT_TRIES);442443if (i == MAX_DPLL_WAIT_TRIES) {444pr_err("MX5: Set parent for periph_apm clock failed\n");445return -EINVAL;446}447448return 0;449}450451static int _clk_main_bus_set_parent(struct clk *clk, struct clk *parent)452{453u32 reg;454455reg = __raw_readl(MXC_CCM_CBCDR);456457if (parent == &pll2_sw_clk)458reg &= ~MXC_CCM_CBCDR_PERIPH_CLK_SEL;459else if (parent == &periph_apm_clk)460reg |= MXC_CCM_CBCDR_PERIPH_CLK_SEL;461else462return -EINVAL;463464__raw_writel(reg, MXC_CCM_CBCDR);465466return 0;467}468469static struct clk main_bus_clk = {470.parent = &pll2_sw_clk,471.set_parent = _clk_main_bus_set_parent,472};473474static unsigned long clk_ahb_get_rate(struct clk *clk)475{476u32 reg, div;477unsigned long parent_rate;478479parent_rate = clk_get_rate(clk->parent);480481reg = __raw_readl(MXC_CCM_CBCDR);482div = ((reg & MXC_CCM_CBCDR_AHB_PODF_MASK) >>483MXC_CCM_CBCDR_AHB_PODF_OFFSET) + 1;484return parent_rate / div;485}486487488static int _clk_ahb_set_rate(struct clk *clk, unsigned long rate)489{490u32 reg, div;491unsigned long parent_rate;492int i = 0;493494parent_rate = clk_get_rate(clk->parent);495496div = parent_rate / rate;497if (div > 8 || div < 1 || ((parent_rate / div) != rate))498return -EINVAL;499500reg = __raw_readl(MXC_CCM_CBCDR);501reg &= ~MXC_CCM_CBCDR_AHB_PODF_MASK;502reg |= (div - 1) << MXC_CCM_CBCDR_AHB_PODF_OFFSET;503__raw_writel(reg, MXC_CCM_CBCDR);504505/* Wait for lock */506do {507reg = __raw_readl(MXC_CCM_CDHIPR);508if (!(reg & MXC_CCM_CDHIPR_AHB_PODF_BUSY))509break;510511udelay(1);512} while (++i < MAX_DPLL_WAIT_TRIES);513514if (i == MAX_DPLL_WAIT_TRIES) {515pr_err("MX5: clk_ahb_set_rate failed\n");516return -EINVAL;517}518519return 0;520}521522static unsigned long _clk_ahb_round_rate(struct clk *clk,523unsigned long rate)524{525u32 div;526unsigned long parent_rate;527528parent_rate = clk_get_rate(clk->parent);529530div = parent_rate / rate;531if (div > 8)532div = 8;533else if (div == 0)534div++;535return parent_rate / div;536}537538539static int _clk_max_enable(struct clk *clk)540{541u32 reg;542543_clk_ccgr_enable(clk);544545/* Handshake with MAX when LPM is entered. */546reg = __raw_readl(MXC_CCM_CLPCR);547if (cpu_is_mx51())548reg &= ~MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;549else if (cpu_is_mx53())550reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;551__raw_writel(reg, MXC_CCM_CLPCR);552553return 0;554}555556static void _clk_max_disable(struct clk *clk)557{558u32 reg;559560_clk_ccgr_disable_inwait(clk);561562/* No Handshake with MAX when LPM is entered as its disabled. */563reg = __raw_readl(MXC_CCM_CLPCR);564if (cpu_is_mx51())565reg |= MX51_CCM_CLPCR_BYPASS_MAX_LPM_HS;566else if (cpu_is_mx53())567reg &= ~MX53_CCM_CLPCR_BYPASS_MAX_LPM_HS;568__raw_writel(reg, MXC_CCM_CLPCR);569}570571static unsigned long clk_ipg_get_rate(struct clk *clk)572{573u32 reg, div;574unsigned long parent_rate;575576parent_rate = clk_get_rate(clk->parent);577578reg = __raw_readl(MXC_CCM_CBCDR);579div = ((reg & MXC_CCM_CBCDR_IPG_PODF_MASK) >>580MXC_CCM_CBCDR_IPG_PODF_OFFSET) + 1;581582return parent_rate / div;583}584585static unsigned long clk_ipg_per_get_rate(struct clk *clk)586{587u32 reg, prediv1, prediv2, podf;588unsigned long parent_rate;589590parent_rate = clk_get_rate(clk->parent);591592if (clk->parent == &main_bus_clk || clk->parent == &lp_apm_clk) {593/* the main_bus_clk is the one before the DVFS engine */594reg = __raw_readl(MXC_CCM_CBCDR);595prediv1 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED1_MASK) >>596MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET) + 1;597prediv2 = ((reg & MXC_CCM_CBCDR_PERCLK_PRED2_MASK) >>598MXC_CCM_CBCDR_PERCLK_PRED2_OFFSET) + 1;599podf = ((reg & MXC_CCM_CBCDR_PERCLK_PODF_MASK) >>600MXC_CCM_CBCDR_PERCLK_PODF_OFFSET) + 1;601return parent_rate / (prediv1 * prediv2 * podf);602} else if (clk->parent == &ipg_clk)603return parent_rate;604else605BUG();606}607608static int _clk_ipg_per_set_parent(struct clk *clk, struct clk *parent)609{610u32 reg;611612reg = __raw_readl(MXC_CCM_CBCMR);613614reg &= ~MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;615reg &= ~MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;616617if (parent == &ipg_clk)618reg |= MXC_CCM_CBCMR_PERCLK_IPG_CLK_SEL;619else if (parent == &lp_apm_clk)620reg |= MXC_CCM_CBCMR_PERCLK_LP_APM_CLK_SEL;621else if (parent != &main_bus_clk)622return -EINVAL;623624__raw_writel(reg, MXC_CCM_CBCMR);625626return 0;627}628629#define clk_nfc_set_parent NULL630631static unsigned long clk_nfc_get_rate(struct clk *clk)632{633unsigned long rate;634u32 reg, div;635636reg = __raw_readl(MXC_CCM_CBCDR);637div = ((reg & MXC_CCM_CBCDR_NFC_PODF_MASK) >>638MXC_CCM_CBCDR_NFC_PODF_OFFSET) + 1;639rate = clk_get_rate(clk->parent) / div;640WARN_ON(rate == 0);641return rate;642}643644static unsigned long clk_nfc_round_rate(struct clk *clk,645unsigned long rate)646{647u32 div;648unsigned long parent_rate = clk_get_rate(clk->parent);649650if (!rate)651return -EINVAL;652653div = parent_rate / rate;654655if (parent_rate % rate)656div++;657658if (div > 8)659return -EINVAL;660661return parent_rate / div;662663}664665static int clk_nfc_set_rate(struct clk *clk, unsigned long rate)666{667u32 reg, div;668669div = clk_get_rate(clk->parent) / rate;670if (div == 0)671div++;672if (((clk_get_rate(clk->parent) / div) != rate) || (div > 8))673return -EINVAL;674675reg = __raw_readl(MXC_CCM_CBCDR);676reg &= ~MXC_CCM_CBCDR_NFC_PODF_MASK;677reg |= (div - 1) << MXC_CCM_CBCDR_NFC_PODF_OFFSET;678__raw_writel(reg, MXC_CCM_CBCDR);679680while (__raw_readl(MXC_CCM_CDHIPR) &681MXC_CCM_CDHIPR_NFC_IPG_INT_MEM_PODF_BUSY){682}683684return 0;685}686687static unsigned long get_high_reference_clock_rate(struct clk *clk)688{689return external_high_reference;690}691692static unsigned long get_low_reference_clock_rate(struct clk *clk)693{694return external_low_reference;695}696697static unsigned long get_oscillator_reference_clock_rate(struct clk *clk)698{699return oscillator_reference;700}701702static unsigned long get_ckih2_reference_clock_rate(struct clk *clk)703{704return ckih2_reference;705}706707static unsigned long clk_emi_slow_get_rate(struct clk *clk)708{709u32 reg, div;710711reg = __raw_readl(MXC_CCM_CBCDR);712div = ((reg & MXC_CCM_CBCDR_EMI_PODF_MASK) >>713MXC_CCM_CBCDR_EMI_PODF_OFFSET) + 1;714715return clk_get_rate(clk->parent) / div;716}717718static unsigned long _clk_ddr_hf_get_rate(struct clk *clk)719{720unsigned long rate;721u32 reg, div;722723reg = __raw_readl(MXC_CCM_CBCDR);724div = ((reg & MXC_CCM_CBCDR_DDR_PODF_MASK) >>725MXC_CCM_CBCDR_DDR_PODF_OFFSET) + 1;726rate = clk_get_rate(clk->parent) / div;727728return rate;729}730731/* External high frequency clock */732static struct clk ckih_clk = {733.get_rate = get_high_reference_clock_rate,734};735736static struct clk ckih2_clk = {737.get_rate = get_ckih2_reference_clock_rate,738};739740static struct clk osc_clk = {741.get_rate = get_oscillator_reference_clock_rate,742};743744/* External low frequency (32kHz) clock */745static struct clk ckil_clk = {746.get_rate = get_low_reference_clock_rate,747};748749static struct clk pll1_main_clk = {750.parent = &osc_clk,751.get_rate = clk_pll_get_rate,752.enable = _clk_pll_enable,753.disable = _clk_pll_disable,754};755756/* Clock tree block diagram (WIP):757* CCM: Clock Controller Module758*759* PLL output -> |760* | CCM Switcher -> CCM_CLK_ROOT_GEN ->761* PLL bypass -> |762*763*/764765/* PLL1 SW supplies to ARM core */766static struct clk pll1_sw_clk = {767.parent = &pll1_main_clk,768.set_parent = _clk_pll1_sw_set_parent,769.get_rate = clk_pll1_sw_get_rate,770};771772/* PLL2 SW supplies to AXI/AHB/IP buses */773static struct clk pll2_sw_clk = {774.parent = &osc_clk,775.get_rate = clk_pll_get_rate,776.set_rate = _clk_pll_set_rate,777.set_parent = _clk_pll2_sw_set_parent,778.enable = _clk_pll_enable,779.disable = _clk_pll_disable,780};781782/* PLL3 SW supplies to serial clocks like USB, SSI, etc. */783static struct clk pll3_sw_clk = {784.parent = &osc_clk,785.set_rate = _clk_pll_set_rate,786.get_rate = clk_pll_get_rate,787.enable = _clk_pll_enable,788.disable = _clk_pll_disable,789};790791/* PLL4 SW supplies to LVDS Display Bridge(LDB) */792static struct clk mx53_pll4_sw_clk = {793.parent = &osc_clk,794.set_rate = _clk_pll_set_rate,795.enable = _clk_pll_enable,796.disable = _clk_pll_disable,797};798799/* Low-power Audio Playback Mode clock */800static struct clk lp_apm_clk = {801.parent = &osc_clk,802.set_parent = _clk_lp_apm_set_parent,803};804805static struct clk periph_apm_clk = {806.parent = &pll1_sw_clk,807.set_parent = _clk_periph_apm_set_parent,808};809810static struct clk cpu_clk = {811.parent = &pll1_sw_clk,812.get_rate = clk_cpu_get_rate,813.set_rate = clk_cpu_set_rate,814};815816static struct clk ahb_clk = {817.parent = &main_bus_clk,818.get_rate = clk_ahb_get_rate,819.set_rate = _clk_ahb_set_rate,820.round_rate = _clk_ahb_round_rate,821};822823static struct clk iim_clk = {824.parent = &ipg_clk,825.enable_reg = MXC_CCM_CCGR0,826.enable_shift = MXC_CCM_CCGRx_CG15_OFFSET,827};828829/* Main IP interface clock for access to registers */830static struct clk ipg_clk = {831.parent = &ahb_clk,832.get_rate = clk_ipg_get_rate,833};834835static struct clk ipg_perclk = {836.parent = &lp_apm_clk,837.get_rate = clk_ipg_per_get_rate,838.set_parent = _clk_ipg_per_set_parent,839};840841static struct clk ahb_max_clk = {842.parent = &ahb_clk,843.enable_reg = MXC_CCM_CCGR0,844.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,845.enable = _clk_max_enable,846.disable = _clk_max_disable,847};848849static struct clk aips_tz1_clk = {850.parent = &ahb_clk,851.secondary = &ahb_max_clk,852.enable_reg = MXC_CCM_CCGR0,853.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,854.enable = _clk_ccgr_enable,855.disable = _clk_ccgr_disable_inwait,856};857858static struct clk aips_tz2_clk = {859.parent = &ahb_clk,860.secondary = &ahb_max_clk,861.enable_reg = MXC_CCM_CCGR0,862.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,863.enable = _clk_ccgr_enable,864.disable = _clk_ccgr_disable_inwait,865};866867static struct clk gpc_dvfs_clk = {868.enable_reg = MXC_CCM_CCGR5,869.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,870.enable = _clk_ccgr_enable,871.disable = _clk_ccgr_disable,872};873874static struct clk gpt_32k_clk = {875.id = 0,876.parent = &ckil_clk,877};878879static struct clk dummy_clk = {880.id = 0,881};882883static struct clk emi_slow_clk = {884.parent = &pll2_sw_clk,885.enable_reg = MXC_CCM_CCGR5,886.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,887.enable = _clk_ccgr_enable,888.disable = _clk_ccgr_disable_inwait,889.get_rate = clk_emi_slow_get_rate,890};891892static int clk_ipu_enable(struct clk *clk)893{894u32 reg;895896_clk_ccgr_enable(clk);897898/* Enable handshake with IPU when certain clock rates are changed */899reg = __raw_readl(MXC_CCM_CCDR);900reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;901__raw_writel(reg, MXC_CCM_CCDR);902903/* Enable handshake with IPU when LPM is entered */904reg = __raw_readl(MXC_CCM_CLPCR);905reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;906__raw_writel(reg, MXC_CCM_CLPCR);907908return 0;909}910911static void clk_ipu_disable(struct clk *clk)912{913u32 reg;914915_clk_ccgr_disable(clk);916917/* Disable handshake with IPU whe dividers are changed */918reg = __raw_readl(MXC_CCM_CCDR);919reg |= MXC_CCM_CCDR_IPU_HS_MASK;920__raw_writel(reg, MXC_CCM_CCDR);921922/* Disable handshake with IPU when LPM is entered */923reg = __raw_readl(MXC_CCM_CLPCR);924reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;925__raw_writel(reg, MXC_CCM_CLPCR);926}927928static struct clk ahbmux1_clk = {929.parent = &ahb_clk,930.secondary = &ahb_max_clk,931.enable_reg = MXC_CCM_CCGR0,932.enable_shift = MXC_CCM_CCGRx_CG8_OFFSET,933.enable = _clk_ccgr_enable,934.disable = _clk_ccgr_disable_inwait,935};936937static struct clk ipu_sec_clk = {938.parent = &emi_fast_clk,939.secondary = &ahbmux1_clk,940};941942static struct clk ddr_hf_clk = {943.parent = &pll1_sw_clk,944.get_rate = _clk_ddr_hf_get_rate,945};946947static struct clk ddr_clk = {948.parent = &ddr_hf_clk,949};950951/* clock definitions for MIPI HSC unit which has been removed952* from documentation, but not from hardware953*/954static int _clk_hsc_enable(struct clk *clk)955{956u32 reg;957958_clk_ccgr_enable(clk);959/* Handshake with IPU when certain clock rates are changed. */960reg = __raw_readl(MXC_CCM_CCDR);961reg &= ~MXC_CCM_CCDR_HSC_HS_MASK;962__raw_writel(reg, MXC_CCM_CCDR);963964reg = __raw_readl(MXC_CCM_CLPCR);965reg &= ~MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;966__raw_writel(reg, MXC_CCM_CLPCR);967968return 0;969}970971static void _clk_hsc_disable(struct clk *clk)972{973u32 reg;974975_clk_ccgr_disable(clk);976/* No handshake with HSC as its not enabled. */977reg = __raw_readl(MXC_CCM_CCDR);978reg |= MXC_CCM_CCDR_HSC_HS_MASK;979__raw_writel(reg, MXC_CCM_CCDR);980981reg = __raw_readl(MXC_CCM_CLPCR);982reg |= MXC_CCM_CLPCR_BYPASS_HSC_LPM_HS;983__raw_writel(reg, MXC_CCM_CLPCR);984}985986static struct clk mipi_hsp_clk = {987.parent = &ipu_clk,988.enable_reg = MXC_CCM_CCGR4,989.enable_shift = MXC_CCM_CCGRx_CG6_OFFSET,990.enable = _clk_hsc_enable,991.disable = _clk_hsc_disable,992.secondary = &mipi_hsc1_clk,993};994995#define DEFINE_CLOCK_CCGR(name, i, er, es, pfx, p, s) \996static struct clk name = { \997.id = i, \998.enable_reg = er, \999.enable_shift = es, \1000.get_rate = pfx##_get_rate, \1001.set_rate = pfx##_set_rate, \1002.round_rate = pfx##_round_rate, \1003.set_parent = pfx##_set_parent, \1004.enable = _clk_ccgr_enable, \1005.disable = _clk_ccgr_disable, \1006.parent = p, \1007.secondary = s, \1008}10091010#define DEFINE_CLOCK_MAX(name, i, er, es, pfx, p, s) \1011static struct clk name = { \1012.id = i, \1013.enable_reg = er, \1014.enable_shift = es, \1015.get_rate = pfx##_get_rate, \1016.set_rate = pfx##_set_rate, \1017.set_parent = pfx##_set_parent, \1018.enable = _clk_max_enable, \1019.disable = _clk_max_disable, \1020.parent = p, \1021.secondary = s, \1022}10231024#define CLK_GET_RATE(name, nr, bitsname) \1025static unsigned long clk_##name##_get_rate(struct clk *clk) \1026{ \1027u32 reg, pred, podf; \1028\1029reg = __raw_readl(MXC_CCM_CSCDR##nr); \1030pred = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK) \1031>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \1032podf = (reg & MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK) \1033>> MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \1034\1035return DIV_ROUND_CLOSEST(clk_get_rate(clk->parent), \1036(pred + 1) * (podf + 1)); \1037}10381039#define CLK_SET_PARENT(name, nr, bitsname) \1040static int clk_##name##_set_parent(struct clk *clk, struct clk *parent) \1041{ \1042u32 reg, mux; \1043\1044mux = _get_mux(parent, &pll1_sw_clk, &pll2_sw_clk, \1045&pll3_sw_clk, &lp_apm_clk); \1046reg = __raw_readl(MXC_CCM_CSCMR##nr) & \1047~MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_MASK; \1048reg |= mux << MXC_CCM_CSCMR##nr##_##bitsname##_CLK_SEL_OFFSET; \1049__raw_writel(reg, MXC_CCM_CSCMR##nr); \1050\1051return 0; \1052}10531054#define CLK_SET_RATE(name, nr, bitsname) \1055static int clk_##name##_set_rate(struct clk *clk, unsigned long rate) \1056{ \1057u32 reg, div, parent_rate; \1058u32 pre = 0, post = 0; \1059\1060parent_rate = clk_get_rate(clk->parent); \1061div = parent_rate / rate; \1062\1063if ((parent_rate / div) != rate) \1064return -EINVAL; \1065\1066__calc_pre_post_dividers(div, &pre, &post, \1067(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK >> \1068MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET) + 1, \1069(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK >> \1070MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET) + 1);\1071\1072/* Set sdhc1 clock divider */ \1073reg = __raw_readl(MXC_CCM_CSCDR##nr) & \1074~(MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_MASK \1075| MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_MASK); \1076reg |= (post - 1) << \1077MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PODF_OFFSET; \1078reg |= (pre - 1) << \1079MXC_CCM_CSCDR##nr##_##bitsname##_CLK_PRED_OFFSET; \1080__raw_writel(reg, MXC_CCM_CSCDR##nr); \1081\1082return 0; \1083}10841085/* UART */1086CLK_GET_RATE(uart, 1, UART)1087CLK_SET_PARENT(uart, 1, UART)10881089static struct clk uart_root_clk = {1090.parent = &pll2_sw_clk,1091.get_rate = clk_uart_get_rate,1092.set_parent = clk_uart_set_parent,1093};10941095/* USBOH3 */1096CLK_GET_RATE(usboh3, 1, USBOH3)1097CLK_SET_PARENT(usboh3, 1, USBOH3)10981099static struct clk usboh3_clk = {1100.parent = &pll2_sw_clk,1101.get_rate = clk_usboh3_get_rate,1102.set_parent = clk_usboh3_set_parent,1103.enable = _clk_ccgr_enable,1104.disable = _clk_ccgr_disable,1105.enable_reg = MXC_CCM_CCGR2,1106.enable_shift = MXC_CCM_CCGRx_CG14_OFFSET,1107};11081109static struct clk usb_ahb_clk = {1110.parent = &ipg_clk,1111.enable = _clk_ccgr_enable,1112.disable = _clk_ccgr_disable,1113.enable_reg = MXC_CCM_CCGR2,1114.enable_shift = MXC_CCM_CCGRx_CG13_OFFSET,1115};11161117static int clk_usb_phy1_set_parent(struct clk *clk, struct clk *parent)1118{1119u32 reg;11201121reg = __raw_readl(MXC_CCM_CSCMR1) & ~MXC_CCM_CSCMR1_USB_PHY_CLK_SEL;11221123if (parent == &pll3_sw_clk)1124reg |= 1 << MXC_CCM_CSCMR1_USB_PHY_CLK_SEL_OFFSET;11251126__raw_writel(reg, MXC_CCM_CSCMR1);11271128return 0;1129}11301131static struct clk usb_phy1_clk = {1132.parent = &pll3_sw_clk,1133.set_parent = clk_usb_phy1_set_parent,1134.enable = _clk_ccgr_enable,1135.enable_reg = MXC_CCM_CCGR2,1136.enable_shift = MXC_CCM_CCGRx_CG0_OFFSET,1137.disable = _clk_ccgr_disable,1138};11391140/* eCSPI */1141CLK_GET_RATE(ecspi, 2, CSPI)1142CLK_SET_PARENT(ecspi, 1, CSPI)11431144static struct clk ecspi_main_clk = {1145.parent = &pll3_sw_clk,1146.get_rate = clk_ecspi_get_rate,1147.set_parent = clk_ecspi_set_parent,1148};11491150/* eSDHC */1151CLK_GET_RATE(esdhc1, 1, ESDHC1_MSHC1)1152CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)1153CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)11541155/* mx51 specific */1156CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)1157CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)1158CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)11591160static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)1161{1162u32 reg;11631164reg = __raw_readl(MXC_CCM_CSCMR1);1165if (parent == &esdhc1_clk)1166reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;1167else if (parent == &esdhc2_clk)1168reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;1169else1170return -EINVAL;1171__raw_writel(reg, MXC_CCM_CSCMR1);11721173return 0;1174}11751176static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)1177{1178u32 reg;11791180reg = __raw_readl(MXC_CCM_CSCMR1);1181if (parent == &esdhc1_clk)1182reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;1183else if (parent == &esdhc2_clk)1184reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;1185else1186return -EINVAL;1187__raw_writel(reg, MXC_CCM_CSCMR1);11881189return 0;1190}11911192/* mx53 specific */1193static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)1194{1195u32 reg;11961197reg = __raw_readl(MXC_CCM_CSCMR1);1198if (parent == &esdhc1_clk)1199reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;1200else if (parent == &esdhc3_mx53_clk)1201reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;1202else1203return -EINVAL;1204__raw_writel(reg, MXC_CCM_CSCMR1);12051206return 0;1207}12081209CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)1210CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)1211CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)12121213static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)1214{1215u32 reg;12161217reg = __raw_readl(MXC_CCM_CSCMR1);1218if (parent == &esdhc1_clk)1219reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;1220else if (parent == &esdhc3_mx53_clk)1221reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;1222else1223return -EINVAL;1224__raw_writel(reg, MXC_CCM_CSCMR1);12251226return 0;1227}12281229#define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s) \1230static struct clk name = { \1231.id = i, \1232.enable_reg = er, \1233.enable_shift = es, \1234.get_rate = gr, \1235.set_rate = sr, \1236.enable = e, \1237.disable = d, \1238.parent = p, \1239.secondary = s, \1240}12411242#define DEFINE_CLOCK(name, i, er, es, gr, sr, p, s) \1243DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, _clk_ccgr_enable, _clk_ccgr_disable, p, s)12441245/* Shared peripheral bus arbiter */1246DEFINE_CLOCK(spba_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG0_OFFSET,1247NULL, NULL, &ipg_clk, NULL);12481249/* UART */1250DEFINE_CLOCK(uart1_ipg_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG3_OFFSET,1251NULL, NULL, &ipg_clk, &aips_tz1_clk);1252DEFINE_CLOCK(uart2_ipg_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG5_OFFSET,1253NULL, NULL, &ipg_clk, &aips_tz1_clk);1254DEFINE_CLOCK(uart3_ipg_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG7_OFFSET,1255NULL, NULL, &ipg_clk, &spba_clk);1256DEFINE_CLOCK(uart1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG4_OFFSET,1257NULL, NULL, &uart_root_clk, &uart1_ipg_clk);1258DEFINE_CLOCK(uart2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG6_OFFSET,1259NULL, NULL, &uart_root_clk, &uart2_ipg_clk);1260DEFINE_CLOCK(uart3_clk, 2, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG8_OFFSET,1261NULL, NULL, &uart_root_clk, &uart3_ipg_clk);12621263/* GPT */1264DEFINE_CLOCK(gpt_ipg_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG10_OFFSET,1265NULL, NULL, &ipg_clk, NULL);1266DEFINE_CLOCK(gpt_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG9_OFFSET,1267NULL, NULL, &ipg_clk, &gpt_ipg_clk);12681269DEFINE_CLOCK(pwm1_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG6_OFFSET,1270NULL, NULL, &ipg_clk, NULL);1271DEFINE_CLOCK(pwm2_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG8_OFFSET,1272NULL, NULL, &ipg_clk, NULL);12731274/* I2C */1275DEFINE_CLOCK(i2c1_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG9_OFFSET,1276NULL, NULL, &ipg_clk, NULL);1277DEFINE_CLOCK(i2c2_clk, 1, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG10_OFFSET,1278NULL, NULL, &ipg_clk, NULL);1279DEFINE_CLOCK(hsi2c_clk, 0, MXC_CCM_CCGR1, MXC_CCM_CCGRx_CG11_OFFSET,1280NULL, NULL, &ipg_clk, NULL);12811282/* FEC */1283DEFINE_CLOCK(fec_clk, 0, MXC_CCM_CCGR2, MXC_CCM_CCGRx_CG12_OFFSET,1284NULL, NULL, &ipg_clk, NULL);12851286/* NFC */1287DEFINE_CLOCK_CCGR(nfc_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG10_OFFSET,1288clk_nfc, &emi_slow_clk, NULL);12891290/* SSI */1291DEFINE_CLOCK(ssi1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG8_OFFSET,1292NULL, NULL, &ipg_clk, NULL);1293DEFINE_CLOCK(ssi1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG9_OFFSET,1294NULL, NULL, &pll3_sw_clk, &ssi1_ipg_clk);1295DEFINE_CLOCK(ssi2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG10_OFFSET,1296NULL, NULL, &ipg_clk, NULL);1297DEFINE_CLOCK(ssi2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG11_OFFSET,1298NULL, NULL, &pll3_sw_clk, &ssi2_ipg_clk);1299DEFINE_CLOCK(ssi3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG12_OFFSET,1300NULL, NULL, &ipg_clk, NULL);1301DEFINE_CLOCK(ssi3_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG13_OFFSET,1302NULL, NULL, &pll3_sw_clk, &ssi3_ipg_clk);13031304/* eCSPI */1305DEFINE_CLOCK_FULL(ecspi1_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,1306NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,1307&ipg_clk, &spba_clk);1308DEFINE_CLOCK(ecspi1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG10_OFFSET,1309NULL, NULL, &ecspi_main_clk, &ecspi1_ipg_clk);1310DEFINE_CLOCK_FULL(ecspi2_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG11_OFFSET,1311NULL, NULL, _clk_ccgr_enable_inrun, _clk_ccgr_disable,1312&ipg_clk, &aips_tz2_clk);1313DEFINE_CLOCK(ecspi2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG12_OFFSET,1314NULL, NULL, &ecspi_main_clk, &ecspi2_ipg_clk);13151316/* CSPI */1317DEFINE_CLOCK(cspi_ipg_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG9_OFFSET,1318NULL, NULL, &ipg_clk, &aips_tz2_clk);1319DEFINE_CLOCK(cspi_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG13_OFFSET,1320NULL, NULL, &ipg_clk, &cspi_ipg_clk);13211322/* SDMA */1323DEFINE_CLOCK(sdma_clk, 1, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG15_OFFSET,1324NULL, NULL, &ahb_clk, NULL);13251326/* eSDHC */1327DEFINE_CLOCK_FULL(esdhc1_ipg_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG0_OFFSET,1328NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);1329DEFINE_CLOCK_MAX(esdhc1_clk, 0, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG1_OFFSET,1330clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);1331DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,1332NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);1333DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,1334NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);1335DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,1336NULL, NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);13371338/* mx51 specific */1339DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,1340clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);13411342static struct clk esdhc3_clk = {1343.id = 2,1344.parent = &esdhc1_clk,1345.set_parent = clk_esdhc3_set_parent,1346.enable_reg = MXC_CCM_CCGR3,1347.enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,1348.enable = _clk_max_enable,1349.disable = _clk_max_disable,1350.secondary = &esdhc3_ipg_clk,1351};1352static struct clk esdhc4_clk = {1353.id = 3,1354.parent = &esdhc1_clk,1355.set_parent = clk_esdhc4_set_parent,1356.enable_reg = MXC_CCM_CCGR3,1357.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,1358.enable = _clk_max_enable,1359.disable = _clk_max_disable,1360.secondary = &esdhc4_ipg_clk,1361};13621363/* mx53 specific */1364static struct clk esdhc2_mx53_clk = {1365.id = 2,1366.parent = &esdhc1_clk,1367.set_parent = clk_esdhc2_mx53_set_parent,1368.enable_reg = MXC_CCM_CCGR3,1369.enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,1370.enable = _clk_max_enable,1371.disable = _clk_max_disable,1372.secondary = &esdhc3_ipg_clk,1373};13741375DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,1376clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);13771378static struct clk esdhc4_mx53_clk = {1379.id = 3,1380.parent = &esdhc1_clk,1381.set_parent = clk_esdhc4_mx53_set_parent,1382.enable_reg = MXC_CCM_CCGR3,1383.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,1384.enable = _clk_max_enable,1385.disable = _clk_max_disable,1386.secondary = &esdhc4_ipg_clk,1387};13881389DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);1390DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);1391DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);13921393/* IPU */1394DEFINE_CLOCK_FULL(ipu_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG5_OFFSET,1395NULL, NULL, clk_ipu_enable, clk_ipu_disable, &ahb_clk, &ipu_sec_clk);13961397DEFINE_CLOCK_FULL(emi_fast_clk, 0, MXC_CCM_CCGR5, MXC_CCM_CCGRx_CG7_OFFSET,1398NULL, NULL, _clk_ccgr_enable, _clk_ccgr_disable_inwait,1399&ddr_clk, NULL);14001401DEFINE_CLOCK(ipu_di0_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG5_OFFSET,1402NULL, NULL, &pll3_sw_clk, NULL);1403DEFINE_CLOCK(ipu_di1_clk, 0, MXC_CCM_CCGR6, MXC_CCM_CCGRx_CG6_OFFSET,1404NULL, NULL, &pll3_sw_clk, NULL);14051406#define _REGISTER_CLOCK(d, n, c) \1407{ \1408.dev_id = d, \1409.con_id = n, \1410.clk = &c, \1411},14121413static struct clk_lookup mx51_lookups[] = {1414_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)1415_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)1416_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)1417_REGISTER_CLOCK(NULL, "gpt", gpt_clk)1418_REGISTER_CLOCK("fec.0", NULL, fec_clk)1419_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)1420_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)1421_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)1422_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)1423_REGISTER_CLOCK("imx-i2c.2", NULL, hsi2c_clk)1424_REGISTER_CLOCK("mxc-ehci.0", "usb", usboh3_clk)1425_REGISTER_CLOCK("mxc-ehci.0", "usb_ahb", usb_ahb_clk)1426_REGISTER_CLOCK("mxc-ehci.0", "usb_phy1", usb_phy1_clk)1427_REGISTER_CLOCK("mxc-ehci.1", "usb", usboh3_clk)1428_REGISTER_CLOCK("mxc-ehci.1", "usb_ahb", usb_ahb_clk)1429_REGISTER_CLOCK("mxc-ehci.2", "usb", usboh3_clk)1430_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)1431_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)1432_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)1433_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)1434_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)1435_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)1436_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)1437_REGISTER_CLOCK("imx-ssi.2", NULL, ssi3_clk)1438_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)1439_REGISTER_CLOCK(NULL, "ckih", ckih_clk)1440_REGISTER_CLOCK(NULL, "ckih2", ckih2_clk)1441_REGISTER_CLOCK(NULL, "gpt_32k", gpt_32k_clk)1442_REGISTER_CLOCK("imx51-ecspi.0", NULL, ecspi1_clk)1443_REGISTER_CLOCK("imx51-ecspi.1", NULL, ecspi2_clk)1444_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)1445_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)1446_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)1447_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)1448_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_clk)1449_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)1450_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)1451_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)1452_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)1453_REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)1454_REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)1455_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)1456_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)1457_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)1458};14591460static struct clk_lookup mx53_lookups[] = {1461_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)1462_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)1463_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)1464_REGISTER_CLOCK(NULL, "gpt", gpt_clk)1465_REGISTER_CLOCK("fec.0", NULL, fec_clk)1466_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)1467_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)1468_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)1469_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)1470_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)1471_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)1472_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)1473_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)1474_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)1475_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)1476_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)1477_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)1478};14791480static void clk_tree_init(void)1481{1482u32 reg;14831484ipg_perclk.set_parent(&ipg_perclk, &lp_apm_clk);14851486/*1487* Initialise the IPG PER CLK dividers to 3. IPG_PER_CLK should be at1488* 8MHz, its derived from lp_apm.1489*1490* FIXME: Verify if true for all boards1491*/1492reg = __raw_readl(MXC_CCM_CBCDR);1493reg &= ~MXC_CCM_CBCDR_PERCLK_PRED1_MASK;1494reg &= ~MXC_CCM_CBCDR_PERCLK_PRED2_MASK;1495reg &= ~MXC_CCM_CBCDR_PERCLK_PODF_MASK;1496reg |= (2 << MXC_CCM_CBCDR_PERCLK_PRED1_OFFSET);1497__raw_writel(reg, MXC_CCM_CBCDR);1498}14991500int __init mx51_clocks_init(unsigned long ckil, unsigned long osc,1501unsigned long ckih1, unsigned long ckih2)1502{1503int i;15041505external_low_reference = ckil;1506external_high_reference = ckih1;1507ckih2_reference = ckih2;1508oscillator_reference = osc;15091510for (i = 0; i < ARRAY_SIZE(mx51_lookups); i++)1511clkdev_add(&mx51_lookups[i]);15121513clk_tree_init();15141515clk_enable(&cpu_clk);1516clk_enable(&main_bus_clk);15171518clk_enable(&iim_clk);1519mx51_revision();1520clk_disable(&iim_clk);1521mx51_display_revision();15221523/* move usb_phy_clk to 24MHz */1524clk_set_parent(&usb_phy1_clk, &osc_clk);15251526/* set the usboh3_clk parent to pll2_sw_clk */1527clk_set_parent(&usboh3_clk, &pll2_sw_clk);15281529/* Set SDHC parents to be PLL2 */1530clk_set_parent(&esdhc1_clk, &pll2_sw_clk);1531clk_set_parent(&esdhc2_clk, &pll2_sw_clk);15321533/* set SDHC root clock as 166.25MHZ*/1534clk_set_rate(&esdhc1_clk, 166250000);1535clk_set_rate(&esdhc2_clk, 166250000);15361537/* System timer */1538mxc_timer_init(&gpt_clk, MX51_IO_ADDRESS(MX51_GPT1_BASE_ADDR),1539MX51_MXC_INT_GPT);1540return 0;1541}15421543int __init mx53_clocks_init(unsigned long ckil, unsigned long osc,1544unsigned long ckih1, unsigned long ckih2)1545{1546int i;15471548external_low_reference = ckil;1549external_high_reference = ckih1;1550ckih2_reference = ckih2;1551oscillator_reference = osc;15521553for (i = 0; i < ARRAY_SIZE(mx53_lookups); i++)1554clkdev_add(&mx53_lookups[i]);15551556clk_tree_init();15571558clk_set_parent(&uart_root_clk, &pll3_sw_clk);1559clk_enable(&cpu_clk);1560clk_enable(&main_bus_clk);15611562clk_enable(&iim_clk);1563mx53_revision();1564clk_disable(&iim_clk);1565mx53_display_revision();15661567/* Set SDHC parents to be PLL2 */1568clk_set_parent(&esdhc1_clk, &pll2_sw_clk);1569clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);15701571/* set SDHC root clock as 200MHZ*/1572clk_set_rate(&esdhc1_clk, 200000000);1573clk_set_rate(&esdhc3_mx53_clk, 200000000);15741575/* System timer */1576mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),1577MX53_INT_GPT);1578return 0;1579}158015811582