blob: 7475a04decf802ef8d2a1e5d41ee8b00b07c38be [file] [log] [blame]
#include <linux/io.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/devfreq.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <dt-bindings/clock/marvell-pxa1U88.h>
#include <linux/debugfs-pxa.h>
#include <linux/cputype.h>
#include "clk.h"
#include "clk-pll-helanx.h"
#include "clk-core-helanx.h"
#include "clk-plat.h"
#define APBS_PLL1_CTRL 0x100
#define APBC_RTC 0x28
#define APBC_TWSI0 0x2c
#define APBC_TWSI1 0x60
#define APBC_TWSI3 0x70
#define APBC_KPC 0x30
#define APBC_UART0 0x0
#define APBC_UART1 0x4
#define APBC_GPIO 0x8
#define APBC_PWM0 0xc
#define APBC_PWM1 0x10
#define APBC_PWM2 0x14
#define APBC_PWM3 0x18
#define APBC_SSP0 0x1c
#define APBC_SSP1 0x20
#define APBC_SWJTAG 0x40
#define APBC_SSP2 0x4c
#define APBC_TERMAL 0x6c
/* IPC/RIPC clock */
#define APBC_IPC_CLK_RST 0x24
#define APBCP_AICER 0x38
#define APBCP_TWSI2 0x28
#define APBCP_UART2 0x1c
#define MPMU_UART_PLL 0x14
#define APMU_CLK_GATE_CTRL 0x40
#define APMU_CCIC0 0x50
#define APMU_CCIC1 0x24
#define APMU_ISP 0x38
#define APMU_SDH0 0x54
#define APMU_SDH1 0x58
#define APMU_SDH2 0xe0
#define APMU_USB 0x5c
#define APMU_NF 0x60
#define APMU_TRACE 0x108
#define APMU_CORE_STATUS 0x090
#define APMU_DVC_DFC_DEBUG 0x140
/* PLL */
#define MPMU_PLL2CR (0x0034)
#define MPMU_PLL3CR (0x001c)
#define MPMU_PLL4CR (0x0050)
#define MPMU_POSR (0x0010)
#define POSR_PLL2_LOCK (1 << 29)
#define POSR_PLL3_LOCK (1 << 30)
#define POSR_PLL4_LOCK (1 << 31)
#define APB_SPARE_PLL2CR (0x104)
#define APB_SPARE_PLL3CR (0x108)
#define APB_SPARE_PLL4CR (0x124)
#define APB_PLL2_SSC_CTRL (0x130)
#define APB_PLL2_SSC_CONF (0x134)
#define APB_PLL2_FREQOFFSET_CTRL (0x138)
#define APB_PLL3_SSC_CTRL (0x13c)
#define APB_PLL3_SSC_CONF (0x140)
#define APB_PLL3_FREQOFFSET_CTRL (0x144)
#define APB_PLL4_SSC_CTRL (0x148)
#define APB_PLL4_SSC_CONF (0x14c)
#define APB_PLL4_FREQOFFSET_CTRL (0x150)
#define APMU_GC 0xcc
#define APMU_GC2D 0xf4
#define APMU_VPU 0xa4
#define APMU_DSI1 0x44
#define APMU_DISP1 0x4c
#define CIU_MC_CONF 0x0040
#define VPU_XTC 0x00a8
#define GPU2D_XTC 0x00a0
#define GPU_XTC 0x00a4
#define SC2_DESC 0xD420F000
#define ISP_XTC 0x84C
#define TOP_MEM_RTC_WTC_SPD 0x44
#ifdef CONFIG_SMC91X
#define APMU_SMC 0xd4
#define SMC_CLK 0xd4283890
#endif
struct pxa1U88_clk_unit {
struct mmp_clk_unit unit;
void __iomem *mpmu_base;
void __iomem *apmu_base;
void __iomem *apbc_base;
void __iomem *apbcp_base;
void __iomem *apbs_base;
void __iomem *ciu_base;
};
static struct mmp_param_fixed_rate_clk fixed_rate_clks[] = {
{PXA1U88_CLK_CLK32, "clk32", NULL, CLK_IS_ROOT, 32768},
{PXA1U88_CLK_VCTCXO, "vctcxo", NULL, CLK_IS_ROOT, 26000000},
{PXA1U88_CLK_PLL1_624, "pll1_624", NULL, CLK_IS_ROOT, 624000000},
{PXA1U88_CLK_PLL1_416, "pll1_416", NULL, CLK_IS_ROOT, 416000000},
{PXA1U88_CLK_PLL1_499, "pll1_499", NULL, CLK_IS_ROOT, 499000000},
{PXA1U88_CLK_PLL1_832, "pll1_832", NULL, CLK_IS_ROOT, 832000000},
{PXA1U88_CLK_PLL1_1248, "pll1_1248", NULL, CLK_IS_ROOT, 1248000000},
};
static struct mmp_param_fixed_factor_clk fixed_factor_clks[] = {
{PXA1U88_CLK_PLL1_2, "pll1_2", "pll1_624", 1, 2, 0},
{PXA1U88_CLK_PLL1_4, "pll1_4", "pll1_2", 1, 2, 0},
{PXA1U88_CLK_PLL1_8, "pll1_8", "pll1_4", 1, 2, 0},
{PXA1U88_CLK_PLL1_16, "pll1_16", "pll1_8", 1, 2, 0},
{PXA1U88_CLK_PLL1_6, "pll1_6", "pll1_2", 1, 3, 0},
{PXA1U88_CLK_PLL1_12, "pll1_12", "pll1_6", 1, 2, 0},
{PXA1U88_CLK_PLL1_24, "pll1_24", "pll1_12", 1, 2, 0},
{PXA1U88_CLK_PLL1_48, "pll1_48", "pll1_24", 1, 2, 0},
{PXA1U88_CLK_PLL1_96, "pll1_96", "pll1_48", 1, 2, 0},
{PXA1U88_CLK_PLL1_13, "pll1_13", "pll1_624", 1, 13, 0},
{PXA1U88_CLK_PLL1_13_1_5, "pll1_13_1_5", "pll1_13", 2, 3, 0},
{PXA1U88_CLK_PLL1_2_1_5, "pll1_2_1_5", "pll1_2", 2, 3, 0},
{PXA1U88_CLK_PLL1_13_16, "pll1_13_16", "pll1_624", 3, 16, 0},
};
static struct mmp_clk_factor_masks uart_factor_masks = {
.factor = 2,
.num_mask = 0x1fff,
.den_mask = 0x1fff,
.num_shift = 16,
.den_shift = 0,
};
static struct mmp_clk_factor_tbl uart_factor_tbl[] = {
{.num = 8125, .den = 1536}, /*14.745MHZ */
};
static DEFINE_SPINLOCK(pll1_lock);
static struct mmp_param_general_gate_clk pll1_gate_clks[] = {
{PXA1U88_CLK_PLL1_416_GATE, "pll1_416_gate", "pll1_416", 0, APMU_CLK_GATE_CTRL, 27, 0, &pll1_lock},
{PXA1U88_CLK_PLL1_624_GATE, "pll1_624_gate", "pll1_624", 0, APMU_CLK_GATE_CTRL, 26, 0, &pll1_lock},
{PXA1U88_CLK_PLL1_832_GATE, "pll1_832_gate", "pll1_832", 0, APMU_CLK_GATE_CTRL, 30, 0, &pll1_lock},
{PXA1U88_CLK_PLL1_1248_GATE, "pll1_1248_gate", "pll1_1248", 0, APMU_CLK_GATE_CTRL, 28, 0, &pll1_lock},
{PXA1U88_CLK_PLL1_312_GATE, "pll1_312_gate", "pll1_2", 0, APMU_CLK_GATE_CTRL, 29, 0, &pll1_lock},
};
enum pll {
PLL2 = 0,
PLL3,
PLL4,
MAX_PLL_NUM
};
enum pll_type {
VCO,
OUT,
OUTP,
MAX_PLL_TYPE,
};
static struct mmp_vco_params pllx_vco_params[MAX_PLL_NUM] = {
{
.vco_min = 1200000000UL,
.vco_max = 3000000000UL,
.lock_enable_bit = POSR_PLL2_LOCK,
},
{
.vco_min = 1200000000UL,
.vco_max = 3000000000UL,
.lock_enable_bit = POSR_PLL3_LOCK,
},
{
.vco_min = 1200000000UL,
.vco_max = 3000000000UL,
.lock_enable_bit = POSR_PLL4_LOCK,
}
};
static struct mmp_pll_params pllx_pll_params[MAX_PLL_NUM] = {
};
static struct mmp_pll_params pllx_pllp_params[MAX_PLL_NUM] = {
};
struct plat_pll_info {
spinlock_t lock;
const char *vco_name;
const char *out_name;
const char *outp_name;
const char *vco_div3_name;
/* clk flags */
unsigned long vco_flag;
unsigned long vcoclk_flag;
unsigned long out_flag;
unsigned long outclk_flag;
unsigned long outp_flag;
unsigned long outpclk_flag;
/* dt index */
unsigned int vcodtidx;
unsigned int outdtidx;
unsigned int outpdtidx;
unsigned int vcodiv3dtidx;
};
struct plat_pll_info pllx_platinfo[MAX_PLL_NUM] = {
{
.vco_name = "pll2_vco",
.out_name = "pll2",
.outp_name = "pll2p",
.vco_div3_name = "pll2_div3",
.vcoclk_flag = CLK_IS_ROOT,
.out_flag = HELANX_PLLOUT,
.outp_flag = HELANX_PLLOUTP,
.vcodtidx = PXA1U88_CLK_PLL2VCO,
.outdtidx = PXA1U88_CLK_PLL2,
.outpdtidx = PXA1U88_CLK_PLL2P,
.vcodiv3dtidx = PXA1U88_CLK_PLL2VCODIV3,
},
{
.vco_name = "pll3_vco",
.out_name = "pll3",
.outp_name = "pll3p",
.vco_div3_name = "pll3_div3",
.vcoclk_flag = CLK_IS_ROOT,
.outpclk_flag = CLK_SET_RATE_PARENT,
.out_flag = HELANX_PLLOUT,
.outp_flag = HELANX_PLLOUTP,
.vcodtidx = PXA1U88_CLK_PLL3VCO,
.outdtidx = PXA1U88_CLK_PLL3,
.outpdtidx = PXA1U88_CLK_PLL3P,
.vcodiv3dtidx = PXA1U88_CLK_PLL3VCODIV3,
},
{
.vco_name = "pll4_vco",
.out_name = "pll4",
.outp_name = "pll4p",
.vco_div3_name = "pll4_div3",
.vcoclk_flag = CLK_IS_ROOT,
.vco_flag = HELANX_PLL_SKIP_DEF_RATE,
/*
* set pll4 flag to allow it change rate
* when lcd choose pll4 as clk source.
*/
.outclk_flag = CLK_SET_RATE_PARENT,
.out_flag = HELANX_PLLOUT,
.outp_flag = HELANX_PLLOUTP,
.vcodtidx = PXA1U88_CLK_PLL4VCO,
.outdtidx = PXA1U88_CLK_PLL4,
.outpdtidx = PXA1U88_CLK_PLL4P,
.vcodiv3dtidx = PXA1U88_CLK_PLL4VCODIV3,
}
};
/* pll default rate determined by ddr_mode */
unsigned long pll_dfrate[DDR_TYPE_MAX][MAX_PLL_NUM][MAX_PLL_TYPE] = {
[DDR_533M] = {
{2115 * MHZ, 1057 * MHZ, 528 * MHZ},
{1526 * MHZ, 1526 * MHZ, 1526 * MHZ},
/* for 533M case, reserve pll4 for LCD */
{1595 * MHZ, 1595 * MHZ, 797 * MHZ},
},
[DDR_667M] = {
{2115 * MHZ, 1057 * MHZ, 528 * MHZ},
{1526 * MHZ, 1526 * MHZ, 1526 * MHZ},
{2670lu * MHZ, 1335 * MHZ, 667 * MHZ},
},
[DDR_800M] = {
{2115 * MHZ, 1057 * MHZ, 528 * MHZ},
{1526 * MHZ, 1526 * MHZ, 1526 * MHZ},
{1595 * MHZ, 1595 * MHZ, 797 * MHZ},
},
};
static int board_is_fpga(void)
{
static int rc;
if (!rc)
rc = of_machine_is_compatible("marvell,pxa1908-fpga");
return rc;
}
static void pxa1U88_dynpll_init(struct pxa1U88_clk_unit *pxa_unit)
{
int idx;
struct clk *clk;
struct mmp_clk_unit *unit = &pxa_unit->unit;
pllx_vco_params[PLL2].cr_reg = pxa_unit->mpmu_base + MPMU_PLL2CR;
pllx_vco_params[PLL2].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL2CR;
pllx_vco_params[PLL3].cr_reg = pxa_unit->mpmu_base + MPMU_PLL3CR;
pllx_vco_params[PLL3].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL3CR;
pllx_vco_params[PLL4].cr_reg = pxa_unit->mpmu_base + MPMU_PLL4CR;
pllx_vco_params[PLL4].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL4CR;
pllx_pll_params[PLL2].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL2CR;
pllx_pll_params[PLL3].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL3CR;
pllx_pll_params[PLL4].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL4CR;
pllx_pllp_params[PLL2].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL2CR;
pllx_pllp_params[PLL3].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL3CR;
pllx_pllp_params[PLL4].pll_swcr = pxa_unit->apbs_base + APB_SPARE_PLL4CR;
for (idx = 0; idx < MAX_PLL_NUM; idx++) {
spin_lock_init(&pllx_platinfo[idx].lock);
/* vco */
pllx_vco_params[idx].lock_reg = pxa_unit->mpmu_base + MPMU_POSR;
pllx_vco_params[idx].default_rate =
pll_dfrate[ddr_mode][idx][VCO];
clk = helanx_clk_register_vco(pllx_platinfo[idx].vco_name,
0, pllx_platinfo[idx].vcoclk_flag, pllx_platinfo[idx].vco_flag,
&pllx_platinfo[idx].lock, &pllx_vco_params[idx]);
clk_set_rate(clk, pllx_vco_params[idx].default_rate);
mmp_clk_add(unit, pllx_platinfo[idx].vcodtidx, clk);
/* pll */
pllx_pll_params[idx].default_rate =
pll_dfrate[ddr_mode][idx][OUT];
clk = helanx_clk_register_pll(pllx_platinfo[idx].out_name,
pllx_platinfo[idx].vco_name,
pllx_platinfo[idx].outclk_flag, pllx_platinfo[idx].out_flag,
&pllx_platinfo[idx].lock, &pllx_pll_params[idx]);
clk_set_rate(clk, pllx_pll_params[idx].default_rate);
mmp_clk_add(unit, pllx_platinfo[idx].outdtidx, clk);
/* pllp */
pllx_pllp_params[idx].default_rate =
pll_dfrate[ddr_mode][idx][OUTP];
clk = helanx_clk_register_pll(pllx_platinfo[idx].outp_name,
pllx_platinfo[idx].vco_name,
pllx_platinfo[idx].outpclk_flag, pllx_platinfo[idx].outp_flag,
&pllx_platinfo[idx].lock, &pllx_pllp_params[idx]);
clk_set_rate(clk, pllx_pllp_params[idx].default_rate);
mmp_clk_add(unit, pllx_platinfo[idx].outpdtidx, clk);
/* vco div3 */
clk = clk_register_fixed_factor(NULL,
pllx_platinfo[idx].vco_div3_name,
pllx_platinfo[idx].vco_name, 0, 1, 3);
mmp_clk_add(unit, pllx_platinfo[idx].vcodiv3dtidx, clk);
}
}
static void pxa1U88_pll_init(struct pxa1U88_clk_unit *pxa_unit)
{
struct clk *clk;
struct mmp_clk_unit *unit = &pxa_unit->unit;
mmp_register_fixed_rate_clks(unit, fixed_rate_clks,
ARRAY_SIZE(fixed_rate_clks));
mmp_register_fixed_factor_clks(unit, fixed_factor_clks,
ARRAY_SIZE(fixed_factor_clks));
clk = clk_register_gate(NULL, "pll1_499_en", "pll1_499", 0,
pxa_unit->apbs_base + APBS_PLL1_CTRL,
31, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_PLL1_499_EN, clk);
clk = mmp_clk_register_factor("uart_pll", "pll1_4",
CLK_SET_RATE_PARENT,
pxa_unit->mpmu_base + MPMU_UART_PLL,
&uart_factor_masks, uart_factor_tbl,
ARRAY_SIZE(uart_factor_tbl), NULL);
mmp_clk_add(unit, PXA1U88_CLK_UART_PLL, clk);
mmp_register_general_gate_clks(unit, pll1_gate_clks,
pxa_unit->apmu_base,
ARRAY_SIZE(pll1_gate_clks));
if (!board_is_fpga())
pxa1U88_dynpll_init(pxa_unit);
}
static DEFINE_SPINLOCK(pwm0_lock);
static DEFINE_SPINLOCK(pwm2_lock);
static struct mmp_param_gate_clk apbc_gate_clks[] = {
{PXA1U88_CLK_TWSI0, "twsi0_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI0, 0x7, 0x3, 0x0, 0, NULL},
{PXA1U88_CLK_TWSI1, "twsi1_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI1, 0x7, 0x3, 0x0, 0, NULL},
{PXA1U88_CLK_TWSI3, "twsi3_clk", "pll1_13_1_5", CLK_SET_RATE_PARENT, APBC_TWSI3, 0x7, 0x3, 0x0, 0, NULL},
{PXA1U88_CLK_GPIO, "gpio_clk", "vctcxo", CLK_SET_RATE_PARENT, APBC_GPIO, 0x7, 0x3, 0x0, 0, NULL},
{PXA1U88_CLK_KPC, "kpc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_KPC, 0x7, 0x3, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
{PXA1U88_CLK_RTC, "rtc_clk", "clk32", CLK_SET_RATE_PARENT, APBC_RTC, 0x87, 0x83, 0x0, MMP_CLK_GATE_NEED_DELAY, NULL},
{PXA1U88_CLK_PWM0, "pwm0_clk", "pwm01_apb_share", CLK_SET_RATE_PARENT, APBC_PWM0, 0x2, 0x2, 0x0, 0, &pwm0_lock},
{PXA1U88_CLK_PWM1, "pwm1_clk", "pwm01_apb_share", CLK_SET_RATE_PARENT, APBC_PWM1, 0x6, 0x2, 0x0, 0, NULL},
{PXA1U88_CLK_PWM2, "pwm2_clk", "pwm23_apb_share", CLK_SET_RATE_PARENT, APBC_PWM2, 0x2, 0x2, 0x0, 0, &pwm2_lock},
{PXA1U88_CLK_PWM3, "pwm3_clk", "pwm23_apb_share", CLK_SET_RATE_PARENT, APBC_PWM3, 0x6, 0x2, 0x0, 0, NULL},
};
static DEFINE_SPINLOCK(uart0_lock);
static DEFINE_SPINLOCK(uart1_lock);
static DEFINE_SPINLOCK(uart2_lock);
static const char *uart_parent_names[] = {"pll1_3_16", "uart_pll"};
static const char *ssp_parent_names[] = {"pll1_96", "pll1_48", "pll1_24", "pll1_12"};
#ifdef CONFIG_CORESIGHT_SUPPORT
static void pxa1U88_coresight_clk_init(struct pxa1U88_clk_unit *pxa_unit)
{
struct mmp_clk_unit *unit = &pxa_unit->unit;
struct clk *clk;
clk = mmp_clk_register_gate(NULL, "DBGCLK", "pll1_416", 0,
pxa_unit->apmu_base + APMU_TRACE,
0x10008, 0x10008, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_DBGCLK, clk);
/* TMC clock */
clk = mmp_clk_register_gate(NULL, "TRACECLK", "DBGCLK", 0,
pxa_unit->apmu_base + APMU_TRACE,
0x10010, 0x10010, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_TRACECLK, clk);
}
#endif
static void pxa1U88_apb_periph_clk_init(struct pxa1U88_clk_unit *pxa_unit)
{
struct clk *clk;
struct mmp_clk_unit *unit = &pxa_unit->unit;
clk = mmp_clk_register_gate(NULL, "pwm01_apb_share", "pll1_48",
CLK_SET_RATE_PARENT,
pxa_unit->apbc_base + APBC_PWM0,
0x5, 0x1, 0x0, 0, &pwm0_lock);
clk = mmp_clk_register_gate(NULL, "pwm23_apb_share", "pll1_48",
CLK_SET_RATE_PARENT,
pxa_unit->apbc_base + APBC_PWM2,
0x5, 0x1, 0x0, 0, &pwm2_lock);
mmp_register_gate_clks(unit, apbc_gate_clks, pxa_unit->apbc_base,
ARRAY_SIZE(apbc_gate_clks));
clk = mmp_clk_register_gate(NULL, "ts_clk", NULL, 0,
pxa_unit->apbc_base + APBC_TERMAL, 0x7, 0x3, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_THERMAL, clk);
clk = mmp_clk_register_gate(NULL, "twsi2_clk", "pll1_13_1_5",
CLK_SET_RATE_PARENT,
pxa_unit->apbcp_base + APBCP_TWSI2,
0x7, 0x3, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_TWSI2, clk);
clk_register_mux(NULL, "uart0_mux", uart_parent_names,
ARRAY_SIZE(uart_parent_names),
CLK_SET_RATE_PARENT,
pxa_unit->apbc_base + APBC_UART0,
4, 3, 0, &uart0_lock);
if (board_is_fpga())
clk = clk_register_fixed_rate(NULL,
"uart0_clk", "uart0_mux", 0, 12500000);
else
clk = mmp_clk_register_gate(NULL, "uart0_clk", "uart0_mux",
CLK_SET_RATE_PARENT,
pxa_unit->apbc_base + APBC_UART0,
0x7, 0x3, 0x0, 0, &uart0_lock);
mmp_clk_add(unit, PXA1U88_CLK_UART0, clk);
clk_register_mux(NULL, "uart1_mux", uart_parent_names,
ARRAY_SIZE(uart_parent_names),
CLK_SET_RATE_PARENT,
pxa_unit->apbc_base + APBC_UART1,
4, 3, 0, &uart1_lock);
clk = mmp_clk_register_gate(NULL, "uart1_clk", "uart1_mux",
CLK_SET_RATE_PARENT,
pxa_unit->apbc_base + APBC_UART1,
0x7, 0x3, 0x0, 0, &uart1_lock);
mmp_clk_add(unit, PXA1U88_CLK_UART1, clk);
clk_register_mux(NULL, "uart2_mux", uart_parent_names,
ARRAY_SIZE(uart_parent_names),
CLK_SET_RATE_PARENT,
pxa_unit->apbcp_base + APBCP_UART2,
4, 3, 0, &uart2_lock);
clk = mmp_clk_register_gate(NULL, "uart2_clk", "uart2_mux",
CLK_SET_RATE_PARENT,
pxa_unit->apbcp_base + APBCP_UART2,
0x7, 0x3, 0x0, 0, &uart2_lock);
mmp_clk_add(unit, PXA1U88_CLK_UART2, clk);
clk = mmp_clk_register_apbc("swjtag", NULL,
pxa_unit->apbc_base + APBC_SWJTAG,
10, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_SWJTAG, clk);
clk = mmp_clk_register_gate(NULL, "ipc_clk", NULL, 0,
pxa_unit->apbc_base + APBC_IPC_CLK_RST,
0x7, 0x3, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_IPC_RST, clk);
clk_prepare_enable(clk);
clk = mmp_clk_register_gate(NULL, "ripc_clk", NULL, 0,
pxa_unit->apbcp_base + APBCP_AICER,
0x7, 0x2, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_AICER, clk);
clk_prepare_enable(clk);
clk_register_mux(NULL, "ssp0_mux", ssp_parent_names,
ARRAY_SIZE(ssp_parent_names), 0,
pxa_unit->apbc_base + APBC_SSP0, 4, 3, 0, NULL);
clk = mmp_clk_register_gate(NULL, "ssp0_clk", "ssp0_mux",
0,
pxa_unit->apbc_base + APBC_SSP0,
0x7, 0x3, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_SSP0, clk);
clk_register_mux(NULL, "ssp2_mux", ssp_parent_names,
ARRAY_SIZE(ssp_parent_names), 0,
pxa_unit->apbc_base + APBC_SSP2, 4, 3, 0, NULL);
clk = mmp_clk_register_gate(NULL, "ssp2_clk", "ssp2_mux",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apbc_base + APBC_SSP2,
0x7, 0x3, 0x0, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_SSP2, clk);
#ifdef CONFIG_CORESIGHT_SUPPORT
pxa1U88_coresight_clk_init(pxa_unit);
#endif
}
static DEFINE_SPINLOCK(sdh0_lock);
static DEFINE_SPINLOCK(sdh1_lock);
static DEFINE_SPINLOCK(sdh2_lock);
static const char *sdh_parent_names[] = {"pll1_416", "pll1_624"};
static struct mmp_clk_mix_config sdh_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 8, 2, 6, 11),
};
/* Protect GC 3D register access APMU_GC&APMU_GC2D */
static DEFINE_SPINLOCK(gc_lock);
static DEFINE_SPINLOCK(gc2d_lock);
/* GC 3D */
static const char *gc3d_parent_names[] = {
"pll1_832_gate", "pll1_624_gate", "pll2p", "pll2_div3"
};
static struct mmp_clk_mix_clk_table gc3d_pptbl[] = {
{.rate = 156000000, .parent_index = 1,/* pll1_624_gate */ .xtc = 0x00055544},
{.rate = 312000000, .parent_index = 1,/* pll1_624_gate */ .xtc = 0x00055544},
{.rate = 416000000, .parent_index = 0,/* pll1_832_gate */ .xtc = 0x00055544},
{.rate = 624000000, .parent_index = 1,/* pll1_624_gate */ .xtc = 0x000AAA55},
{.rate = 705000000, .parent_index = 3, /* pll2_div3 */ .xtc = 0x000AAA55},
};
static struct mmp_clk_mix_config gc3d_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 12, 2, 6, 15),
.table = gc3d_pptbl,
.table_size = ARRAY_SIZE(gc3d_pptbl),
};
/* GC shader */
static const char * const gcsh_parent_names[] = {
"pll1_832_gate", "pll1_624_gate", "pll2p", "pll3p",
};
static struct mmp_clk_mix_clk_table gcsh_pptbl[] = {
{.rate = 156000000, .parent_index = 1,/* pll1_624_gate */},
{.rate = 312000000, .parent_index = 1,/* pll1_624_gate */},
{.rate = 416000000, .parent_index = 0,/* pll1_832_gate */},
{.rate = 624000000, .parent_index = 1,/* pll1_624_gate */},
};
static struct mmp_clk_mix_config gcsh_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 28, 2, 26, 31),
.table = gcsh_pptbl,
.table_size = ARRAY_SIZE(gcsh_pptbl),
};
/* GC 2D */
static const char *gc2d_parent_names[] = {
"pll1_416_gate", "pll1_624_gate", "pll2", "pll2p",
};
/* ulc GC2D has no compress feature, adjust the PP */
static struct mmp_clk_mix_clk_table gc2d_pptbl[] = {
{.rate = 156000000, .parent_index = 1,/* pll1_624_gate */ .xtc = 0x00000044},
{.rate = 312000000, .parent_index = 1,/* pll1_624_gate */ .xtc = 0x00055544},
{.rate = 416000000, .parent_index = 0,/* pll1_416_gate */ .xtc = 0x000AAA44},
};
static struct mmp_clk_mix_config gc2d_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 12, 2, 6, 15),
.table = gc2d_pptbl,
.table_size = ARRAY_SIZE(gc2d_pptbl),
};
/* GC bus(shared by GC 3D and 2D) */
static const char *gcbus_parent_names[] = {
"pll1_416_gate", "pll1_624_gate", "pll2", "pll4",
};
/* ulc GCbus adjusted from 128bit to 64bit, adjust the PP */
static struct mmp_clk_mix_clk_table gcbus_pptbl[] = {
{.rate = 156000000, .parent_index = 1,/* pll1_624_gate */},
{.rate = 312000000, .parent_index = 1,/* pll1_624_gate */},
{.rate = 416000000, .parent_index = 0, /* pll1_416_gate */},
{.rate = 624000000, .parent_index = 1, /* pll1_624_gate */},
};
static struct mmp_clk_mix_config gcbus_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 17, 2, 20, 16),
.table = gcbus_pptbl,
.table_size = ARRAY_SIZE(gcbus_pptbl),
};
/* Protect register access APMU_VPU */
static DEFINE_SPINLOCK(vpu_lock);
/* VPU fclk */
static const char *vpufclk_parent_names[] = {
"pll1_416_gate", "pll1_624_gate", "pll2_div3", "pll2p",
};
static struct mmp_clk_mix_clk_table vpufclk_pptbl[] = {
{.rate = 156000000, .parent_index = 1,/* pll1_624_gate */ .xtc = 0x00380404},
{.rate = 208000000, .parent_index = 0,/* pll1_416_gate */ .xtc = 0x00385454},
{.rate = 312000000, .parent_index = 1,/* pll1_624_gate */ .xtc = 0x00385454},
{.rate = 416000000, .parent_index = 0, /* pll1_416_gate */ .xtc = 0x00B85454},
{.rate = 528000000, .parent_index = 3, /* pll2p */ .xtc = 0x00B8A5A4},
};
static struct mmp_clk_mix_config vpufclk_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 8, 2, 6, 20),
.table = vpufclk_pptbl,
.table_size = ARRAY_SIZE(vpufclk_pptbl),
};
/* vpu bus */
static const char *vpubus_parent_names[] = {
"pll1_416_gate", "pll1_624_gate", "pll2", "pll2_div3",
};
static struct mmp_clk_mix_clk_table vpubus_pptbl[] = {
{.rate = 156000000, .parent_index = 1,/* pll1_624_gate */},
{.rate = 208000000, .parent_index = 0,/* pll1_416_gate */},
{.rate = 312000000, .parent_index = 1,/* pll1_624_gate */},
{.rate = 416000000, .parent_index = 0, /* pll1_416_gate */},
};
static struct mmp_clk_mix_config vpubus_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 13, 2, 11, 21),
.table = vpubus_pptbl,
.table_size = ARRAY_SIZE(vpubus_pptbl),
};
static DEFINE_SPINLOCK(disp_lock);
static const char *disp1_parent_names[] = {"pll1_624", "pll1_832", "pll1_499_en"};
static const char *disp2_parent_names[] = {"pll2", "pll2p", "pll2_div3"};
static const char *disp3_parent_names[] = {"pll3p", "pll3_div3"};
static const char *disp4_parent_names[] = {"pll4", "pll4_div3"};
static const char *disp_axi_parent_names[] = {"pll1_416", "pll1_624", "pll2", "pll2p"};
static int disp_axi_mux_table[] = {0x0, 0x1, 0x2, 0x3};
static struct mmp_clk_mix_config disp_axi_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(2, 19, 2, 17, 22),
.mux_table = disp_axi_mux_table,
};
/* sc2 clk */
static DEFINE_SPINLOCK(ccic0_lock);
static DEFINE_SPINLOCK(ccic1_lock);
static DEFINE_SPINLOCK(isp_lock);
static const char *sc2_4x_parent_names[] = {"pll1_832_gate", "pll1_624_gate",
"pll2_div3", "pll2p", "pll4_div3"};
static int sc2_4x_mux_table[] = {0x0, 0x1, 0x02, 0x82, 0x03};
static struct mmp_clk_mix_config sc2_4x_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 18, 2, 16, 15),
.mux_table = sc2_4x_mux_table,
};
static const char *sc2_csi_parent_names[] = {"pll1_416_gate", "pll1_624_gate",
"pll2_div3", "pll2p", "pll4_div3"};
static int sc2_csi_mux_table[] = {0x0, 0x1, 0x02, 0x22, 0x03};
static struct mmp_clk_mix_config sc2_csi_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 18, 2, 16, 15),
.mux_table = sc2_csi_mux_table,
};
static const char *sc2_axi_parent_names[] = {"pll1_416_gate", "pll1_624_gate",
"pll2", "pll2p"};
static struct mmp_clk_mix_config sc2_axi_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 18, 2, 21, 23),
};
static const char *sc2_phy_parent_names[] = {"pll1_6", "pll1_12"};
static const char *isp_pipe_parent_names[] = {"pll1_416_gate", "pll1_624_gate",
"pll4_div3", "pll2p",};
static struct mmp_clk_mix_config isp_pipe_mix_config = {
.reg_info = DEFINE_MIX_REG_INFO(3, 4, 2, 2, 7),
};
#ifdef CONFIG_SMC91X
static void __init smc91x_clk_init(void __iomem *apmu_base)
{
struct device_node *np = of_find_node_by_name(NULL, "smc91x");
const char *str = NULL;
void __iomem *reg;
if (np && !of_property_read_string(np, "clksrc", &str))
if (!strcmp(str, "smc91x")) {
/* Enable clock to SMC Controller */
writel(0x5b, apmu_base + APMU_SMC);
/* Configure SMC Controller */
/* Set CS0 to A\D type memory */
reg = ioremap(SMC_CLK, 4);
writel(0x52880008, reg);
iounmap(reg);
}
}
#endif
struct pxa1U88_clk_disp {
struct mmp_clk_gate gate;
struct clk_mux mux;
struct clk_divider divider;
const struct clk_ops *mux_ops;
const struct clk_ops *div_ops;
const struct clk_ops *gate_ops;
};
static struct pxa1U88_clk_disp disp1_clks;
static struct pxa1U88_clk_disp disp4_clks;
static void pxa1U88_axi_periph_clk_init(struct pxa1U88_clk_unit *pxa_unit)
{
struct clk *clk;
struct mmp_clk_unit *unit = &pxa_unit->unit;
const char **parent_names;
u32 parent_num;
clk = mmp_clk_register_gate(NULL, "usb_clk", NULL, 0,
pxa_unit->apmu_base + APMU_USB,
0x9, 0x9, 0x1, 0, NULL);
mmp_clk_add(unit, PXA1U88_CLK_USB, clk);
/* nand flash clock, no one use it, expect to be disabled */
mmp_clk_register_gate(NULL, "nf_clk", NULL, 0,
pxa_unit->apmu_base + APMU_NF,
0x1db, 0x1db, 0x0, 0, NULL);
clk = mmp_clk_register_gate(NULL, "sdh_axi_clk", NULL, 0,
pxa_unit->apmu_base + APMU_SDH0,
0x8, 0x8, 0x0, 0, &sdh0_lock);
mmp_clk_add(unit, PXA1U88_CLK_SDH_AXI, clk);
sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH0;
mmp_clk_register_mix(NULL, "sdh0_mix_clk", sdh_parent_names,
ARRAY_SIZE(sdh_parent_names),
CLK_SET_RATE_PARENT,
&sdh_mix_config, &sdh0_lock);
clk = mmp_clk_register_gate(NULL, "sdh0_clk", "sdh0_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_SDH0,
0x12, 0x12, 0x0, 0, &sdh0_lock);
mmp_clk_add(unit, PXA1U88_CLK_SDH0, clk);
clk = mmp_clk_register_dvfs_dummy("sdh0_dummy", NULL,
0, DUMMY_VL_TO_KHZ(0));
mmp_clk_add(unit, PXA1U88_CLK_SDH0_DUMMY, clk);
sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH1;
mmp_clk_register_mix(NULL, "sdh1_mix_clk", sdh_parent_names,
ARRAY_SIZE(sdh_parent_names),
CLK_SET_RATE_PARENT,
&sdh_mix_config, &sdh1_lock);
clk = mmp_clk_register_gate(NULL, "sdh1_clk", "sdh1_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_SDH1,
0x12, 0x12, 0x0, 0, &sdh1_lock);
mmp_clk_add(unit, PXA1U88_CLK_SDH1, clk);
clk = mmp_clk_register_dvfs_dummy("sdh1_dummy", NULL,
0, DUMMY_VL_TO_KHZ(0));
mmp_clk_add(unit, PXA1U88_CLK_SDH1_DUMMY, clk);
sdh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_SDH2;
mmp_clk_register_mix(NULL, "sdh2_mix_clk", sdh_parent_names,
ARRAY_SIZE(sdh_parent_names),
CLK_SET_RATE_PARENT,
&sdh_mix_config, &sdh2_lock);
clk = mmp_clk_register_gate(NULL, "sdh2_clk", "sdh2_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_SDH2,
0x12, 0x12, 0x0, 0, &sdh2_lock);
mmp_clk_add(unit, PXA1U88_CLK_SDH2, clk);
clk = mmp_clk_register_dvfs_dummy("sdh2_dummy", NULL,
0, DUMMY_VL_TO_KHZ(0));
mmp_clk_add(unit, PXA1U88_CLK_SDH2_DUMMY, clk);
/*
* DE suggest SW to release GC_2D_3D_AXI_Reset
* before both 3D/2D power on sequence
*/
clk = mmp_clk_register_gate(NULL, "gc_axi_rst", NULL,
0, pxa_unit->apmu_base + APMU_GC2D,
0x1, 0x1, 0x0, 0, &gc2d_lock);
clk_prepare_enable(clk);
gc3d_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_GC;
gc3d_mix_config.reg_info.reg_clk_xtc = pxa_unit->ciu_base + GPU_XTC;
clk = mmp_clk_register_mix(NULL, "gc3d_mix_clk", gc3d_parent_names,
ARRAY_SIZE(gc3d_parent_names),
0, &gc3d_mix_config, &gc_lock);
#ifdef CONFIG_PM_DEVFREQ
__init_comp_devfreq_table(clk, DEVFREQ_GPU_3D);
#endif
clk = mmp_clk_register_gate(NULL, "gc3d_clk", "gc3d_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_GC,
(3 << 4), (3 << 4), 0x0, 0, &gc_lock);
clk_set_rate(clk, 312000000);
mmp_clk_add(unit, PXA1U88_CLK_GC3D, clk);
register_mixclk_dcstatinfo(clk);
gcsh_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_GC;
parent_names = (const char **)gcsh_parent_names;
parent_num = ARRAY_SIZE(gcsh_parent_names);
clk = mmp_clk_register_mix(NULL, "gcsh_mix_clk", parent_names,
parent_num,
0, &gcsh_mix_config, &gc_lock);
#ifdef CONFIG_PM_DEVFREQ
__init_comp_devfreq_table(clk, DEVFREQ_GPU_SH);
#endif
clk = mmp_clk_register_gate(NULL, "gcsh_clk", "gcsh_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_GC,
(1 << 25), (1 << 25), 0x0, 0, &gc_lock);
clk_set_rate(clk, 312000000);
mmp_clk_add(unit, PXA1U88_CLK_GCSH, clk);
register_mixclk_dcstatinfo(clk);
gc2d_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_GC2D;
gc2d_mix_config.reg_info.reg_clk_xtc = pxa_unit->ciu_base + GPU2D_XTC;
clk = mmp_clk_register_mix(NULL, "gc2d_mix_clk", gc2d_parent_names,
ARRAY_SIZE(gc2d_parent_names),
0, &gc2d_mix_config, &gc2d_lock);
#ifdef CONFIG_PM_DEVFREQ
__init_comp_devfreq_table(clk, DEVFREQ_GPU_2D);
#endif
clk = mmp_clk_register_gate(NULL, "gc2d_clk", "gc2d_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_GC2D,
(3 << 4), (3 << 4), 0x0, 0, &gc2d_lock);
clk_set_rate(clk, 156000000);
mmp_clk_add(unit, PXA1U88_CLK_GC2D, clk);
register_mixclk_dcstatinfo(clk);
gcbus_mix_config.reg_info.reg_clk_ctrl =
pxa_unit->apmu_base + APMU_GC2D;
mmp_clk_register_mix(NULL, "gcbus_mix_clk", gcbus_parent_names,
ARRAY_SIZE(gcbus_parent_names),
0, &gcbus_mix_config, &gc2d_lock);
clk = mmp_clk_register_gate(NULL, "gcbus_clk", "gcbus_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_GC2D,
(1 << 3), (1 << 3), 0x0, 0, &gc2d_lock);
clk_set_rate(clk, 312000000);
mmp_clk_add(unit, PXA1U88_CLK_GCBUS, clk);
vpufclk_mix_config.reg_info.reg_clk_ctrl =
pxa_unit->apmu_base + APMU_VPU;
vpufclk_mix_config.reg_info.reg_clk_xtc =
pxa_unit->ciu_base + VPU_XTC;
clk = mmp_clk_register_mix(NULL, "vpufunc_mix_clk",
vpufclk_parent_names, ARRAY_SIZE(vpufclk_parent_names),
0, &vpufclk_mix_config, &vpu_lock);
#ifdef CONFIG_VPU_DEVFREQ
__init_comp_devfreq_table(clk, DEVFREQ_VPU_BASE);
#endif
clk = mmp_clk_register_gate(NULL, "vpufunc_clk", "vpufunc_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_VPU,
(3 << 4), (3 << 4), 0x0, 0, &vpu_lock);
clk_set_rate(clk, 416000000);
mmp_clk_add(unit, PXA1U88_CLK_VPU, clk);
register_mixclk_dcstatinfo(clk);
vpubus_mix_config.reg_info.reg_clk_ctrl =
pxa_unit->apmu_base + APMU_VPU;
mmp_clk_register_mix(NULL, "vpubus_mix_clk",
vpubus_parent_names, ARRAY_SIZE(vpubus_parent_names),
0, &vpubus_mix_config, &vpu_lock);
clk = mmp_clk_register_gate(NULL, "vpubus_clk", "vpubus_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_VPU,
(1 << 3), (1 << 3), 0x0, 0, &vpu_lock);
clk_set_rate(clk, 416000000);
mmp_clk_add(unit, PXA1U88_CLK_VPUBUS, clk);
clk = mmp_clk_register_gate(NULL, "dsi_esc_clk", NULL, 0,
pxa_unit->apmu_base + APMU_DSI1,
0xf, 0xc, 0x0, 0, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DSI_ESC, clk);
disp1_clks.mux_ops = &clk_mux_ops;
disp1_clks.mux.mask = 0x2;
disp1_clks.mux.shift = 9;
disp1_clks.mux.reg = pxa_unit->apmu_base + APMU_DISP1;
disp1_clks.gate.mask = 0x20;
disp1_clks.gate.reg = pxa_unit->apmu_base + APMU_DISP1;
disp1_clks.gate.val_disable = 0x0;
disp1_clks.gate.val_enable = 0x20;
disp1_clks.gate.flags = 0x0;
disp1_clks.gate_ops = &mmp_clk_gate_ops;
clk = clk_register_composite(NULL, "disp1_sel_clk", (const char **)disp1_parent_names,
ARRAY_SIZE(disp1_parent_names),
&disp1_clks.mux.hw, disp1_clks.mux_ops,
NULL, NULL,
&disp1_clks.gate.hw, disp1_clks.gate_ops,
CLK_SET_RATE_PARENT);
mmp_clk_add(unit, PXA1U88_CLK_DISP1, clk);
clk_register_clkdev(clk, "disp1_sel_clk", NULL);
clk = clk_register_mux(NULL, "disp2_sel_clk", disp2_parent_names,
ARRAY_SIZE(disp2_parent_names),
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_DISP1,
11, 2, 0, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DISP2, clk);
clk = mmp_clk_register_gate(NULL, "dsip2_clk", "disp2_sel_clk",
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_DISP1,
0x40, 0x40, 0x0, 0, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DISP2_EN, clk);
clk = clk_register_mux(NULL, "disp3_sel_clk", disp3_parent_names,
ARRAY_SIZE(disp3_parent_names),
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_DISP1,
13, 1, 0, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DISP3, clk);
clk = mmp_clk_register_gate(NULL, "dsip3_en_clk", "disp3_sel_clk",
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_DISP1,
0x80, 0x80, 0x0, 0, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DISP3_EN, clk);
disp4_clks.mux_ops = &clk_mux_ops;
disp4_clks.mux.mask = 0x1;
disp4_clks.mux.shift = 14;
disp4_clks.mux.reg = pxa_unit->apmu_base + APMU_DISP1;
disp4_clks.gate.mask = 0x100;
disp4_clks.gate.reg = pxa_unit->apmu_base + APMU_DISP1;
disp4_clks.gate.val_disable = 0x0;
disp4_clks.gate.val_enable = 0x100;
disp4_clks.gate.flags = 0x0;
disp4_clks.gate_ops = &mmp_clk_gate_ops;
clk = clk_register_composite(NULL, "dsi_pll", (const char **)disp4_parent_names,
ARRAY_SIZE(disp4_parent_names),
&disp4_clks.mux.hw, disp4_clks.mux_ops,
NULL, NULL,
&disp4_clks.gate.hw, disp4_clks.gate_ops,
0);
mmp_clk_add(unit, PXA1U88_CLK_DISP4, clk);
clk_register_clkdev(clk, "dsi_pll", NULL);
disp_axi_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_DISP1;
clk = mmp_clk_register_mix(NULL, "disp_axi_sel_clk", disp_axi_parent_names,
ARRAY_SIZE(disp_axi_parent_names),
CLK_SET_RATE_PARENT,
&disp_axi_mix_config, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DISP_AXI_SEL_CLK, clk);
clk_set_rate(clk, 208000000);
clk = mmp_clk_register_gate(NULL, "disp_axi_clk", "disp_axi_sel_clk",
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_DISP1,
0x10009, 0x10009, 0x10001, 0, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DISP_AXI_CLK, clk);
clk = mmp_clk_register_gate(NULL, "LCDCIHCLK", "disp_axi_clk", 0,
pxa_unit->apmu_base + APMU_DISP1,
0x16, 0x16, 0x4, 0, &disp_lock);
mmp_clk_add(unit, PXA1U88_CLK_DISP_HCLK, clk);
/* SC2 VCLK */
clk_register_divider(NULL, "isim_vclk_div", "pll1_312_gate",
0, pxa_unit->apmu_base + APMU_CCIC1,
22, 4, 0, &ccic1_lock);
clk = mmp_clk_register_gate(NULL, "isim_vclk_gate", "isim_vclk_div", 0,
pxa_unit->apmu_base + APMU_CCIC1,
0x4000000, 0x4000000, 0x0, 0, &ccic1_lock);
mmp_clk_add(unit, PXA1U88_CLK_SC2_MCLK, clk);
sc2_4x_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_CCIC0;
mmp_clk_register_mix(NULL, "sc2_4x_mix_clk", sc2_4x_parent_names,
ARRAY_SIZE(sc2_4x_parent_names), 0,
&sc2_4x_mix_config, &ccic0_lock);
clk = mmp_clk_register_gate(NULL, "sc2_4x_clk", "sc2_4x_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_CCIC0,
0x12, 0x12, 0x0, 0, &ccic0_lock);
mmp_clk_add(unit, PXA1U88_CLK_SC2_4X_CLK, clk);
sc2_csi_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_CCIC1;
mmp_clk_register_mix(NULL, "sc2_csi_mix_clk",
sc2_csi_parent_names,
ARRAY_SIZE(sc2_csi_parent_names), 0,
&sc2_csi_mix_config, &ccic1_lock);
clk = mmp_clk_register_gate(NULL, "sc2_csi_clk", "sc2_csi_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_CCIC1,
0x12, 0x12, 0x0, 0, &ccic1_lock);
mmp_clk_add(unit, PXA1U88_CLK_SC2_CSI_CLK, clk);
sc2_axi_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_ISP;
mmp_clk_register_mix(NULL, "sc2_axi_mix_clk",
sc2_axi_parent_names,
ARRAY_SIZE(sc2_axi_parent_names), 0,
&sc2_axi_mix_config, &isp_lock);
clk = mmp_clk_register_gate(NULL, "sc2_axi_clk", "sc2_axi_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_ISP,
0x30000, 0x30000, 0x0, 0, &isp_lock);
mmp_clk_add(unit, PXA1U88_CLK_SC2_AXI_CLK, clk);
clk_register_mux(NULL, "sc2_phy2ln_mux", sc2_phy_parent_names,
ARRAY_SIZE(sc2_phy_parent_names), 0, pxa_unit->apmu_base + APMU_CCIC1,
7, 1, 0, &ccic1_lock);
clk = mmp_clk_register_gate(NULL, "sc2_phy2ln_clk", "sc2_phy2ln_mux",
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_CCIC1,
0x24, 0x24, 0x0, 0, &ccic1_lock);
mmp_clk_add(unit, PXA1U88_CLK_SC2_PHY2LN_CLK_EN, clk);
clk_register_mux(NULL, "sc2_phy4ln_mux", sc2_phy_parent_names,
ARRAY_SIZE(sc2_phy_parent_names), 0, pxa_unit->apmu_base + APMU_CCIC0,
7, 1, 0, &ccic0_lock);
clk = mmp_clk_register_gate(NULL, "sc2_phy4ln_clk", "sc2_phy4ln_mux",
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_CCIC0,
0x24, 0x24, 0x0, 0, &ccic0_lock);
mmp_clk_add(unit, PXA1U88_CLK_SC2_PHY4LN_CLK_EN, clk);
isp_pipe_mix_config.reg_info.reg_clk_ctrl = pxa_unit->apmu_base + APMU_ISP;
mmp_clk_register_mix(NULL, "isp_pipe_mix_clk",
isp_pipe_parent_names,
ARRAY_SIZE(isp_pipe_parent_names), 0,
&isp_pipe_mix_config, &isp_lock);
/* add isp ahb and isp axi reset to pipe clk enable */
clk = mmp_clk_register_gate(NULL, "isp_pipe_clk", "isp_pipe_mix_clk",
CLK_SET_RATE_PARENT | CLK_SET_RATE_ENABLED,
pxa_unit->apmu_base + APMU_ISP,
0x503, 0x503, 0x0, 0, &isp_lock);
mmp_clk_add(unit, PXA1U88_CLK_ISP_PIPE_CLK, clk);
clk_register_divider(NULL, "isp_core_div", "pll1_624_gate",
0, pxa_unit->apmu_base + APMU_ISP,
24, 3, 0, &isp_lock);
clk = mmp_clk_register_gate(NULL, "isp_core_gate", "isp_core_div",
CLK_SET_RATE_PARENT,
pxa_unit->apmu_base + APMU_ISP,
0x18000000, 0x18000000, 0x0, 0, &isp_lock);
mmp_clk_add(unit, PXA1U88_CLK_ISP_CORE_CLK_EN, clk);
clk = mmp_clk_register_gate(NULL, "sc2_ahb_gate", NULL, 0,
pxa_unit->apmu_base + APMU_CCIC0,
0x600000, 0x600000, 0x0, 0, &ccic0_lock);
mmp_clk_add(unit, PXA1U88_CLK_SC2_AHB_CLK, clk);
}
static DEFINE_SPINLOCK(fc_seq_lock);
/* CORE */
static const char *core_parent[] = {
"pll1_624", "pll1_1248", "pll2", "pll1_832", "pll3p",
};
static struct parents_table core_parent_table[] = {
{
.parent_name = "pll1_624",
.hw_sel_val = 0x0,
},
{
.parent_name = "pll1_1248",
.hw_sel_val = 0x1,
},
{
.parent_name = "pll2",
.hw_sel_val = 0x2,
},
{
.parent_name = "pll1_832",
.hw_sel_val = 0x3,
},
{
.parent_name = "pll3p",
.hw_sel_val = 0x5,
},
};
/*
* For HELAN2:
* PCLK = AP_CLK_SRC / (CORE_CLK_DIV + 1)
* BIU_CLK = PCLK / (BIU_CLK_DIV + 1)
* MC_CLK = PCLK / (MC_CLK_DIV + 1)
*
* AP clock source:
* 0x0 = PLL1 624 MHz
* 0x1 = PLL1 1248 MHz or PLL3_CLKOUT
* (depending on FCAP[2])
* 0x2 = PLL2_CLKOUT
* 0x3 = PLL1 832 MHZ
* 0x5 = PLL3_CLKOUTP
*/
static struct cpu_opt helan2_op_array[] = {
{
.pclk = 624,
.pdclk = 312,
.baclk = 156,
.ap_clk_sel = 0x0,
},
{
.pclk = 832,
.pdclk = 416,
.baclk = 208,
.ap_clk_sel = 0x3,
},
{
.pclk = 1057,
.pdclk = 528,
.baclk = 264,
.ap_clk_sel = 0x2,
},
{
.pclk = 1248,
.pdclk = 624,
.baclk = 312,
.ap_clk_sel = 0x1,
},
{
.pclk = 1526,
.pdclk = 763,
.baclk = 381,
.ap_clk_sel = 0x5,
.ap_clk_src = 1526,
},
{
.pclk = 1803,
.pdclk = 901,
.baclk = 450,
.ap_clk_sel = 0x5,
.ap_clk_src = 1803,
}
};
static struct cpu_rtcwtc cpu_rtcwtc_1908sec[] = {
{.max_pclk = 832, .l1_xtc = 0x55555555, .l2_xtc = 0x00005555,},
{.max_pclk = 1057, .l1_xtc = 0x55555555, .l2_xtc = 0x0000555A,},
{.max_pclk = 1526, .l1_xtc = 0xAAAAAAAA, .l2_xtc = 0x0000AAAA,},
};
static struct core_params core_params = {
.parent_table = core_parent_table,
.parent_table_size = ARRAY_SIZE(core_parent_table),
.cpu_opt = helan2_op_array,
.cpu_opt_size = ARRAY_SIZE(helan2_op_array),
.cpu_rtcwtc_table = cpu_rtcwtc_1908sec,
.cpu_rtcwtc_table_size = ARRAY_SIZE(cpu_rtcwtc_1908sec),
.bridge_cpurate = 1248,
.max_cpurate = 1248,
.dcstat_support = true,
};
static struct pxa1U88_clk_unit *globla_pxa_unit;
static int pxa1u88_powermode(u32 cpu)
{
unsigned status_temp = 0;
status_temp = ((__raw_readl(globla_pxa_unit->apmu_base +
APMU_CORE_STATUS)) &
((1 << (6 + 3 * cpu)) | (1 << (7 + 3 * cpu))));
if (!status_temp)
return MAX_LPM_INDEX;
if (status_temp & (1 << (6 + 3 * cpu)))
return LPM_C1;
else if (status_temp & (1 << (7 + 3 * cpu)))
return LPM_C2;
return 0;
}
/* DDR */
static const char *ddr_parent[] = {
"pll1_624", "pll1_832", "pll1_1248", "pll2", "pll4", "pll3p",
};
/*
* DDR clock source:
* 0x0 = PLL1 624 MHz
* 0x1 = PLL1 832 MHz
* 0x4 = PLL2_CLKOUT
* 0x5 = PLL4_CLKOUT
* 0x6 = PLL3_CLKOUTP(helan2), PLL1_1248(ULC)
*/
static struct parents_table ddr_parent_table[] = {
{
.parent_name = "pll1_624",
.hw_sel_val = 0x0,
},
{
.parent_name = "pll1_832",
.hw_sel_val = 0x1,
},
{
.parent_name = "pll2",
.hw_sel_val = 0x4,
},
{
.parent_name = "pll4",
.hw_sel_val = 0x5,
},
/* only cares ulc, and pll3p dedicate for cpu, ignore it */
{
.parent_name = "pll1_1248",
.hw_sel_val = 0x6,
},
};
/* helan2 only support 800M */
static struct ddr_opt lpddr800_oparray[] = {
{
.dclk = 156,
.ddr_tbl_index = 2,
.ddr_clk_sel = 0x0,
},
{
.dclk = 312,
.ddr_tbl_index = 4,
.ddr_clk_sel = 0x0,
},
{
.dclk = 416,
.ddr_tbl_index = 6,
.ddr_clk_sel = 0x1,
},
{
.dclk = 528,
.ddr_tbl_index = 8,
.ddr_clk_sel = 0x4,
},
{
.dclk = 797,
.ddr_tbl_index = 10,
.ddr_clk_sel = 0x5,
},
};
static unsigned long hwdfc_freq_table[] = {
0, 312000, 312000, 416000, 528000, 528000, 624000, 667000
};
/*
* ULC support max to 667M, and has extra 624M PP
* FIXME: ULC could assign specific lpm tbl, use 0 for bringup.
*/
static struct ddr_opt lpddr533_oparray[] = {
{
.dclk = 156,
.ddr_tbl_index = 2,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x0,
},
{
.dclk = 312,
.ddr_tbl_index = 4,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x0,
},
{
.dclk = 416,
.ddr_tbl_index = 6,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x1,
},
{
.dclk = 528,
.ddr_tbl_index = 8,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x4,
},
};
static struct ddr_opt lpddr667_oparray[] = {
{
.dclk = 156,
.ddr_tbl_index = 2,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x0,
},
{
.dclk = 312,
.ddr_tbl_index = 4,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x0,
},
{
.dclk = 416,
.ddr_tbl_index = 6,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x1,
},
{
.dclk = 528,
.ddr_tbl_index = 8,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x4,
},
/* FIXME: if we really need 624M PP? Here for verification */
{
.dclk = 624,
.ddr_tbl_index = 10,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x6,
},
{
.dclk = 667,
.ddr_tbl_index = 12,
.ddr_lpmtbl_index = 0,
.ddr_clk_sel = 0x5,
},
};
static struct ddr_params ddr_params = {
.parent_table = ddr_parent_table,
.parent_table_size = ARRAY_SIZE(ddr_parent_table),
.hwdfc_freq_table = hwdfc_freq_table,
.hwdfc_table_size = ARRAY_SIZE(hwdfc_freq_table),
.dcstat_support = true,
};
static const char *axi_parent[] = {
"pll1_416", "pll1_624", "pll2", "pll2p",
};
/*
* AXI clock source:
* 0x0 = PLL1 416 MHz
* 0x1 = PLL1 624 MHz
* 0x2 = PLL2_CLKOUT
* 0x3 = PLL2_CLKOUTP
*/
static struct parents_table axi_parent_table[] = {
{
.parent_name = "pll1_416",
.hw_sel_val = 0x0,
},
{
.parent_name = "pll1_624",
.hw_sel_val = 0x1,
},
{
.parent_name = "pll2",
.hw_sel_val = 0x2,
},
{
.parent_name = "pll2p",
.hw_sel_val = 0x3,
},
};
static struct axi_opt axi_oparray[] = {
{
.aclk = 156,
.axi_clk_sel = 0x1,
},
{
.aclk = 208,
.axi_clk_sel = 0x0,
},
};
static struct axi_params axi_params = {
.parent_table = axi_parent_table,
.parent_table_size = ARRAY_SIZE(axi_parent_table),
.dcstat_support = true,
};
static struct ddr_combclk_relation aclk_dclk_relationtbl_1U88[] = {
{.dclk_rate = 156000000, .combclk_rate = 156000000},
{.dclk_rate = 312000000, .combclk_rate = 156000000},
{.dclk_rate = 416000000, .combclk_rate = 208000000},
{.dclk_rate = 528000000, .combclk_rate = 208000000},
{.dclk_rate = 624000000, .combclk_rate = 208000000},
{.dclk_rate = 667000000, .combclk_rate = 208000000},
{.dclk_rate = 797000000, .combclk_rate = 208000000},
};
static void __init pxa1U88_acpu_init(struct pxa1U88_clk_unit *pxa_unit)
{
struct mmp_clk_unit *unit = &pxa_unit->unit;
struct clk *clk;
core_params.apmu_base = pxa_unit->apmu_base;
core_params.mpmu_base = pxa_unit->mpmu_base;
core_params.ciu_base = pxa_unit->ciu_base;
/* for debug purpose, pass max cpu frequency from uboot cmdline */
if (max_freq)
core_params.max_cpurate = max_freq;
core_params.pxa_powermode = pxa1u88_powermode;
mmp_clk_parents_lookup(core_params.parent_table,
core_params.parent_table_size);
ddr_params.apmu_base = pxa_unit->apmu_base;
ddr_params.mpmu_base = pxa_unit->mpmu_base;
ddr_params.ddr_opt = lpddr533_oparray;
ddr_params.ddr_opt_size = ARRAY_SIZE(lpddr533_oparray);
if (ddr_mode == DDR_667M) {
ddr_params.ddr_opt = lpddr667_oparray;
ddr_params.ddr_opt_size =
ARRAY_SIZE(lpddr667_oparray);
} else if (ddr_mode == DDR_800M) {
ddr_params.ddr_opt = lpddr800_oparray;
ddr_params.ddr_opt_size = ARRAY_SIZE(lpddr800_oparray);
}
mmp_clk_parents_lookup(ddr_params.parent_table,
ddr_params.parent_table_size);
axi_params.apmu_base = pxa_unit->apmu_base;
axi_params.mpmu_base = pxa_unit->mpmu_base;
axi_params.axi_opt = axi_oparray;
axi_params.axi_opt_size = ARRAY_SIZE(axi_oparray);
mmp_clk_parents_lookup(axi_params.parent_table,
axi_params.parent_table_size);
clk = mmp_clk_register_core("cpu", core_parent,
ARRAY_SIZE(core_parent), CLK_GET_RATE_NOCACHE,
0, &fc_seq_lock, &core_params);
clk_prepare_enable(clk);
mmp_clk_add(unit, PXA1U88_CLK_CPU, clk);
clk = mmp_clk_register_ddr("ddr", ddr_parent,
ARRAY_SIZE(ddr_parent), CLK_GET_RATE_NOCACHE,
0, &fc_seq_lock, &ddr_params);
mmp_clk_add(unit, PXA1U88_CLK_DDR, clk);
clk_prepare_enable(clk);
clk = mmp_clk_register_axi("axi", axi_parent,
ARRAY_SIZE(axi_parent), CLK_GET_RATE_NOCACHE,
0, &fc_seq_lock, &axi_params);
clk_prepare_enable(clk);
mmp_clk_add(unit, PXA1U88_CLK_AXI, clk);
register_clk_bind2ddr(clk,
axi_params.axi_opt[axi_params.axi_opt_size - 1].aclk * MHZ,
aclk_dclk_relationtbl_1U88,
ARRAY_SIZE(aclk_dclk_relationtbl_1U88));
}
static void __init pxa1U88_misc_init(struct pxa1U88_clk_unit *pxa_unit)
{
unsigned int val;
/* enable all MCK and AXI fabric dynamic clk gating */
val = __raw_readl(pxa_unit->ciu_base + CIU_MC_CONF);
/* enable dclk gating */
val &= ~(1 << 19);
/* enable 1x2 fabric AXI clock dynamic gating */
val |= (0xff << 8) | /* MCK5 P0~P7*/
(1 << 16) | /* CP 2x1 fabric*/
(1 << 17) | (1 << 18) | /* AP&CP */
(1 << 20) | (1 << 21) | /* SP&CSAP 2x1 fabric */
(1 << 26) | (1 << 27) | /* Fabric 0/1 */
(1 << 29) | (1 << 30); /* CA7 2x1 fabric */
__raw_writel(val, pxa_unit->ciu_base + CIU_MC_CONF);
/* TOP_MEM_RTC_WTC_SPD = 0xEE006656 */
__raw_writel(0xEE006656, pxa_unit->ciu_base + TOP_MEM_RTC_WTC_SPD);
/*enable HW-DVC and HW-DFC when CP is fast wakeup*/
val = __raw_readl(pxa_unit->apmu_base + APMU_DVC_DFC_DEBUG);
val |= (1 << 5);
__raw_writel(val, pxa_unit->apmu_base + APMU_DVC_DFC_DEBUG);
}
static void __init pxa1U88_clk_init(struct device_node *np)
{
struct pxa1U88_clk_unit *pxa_unit;
pxa_unit = kzalloc(sizeof(*pxa_unit), GFP_KERNEL);
if (!pxa_unit) {
pr_err("failed to allocate memory for pxa1U88 clock unit\n");
return;
}
pxa_unit->mpmu_base = of_iomap(np, 0);
if (!pxa_unit->mpmu_base) {
pr_err("failed to map mpmu registers\n");
goto err;
}
pxa_unit->apmu_base = of_iomap(np, 1);
if (!pxa_unit->apmu_base) {
pr_err("failed to map apmu registers\n");
goto err;
}
pxa_unit->apbc_base = of_iomap(np, 2);
if (!pxa_unit->apbc_base) {
pr_err("failed to map apbc registers\n");
goto err;
}
pxa_unit->apbcp_base = of_iomap(np, 3);
if (!pxa_unit->apbcp_base) {
pr_err("failed to map apbcp registers\n");
goto err;
}
pxa_unit->apbs_base = of_iomap(np, 4);
if (!pxa_unit->apbs_base) {
pr_err("failed to map apbs registers\n");
goto err;
}
pxa_unit->ciu_base = of_iomap(np, 5);
if (!pxa_unit->ciu_base) {
pr_err("failed to map ciu registers\n");
goto err;
}
mmp_clk_init(np, &pxa_unit->unit, PXA1U88_NR_CLKS);
pxa1U88_misc_init(pxa_unit);
pxa1U88_pll_init(pxa_unit);
if (!board_is_fpga())
pxa1U88_acpu_init(pxa_unit);
pxa1U88_apb_periph_clk_init(pxa_unit);
pxa1U88_axi_periph_clk_init(pxa_unit);
#ifdef CONFIG_SMC91X
if (board_is_fpga())
smc91x_clk_init(pxa_unit->apmu_base);
#endif
#if defined(CONFIG_PXA_DVFS)
if (!board_is_fpga())
setup_pxa1908_dvfs_platinfo();
#endif
#ifdef CONFIG_DEBUG_FS
globla_pxa_unit = pxa_unit;
#endif
return;
err:
kfree(pxa_unit);
}
CLK_OF_DECLARE(pxa1U88_clk, "marvell,pxa1U88-clock", pxa1U88_clk_init);
#ifdef CONFIG_DEBUG_FS
static struct dentry *stat;
CLK_DCSTAT_OPS(globla_pxa_unit->unit.clk_table[PXA1U88_CLK_DDR], ddr);
CLK_DCSTAT_OPS(globla_pxa_unit->unit.clk_table[PXA1U88_CLK_AXI], axi);
CLK_DCSTAT_OPS(globla_pxa_unit->unit.clk_table[PXA1U88_CLK_GC3D], gc);
CLK_DCSTAT_OPS(globla_pxa_unit->unit.clk_table[PXA1U88_CLK_GC2D], gc2d);
CLK_DCSTAT_OPS(globla_pxa_unit->unit.clk_table[PXA1U88_CLK_GCSH], gcsh);
CLK_DCSTAT_OPS(globla_pxa_unit->unit.clk_table[PXA1U88_CLK_VPU], vpu);
static int __init __init_pxa1u88_dcstat_debugfs_node(void)
{
struct dentry *cpu_dc_stat = NULL, *ddr_dc_stat = NULL;
struct dentry *axi_dc_stat = NULL;
struct dentry *gc_dc_stat = NULL, *vpu_dc_stat = NULL;
struct dentry *gc2d_dc_stat = NULL, *gcsh_dc_stat = NULL;
if (!cpu_is_pxa1908())
return 0;
stat = debugfs_create_dir("stat", pxa);
if (!stat)
return -ENOENT;
cpu_dc_stat = cpu_dcstat_file_create("cpu_dc_stat", stat);
if (!cpu_dc_stat)
goto err_cpu_dc_stat;
ddr_dc_stat = clk_dcstat_file_create("ddr_dc_stat", stat,
&ddr_dc_ops);
if (!ddr_dc_stat)
goto err_ddr_dc_stat;
axi_dc_stat = clk_dcstat_file_create("axi_dc_stat", stat,
&axi_dc_ops);
if (!axi_dc_stat)
goto err_axi_dc_stat;
gc_dc_stat = clk_dcstat_file_create("gc3d_core0_dc_stat",
stat, &gc_dc_ops);
if (!gc_dc_stat)
goto err_gc_dc_stat;
gc2d_dc_stat = clk_dcstat_file_create("gc2d_core0_dc_stat",
stat, &gc2d_dc_ops);
if (!gc2d_dc_stat)
goto err_gc2d_dc_stat;
gcsh_dc_stat = clk_dcstat_file_create("gcsh_core0_dc_stat",
stat, &gcsh_dc_ops);
if (!gcsh_dc_stat)
goto err_gcshader_dc_stat;
vpu_dc_stat = clk_dcstat_file_create("vpu_dc_stat",
stat, &vpu_dc_ops);
if (!vpu_dc_stat)
goto err_vpu_dc_stat;
return 0;
err_vpu_dc_stat:
debugfs_remove(gcsh_dc_stat);
err_gcshader_dc_stat:
debugfs_remove(gc2d_dc_stat);
err_gc2d_dc_stat:
debugfs_remove(gc_dc_stat);
err_gc_dc_stat:
debugfs_remove(axi_dc_stat);
err_axi_dc_stat:
debugfs_remove(ddr_dc_stat);
err_ddr_dc_stat:
debugfs_remove(cpu_dc_stat);
err_cpu_dc_stat:
debugfs_remove(stat);
return -ENOENT;
}
/* clock init is before debugfs_create_dir("pxa", NULL), so
* use arch_initcall init the pxa1u88 dcstat node.
*/
arch_initcall(__init_pxa1u88_dcstat_debugfs_node);
#endif