643 lines
14 KiB
C
643 lines
14 KiB
C
|
#include <linux/clk.h>
|
||
|
#include <linux/kernel.h>
|
||
|
#include <linux/init.h>
|
||
|
#include <linux/io.h>
|
||
|
|
||
|
#include <mach/clock.h>
|
||
|
#include <mach/hardware.h>
|
||
|
#include <mach/common.h>
|
||
|
|
||
|
#include <asm/clkdev.h>
|
||
|
#include <asm/bug.h>
|
||
|
#include <asm/div64.h>
|
||
|
|
||
|
#include "crm_regs.h"
|
||
|
|
||
|
#define CRM_SMALL_DIVIDER(base, name) \
|
||
|
crm_small_divider(base, \
|
||
|
base ## _ ## name ## _OFFSET, \
|
||
|
base ## _ ## name ## _MASK)
|
||
|
#define CRM_1DIVIDER(base, name) \
|
||
|
crm_divider(base, \
|
||
|
base ## _ ## name ## _OFFSET, \
|
||
|
base ## _ ## name ## _MASK, 1)
|
||
|
#define CRM_16DIVIDER(base, name) \
|
||
|
crm_divider(base, \
|
||
|
base ## _ ## name ## _OFFSET, \
|
||
|
base ## _ ## name ## _MASK, 16)
|
||
|
|
||
|
static u32 crm_small_divider(void __iomem *reg, u8 offset, u32 mask)
|
||
|
{
|
||
|
static const u32 crm_small_dividers[] = {
|
||
|
2, 3, 4, 5, 6, 8, 10, 12
|
||
|
};
|
||
|
u8 idx;
|
||
|
|
||
|
idx = (__raw_readl(reg) & mask) >> offset;
|
||
|
if (idx > 7)
|
||
|
return 1;
|
||
|
|
||
|
return crm_small_dividers[idx];
|
||
|
}
|
||
|
|
||
|
static u32 crm_divider(void __iomem *reg, u8 offset, u32 mask, u32 z)
|
||
|
{
|
||
|
u32 div;
|
||
|
div = (__raw_readl(reg) & mask) >> offset;
|
||
|
return div ? div : z;
|
||
|
}
|
||
|
|
||
|
static int _clk_1bit_enable(struct clk *clk)
|
||
|
{
|
||
|
u32 reg;
|
||
|
|
||
|
reg = __raw_readl(clk->enable_reg);
|
||
|
reg |= 1 << clk->enable_shift;
|
||
|
__raw_writel(reg, clk->enable_reg);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void _clk_1bit_disable(struct clk *clk)
|
||
|
{
|
||
|
u32 reg;
|
||
|
|
||
|
reg = __raw_readl(clk->enable_reg);
|
||
|
reg &= ~(1 << clk->enable_shift);
|
||
|
__raw_writel(reg, clk->enable_reg);
|
||
|
}
|
||
|
|
||
|
static int _clk_3bit_enable(struct clk *clk)
|
||
|
{
|
||
|
u32 reg;
|
||
|
|
||
|
reg = __raw_readl(clk->enable_reg);
|
||
|
reg |= 0x7 << clk->enable_shift;
|
||
|
__raw_writel(reg, clk->enable_reg);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void _clk_3bit_disable(struct clk *clk)
|
||
|
{
|
||
|
u32 reg;
|
||
|
|
||
|
reg = __raw_readl(clk->enable_reg);
|
||
|
reg &= ~(0x7 << clk->enable_shift);
|
||
|
__raw_writel(reg, clk->enable_reg);
|
||
|
}
|
||
|
|
||
|
static unsigned long ckih_rate;
|
||
|
|
||
|
static unsigned long clk_ckih_get_rate(struct clk *clk)
|
||
|
{
|
||
|
return ckih_rate;
|
||
|
}
|
||
|
|
||
|
static struct clk ckih_clk = {
|
||
|
.get_rate = clk_ckih_get_rate,
|
||
|
};
|
||
|
|
||
|
static unsigned long clk_ckih_x2_get_rate(struct clk *clk)
|
||
|
{
|
||
|
return 2 * clk_get_rate(clk->parent);
|
||
|
}
|
||
|
|
||
|
static struct clk ckih_x2_clk = {
|
||
|
.parent = &ckih_clk,
|
||
|
.get_rate = clk_ckih_x2_get_rate,
|
||
|
};
|
||
|
|
||
|
static unsigned long clk_ckil_get_rate(struct clk *clk)
|
||
|
{
|
||
|
return CKIL_CLK_FREQ;
|
||
|
}
|
||
|
|
||
|
static struct clk ckil_clk = {
|
||
|
.get_rate = clk_ckil_get_rate,
|
||
|
};
|
||
|
|
||
|
/* plls stuff */
|
||
|
static struct clk mcu_pll_clk;
|
||
|
static struct clk dsp_pll_clk;
|
||
|
static struct clk usb_pll_clk;
|
||
|
|
||
|
static struct clk *pll_clk(u8 sel)
|
||
|
{
|
||
|
switch (sel) {
|
||
|
case 0:
|
||
|
return &mcu_pll_clk;
|
||
|
case 1:
|
||
|
return &dsp_pll_clk;
|
||
|
case 2:
|
||
|
return &usb_pll_clk;
|
||
|
}
|
||
|
BUG();
|
||
|
}
|
||
|
|
||
|
static void __iomem *pll_base(struct clk *clk)
|
||
|
{
|
||
|
if (clk == &mcu_pll_clk)
|
||
|
return MXC_PLL0_BASE;
|
||
|
else if (clk == &dsp_pll_clk)
|
||
|
return MXC_PLL1_BASE;
|
||
|
else if (clk == &usb_pll_clk)
|
||
|
return MXC_PLL2_BASE;
|
||
|
BUG();
|
||
|
}
|
||
|
|
||
|
static unsigned long clk_pll_get_rate(struct clk *clk)
|
||
|
{
|
||
|
const void __iomem *pllbase;
|
||
|
unsigned long dp_op, dp_mfd, dp_mfn, pll_hfsm, ref_clk, mfi;
|
||
|
long mfn, mfn_abs, mfd, pdf;
|
||
|
s64 temp;
|
||
|
pllbase = pll_base(clk);
|
||
|
|
||
|
pll_hfsm = __raw_readl(pllbase + MXC_PLL_DP_CTL) & MXC_PLL_DP_CTL_HFSM;
|
||
|
if (pll_hfsm == 0) {
|
||
|
dp_op = __raw_readl(pllbase + MXC_PLL_DP_OP);
|
||
|
dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_MFD);
|
||
|
dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_MFN);
|
||
|
} else {
|
||
|
dp_op = __raw_readl(pllbase + MXC_PLL_DP_HFS_OP);
|
||
|
dp_mfd = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFD);
|
||
|
dp_mfn = __raw_readl(pllbase + MXC_PLL_DP_HFS_MFN);
|
||
|
}
|
||
|
|
||
|
pdf = dp_op & MXC_PLL_DP_OP_PDF_MASK;
|
||
|
mfi = (dp_op >> MXC_PLL_DP_OP_MFI_OFFSET) & MXC_PLL_DP_OP_PDF_MASK;
|
||
|
mfi = (mfi <= 5) ? 5 : mfi;
|
||
|
mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
|
||
|
mfn = dp_mfn & MXC_PLL_DP_MFN_MASK;
|
||
|
mfn = (mfn <= 0x4000000) ? mfn : (mfn - 0x10000000);
|
||
|
|
||
|
if (mfn < 0)
|
||
|
mfn_abs = -mfn;
|
||
|
else
|
||
|
mfn_abs = mfn;
|
||
|
|
||
|
/* XXX: actually this asumes that ckih is fed to pll, but spec says
|
||
|
* that ckih_x2 is also possible. need to check this out.
|
||
|
*/
|
||
|
ref_clk = clk_get_rate(&ckih_clk);
|
||
|
|
||
|
ref_clk *= 2;
|
||
|
ref_clk /= pdf + 1;
|
||
|
|
||
|
temp = (u64) ref_clk * mfn_abs;
|
||
|
do_div(temp, mfd);
|
||
|
if (mfn < 0)
|
||
|
temp = -temp;
|
||
|
temp += ref_clk * mfi;
|
||
|
|
||
|
return temp;
|
||
|
}
|
||
|
|
||
|
static int clk_pll_enable(struct clk *clk)
|
||
|
{
|
||
|
void __iomem *ctl;
|
||
|
u32 reg;
|
||
|
|
||
|
ctl = pll_base(clk);
|
||
|
reg = __raw_readl(ctl);
|
||
|
reg |= (MXC_PLL_DP_CTL_RST | MXC_PLL_DP_CTL_UPEN);
|
||
|
__raw_writel(reg, ctl);
|
||
|
do {
|
||
|
reg = __raw_readl(ctl);
|
||
|
} while ((reg & MXC_PLL_DP_CTL_LRF) != MXC_PLL_DP_CTL_LRF);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void clk_pll_disable(struct clk *clk)
|
||
|
{
|
||
|
void __iomem *ctl;
|
||
|
u32 reg;
|
||
|
|
||
|
ctl = pll_base(clk);
|
||
|
reg = __raw_readl(ctl);
|
||
|
reg &= ~(MXC_PLL_DP_CTL_RST | MXC_PLL_DP_CTL_UPEN);
|
||
|
__raw_writel(reg, ctl);
|
||
|
}
|
||
|
|
||
|
static struct clk mcu_pll_clk = {
|
||
|
.parent = &ckih_clk,
|
||
|
.get_rate = clk_pll_get_rate,
|
||
|
.enable = clk_pll_enable,
|
||
|
.disable = clk_pll_disable,
|
||
|
};
|
||
|
|
||
|
static struct clk dsp_pll_clk = {
|
||
|
.parent = &ckih_clk,
|
||
|
.get_rate = clk_pll_get_rate,
|
||
|
.enable = clk_pll_enable,
|
||
|
.disable = clk_pll_disable,
|
||
|
};
|
||
|
|
||
|
static struct clk usb_pll_clk = {
|
||
|
.parent = &ckih_clk,
|
||
|
.get_rate = clk_pll_get_rate,
|
||
|
.enable = clk_pll_enable,
|
||
|
.disable = clk_pll_disable,
|
||
|
};
|
||
|
/* plls stuff end */
|
||
|
|
||
|
/* ap_ref_clk stuff */
|
||
|
static struct clk ap_ref_clk;
|
||
|
|
||
|
static unsigned long clk_ap_ref_get_rate(struct clk *clk)
|
||
|
{
|
||
|
u32 ascsr, acsr;
|
||
|
u8 ap_pat_ref_div_2, ap_isel, acs, ads;
|
||
|
|
||
|
ascsr = __raw_readl(MXC_CRMAP_ASCSR);
|
||
|
acsr = __raw_readl(MXC_CRMAP_ACSR);
|
||
|
|
||
|
/* 0 for ckih, 1 for ckih*2 */
|
||
|
ap_isel = ascsr & MXC_CRMAP_ASCSR_APISEL;
|
||
|
/* reg divider */
|
||
|
ap_pat_ref_div_2 = (ascsr >> MXC_CRMAP_ASCSR_AP_PATDIV2_OFFSET) & 0x1;
|
||
|
/* undocumented, 1 for disabling divider */
|
||
|
ads = (acsr >> MXC_CRMAP_ACSR_ADS_OFFSET) & 0x1;
|
||
|
/* 0 for pat_ref, 1 for divider out */
|
||
|
acs = acsr & MXC_CRMAP_ACSR_ACS;
|
||
|
|
||
|
if (acs & !ads)
|
||
|
/* use divided clock */
|
||
|
return clk_get_rate(clk->parent) / (ap_pat_ref_div_2 ? 2 : 1);
|
||
|
|
||
|
return clk_get_rate(clk->parent) * (ap_isel ? 2 : 1);
|
||
|
}
|
||
|
|
||
|
static struct clk ap_ref_clk = {
|
||
|
.parent = &ckih_clk,
|
||
|
.get_rate = clk_ap_ref_get_rate,
|
||
|
};
|
||
|
/* ap_ref_clk stuff end */
|
||
|
|
||
|
/* ap_pre_dfs_clk stuff */
|
||
|
static struct clk ap_pre_dfs_clk;
|
||
|
|
||
|
static unsigned long clk_ap_pre_dfs_get_rate(struct clk *clk)
|
||
|
{
|
||
|
u32 acsr, ascsr;
|
||
|
|
||
|
acsr = __raw_readl(MXC_CRMAP_ACSR);
|
||
|
ascsr = __raw_readl(MXC_CRMAP_ASCSR);
|
||
|
|
||
|
if (acsr & MXC_CRMAP_ACSR_ACS) {
|
||
|
u8 sel;
|
||
|
sel = (ascsr & MXC_CRMAP_ASCSR_APSEL_MASK) >>
|
||
|
MXC_CRMAP_ASCSR_APSEL_OFFSET;
|
||
|
return clk_get_rate(pll_clk(sel)) /
|
||
|
CRM_SMALL_DIVIDER(MXC_CRMAP_ACDR, ARMDIV);
|
||
|
}
|
||
|
return clk_get_rate(&ap_ref_clk);
|
||
|
}
|
||
|
|
||
|
static struct clk ap_pre_dfs_clk = {
|
||
|
.get_rate = clk_ap_pre_dfs_get_rate,
|
||
|
};
|
||
|
/* ap_pre_dfs_clk stuff end */
|
||
|
|
||
|
/* usb_clk stuff */
|
||
|
static struct clk usb_clk;
|
||
|
|
||
|
static struct clk *clk_usb_parent(struct clk *clk)
|
||
|
{
|
||
|
u32 acsr, ascsr;
|
||
|
|
||
|
acsr = __raw_readl(MXC_CRMAP_ACSR);
|
||
|
ascsr = __raw_readl(MXC_CRMAP_ASCSR);
|
||
|
|
||
|
if (acsr & MXC_CRMAP_ACSR_ACS) {
|
||
|
u8 sel;
|
||
|
sel = (ascsr & MXC_CRMAP_ASCSR_USBSEL_MASK) >>
|
||
|
MXC_CRMAP_ASCSR_USBSEL_OFFSET;
|
||
|
return pll_clk(sel);
|
||
|
}
|
||
|
return &ap_ref_clk;
|
||
|
}
|
||
|
|
||
|
static unsigned long clk_usb_get_rate(struct clk *clk)
|
||
|
{
|
||
|
return clk_get_rate(clk->parent) /
|
||
|
CRM_SMALL_DIVIDER(MXC_CRMAP_ACDER2, USBDIV);
|
||
|
}
|
||
|
|
||
|
static struct clk usb_clk = {
|
||
|
.enable_reg = MXC_CRMAP_ACDER2,
|
||
|
.enable_shift = MXC_CRMAP_ACDER2_USBEN_OFFSET,
|
||
|
.get_rate = clk_usb_get_rate,
|
||
|
.enable = _clk_1bit_enable,
|
||
|
.disable = _clk_1bit_disable,
|
||
|
};
|
||
|
/* usb_clk stuff end */
|
||
|
|
||
|
static unsigned long clk_ipg_get_rate(struct clk *clk)
|
||
|
{
|
||
|
return clk_get_rate(clk->parent) / CRM_16DIVIDER(MXC_CRMAP_ACDR, IPDIV);
|
||
|
}
|
||
|
|
||
|
static unsigned long clk_ahb_get_rate(struct clk *clk)
|
||
|
{
|
||
|
return clk_get_rate(clk->parent) /
|
||
|
CRM_16DIVIDER(MXC_CRMAP_ACDR, AHBDIV);
|
||
|
}
|
||
|
|
||
|
static struct clk ipg_clk = {
|
||
|
.parent = &ap_pre_dfs_clk,
|
||
|
.get_rate = clk_ipg_get_rate,
|
||
|
};
|
||
|
|
||
|
static struct clk ahb_clk = {
|
||
|
.parent = &ap_pre_dfs_clk,
|
||
|
.get_rate = clk_ahb_get_rate,
|
||
|
};
|
||
|
|
||
|
/* perclk_clk stuff */
|
||
|
static struct clk perclk_clk;
|
||
|
|
||
|
static unsigned long clk_perclk_get_rate(struct clk *clk)
|
||
|
{
|
||
|
u32 acder2;
|
||
|
|
||
|
acder2 = __raw_readl(MXC_CRMAP_ACDER2);
|
||
|
if (acder2 & MXC_CRMAP_ACDER2_BAUD_ISEL_MASK)
|
||
|
return 2 * clk_get_rate(clk->parent);
|
||
|
|
||
|
return clk_get_rate(clk->parent);
|
||
|
}
|
||
|
|
||
|
static struct clk perclk_clk = {
|
||
|
.parent = &ckih_clk,
|
||
|
.get_rate = clk_perclk_get_rate,
|
||
|
};
|
||
|
/* perclk_clk stuff end */
|
||
|
|
||
|
/* uart_clk stuff */
|
||
|
static struct clk uart_clk[];
|
||
|
|
||
|
static unsigned long clk_uart_get_rate(struct clk *clk)
|
||
|
{
|
||
|
u32 div;
|
||
|
|
||
|
switch (clk->id) {
|
||
|
case 0:
|
||
|
case 1:
|
||
|
div = CRM_SMALL_DIVIDER(MXC_CRMAP_ACDER2, BAUDDIV);
|
||
|
break;
|
||
|
case 2:
|
||
|
div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRA, UART3DIV);
|
||
|
break;
|
||
|
default:
|
||
|
BUG();
|
||
|
}
|
||
|
return clk_get_rate(clk->parent) / div;
|
||
|
}
|
||
|
|
||
|
static struct clk uart_clk[] = {
|
||
|
{
|
||
|
.id = 0,
|
||
|
.parent = &perclk_clk,
|
||
|
.enable_reg = MXC_CRMAP_APRA,
|
||
|
.enable_shift = MXC_CRMAP_APRA_UART1EN_OFFSET,
|
||
|
.get_rate = clk_uart_get_rate,
|
||
|
.enable = _clk_1bit_enable,
|
||
|
.disable = _clk_1bit_disable,
|
||
|
}, {
|
||
|
.id = 1,
|
||
|
.parent = &perclk_clk,
|
||
|
.enable_reg = MXC_CRMAP_APRA,
|
||
|
.enable_shift = MXC_CRMAP_APRA_UART2EN_OFFSET,
|
||
|
.get_rate = clk_uart_get_rate,
|
||
|
.enable = _clk_1bit_enable,
|
||
|
.disable = _clk_1bit_disable,
|
||
|
}, {
|
||
|
.id = 2,
|
||
|
.parent = &perclk_clk,
|
||
|
.enable_reg = MXC_CRMAP_APRA,
|
||
|
.enable_shift = MXC_CRMAP_APRA_UART3EN_OFFSET,
|
||
|
.get_rate = clk_uart_get_rate,
|
||
|
.enable = _clk_1bit_enable,
|
||
|
.disable = _clk_1bit_disable,
|
||
|
},
|
||
|
};
|
||
|
/* uart_clk stuff end */
|
||
|
|
||
|
/* sdhc_clk stuff */
|
||
|
static struct clk nfc_clk;
|
||
|
|
||
|
static unsigned long clk_nfc_get_rate(struct clk *clk)
|
||
|
{
|
||
|
return clk_get_rate(clk->parent) /
|
||
|
CRM_1DIVIDER(MXC_CRMAP_ACDER2, NFCDIV);
|
||
|
}
|
||
|
|
||
|
static struct clk nfc_clk = {
|
||
|
.parent = &ahb_clk,
|
||
|
.enable_reg = MXC_CRMAP_ACDER2,
|
||
|
.enable_shift = MXC_CRMAP_ACDER2_NFCEN_OFFSET,
|
||
|
.get_rate = clk_nfc_get_rate,
|
||
|
.enable = _clk_1bit_enable,
|
||
|
.disable = _clk_1bit_disable,
|
||
|
};
|
||
|
/* sdhc_clk stuff end */
|
||
|
|
||
|
/* sdhc_clk stuff */
|
||
|
static struct clk sdhc_clk[];
|
||
|
|
||
|
static struct clk *clk_sdhc_parent(struct clk *clk)
|
||
|
{
|
||
|
u32 aprb;
|
||
|
u8 sel;
|
||
|
u32 mask;
|
||
|
int offset;
|
||
|
|
||
|
aprb = __raw_readl(MXC_CRMAP_APRB);
|
||
|
|
||
|
switch (clk->id) {
|
||
|
case 0:
|
||
|
mask = MXC_CRMAP_APRB_SDHC1_ISEL_MASK;
|
||
|
offset = MXC_CRMAP_APRB_SDHC1_ISEL_OFFSET;
|
||
|
break;
|
||
|
case 1:
|
||
|
mask = MXC_CRMAP_APRB_SDHC2_ISEL_MASK;
|
||
|
offset = MXC_CRMAP_APRB_SDHC2_ISEL_OFFSET;
|
||
|
break;
|
||
|
default:
|
||
|
BUG();
|
||
|
}
|
||
|
sel = (aprb & mask) >> offset;
|
||
|
|
||
|
switch (sel) {
|
||
|
case 0:
|
||
|
return &ckih_clk;
|
||
|
case 1:
|
||
|
return &ckih_x2_clk;
|
||
|
}
|
||
|
return &usb_clk;
|
||
|
}
|
||
|
|
||
|
static unsigned long clk_sdhc_get_rate(struct clk *clk)
|
||
|
{
|
||
|
u32 div;
|
||
|
|
||
|
switch (clk->id) {
|
||
|
case 0:
|
||
|
div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRB, SDHC1_DIV);
|
||
|
break;
|
||
|
case 1:
|
||
|
div = CRM_SMALL_DIVIDER(MXC_CRMAP_APRB, SDHC2_DIV);
|
||
|
break;
|
||
|
default:
|
||
|
BUG();
|
||
|
}
|
||
|
|
||
|
return clk_get_rate(clk->parent) / div;
|
||
|
}
|
||
|
|
||
|
static int clk_sdhc_enable(struct clk *clk)
|
||
|
{
|
||
|
u32 amlpmre1, aprb;
|
||
|
|
||
|
amlpmre1 = __raw_readl(MXC_CRMAP_AMLPMRE1);
|
||
|
aprb = __raw_readl(MXC_CRMAP_APRB);
|
||
|
switch (clk->id) {
|
||
|
case 0:
|
||
|
amlpmre1 |= (0x7 << MXC_CRMAP_AMLPMRE1_MLPME4_OFFSET);
|
||
|
aprb |= (0x1 << MXC_CRMAP_APRB_SDHC1EN_OFFSET);
|
||
|
break;
|
||
|
case 1:
|
||
|
amlpmre1 |= (0x7 << MXC_CRMAP_AMLPMRE1_MLPME5_OFFSET);
|
||
|
aprb |= (0x1 << MXC_CRMAP_APRB_SDHC2EN_OFFSET);
|
||
|
break;
|
||
|
}
|
||
|
__raw_writel(amlpmre1, MXC_CRMAP_AMLPMRE1);
|
||
|
__raw_writel(aprb, MXC_CRMAP_APRB);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static void clk_sdhc_disable(struct clk *clk)
|
||
|
{
|
||
|
u32 amlpmre1, aprb;
|
||
|
|
||
|
amlpmre1 = __raw_readl(MXC_CRMAP_AMLPMRE1);
|
||
|
aprb = __raw_readl(MXC_CRMAP_APRB);
|
||
|
switch (clk->id) {
|
||
|
case 0:
|
||
|
amlpmre1 &= ~(0x7 << MXC_CRMAP_AMLPMRE1_MLPME4_OFFSET);
|
||
|
aprb &= ~(0x1 << MXC_CRMAP_APRB_SDHC1EN_OFFSET);
|
||
|
break;
|
||
|
case 1:
|
||
|
amlpmre1 &= ~(0x7 << MXC_CRMAP_AMLPMRE1_MLPME5_OFFSET);
|
||
|
aprb &= ~(0x1 << MXC_CRMAP_APRB_SDHC2EN_OFFSET);
|
||
|
break;
|
||
|
}
|
||
|
__raw_writel(amlpmre1, MXC_CRMAP_AMLPMRE1);
|
||
|
__raw_writel(aprb, MXC_CRMAP_APRB);
|
||
|
}
|
||
|
|
||
|
static struct clk sdhc_clk[] = {
|
||
|
{
|
||
|
.id = 0,
|
||
|
.get_rate = clk_sdhc_get_rate,
|
||
|
.enable = clk_sdhc_enable,
|
||
|
.disable = clk_sdhc_disable,
|
||
|
}, {
|
||
|
.id = 1,
|
||
|
.get_rate = clk_sdhc_get_rate,
|
||
|
.enable = clk_sdhc_enable,
|
||
|
.disable = clk_sdhc_disable,
|
||
|
},
|
||
|
};
|
||
|
/* sdhc_clk stuff end */
|
||
|
|
||
|
/* wdog_clk stuff */
|
||
|
static struct clk wdog_clk[] = {
|
||
|
{
|
||
|
.id = 0,
|
||
|
.parent = &ipg_clk,
|
||
|
.enable_reg = MXC_CRMAP_AMLPMRD,
|
||
|
.enable_shift = MXC_CRMAP_AMLPMRD_MLPMD7_OFFSET,
|
||
|
.enable = _clk_3bit_enable,
|
||
|
.disable = _clk_3bit_disable,
|
||
|
}, {
|
||
|
.id = 1,
|
||
|
.parent = &ipg_clk,
|
||
|
.enable_reg = MXC_CRMAP_AMLPMRD,
|
||
|
.enable_shift = MXC_CRMAP_AMLPMRD_MLPMD3_OFFSET,
|
||
|
.enable = _clk_3bit_enable,
|
||
|
.disable = _clk_3bit_disable,
|
||
|
},
|
||
|
};
|
||
|
/* wdog_clk stuff end */
|
||
|
|
||
|
/* gpt_clk stuff */
|
||
|
static struct clk gpt_clk = {
|
||
|
.parent = &ipg_clk,
|
||
|
.enable_reg = MXC_CRMAP_AMLPMRC,
|
||
|
.enable_shift = MXC_CRMAP_AMLPMRC_MLPMC4_OFFSET,
|
||
|
.enable = _clk_3bit_enable,
|
||
|
.disable = _clk_3bit_disable,
|
||
|
};
|
||
|
/* gpt_clk stuff end */
|
||
|
|
||
|
/* cspi_clk stuff */
|
||
|
static struct clk cspi_clk[] = {
|
||
|
{
|
||
|
.id = 0,
|
||
|
.parent = &ipg_clk,
|
||
|
.enable_reg = MXC_CRMAP_AMLPMRE2,
|
||
|
.enable_shift = MXC_CRMAP_AMLPMRE2_MLPME0_OFFSET,
|
||
|
.enable = _clk_3bit_enable,
|
||
|
.disable = _clk_3bit_disable,
|
||
|
}, {
|
||
|
.id = 1,
|
||
|
.parent = &ipg_clk,
|
||
|
.enable_reg = MXC_CRMAP_AMLPMRE1,
|
||
|
.enable_shift = MXC_CRMAP_AMLPMRE1_MLPME6_OFFSET,
|
||
|
.enable = _clk_3bit_enable,
|
||
|
.disable = _clk_3bit_disable,
|
||
|
},
|
||
|
};
|
||
|
/* cspi_clk stuff end */
|
||
|
|
||
|
#define _REGISTER_CLOCK(d, n, c) \
|
||
|
{ \
|
||
|
.dev_id = d, \
|
||
|
.con_id = n, \
|
||
|
.clk = &c, \
|
||
|
},
|
||
|
|
||
|
static struct clk_lookup lookups[] = {
|
||
|
_REGISTER_CLOCK("imx-uart.0", NULL, uart_clk[0])
|
||
|
_REGISTER_CLOCK("imx-uart.1", NULL, uart_clk[1])
|
||
|
_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk[2])
|
||
|
_REGISTER_CLOCK("mxc-mmc.0", NULL, sdhc_clk[0])
|
||
|
_REGISTER_CLOCK("mxc-mmc.1", NULL, sdhc_clk[1])
|
||
|
_REGISTER_CLOCK("mxc-wdt.0", NULL, wdog_clk[0])
|
||
|
_REGISTER_CLOCK("spi_imx.0", NULL, cspi_clk[0])
|
||
|
_REGISTER_CLOCK("spi_imx.1", NULL, cspi_clk[1])
|
||
|
};
|
||
|
|
||
|
int __init mxc91231_clocks_init(unsigned long fref)
|
||
|
{
|
||
|
void __iomem *gpt_base;
|
||
|
int i;
|
||
|
|
||
|
ckih_rate = fref;
|
||
|
|
||
|
usb_clk.parent = clk_usb_parent(&usb_clk);
|
||
|
sdhc_clk[0].parent = clk_sdhc_parent(&sdhc_clk[0]);
|
||
|
sdhc_clk[1].parent = clk_sdhc_parent(&sdhc_clk[1]);
|
||
|
|
||
|
for (i = 0; i < ARRAY_SIZE(lookups); i++)
|
||
|
clkdev_add(&lookups[i]);
|
||
|
|
||
|
gpt_base = MXC91231_IO_ADDRESS(MXC91231_GPT1_BASE_ADDR);
|
||
|
mxc_timer_init(&gpt_clk, gpt_base, MXC91231_INT_GPT);
|
||
|
|
||
|
return 0;
|
||
|
}
|