diff options
Diffstat (limited to 'drivers')
42 files changed, 6419 insertions, 1072 deletions
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 00b7344..26c3779d 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -704,7 +704,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, phys_addr_t sdramwins_phys_base, size_t sdramwins_size) { - struct device_node *np; int win; mbus->mbuswins_base = ioremap(mbuswins_phys_base, mbuswins_size); @@ -717,12 +716,6 @@ static int __init mvebu_mbus_common_init(struct mvebu_mbus_state *mbus, return -ENOMEM; } - np = of_find_compatible_node(NULL, NULL, "marvell,coherency-fabric"); - if (np) { - mbus->hw_io_coherency = 1; - of_node_put(np); - } - for (win = 0; win < mbus->soc->num_wins; win++) mvebu_mbus_disable_window(mbus, win); @@ -892,7 +885,7 @@ static void __init mvebu_mbus_get_pcie_resources(struct device_node *np, } } -int __init mvebu_mbus_dt_init(void) +int __init mvebu_mbus_dt_init(bool is_coherent) { struct resource mbuswins_res, sdramwins_res; struct device_node *np, *controller; @@ -930,6 +923,8 @@ int __init mvebu_mbus_dt_init(void) return -EINVAL; } + mbus_state.hw_io_coherency = is_coherent; + /* Get optional pcie-{mem,io}-aperture properties */ mvebu_mbus_get_pcie_resources(np, &mbus_state.pcie_mem_aperture, &mbus_state.pcie_io_aperture); diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 4fdfd6c..3a21964 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -108,3 +108,5 @@ endmenu source "drivers/clk/bcm/Kconfig" source "drivers/clk/mvebu/Kconfig" + +source "drivers/clk/samsung/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 5f8a287..17d7f13 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -41,7 +41,7 @@ obj-$(CONFIG_PLAT_ORION) += mvebu/ obj-$(CONFIG_ARCH_MXS) += mxs/ obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ -obj-$(CONFIG_PLAT_SAMSUNG) += samsung/ +obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/ obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ diff --git a/drivers/clk/at91/Makefile b/drivers/clk/at91/Makefile index 46c1d3d..4998aee 100644 --- a/drivers/clk/at91/Makefile +++ b/drivers/clk/at91/Makefile @@ -2,8 +2,8 @@ # Makefile for at91 specific clk # -obj-y += pmc.o -obj-y += clk-main.o clk-pll.o clk-plldiv.o clk-master.o +obj-y += pmc.o sckc.o +obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o obj-y += clk-system.o clk-peripheral.o clk-programmable.o obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index 8e9e8cc..7333061 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -30,99 +30,546 @@ #define MAINF_LOOP_MIN_WAIT (USEC_PER_SEC / SLOW_CLOCK_FREQ) #define MAINF_LOOP_MAX_WAIT MAINFRDY_TIMEOUT -struct clk_main { +#define MOR_KEY_MASK (0xff << 16) + +struct clk_main_osc { struct clk_hw hw; struct at91_pmc *pmc; - unsigned long rate; unsigned int irq; wait_queue_head_t wait; }; -#define to_clk_main(hw) container_of(hw, struct clk_main, hw) +#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw) + +struct clk_main_rc_osc { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + unsigned long frequency; + unsigned long accuracy; +}; + +#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw) + +struct clk_rm9200_main { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw) -static irqreturn_t clk_main_irq_handler(int irq, void *dev_id) +struct clk_sam9x5_main { + struct clk_hw hw; + struct at91_pmc *pmc; + unsigned int irq; + wait_queue_head_t wait; + u8 parent; +}; + +#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw) + +static irqreturn_t clk_main_osc_irq_handler(int irq, void *dev_id) { - struct clk_main *clkmain = (struct clk_main *)dev_id; + struct clk_main_osc *osc = dev_id; - wake_up(&clkmain->wait); - disable_irq_nosync(clkmain->irq); + wake_up(&osc->wait); + disable_irq_nosync(osc->irq); return IRQ_HANDLED; } -static int clk_main_prepare(struct clk_hw *hw) +static int clk_main_osc_prepare(struct clk_hw *hw) { - struct clk_main *clkmain = to_clk_main(hw); - struct at91_pmc *pmc = clkmain->pmc; - unsigned long halt_time, timeout; + struct clk_main_osc *osc = to_clk_main_osc(hw); + struct at91_pmc *pmc = osc->pmc; u32 tmp; + tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; + if (tmp & AT91_PMC_OSCBYPASS) + return 0; + + if (!(tmp & AT91_PMC_MOSCEN)) { + tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY; + pmc_write(pmc, AT91_CKGR_MOR, tmp); + } + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS)) { - enable_irq(clkmain->irq); - wait_event(clkmain->wait, + enable_irq(osc->irq); + wait_event(osc->wait, pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); } - if (clkmain->rate) - return 0; + return 0; +} + +static void clk_main_osc_unprepare(struct clk_hw *hw) +{ + struct clk_main_osc *osc = to_clk_main_osc(hw); + struct at91_pmc *pmc = osc->pmc; + u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); + + if (tmp & AT91_PMC_OSCBYPASS) + return; + + if (!(tmp & AT91_PMC_MOSCEN)) + return; + + tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN); + pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); +} + +static int clk_main_osc_is_prepared(struct clk_hw *hw) +{ + struct clk_main_osc *osc = to_clk_main_osc(hw); + struct at91_pmc *pmc = osc->pmc; + u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); + + if (tmp & AT91_PMC_OSCBYPASS) + return 1; + + return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCS) && + (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN)); +} + +static const struct clk_ops main_osc_ops = { + .prepare = clk_main_osc_prepare, + .unprepare = clk_main_osc_unprepare, + .is_prepared = clk_main_osc_is_prepared, +}; + +static struct clk * __init +at91_clk_register_main_osc(struct at91_pmc *pmc, + unsigned int irq, + const char *name, + const char *parent_name, + bool bypass) +{ + int ret; + struct clk_main_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name || !parent_name) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); + if (!osc) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &main_osc_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_IGNORE_UNUSED; + + osc->hw.init = &init; + osc->pmc = pmc; + osc->irq = irq; + + init_waitqueue_head(&osc->wait); + irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); + ret = request_irq(osc->irq, clk_main_osc_irq_handler, + IRQF_TRIGGER_HIGH, name, osc); + if (ret) + return ERR_PTR(ret); + + if (bypass) + pmc_write(pmc, AT91_CKGR_MOR, + (pmc_read(pmc, AT91_CKGR_MOR) & + ~(MOR_KEY_MASK | AT91_PMC_MOSCEN)) | + AT91_PMC_OSCBYPASS | AT91_PMC_KEY); + + clk = clk_register(NULL, &osc->hw); + if (IS_ERR(clk)) { + free_irq(irq, osc); + kfree(osc); + } + + return clk; +} + +void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + unsigned int irq; + const char *name = np->name; + const char *parent_name; + bool bypass; + + of_property_read_string(np, "clock-output-names", &name); + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + parent_name = of_clk_get_parent_name(np, 0); + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_main_osc(pmc, irq, name, parent_name, bypass); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +static irqreturn_t clk_main_rc_osc_irq_handler(int irq, void *dev_id) +{ + struct clk_main_rc_osc *osc = dev_id; + + wake_up(&osc->wait); + disable_irq_nosync(osc->irq); + + return IRQ_HANDLED; +} + +static int clk_main_rc_osc_prepare(struct clk_hw *hw) +{ + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); + struct at91_pmc *pmc = osc->pmc; + u32 tmp; + + tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; + + if (!(tmp & AT91_PMC_MOSCRCEN)) { + tmp |= AT91_PMC_MOSCRCEN | AT91_PMC_KEY; + pmc_write(pmc, AT91_CKGR_MOR, tmp); + } + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS)) { + enable_irq(osc->irq); + wait_event(osc->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS); + } + + return 0; +} + +static void clk_main_rc_osc_unprepare(struct clk_hw *hw) +{ + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); + struct at91_pmc *pmc = osc->pmc; + u32 tmp = pmc_read(pmc, AT91_CKGR_MOR); + + if (!(tmp & AT91_PMC_MOSCRCEN)) + return; + + tmp &= ~(MOR_KEY_MASK | AT91_PMC_MOSCRCEN); + pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_KEY); +} + +static int clk_main_rc_osc_is_prepared(struct clk_hw *hw) +{ + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); + struct at91_pmc *pmc = osc->pmc; + + return !!((pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCRCS) && + (pmc_read(pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCRCEN)); +} + +static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); + + return osc->frequency; +} + +static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_acc) +{ + struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw); + + return osc->accuracy; +} + +static const struct clk_ops main_rc_osc_ops = { + .prepare = clk_main_rc_osc_prepare, + .unprepare = clk_main_rc_osc_unprepare, + .is_prepared = clk_main_rc_osc_is_prepared, + .recalc_rate = clk_main_rc_osc_recalc_rate, + .recalc_accuracy = clk_main_rc_osc_recalc_accuracy, +}; + +static struct clk * __init +at91_clk_register_main_rc_osc(struct at91_pmc *pmc, + unsigned int irq, + const char *name, + u32 frequency, u32 accuracy) +{ + int ret; + struct clk_main_rc_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !irq || !name || !frequency) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); + if (!osc) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &main_rc_osc_ops; + init.parent_names = NULL; + init.num_parents = 0; + init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED; + + osc->hw.init = &init; + osc->pmc = pmc; + osc->irq = irq; + osc->frequency = frequency; + osc->accuracy = accuracy; + + init_waitqueue_head(&osc->wait); + irq_set_status_flags(osc->irq, IRQ_NOAUTOEN); + ret = request_irq(osc->irq, clk_main_rc_osc_irq_handler, + IRQF_TRIGGER_HIGH, name, osc); + if (ret) + return ERR_PTR(ret); + + clk = clk_register(NULL, &osc->hw); + if (IS_ERR(clk)) { + free_irq(irq, osc); + kfree(osc); + } + + return clk; +} + +void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + unsigned int irq; + u32 frequency = 0; + u32 accuracy = 0; + const char *name = np->name; + + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "clock-frequency", &frequency); + of_property_read_u32(np, "clock-accuracy", &accuracy); + + irq = irq_of_parse_and_map(np, 0); + if (!irq) + return; + + clk = at91_clk_register_main_rc_osc(pmc, irq, name, frequency, + accuracy); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + + +static int clk_main_probe_frequency(struct at91_pmc *pmc) +{ + unsigned long prep_time, timeout; + u32 tmp; timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT); do { - halt_time = jiffies; + prep_time = jiffies; tmp = pmc_read(pmc, AT91_CKGR_MCFR); if (tmp & AT91_PMC_MAINRDY) return 0; usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT); - } while (time_before(halt_time, timeout)); + } while (time_before(prep_time, timeout)); - return 0; + return -ETIMEDOUT; } -static int clk_main_is_prepared(struct clk_hw *hw) +static unsigned long clk_main_recalc_rate(struct at91_pmc *pmc, + unsigned long parent_rate) { - struct clk_main *clkmain = to_clk_main(hw); + u32 tmp; + + if (parent_rate) + return parent_rate; + + tmp = pmc_read(pmc, AT91_CKGR_MCFR); + if (!(tmp & AT91_PMC_MAINRDY)) + return 0; - return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCS); + return ((tmp & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV; } -static unsigned long clk_main_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) +static int clk_rm9200_main_prepare(struct clk_hw *hw) { - u32 tmp; - struct clk_main *clkmain = to_clk_main(hw); + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); + + return clk_main_probe_frequency(clkmain->pmc); +} + +static int clk_rm9200_main_is_prepared(struct clk_hw *hw) +{ + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); + + return !!(pmc_read(clkmain->pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINRDY); +} + +static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw); + + return clk_main_recalc_rate(clkmain->pmc, parent_rate); +} + +static const struct clk_ops rm9200_main_ops = { + .prepare = clk_rm9200_main_prepare, + .is_prepared = clk_rm9200_main_is_prepared, + .recalc_rate = clk_rm9200_main_recalc_rate, +}; + +static struct clk * __init +at91_clk_register_rm9200_main(struct at91_pmc *pmc, + const char *name, + const char *parent_name) +{ + struct clk_rm9200_main *clkmain; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name) + return ERR_PTR(-EINVAL); + + if (!parent_name) + return ERR_PTR(-EINVAL); + + clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); + if (!clkmain) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &rm9200_main_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = 0; + + clkmain->hw.init = &init; + clkmain->pmc = pmc; + + clk = clk_register(NULL, &clkmain->hw); + if (IS_ERR(clk)) + kfree(clkmain); + + return clk; +} + +void __init of_at91rm9200_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + + parent_name = of_clk_get_parent_name(np, 0); + of_property_read_string(np, "clock-output-names", &name); + + clk = at91_clk_register_rm9200_main(pmc, name, parent_name); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +static irqreturn_t clk_sam9x5_main_irq_handler(int irq, void *dev_id) +{ + struct clk_sam9x5_main *clkmain = dev_id; + + wake_up(&clkmain->wait); + disable_irq_nosync(clkmain->irq); + + return IRQ_HANDLED; +} + +static int clk_sam9x5_main_prepare(struct clk_hw *hw) +{ + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); struct at91_pmc *pmc = clkmain->pmc; - if (clkmain->rate) - return clkmain->rate; + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { + enable_irq(clkmain->irq); + wait_event(clkmain->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); + } + + return clk_main_probe_frequency(pmc); +} - tmp = pmc_read(pmc, AT91_CKGR_MCFR) & AT91_PMC_MAINF; - clkmain->rate = (tmp * parent_rate) / MAINF_DIV; +static int clk_sam9x5_main_is_prepared(struct clk_hw *hw) +{ + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); - return clkmain->rate; + return !!(pmc_read(clkmain->pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); } -static const struct clk_ops main_ops = { - .prepare = clk_main_prepare, - .is_prepared = clk_main_is_prepared, - .recalc_rate = clk_main_recalc_rate, +static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); + + return clk_main_recalc_rate(clkmain->pmc, parent_rate); +} + +static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); + struct at91_pmc *pmc = clkmain->pmc; + u32 tmp; + + if (index > 1) + return -EINVAL; + + tmp = pmc_read(pmc, AT91_CKGR_MOR) & ~MOR_KEY_MASK; + + if (index && !(tmp & AT91_PMC_MOSCSEL)) + pmc_write(pmc, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); + else if (!index && (tmp & AT91_PMC_MOSCSEL)) + pmc_write(pmc, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); + + while (!(pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS)) { + enable_irq(clkmain->irq); + wait_event(clkmain->wait, + pmc_read(pmc, AT91_PMC_SR) & AT91_PMC_MOSCSELS); + } + + return 0; +} + +static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw) +{ + struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw); + + return !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & AT91_PMC_MOSCEN); +} + +static const struct clk_ops sam9x5_main_ops = { + .prepare = clk_sam9x5_main_prepare, + .is_prepared = clk_sam9x5_main_is_prepared, + .recalc_rate = clk_sam9x5_main_recalc_rate, + .set_parent = clk_sam9x5_main_set_parent, + .get_parent = clk_sam9x5_main_get_parent, }; static struct clk * __init -at91_clk_register_main(struct at91_pmc *pmc, - unsigned int irq, - const char *name, - const char *parent_name, - unsigned long rate) +at91_clk_register_sam9x5_main(struct at91_pmc *pmc, + unsigned int irq, + const char *name, + const char **parent_names, + int num_parents) { int ret; - struct clk_main *clkmain; + struct clk_sam9x5_main *clkmain; struct clk *clk = NULL; struct clk_init_data init; if (!pmc || !irq || !name) return ERR_PTR(-EINVAL); - if (!rate && !parent_name) + if (!parent_names || !num_parents) return ERR_PTR(-EINVAL); clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL); @@ -130,19 +577,20 @@ at91_clk_register_main(struct at91_pmc *pmc, return ERR_PTR(-ENOMEM); init.name = name; - init.ops = &main_ops; - init.parent_names = parent_name ? &parent_name : NULL; - init.num_parents = parent_name ? 1 : 0; - init.flags = parent_name ? 0 : CLK_IS_ROOT; + init.ops = &sam9x5_main_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = CLK_SET_PARENT_GATE; clkmain->hw.init = &init; - clkmain->rate = rate; clkmain->pmc = pmc; clkmain->irq = irq; + clkmain->parent = !!(pmc_read(clkmain->pmc, AT91_CKGR_MOR) & + AT91_PMC_MOSCEN); init_waitqueue_head(&clkmain->wait); irq_set_status_flags(clkmain->irq, IRQ_NOAUTOEN); - ret = request_irq(clkmain->irq, clk_main_irq_handler, - IRQF_TRIGGER_HIGH, "clk-main", clkmain); + ret = request_irq(clkmain->irq, clk_sam9x5_main_irq_handler, + IRQF_TRIGGER_HIGH, name, clkmain); if (ret) return ERR_PTR(ret); @@ -155,33 +603,36 @@ at91_clk_register_main(struct at91_pmc *pmc, return clk; } - - -static void __init -of_at91_clk_main_setup(struct device_node *np, struct at91_pmc *pmc) +void __init of_at91sam9x5_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc) { struct clk *clk; + const char *parent_names[2]; + int num_parents; unsigned int irq; - const char *parent_name; const char *name = np->name; - u32 rate = 0; + int i; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > 2) + return; + + for (i = 0; i < num_parents; ++i) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } - parent_name = of_clk_get_parent_name(np, 0); of_property_read_string(np, "clock-output-names", &name); - of_property_read_u32(np, "clock-frequency", &rate); + irq = irq_of_parse_and_map(np, 0); if (!irq) return; - clk = at91_clk_register_main(pmc, irq, name, parent_name, rate); + clk = at91_clk_register_sam9x5_main(pmc, irq, name, parent_names, + num_parents); if (IS_ERR(clk)) return; of_clk_add_provider(np, of_clk_src_simple_get, clk); } - -void __init of_at91rm9200_clk_main_setup(struct device_node *np, - struct at91_pmc *pmc) -{ - of_at91_clk_main_setup(np, pmc); -} diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c new file mode 100644 index 0000000..0300c46 --- /dev/null +++ b/drivers/clk/at91/clk-slow.c @@ -0,0 +1,467 @@ +/* + * drivers/clk/at91/clk-slow.c + * + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/clk/at91_pmc.h> +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/io.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <linux/sched.h> +#include <linux/wait.h> + +#include "pmc.h" +#include "sckc.h" + +#define SLOW_CLOCK_FREQ 32768 +#define SLOWCK_SW_CYCLES 5 +#define SLOWCK_SW_TIME_USEC ((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \ + SLOW_CLOCK_FREQ) + +#define AT91_SCKC_CR 0x00 +#define AT91_SCKC_RCEN (1 << 0) +#define AT91_SCKC_OSC32EN (1 << 1) +#define AT91_SCKC_OSC32BYP (1 << 2) +#define AT91_SCKC_OSCSEL (1 << 3) + +struct clk_slow_osc { + struct clk_hw hw; + void __iomem *sckcr; + unsigned long startup_usec; +}; + +#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw) + +struct clk_slow_rc_osc { + struct clk_hw hw; + void __iomem *sckcr; + unsigned long frequency; + unsigned long accuracy; + unsigned long startup_usec; +}; + +#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw) + +struct clk_sam9260_slow { + struct clk_hw hw; + struct at91_pmc *pmc; +}; + +#define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw) + +struct clk_sam9x5_slow { + struct clk_hw hw; + void __iomem *sckcr; + u8 parent; +}; + +#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw) + + +static int clk_slow_osc_prepare(struct clk_hw *hw) +{ + struct clk_slow_osc *osc = to_clk_slow_osc(hw); + void __iomem *sckcr = osc->sckcr; + u32 tmp = readl(sckcr); + + if (tmp & AT91_SCKC_OSC32BYP) + return 0; + + writel(tmp | AT91_SCKC_OSC32EN, sckcr); + + usleep_range(osc->startup_usec, osc->startup_usec + 1); + + return 0; +} + +static void clk_slow_osc_unprepare(struct clk_hw *hw) +{ + struct clk_slow_osc *osc = to_clk_slow_osc(hw); + void __iomem *sckcr = osc->sckcr; + u32 tmp = readl(sckcr); + + if (tmp & AT91_SCKC_OSC32BYP) + return; + + writel(tmp & ~AT91_SCKC_OSC32EN, sckcr); +} + +static int clk_slow_osc_is_prepared(struct clk_hw *hw) +{ + struct clk_slow_osc *osc = to_clk_slow_osc(hw); + void __iomem *sckcr = osc->sckcr; + u32 tmp = readl(sckcr); + + if (tmp & AT91_SCKC_OSC32BYP) + return 1; + + return !!(tmp & AT91_SCKC_OSC32EN); +} + +static const struct clk_ops slow_osc_ops = { + .prepare = clk_slow_osc_prepare, + .unprepare = clk_slow_osc_unprepare, + .is_prepared = clk_slow_osc_is_prepared, +}; + +static struct clk * __init +at91_clk_register_slow_osc(void __iomem *sckcr, + const char *name, + const char *parent_name, + unsigned long startup, + bool bypass) +{ + struct clk_slow_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!sckcr || !name || !parent_name) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); + if (!osc) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &slow_osc_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + init.flags = CLK_IGNORE_UNUSED; + + osc->hw.init = &init; + osc->sckcr = sckcr; + osc->startup_usec = startup; + + if (bypass) + writel((readl(sckcr) & ~AT91_SCKC_OSC32EN) | AT91_SCKC_OSC32BYP, + sckcr); + + clk = clk_register(NULL, &osc->hw); + if (IS_ERR(clk)) + kfree(osc); + + return clk; +} + +void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, + void __iomem *sckcr) +{ + struct clk *clk; + const char *parent_name; + const char *name = np->name; + u32 startup; + bool bypass; + + parent_name = of_clk_get_parent_name(np, 0); + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "atmel,startup-time-usec", &startup); + bypass = of_property_read_bool(np, "atmel,osc-bypass"); + + clk = at91_clk_register_slow_osc(sckcr, name, parent_name, startup, + bypass); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + + return osc->frequency; +} + +static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_acc) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + + return osc->accuracy; +} + +static int clk_slow_rc_osc_prepare(struct clk_hw *hw) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + void __iomem *sckcr = osc->sckcr; + + writel(readl(sckcr) | AT91_SCKC_RCEN, sckcr); + + usleep_range(osc->startup_usec, osc->startup_usec + 1); + + return 0; +} + +static void clk_slow_rc_osc_unprepare(struct clk_hw *hw) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + void __iomem *sckcr = osc->sckcr; + + writel(readl(sckcr) & ~AT91_SCKC_RCEN, sckcr); +} + +static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw) +{ + struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw); + + return !!(readl(osc->sckcr) & AT91_SCKC_RCEN); +} + +static const struct clk_ops slow_rc_osc_ops = { + .prepare = clk_slow_rc_osc_prepare, + .unprepare = clk_slow_rc_osc_unprepare, + .is_prepared = clk_slow_rc_osc_is_prepared, + .recalc_rate = clk_slow_rc_osc_recalc_rate, + .recalc_accuracy = clk_slow_rc_osc_recalc_accuracy, +}; + +static struct clk * __init +at91_clk_register_slow_rc_osc(void __iomem *sckcr, + const char *name, + unsigned long frequency, + unsigned long accuracy, + unsigned long startup) +{ + struct clk_slow_rc_osc *osc; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!sckcr || !name) + return ERR_PTR(-EINVAL); + + osc = kzalloc(sizeof(*osc), GFP_KERNEL); + if (!osc) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &slow_rc_osc_ops; + init.parent_names = NULL; + init.num_parents = 0; + init.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED; + + osc->hw.init = &init; + osc->sckcr = sckcr; + osc->frequency = frequency; + osc->accuracy = accuracy; + osc->startup_usec = startup; + + clk = clk_register(NULL, &osc->hw); + if (IS_ERR(clk)) + kfree(osc); + + return clk; +} + +void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, + void __iomem *sckcr) +{ + struct clk *clk; + u32 frequency = 0; + u32 accuracy = 0; + u32 startup = 0; + const char *name = np->name; + + of_property_read_string(np, "clock-output-names", &name); + of_property_read_u32(np, "clock-frequency", &frequency); + of_property_read_u32(np, "clock-accuracy", &accuracy); + of_property_read_u32(np, "atmel,startup-time-usec", &startup); + + clk = at91_clk_register_slow_rc_osc(sckcr, name, frequency, accuracy, + startup); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); + void __iomem *sckcr = slowck->sckcr; + u32 tmp; + + if (index > 1) + return -EINVAL; + + tmp = readl(sckcr); + + if ((!index && !(tmp & AT91_SCKC_OSCSEL)) || + (index && (tmp & AT91_SCKC_OSCSEL))) + return 0; + + if (index) + tmp |= AT91_SCKC_OSCSEL; + else + tmp &= ~AT91_SCKC_OSCSEL; + + writel(tmp, sckcr); + + usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1); + + return 0; +} + +static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw) +{ + struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw); + + return !!(readl(slowck->sckcr) & AT91_SCKC_OSCSEL); +} + +static const struct clk_ops sam9x5_slow_ops = { + .set_parent = clk_sam9x5_slow_set_parent, + .get_parent = clk_sam9x5_slow_get_parent, +}; + +static struct clk * __init +at91_clk_register_sam9x5_slow(void __iomem *sckcr, + const char *name, + const char **parent_names, + int num_parents) +{ + struct clk_sam9x5_slow *slowck; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!sckcr || !name || !parent_names || !num_parents) + return ERR_PTR(-EINVAL); + + slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); + if (!slowck) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &sam9x5_slow_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = 0; + + slowck->hw.init = &init; + slowck->sckcr = sckcr; + slowck->parent = !!(readl(sckcr) & AT91_SCKC_OSCSEL); + + clk = clk_register(NULL, &slowck->hw); + if (IS_ERR(clk)) + kfree(slowck); + + return clk; +} + +void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, + void __iomem *sckcr) +{ + struct clk *clk; + const char *parent_names[2]; + int num_parents; + const char *name = np->name; + int i; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > 2) + return; + + for (i = 0; i < num_parents; ++i) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91_clk_register_sam9x5_slow(sckcr, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} + +static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw) +{ + struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw); + + return !!(pmc_read(slowck->pmc, AT91_PMC_SR) & AT91_PMC_OSCSEL); +} + +static const struct clk_ops sam9260_slow_ops = { + .get_parent = clk_sam9260_slow_get_parent, +}; + +static struct clk * __init +at91_clk_register_sam9260_slow(struct at91_pmc *pmc, + const char *name, + const char **parent_names, + int num_parents) +{ + struct clk_sam9260_slow *slowck; + struct clk *clk = NULL; + struct clk_init_data init; + + if (!pmc || !name) + return ERR_PTR(-EINVAL); + + if (!parent_names || !num_parents) + return ERR_PTR(-EINVAL); + + slowck = kzalloc(sizeof(*slowck), GFP_KERNEL); + if (!slowck) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &sam9260_slow_ops; + init.parent_names = parent_names; + init.num_parents = num_parents; + init.flags = 0; + + slowck->hw.init = &init; + slowck->pmc = pmc; + + clk = clk_register(NULL, &slowck->hw); + if (IS_ERR(clk)) + kfree(slowck); + + return clk; +} + +void __init of_at91sam9260_clk_slow_setup(struct device_node *np, + struct at91_pmc *pmc) +{ + struct clk *clk; + const char *parent_names[2]; + int num_parents; + const char *name = np->name; + int i; + + num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + if (num_parents <= 0 || num_parents > 1) + return; + + for (i = 0; i < num_parents; ++i) { + parent_names[i] = of_clk_get_parent_name(np, i); + if (!parent_names[i]) + return; + } + + of_property_read_string(np, "clock-output-names", &name); + + clk = at91_clk_register_sam9260_slow(pmc, name, parent_names, + num_parents); + if (IS_ERR(clk)) + return; + + of_clk_add_provider(np, of_clk_src_simple_get, clk); +} diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c index 6a61477..524196b 100644 --- a/drivers/clk/at91/pmc.c +++ b/drivers/clk/at91/pmc.c @@ -229,11 +229,28 @@ out_free_pmc: } static const struct of_device_id pmc_clk_ids[] __initconst = { + /* Slow oscillator */ + { + .compatible = "atmel,at91sam9260-clk-slow", + .data = of_at91sam9260_clk_slow_setup, + }, /* Main clock */ { + .compatible = "atmel,at91rm9200-clk-main-osc", + .data = of_at91rm9200_clk_main_osc_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-main-rc-osc", + .data = of_at91sam9x5_clk_main_rc_osc_setup, + }, + { .compatible = "atmel,at91rm9200-clk-main", .data = of_at91rm9200_clk_main_setup, }, + { + .compatible = "atmel,at91sam9x5-clk-main", + .data = of_at91sam9x5_clk_main_setup, + }, /* PLL clocks */ { .compatible = "atmel,at91rm9200-clk-pll", diff --git a/drivers/clk/at91/pmc.h b/drivers/clk/at91/pmc.h index 4413509..6c76259 100644 --- a/drivers/clk/at91/pmc.h +++ b/drivers/clk/at91/pmc.h @@ -58,8 +58,17 @@ static inline void pmc_write(struct at91_pmc *pmc, int offset, u32 value) int of_at91_get_clk_range(struct device_node *np, const char *propname, struct clk_range *range); +extern void __init of_at91sam9260_clk_slow_setup(struct device_node *np, + struct at91_pmc *pmc); + +extern void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np, + struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np, + struct at91_pmc *pmc); extern void __init of_at91rm9200_clk_main_setup(struct device_node *np, struct at91_pmc *pmc); +extern void __init of_at91sam9x5_clk_main_setup(struct device_node *np, + struct at91_pmc *pmc); extern void __init of_at91rm9200_clk_pll_setup(struct device_node *np, struct at91_pmc *pmc); diff --git a/drivers/clk/at91/sckc.c b/drivers/clk/at91/sckc.c new file mode 100644 index 0000000..1184d76 --- /dev/null +++ b/drivers/clk/at91/sckc.c @@ -0,0 +1,57 @@ +/* + * drivers/clk/at91/sckc.c + * + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/clk-provider.h> +#include <linux/clkdev.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/io.h> + +#include "sckc.h" + +static const struct of_device_id sckc_clk_ids[] __initconst = { + /* Slow clock */ + { + .compatible = "atmel,at91sam9x5-clk-slow-osc", + .data = of_at91sam9x5_clk_slow_osc_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-slow-rc-osc", + .data = of_at91sam9x5_clk_slow_rc_osc_setup, + }, + { + .compatible = "atmel,at91sam9x5-clk-slow", + .data = of_at91sam9x5_clk_slow_setup, + }, + { /*sentinel*/ } +}; + +static void __init of_at91sam9x5_sckc_setup(struct device_node *np) +{ + struct device_node *childnp; + void (*clk_setup)(struct device_node *, void __iomem *); + const struct of_device_id *clk_id; + void __iomem *regbase = of_iomap(np, 0); + + if (!regbase) + return; + + for_each_child_of_node(np, childnp) { + clk_id = of_match_node(sckc_clk_ids, childnp); + if (!clk_id) + continue; + clk_setup = clk_id->data; + clk_setup(childnp, regbase); + } +} +CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc", + of_at91sam9x5_sckc_setup); diff --git a/drivers/clk/at91/sckc.h b/drivers/clk/at91/sckc.h new file mode 100644 index 0000000..836fcf5 --- /dev/null +++ b/drivers/clk/at91/sckc.h @@ -0,0 +1,22 @@ +/* + * drivers/clk/at91/sckc.h + * + * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __AT91_SCKC_H_ +#define __AT91_SCKC_H_ + +extern void __init of_at91sam9x5_clk_slow_osc_setup(struct device_node *np, + void __iomem *sckcr); +extern void __init of_at91sam9x5_clk_slow_rc_osc_setup(struct device_node *np, + void __iomem *sckcr); +extern void __init of_at91sam9x5_clk_slow_setup(struct device_node *np, + void __iomem *sckcr); + +#endif /* __AT91_SCKC_H_ */ diff --git a/drivers/clk/samsung/Kconfig b/drivers/clk/samsung/Kconfig new file mode 100644 index 0000000..84196ec --- /dev/null +++ b/drivers/clk/samsung/Kconfig @@ -0,0 +1,26 @@ +config COMMON_CLK_SAMSUNG + bool + select COMMON_CLK + +config S3C2410_COMMON_CLK + bool + select COMMON_CLK_SAMSUNG + help + Build the s3c2410 clock driver based on the common clock framework. + +config S3C2410_COMMON_DCLK + bool + select COMMON_CLK_SAMSUNG + select REGMAP_MMIO + help + Temporary symbol to build the dclk driver based on the common clock + framework. + +config S3C2412_COMMON_CLK + bool + select COMMON_CLK_SAMSUNG + +config S3C2443_COMMON_CLK + bool + select COMMON_CLK_SAMSUNG + diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile index 2cb62f8..69e8177 100644 --- a/drivers/clk/samsung/Makefile +++ b/drivers/clk/samsung/Makefile @@ -3,8 +3,11 @@ # obj-$(CONFIG_COMMON_CLK) += clk.o clk-pll.o +obj-$(CONFIG_SOC_EXYNOS3250) += clk-exynos3250.o obj-$(CONFIG_ARCH_EXYNOS4) += clk-exynos4.o obj-$(CONFIG_SOC_EXYNOS5250) += clk-exynos5250.o +obj-$(CONFIG_SOC_EXYNOS5260) += clk-exynos5260.o +obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-audss.o diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c new file mode 100644 index 0000000..7a17bd4 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -0,0 +1,780 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for Exynos3250 SoC. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> +#include <linux/syscore_ops.h> + +#include <dt-bindings/clock/exynos3250.h> + +#include "clk.h" +#include "clk-pll.h" + +#define SRC_LEFTBUS 0x4200 +#define DIV_LEFTBUS 0x4500 +#define GATE_IP_LEFTBUS 0x4800 +#define SRC_RIGHTBUS 0x8200 +#define DIV_RIGHTBUS 0x8500 +#define GATE_IP_RIGHTBUS 0x8800 +#define GATE_IP_PERIR 0x8960 +#define MPLL_LOCK 0xc010 +#define MPLL_CON0 0xc110 +#define VPLL_LOCK 0xc020 +#define VPLL_CON0 0xc120 +#define UPLL_LOCK 0xc030 +#define UPLL_CON0 0xc130 +#define SRC_TOP0 0xc210 +#define SRC_TOP1 0xc214 +#define SRC_CAM 0xc220 +#define SRC_MFC 0xc228 +#define SRC_G3D 0xc22c +#define SRC_LCD 0xc234 +#define SRC_ISP 0xc238 +#define SRC_FSYS 0xc240 +#define SRC_PERIL0 0xc250 +#define SRC_PERIL1 0xc254 +#define SRC_MASK_TOP 0xc310 +#define SRC_MASK_CAM 0xc320 +#define SRC_MASK_LCD 0xc334 +#define SRC_MASK_ISP 0xc338 +#define SRC_MASK_FSYS 0xc340 +#define SRC_MASK_PERIL0 0xc350 +#define SRC_MASK_PERIL1 0xc354 +#define DIV_TOP 0xc510 +#define DIV_CAM 0xc520 +#define DIV_MFC 0xc528 +#define DIV_G3D 0xc52c +#define DIV_LCD 0xc534 +#define DIV_ISP 0xc538 +#define DIV_FSYS0 0xc540 +#define DIV_FSYS1 0xc544 +#define DIV_FSYS2 0xc548 +#define DIV_PERIL0 0xc550 +#define DIV_PERIL1 0xc554 +#define DIV_PERIL3 0xc55c +#define DIV_PERIL4 0xc560 +#define DIV_PERIL5 0xc564 +#define DIV_CAM1 0xc568 +#define CLKDIV2_RATIO 0xc580 +#define GATE_SCLK_CAM 0xc820 +#define GATE_SCLK_MFC 0xc828 +#define GATE_SCLK_G3D 0xc82c +#define GATE_SCLK_LCD 0xc834 +#define GATE_SCLK_ISP_TOP 0xc838 +#define GATE_SCLK_FSYS 0xc840 +#define GATE_SCLK_PERIL 0xc850 +#define GATE_IP_CAM 0xc920 +#define GATE_IP_MFC 0xc928 +#define GATE_IP_G3D 0xc92c +#define GATE_IP_LCD 0xc934 +#define GATE_IP_ISP 0xc938 +#define GATE_IP_FSYS 0xc940 +#define GATE_IP_PERIL 0xc950 +#define GATE_BLOCK 0xc970 +#define APLL_LOCK 0x14000 +#define APLL_CON0 0x14100 +#define SRC_CPU 0x14200 +#define DIV_CPU0 0x14500 +#define DIV_CPU1 0x14504 + +/* list of PLLs to be registered */ +enum exynos3250_plls { + apll, mpll, vpll, upll, + nr_plls +}; + +static void __iomem *reg_base; + +/* + * Support for CMU save/restore across system suspends + */ +#ifdef CONFIG_PM_SLEEP +static struct samsung_clk_reg_dump *exynos3250_clk_regs; + +static unsigned long exynos3250_cmu_clk_regs[] __initdata = { + SRC_LEFTBUS, + DIV_LEFTBUS, + GATE_IP_LEFTBUS, + SRC_RIGHTBUS, + DIV_RIGHTBUS, + GATE_IP_RIGHTBUS, + GATE_IP_PERIR, + MPLL_LOCK, + MPLL_CON0, + VPLL_LOCK, + VPLL_CON0, + UPLL_LOCK, + UPLL_CON0, + SRC_TOP0, + SRC_TOP1, + SRC_CAM, + SRC_MFC, + SRC_G3D, + SRC_LCD, + SRC_ISP, + SRC_FSYS, + SRC_PERIL0, + SRC_PERIL1, + SRC_MASK_TOP, + SRC_MASK_CAM, + SRC_MASK_LCD, + SRC_MASK_ISP, + SRC_MASK_FSYS, + SRC_MASK_PERIL0, + SRC_MASK_PERIL1, + DIV_TOP, + DIV_CAM, + DIV_MFC, + DIV_G3D, + DIV_LCD, + DIV_ISP, + DIV_FSYS0, + DIV_FSYS1, + DIV_FSYS2, + DIV_PERIL0, + DIV_PERIL1, + DIV_PERIL3, + DIV_PERIL4, + DIV_PERIL5, + DIV_CAM1, + CLKDIV2_RATIO, + GATE_SCLK_CAM, + GATE_SCLK_MFC, + GATE_SCLK_G3D, + GATE_SCLK_LCD, + GATE_SCLK_ISP_TOP, + GATE_SCLK_FSYS, + GATE_SCLK_PERIL, + GATE_IP_CAM, + GATE_IP_MFC, + GATE_IP_G3D, + GATE_IP_LCD, + GATE_IP_ISP, + GATE_IP_FSYS, + GATE_IP_PERIL, + GATE_BLOCK, + APLL_LOCK, + SRC_CPU, + DIV_CPU0, + DIV_CPU1, +}; + +static int exynos3250_clk_suspend(void) +{ + samsung_clk_save(reg_base, exynos3250_clk_regs, + ARRAY_SIZE(exynos3250_cmu_clk_regs)); + return 0; +} + +static void exynos3250_clk_resume(void) +{ + samsung_clk_restore(reg_base, exynos3250_clk_regs, + ARRAY_SIZE(exynos3250_cmu_clk_regs)); +} + +static struct syscore_ops exynos3250_clk_syscore_ops = { + .suspend = exynos3250_clk_suspend, + .resume = exynos3250_clk_resume, +}; + +static void exynos3250_clk_sleep_init(void) +{ + exynos3250_clk_regs = + samsung_clk_alloc_reg_dump(exynos3250_cmu_clk_regs, + ARRAY_SIZE(exynos3250_cmu_clk_regs)); + if (!exynos3250_clk_regs) { + pr_warn("%s: Failed to allocate sleep save data\n", __func__); + goto err; + } + + register_syscore_ops(&exynos3250_clk_syscore_ops); + return; +err: + kfree(exynos3250_clk_regs); +} +#else +static inline void exynos3250_clk_sleep_init(void) { } +#endif + +/* list of all parent clock list */ +PNAME(mout_vpllsrc_p) = { "fin_pll", }; + +PNAME(mout_apll_p) = { "fin_pll", "fout_apll", }; +PNAME(mout_mpll_p) = { "fin_pll", "fout_mpll", }; +PNAME(mout_vpll_p) = { "fin_pll", "fout_vpll", }; +PNAME(mout_upll_p) = { "fin_pll", "fout_upll", }; + +PNAME(mout_mpll_user_p) = { "fin_pll", "div_mpll_pre", }; +PNAME(mout_epll_user_p) = { "fin_pll", "mout_epll", }; +PNAME(mout_core_p) = { "mout_apll", "mout_mpll_user_c", }; +PNAME(mout_hpm_p) = { "mout_apll", "mout_mpll_user_c", }; + +PNAME(mout_ebi_p) = { "div_aclk_200", "div_aclk_160", }; +PNAME(mout_ebi_1_p) = { "mout_ebi", "mout_vpll", }; + +PNAME(mout_gdl_p) = { "mout_mpll_user_l", }; +PNAME(mout_gdr_p) = { "mout_mpll_user_r", }; + +PNAME(mout_aclk_400_mcuisp_sub_p) + = { "fin_pll", "div_aclk_400_mcuisp", }; +PNAME(mout_aclk_266_0_p) = { "div_mpll_pre", "mout_vpll", }; +PNAME(mout_aclk_266_1_p) = { "mout_epll_user", }; +PNAME(mout_aclk_266_p) = { "mout_aclk_266_0", "mout_aclk_266_1", }; +PNAME(mout_aclk_266_sub_p) = { "fin_pll", "div_aclk_266", }; + +PNAME(group_div_mpll_pre_p) = { "div_mpll_pre", }; +PNAME(group_epll_vpll_p) = { "mout_epll_user", "mout_vpll" }; +PNAME(group_sclk_p) = { "xxti", "xusbxti", + "none", "none", + "none", "none", "div_mpll_pre", + "mout_epll_user", "mout_vpll", }; +PNAME(group_sclk_audio_p) = { "audiocdclk", "none", + "none", "none", + "xxti", "xusbxti", + "div_mpll_pre", "mout_epll_user", + "mout_vpll", }; +PNAME(group_sclk_cam_blk_p) = { "xxti", "xusbxti", + "none", "none", "none", + "none", "div_mpll_pre", + "mout_epll_user", "mout_vpll", + "div_cam_blk_320", }; +PNAME(group_sclk_fimd0_p) = { "xxti", "xusbxti", + "m_bitclkhsdiv4_2l", "none", + "none", "none", "div_mpll_pre", + "mout_epll_user", "mout_vpll", + "none", "none", "none", + "div_lcd_blk_145", }; + +PNAME(mout_mfc_p) = { "mout_mfc_0", "mout_mfc_1" }; +PNAME(mout_g3d_p) = { "mout_g3d_0", "mout_g3d_1" }; + +static struct samsung_fixed_factor_clock fixed_factor_clks[] __initdata = { + FFACTOR(0, "sclk_mpll_1600", "mout_mpll", 1, 1, 0), + FFACTOR(0, "sclk_mpll_mif", "mout_mpll", 1, 2, 0), + FFACTOR(0, "sclk_bpll", "fout_bpll", 1, 2, 0), + FFACTOR(0, "div_cam_blk_320", "sclk_mpll_1600", 1, 5, 0), + FFACTOR(0, "div_lcd_blk_145", "sclk_mpll_1600", 1, 11, 0), + + /* HACK: fin_pll hardcoded to xusbxti until detection is implemented. */ + FFACTOR(CLK_FIN_PLL, "fin_pll", "xusbxti", 1, 1, 0), +}; + +static struct samsung_mux_clock mux_clks[] __initdata = { + /* + * NOTE: Following table is sorted by register address in ascending + * order and then bitfield shift in descending order, as it is done + * in the User's Manual. When adding new entries, please make sure + * that the order is preserved, to avoid merge conflicts and make + * further work with defined data easier. + */ + + /* SRC_LEFTBUS */ + MUX(CLK_MOUT_MPLL_USER_L, "mout_mpll_user_l", mout_mpll_user_p, + SRC_LEFTBUS, 4, 1), + MUX(CLK_MOUT_GDL, "mout_gdl", mout_gdl_p, SRC_LEFTBUS, 0, 1), + + /* SRC_RIGHTBUS */ + MUX(CLK_MOUT_MPLL_USER_R, "mout_mpll_user_r", mout_mpll_user_p, + SRC_RIGHTBUS, 4, 1), + MUX(CLK_MOUT_GDR, "mout_gdr", mout_gdr_p, SRC_RIGHTBUS, 0, 1), + + /* SRC_TOP0 */ + MUX(CLK_MOUT_EBI, "mout_ebi", mout_ebi_p, SRC_TOP0, 28, 1), + MUX(CLK_MOUT_ACLK_200, "mout_aclk_200", group_div_mpll_pre_p,SRC_TOP0, 24, 1), + MUX(CLK_MOUT_ACLK_160, "mout_aclk_160", group_div_mpll_pre_p, SRC_TOP0, 20, 1), + MUX(CLK_MOUT_ACLK_100, "mout_aclk_100", group_div_mpll_pre_p, SRC_TOP0, 16, 1), + MUX(CLK_MOUT_ACLK_266_1, "mout_aclk_266_1", mout_aclk_266_1_p, SRC_TOP0, 14, 1), + MUX(CLK_MOUT_ACLK_266_0, "mout_aclk_266_0", mout_aclk_266_0_p, SRC_TOP0, 13, 1), + MUX(CLK_MOUT_ACLK_266, "mout_aclk_266", mout_aclk_266_p, SRC_TOP0, 12, 1), + MUX(CLK_MOUT_VPLL, "mout_vpll", mout_vpll_p, SRC_TOP0, 8, 1), + MUX(CLK_MOUT_EPLL_USER, "mout_epll_user", mout_epll_user_p, SRC_TOP0, 4, 1), + MUX(CLK_MOUT_EBI_1, "mout_ebi_1", mout_ebi_1_p, SRC_TOP0, 0, 1), + + /* SRC_TOP1 */ + MUX(CLK_MOUT_UPLL, "mout_upll", mout_upll_p, SRC_TOP1, 28, 1), + MUX(CLK_MOUT_ACLK_400_MCUISP_SUB, "mout_aclk_400_mcuisp_sub", mout_aclk_400_mcuisp_sub_p, + SRC_TOP1, 24, 1), + MUX(CLK_MOUT_ACLK_266_SUB, "mout_aclk_266_sub", mout_aclk_266_sub_p, SRC_TOP1, 20, 1), + MUX(CLK_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_TOP1, 12, 1), + MUX(CLK_MOUT_ACLK_400_MCUISP, "mout_aclk_400_mcuisp", group_div_mpll_pre_p, SRC_TOP1, 8, 1), + MUX(CLK_MOUT_VPLLSRC, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1), + + /* SRC_CAM */ + MUX(CLK_MOUT_CAM1, "mout_cam1", group_sclk_p, SRC_CAM, 20, 4), + MUX(CLK_MOUT_CAM_BLK, "mout_cam_blk", group_sclk_cam_blk_p, SRC_CAM, 0, 4), + + /* SRC_MFC */ + MUX(CLK_MOUT_MFC, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1), + MUX(CLK_MOUT_MFC_1, "mout_mfc_1", group_epll_vpll_p, SRC_MFC, 4, 1), + MUX(CLK_MOUT_MFC_0, "mout_mfc_0", group_div_mpll_pre_p, SRC_MFC, 0, 1), + + /* SRC_G3D */ + MUX(CLK_MOUT_G3D, "mout_g3d", mout_g3d_p, SRC_G3D, 8, 1), + MUX(CLK_MOUT_G3D_1, "mout_g3d_1", group_epll_vpll_p, SRC_G3D, 4, 1), + MUX(CLK_MOUT_G3D_0, "mout_g3d_0", group_div_mpll_pre_p, SRC_G3D, 0, 1), + + /* SRC_LCD */ + MUX(CLK_MOUT_MIPI0, "mout_mipi0", group_sclk_p, SRC_LCD, 12, 4), + MUX(CLK_MOUT_FIMD0, "mout_fimd0", group_sclk_fimd0_p, SRC_LCD, 0, 4), + + /* SRC_ISP */ + MUX(CLK_MOUT_UART_ISP, "mout_uart_isp", group_sclk_p, SRC_ISP, 12, 4), + MUX(CLK_MOUT_SPI1_ISP, "mout_spi1_isp", group_sclk_p, SRC_ISP, 8, 4), + MUX(CLK_MOUT_SPI0_ISP, "mout_spi0_isp", group_sclk_p, SRC_ISP, 4, 4), + + /* SRC_FSYS */ + MUX(CLK_MOUT_TSADC, "mout_tsadc", group_sclk_p, SRC_FSYS, 28, 4), + MUX(CLK_MOUT_MMC1, "mout_mmc1", group_sclk_p, SRC_FSYS, 4, 3), + MUX(CLK_MOUT_MMC0, "mout_mmc0", group_sclk_p, SRC_FSYS, 0, 3), + + /* SRC_PERIL0 */ + MUX(CLK_MOUT_UART1, "mout_uart1", group_sclk_p, SRC_PERIL0, 4, 4), + MUX(CLK_MOUT_UART0, "mout_uart0", group_sclk_p, SRC_PERIL0, 0, 4), + + /* SRC_PERIL1 */ + MUX(CLK_MOUT_SPI1, "mout_spi1", group_sclk_p, SRC_PERIL1, 20, 4), + MUX(CLK_MOUT_SPI0, "mout_spi0", group_sclk_p, SRC_PERIL1, 16, 4), + MUX(CLK_MOUT_AUDIO, "mout_audio", group_sclk_audio_p, SRC_PERIL1, 4, 4), + + /* SRC_CPU */ + MUX(CLK_MOUT_MPLL_USER_C, "mout_mpll_user_c", mout_mpll_user_p, + SRC_CPU, 24, 1), + MUX(CLK_MOUT_HPM, "mout_hpm", mout_hpm_p, SRC_CPU, 20, 1), + MUX(CLK_MOUT_CORE, "mout_core", mout_core_p, SRC_CPU, 16, 1), + MUX(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1), +}; + +static struct samsung_div_clock div_clks[] __initdata = { + /* + * NOTE: Following table is sorted by register address in ascending + * order and then bitfield shift in descending order, as it is done + * in the User's Manual. When adding new entries, please make sure + * that the order is preserved, to avoid merge conflicts and make + * further work with defined data easier. + */ + + /* DIV_LEFTBUS */ + DIV(CLK_DIV_GPL, "div_gpl", "div_gdl", DIV_LEFTBUS, 4, 3), + DIV(CLK_DIV_GDL, "div_gdl", "mout_gdl", DIV_LEFTBUS, 0, 4), + + /* DIV_RIGHTBUS */ + DIV(CLK_DIV_GPR, "div_gpr", "div_gdr", DIV_RIGHTBUS, 4, 3), + DIV(CLK_DIV_GDR, "div_gdr", "mout_gdr", DIV_RIGHTBUS, 0, 4), + + /* DIV_TOP */ + DIV(CLK_DIV_MPLL_PRE, "div_mpll_pre", "sclk_mpll_mif", DIV_TOP, 28, 2), + DIV(CLK_DIV_ACLK_400_MCUISP, "div_aclk_400_mcuisp", + "mout_aclk_400_mcuisp", DIV_TOP, 24, 3), + DIV(CLK_DIV_EBI, "div_ebi", "mout_ebi_1", DIV_TOP, 16, 3), + DIV(CLK_DIV_ACLK_200, "div_aclk_200", "mout_aclk_200", DIV_TOP, 12, 3), + DIV(CLK_DIV_ACLK_160, "div_aclk_160", "mout_aclk_160", DIV_TOP, 8, 3), + DIV(CLK_DIV_ACLK_100, "div_aclk_100", "mout_aclk_100", DIV_TOP, 4, 4), + DIV(CLK_DIV_ACLK_266, "div_aclk_266", "mout_aclk_266", DIV_TOP, 0, 3), + + /* DIV_CAM */ + DIV(CLK_DIV_CAM1, "div_cam1", "mout_cam1", DIV_CAM, 20, 4), + DIV(CLK_DIV_CAM_BLK, "div_cam_blk", "mout_cam_blk", DIV_CAM, 0, 4), + + /* DIV_MFC */ + DIV(CLK_DIV_MFC, "div_mfc", "mout_mfc", DIV_MFC, 0, 4), + + /* DIV_G3D */ + DIV(CLK_DIV_G3D, "div_g3d", "mout_g3d", DIV_G3D, 0, 4), + + /* DIV_LCD */ + DIV_F(CLK_DIV_MIPI0_PRE, "div_mipi0_pre", "div_mipi0", DIV_LCD, 20, 4, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_MIPI0, "div_mipi0", "mout_mipi0", DIV_LCD, 16, 4), + DIV(CLK_DIV_FIMD0, "div_fimd0", "mout_fimd0", DIV_LCD, 0, 4), + + /* DIV_ISP */ + DIV(CLK_DIV_UART_ISP, "div_uart_isp", "mout_uart_isp", DIV_ISP, 28, 4), + DIV_F(CLK_DIV_SPI1_ISP_PRE, "div_spi1_isp_pre", "div_spi1_isp", + DIV_ISP, 20, 8, CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI1_ISP, "div_spi1_isp", "mout_spi1_isp", DIV_ISP, 16, 4), + DIV_F(CLK_DIV_SPI0_ISP_PRE, "div_spi0_isp_pre", "div_spi0_isp", + DIV_ISP, 8, 8, CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI0_ISP, "div_spi0_isp", "mout_spi0_isp", DIV_ISP, 0, 4), + + /* DIV_FSYS0 */ + DIV_F(CLK_DIV_TSADC_PRE, "div_tsadc_pre", "div_tsadc", DIV_FSYS0, 8, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_TSADC, "div_tsadc", "mout_tsadc", DIV_FSYS0, 0, 4), + + /* DIV_FSYS1 */ + DIV_F(CLK_DIV_MMC1_PRE, "div_mmc1_pre", "div_mmc1", DIV_FSYS1, 24, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_MMC1, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4), + DIV_F(CLK_DIV_MMC0_PRE, "div_mmc0_pre", "div_mmc0", DIV_FSYS1, 8, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_MMC0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), + + /* DIV_PERIL0 */ + DIV(CLK_DIV_UART1, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4), + DIV(CLK_DIV_UART0, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4), + + /* DIV_PERIL1 */ + DIV_F(CLK_DIV_SPI1_PRE, "div_spi1_pre", "div_spi1", DIV_PERIL1, 24, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI1, "div_spi1", "mout_spi1", DIV_PERIL1, 16, 4), + DIV_F(CLK_DIV_SPI0_PRE, "div_spi0_pre", "div_spi0", DIV_PERIL1, 8, 8, + CLK_SET_RATE_PARENT, 0), + DIV(CLK_DIV_SPI0, "div_spi0", "mout_spi0", DIV_PERIL1, 0, 4), + + /* DIV_PERIL4 */ + DIV(CLK_DIV_PCM, "div_pcm", "div_audio", DIV_PERIL4, 20, 8), + DIV(CLK_DIV_AUDIO, "div_audio", "mout_audio", DIV_PERIL4, 16, 4), + + /* DIV_PERIL5 */ + DIV(CLK_DIV_I2S, "div_i2s", "div_audio", DIV_PERIL5, 8, 6), + + /* DIV_CPU0 */ + DIV(CLK_DIV_CORE2, "div_core2", "div_core", DIV_CPU0, 28, 3), + DIV(CLK_DIV_APLL, "div_apll", "mout_apll", DIV_CPU0, 24, 3), + DIV(CLK_DIV_PCLK_DBG, "div_pclk_dbg", "div_core2", DIV_CPU0, 20, 3), + DIV(CLK_DIV_ATB, "div_atb", "div_core2", DIV_CPU0, 16, 3), + DIV(CLK_DIV_COREM, "div_corem", "div_core2", DIV_CPU0, 4, 3), + DIV(CLK_DIV_CORE, "div_core", "mout_core", DIV_CPU0, 0, 3), + + /* DIV_CPU1 */ + DIV(CLK_DIV_HPM, "div_hpm", "div_copy", DIV_CPU1, 4, 3), + DIV(CLK_DIV_COPY, "div_copy", "mout_hpm", DIV_CPU1, 0, 3), +}; + +static struct samsung_gate_clock gate_clks[] __initdata = { + /* + * NOTE: Following table is sorted by register address in ascending + * order and then bitfield shift in descending order, as it is done + * in the User's Manual. When adding new entries, please make sure + * that the order is preserved, to avoid merge conflicts and make + * further work with defined data easier. + */ + + /* GATE_IP_LEFTBUS */ + GATE(CLK_ASYNC_G3D, "async_g3d", "div_aclk_100", GATE_IP_LEFTBUS, 6, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_MFCL, "async_mfcl", "div_aclk_100", GATE_IP_LEFTBUS, 4, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMULEFT, "ppmuleft", "div_aclk_100", GATE_IP_LEFTBUS, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_GPIO_LEFT, "gpio_left", "div_aclk_100", GATE_IP_LEFTBUS, 0, + CLK_IGNORE_UNUSED, 0), + + /* GATE_IP_RIGHTBUS */ + GATE(CLK_ASYNC_ISPMX, "async_ispmx", "div_aclk_100", + GATE_IP_RIGHTBUS, 9, CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_FSYSD, "async_fsysd", "div_aclk_100", + GATE_IP_RIGHTBUS, 5, CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_LCD0X, "async_lcd0x", "div_aclk_100", + GATE_IP_RIGHTBUS, 3, CLK_IGNORE_UNUSED, 0), + GATE(CLK_ASYNC_CAMX, "async_camx", "div_aclk_100", GATE_IP_RIGHTBUS, 2, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMURIGHT, "ppmuright", "div_aclk_100", GATE_IP_RIGHTBUS, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_GPIO_RIGHT, "gpio_right", "div_aclk_100", GATE_IP_RIGHTBUS, 0, + CLK_IGNORE_UNUSED, 0), + + /* GATE_IP_PERIR */ + GATE(CLK_MONOCNT, "monocnt", "div_aclk_100", GATE_IP_PERIR, 22, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC6, "tzpc6", "div_aclk_100", GATE_IP_PERIR, 21, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PROVISIONKEY1, "provisionkey1", "div_aclk_100", + GATE_IP_PERIR, 20, CLK_IGNORE_UNUSED, 0), + GATE(CLK_PROVISIONKEY0, "provisionkey0", "div_aclk_100", + GATE_IP_PERIR, 19, CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_ISPPART, "cmu_isppart", "div_aclk_100", GATE_IP_PERIR, 18, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TMU_APBIF, "tmu_apbif", "div_aclk_100", + GATE_IP_PERIR, 17, 0, 0), + GATE(CLK_KEYIF, "keyif", "div_aclk_100", GATE_IP_PERIR, 16, 0, 0), + GATE(CLK_RTC, "rtc", "div_aclk_100", GATE_IP_PERIR, 15, 0, 0), + GATE(CLK_WDT, "wdt", "div_aclk_100", GATE_IP_PERIR, 14, 0, 0), + GATE(CLK_MCT, "mct", "div_aclk_100", GATE_IP_PERIR, 13, 0, 0), + GATE(CLK_SECKEY, "seckey", "div_aclk_100", GATE_IP_PERIR, 12, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC5, "tzpc5", "div_aclk_100", GATE_IP_PERIR, 10, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC4, "tzpc4", "div_aclk_100", GATE_IP_PERIR, 9, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC3, "tzpc3", "div_aclk_100", GATE_IP_PERIR, 8, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC2, "tzpc2", "div_aclk_100", GATE_IP_PERIR, 7, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC1, "tzpc1", "div_aclk_100", GATE_IP_PERIR, 6, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC0, "tzpc0", "div_aclk_100", GATE_IP_PERIR, 5, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_COREPART, "cmu_corepart", "div_aclk_100", GATE_IP_PERIR, 4, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_CMU_TOPPART, "cmu_toppart", "div_aclk_100", GATE_IP_PERIR, 3, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PMU_APBIF, "pmu_apbif", "div_aclk_100", GATE_IP_PERIR, 2, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_SYSREG, "sysreg", "div_aclk_100", GATE_IP_PERIR, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_CHIP_ID, "chip_id", "div_aclk_100", GATE_IP_PERIR, 0, + CLK_IGNORE_UNUSED, 0), + + /* GATE_SCLK_CAM */ + GATE(CLK_SCLK_JPEG, "sclk_jpeg", "div_cam_blk", + GATE_SCLK_CAM, 8, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_M2MSCALER, "sclk_m2mscaler", "div_cam_blk", + GATE_SCLK_CAM, 2, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_GSCALER1, "sclk_gscaler1", "div_cam_blk", + GATE_SCLK_CAM, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_GSCALER0, "sclk_gscaler0", "div_cam_blk", + GATE_SCLK_CAM, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_MFC */ + GATE(CLK_SCLK_MFC, "sclk_mfc", "div_mfc", + GATE_SCLK_MFC, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_G3D */ + GATE(CLK_SCLK_G3D, "sclk_g3d", "div_g3d", + GATE_SCLK_G3D, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_LCD */ + GATE(CLK_SCLK_MIPIDPHY2L, "sclk_mipidphy2l", "div_mipi0", + GATE_SCLK_LCD, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MIPI0, "sclk_mipi0", "div_mipi0_pre", + GATE_SCLK_LCD, 3, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_FIMD0, "sclk_fimd0", "div_fimd0", + GATE_SCLK_LCD, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_ISP_TOP */ + GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1", + GATE_SCLK_ISP_TOP, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "div_uart_isp", + GATE_SCLK_ISP_TOP, 3, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI1_ISP, "sclk_spi1_isp", "div_spi1_isp", + GATE_SCLK_ISP_TOP, 2, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI0_ISP, "sclk_spi0_isp", "div_spi0_isp", + GATE_SCLK_ISP_TOP, 1, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_FSYS */ + GATE(CLK_SCLK_UPLL, "sclk_upll", "mout_upll", GATE_SCLK_FSYS, 10, 0, 0), + GATE(CLK_SCLK_TSADC, "sclk_tsadc", "div_tsadc_pre", + GATE_SCLK_FSYS, 9, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_EBI, "sclk_ebi", "div_ebi", + GATE_SCLK_FSYS, 6, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc1_pre", + GATE_SCLK_FSYS, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc0_pre", + GATE_SCLK_FSYS, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_SCLK_PERIL */ + GATE(CLK_SCLK_I2S, "sclk_i2s", "div_i2s", + GATE_SCLK_PERIL, 18, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_PCM, "sclk_pcm", "div_pcm", + GATE_SCLK_PERIL, 16, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI1, "sclk_spi1", "div_spi1_pre", + GATE_SCLK_PERIL, 7, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI0, "sclk_spi0", "div_spi0_pre", + GATE_SCLK_PERIL, 6, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1", + GATE_SCLK_PERIL, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", + GATE_SCLK_PERIL, 0, CLK_SET_RATE_PARENT, 0), + + /* GATE_IP_CAM */ + GATE(CLK_QEJPEG, "qejpeg", "div_cam_blk_320", GATE_IP_CAM, 19, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PIXELASYNCM1, "pixelasyncm1", "div_cam_blk_320", + GATE_IP_CAM, 18, CLK_IGNORE_UNUSED, 0), + GATE(CLK_PIXELASYNCM0, "pixelasyncm0", "div_cam_blk_320", + GATE_IP_CAM, 17, CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMUCAMIF, "ppmucamif", "div_cam_blk_320", + GATE_IP_CAM, 16, CLK_IGNORE_UNUSED, 0), + GATE(CLK_QEM2MSCALER, "qem2mscaler", "div_cam_blk_320", + GATE_IP_CAM, 14, CLK_IGNORE_UNUSED, 0), + GATE(CLK_QEGSCALER1, "qegscaler1", "div_cam_blk_320", + GATE_IP_CAM, 13, CLK_IGNORE_UNUSED, 0), + GATE(CLK_QEGSCALER0, "qegscaler0", "div_cam_blk_320", + GATE_IP_CAM, 12, CLK_IGNORE_UNUSED, 0), + GATE(CLK_SMMUJPEG, "smmujpeg", "div_cam_blk_320", + GATE_IP_CAM, 11, 0, 0), + GATE(CLK_SMMUM2M2SCALER, "smmum2m2scaler", "div_cam_blk_320", + GATE_IP_CAM, 9, 0, 0), + GATE(CLK_SMMUGSCALER1, "smmugscaler1", "div_cam_blk_320", + GATE_IP_CAM, 8, 0, 0), + GATE(CLK_SMMUGSCALER0, "smmugscaler0", "div_cam_blk_320", + GATE_IP_CAM, 7, 0, 0), + GATE(CLK_JPEG, "jpeg", "div_cam_blk_320", GATE_IP_CAM, 6, 0, 0), + GATE(CLK_M2MSCALER, "m2mscaler", "div_cam_blk_320", + GATE_IP_CAM, 2, 0, 0), + GATE(CLK_GSCALER1, "gscaler1", "div_cam_blk_320", GATE_IP_CAM, 1, 0, 0), + GATE(CLK_GSCALER0, "gscaler0", "div_cam_blk_320", GATE_IP_CAM, 0, 0, 0), + + /* GATE_IP_MFC */ + GATE(CLK_QEMFC, "qemfc", "div_aclk_200", GATE_IP_MFC, 5, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMUMFC_L, "ppmumfc_l", "div_aclk_200", GATE_IP_MFC, 3, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_SMMUMFC_L, "smmumfc_l", "div_aclk_200", GATE_IP_MFC, 1, 0, 0), + GATE(CLK_MFC, "mfc", "div_aclk_200", GATE_IP_MFC, 0, 0, 0), + + /* GATE_IP_G3D */ + GATE(CLK_SMMUG3D, "smmug3d", "div_aclk_200", GATE_IP_G3D, 3, 0, 0), + GATE(CLK_QEG3D, "qeg3d", "div_aclk_200", GATE_IP_G3D, 2, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMUG3D, "ppmug3d", "div_aclk_200", GATE_IP_G3D, 1, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_G3D, "g3d", "div_aclk_200", GATE_IP_G3D, 0, 0, 0), + + /* GATE_IP_LCD */ + GATE(CLK_QE_CH1_LCD, "qe_ch1_lcd", "div_aclk_160", GATE_IP_LCD, 7, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_QE_CH0_LCD, "qe_ch0_lcd", "div_aclk_160", GATE_IP_LCD, 6, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_PPMULCD0, "ppmulcd0", "div_aclk_160", GATE_IP_LCD, 5, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_SMMUFIMD0, "smmufimd0", "div_aclk_160", GATE_IP_LCD, 4, 0, 0), + GATE(CLK_DSIM0, "dsim0", "div_aclk_160", GATE_IP_LCD, 3, 0, 0), + GATE(CLK_SMIES, "smies", "div_aclk_160", GATE_IP_LCD, 2, 0, 0), + GATE(CLK_FIMD0, "fimd0", "div_aclk_160", GATE_IP_LCD, 0, 0, 0), + + /* GATE_IP_ISP */ + GATE(CLK_CAM1, "cam1", "mout_aclk_266_sub", GATE_IP_ISP, 5, 0, 0), + GATE(CLK_UART_ISP_TOP, "uart_isp_top", "mout_aclk_266_sub", + GATE_IP_ISP, 3, 0, 0), + GATE(CLK_SPI1_ISP_TOP, "spi1_isp_top", "mout_aclk_266_sub", + GATE_IP_ISP, 2, 0, 0), + GATE(CLK_SPI0_ISP_TOP, "spi0_isp_top", "mout_aclk_266_sub", + GATE_IP_ISP, 1, 0, 0), + + /* GATE_IP_FSYS */ + GATE(CLK_TSADC, "tsadc", "div_aclk_200", GATE_IP_FSYS, 20, 0, 0), + GATE(CLK_PPMUFILE, "ppmufile", "div_aclk_200", GATE_IP_FSYS, 17, + CLK_IGNORE_UNUSED, 0), + GATE(CLK_USBOTG, "usbotg", "div_aclk_200", GATE_IP_FSYS, 13, 0, 0), + GATE(CLK_USBHOST, "usbhost", "div_aclk_200", GATE_IP_FSYS, 12, 0, 0), + GATE(CLK_SROMC, "sromc", "div_aclk_200", GATE_IP_FSYS, 11, 0, 0), + GATE(CLK_SDMMC1, "sdmmc1", "div_aclk_200", GATE_IP_FSYS, 6, 0, 0), + GATE(CLK_SDMMC0, "sdmmc0", "div_aclk_200", GATE_IP_FSYS, 5, 0, 0), + GATE(CLK_PDMA1, "pdma1", "div_aclk_200", GATE_IP_FSYS, 1, 0, 0), + GATE(CLK_PDMA0, "pdma0", "div_aclk_200", GATE_IP_FSYS, 0, 0, 0), + + /* GATE_IP_PERIL */ + GATE(CLK_PWM, "pwm", "div_aclk_100", GATE_IP_PERIL, 24, 0, 0), + GATE(CLK_PCM, "pcm", "div_aclk_100", GATE_IP_PERIL, 23, 0, 0), + GATE(CLK_I2S, "i2s", "div_aclk_100", GATE_IP_PERIL, 21, 0, 0), + GATE(CLK_SPI1, "spi1", "div_aclk_100", GATE_IP_PERIL, 17, 0, 0), + GATE(CLK_SPI0, "spi0", "div_aclk_100", GATE_IP_PERIL, 16, 0, 0), + GATE(CLK_I2C7, "i2c7", "div_aclk_100", GATE_IP_PERIL, 13, 0, 0), + GATE(CLK_I2C6, "i2c6", "div_aclk_100", GATE_IP_PERIL, 12, 0, 0), + GATE(CLK_I2C5, "i2c5", "div_aclk_100", GATE_IP_PERIL, 11, 0, 0), + GATE(CLK_I2C4, "i2c4", "div_aclk_100", GATE_IP_PERIL, 10, 0, 0), + GATE(CLK_I2C3, "i2c3", "div_aclk_100", GATE_IP_PERIL, 9, 0, 0), + GATE(CLK_I2C2, "i2c2", "div_aclk_100", GATE_IP_PERIL, 8, 0, 0), + GATE(CLK_I2C1, "i2c1", "div_aclk_100", GATE_IP_PERIL, 7, 0, 0), + GATE(CLK_I2C0, "i2c0", "div_aclk_100", GATE_IP_PERIL, 6, 0, 0), + GATE(CLK_UART1, "uart1", "div_aclk_100", GATE_IP_PERIL, 1, 0, 0), + GATE(CLK_UART0, "uart0", "div_aclk_100", GATE_IP_PERIL, 0, 0, 0), +}; + +/* APLL & MPLL & BPLL & UPLL */ +static struct samsung_pll_rate_table exynos3250_pll_rates[] = { + PLL_35XX_RATE(1200000000, 400, 4, 1), + PLL_35XX_RATE(1100000000, 275, 3, 1), + PLL_35XX_RATE(1066000000, 533, 6, 1), + PLL_35XX_RATE(1000000000, 250, 3, 1), + PLL_35XX_RATE( 960000000, 320, 4, 1), + PLL_35XX_RATE( 900000000, 300, 4, 1), + PLL_35XX_RATE( 850000000, 425, 6, 1), + PLL_35XX_RATE( 800000000, 200, 3, 1), + PLL_35XX_RATE( 700000000, 175, 3, 1), + PLL_35XX_RATE( 667000000, 667, 12, 1), + PLL_35XX_RATE( 600000000, 400, 4, 2), + PLL_35XX_RATE( 533000000, 533, 6, 2), + PLL_35XX_RATE( 520000000, 260, 3, 2), + PLL_35XX_RATE( 500000000, 250, 3, 2), + PLL_35XX_RATE( 400000000, 200, 3, 2), + PLL_35XX_RATE( 200000000, 200, 3, 3), + PLL_35XX_RATE( 100000000, 200, 3, 4), + { /* sentinel */ } +}; + +/* VPLL */ +static struct samsung_pll_rate_table exynos3250_vpll_rates[] = { + PLL_36XX_RATE(600000000, 100, 2, 1, 0), + PLL_36XX_RATE(533000000, 266, 3, 2, 32768), + PLL_36XX_RATE(519230987, 173, 2, 2, 5046), + PLL_36XX_RATE(500000000, 250, 3, 2, 0), + PLL_36XX_RATE(445500000, 148, 2, 2, 32768), + PLL_36XX_RATE(445055007, 148, 2, 2, 23047), + PLL_36XX_RATE(400000000, 200, 3, 2, 0), + PLL_36XX_RATE(371250000, 123, 2, 2, 49152), + PLL_36XX_RATE(370878997, 185, 3, 2, 28803), + PLL_36XX_RATE(340000000, 170, 3, 2, 0), + PLL_36XX_RATE(335000015, 111, 2, 2, 43691), + PLL_36XX_RATE(333000000, 111, 2, 2, 0), + PLL_36XX_RATE(330000000, 110, 2, 2, 0), + PLL_36XX_RATE(320000015, 106, 2, 2, 43691), + PLL_36XX_RATE(300000000, 100, 2, 2, 0), + PLL_36XX_RATE(275000000, 275, 3, 3, 0), + PLL_36XX_RATE(222750000, 148, 2, 3, 32768), + PLL_36XX_RATE(222528007, 148, 2, 3, 23069), + PLL_36XX_RATE(160000000, 160, 3, 3, 0), + PLL_36XX_RATE(148500000, 99, 2, 3, 0), + PLL_36XX_RATE(148352005, 98, 2, 3, 59070), + PLL_36XX_RATE(108000000, 144, 2, 4, 0), + PLL_36XX_RATE( 74250000, 99, 2, 4, 0), + PLL_36XX_RATE( 74176002, 98, 3, 4, 59070), + PLL_36XX_RATE( 54054000, 216, 3, 5, 14156), + PLL_36XX_RATE( 54000000, 144, 2, 5, 0), + { /* sentinel */ } +}; + +static struct samsung_pll_clock exynos3250_plls[nr_plls] __initdata = { + [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", + APLL_LOCK, APLL_CON0, NULL), + [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", + MPLL_LOCK, MPLL_CON0, NULL), + [vpll] = PLL(pll_36xx, CLK_FOUT_VPLL, "fout_vpll", "fin_pll", + VPLL_LOCK, VPLL_CON0, NULL), + [upll] = PLL(pll_35xx, CLK_FOUT_UPLL, "fout_upll", "fin_pll", + UPLL_LOCK, UPLL_CON0, NULL), +}; + +static void __init exynos3250_cmu_init(struct device_node *np) +{ + struct samsung_clk_provider *ctx; + + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + samsung_clk_register_fixed_factor(ctx, fixed_factor_clks, + ARRAY_SIZE(fixed_factor_clks)); + + exynos3250_plls[apll].rate_table = exynos3250_pll_rates; + exynos3250_plls[mpll].rate_table = exynos3250_pll_rates; + exynos3250_plls[vpll].rate_table = exynos3250_vpll_rates; + exynos3250_plls[upll].rate_table = exynos3250_pll_rates; + + samsung_clk_register_pll(ctx, exynos3250_plls, + ARRAY_SIZE(exynos3250_plls), reg_base); + + samsung_clk_register_mux(ctx, mux_clks, ARRAY_SIZE(mux_clks)); + samsung_clk_register_div(ctx, div_clks, ARRAY_SIZE(div_clks)); + samsung_clk_register_gate(ctx, gate_clks, ARRAY_SIZE(gate_clks)); + + exynos3250_clk_sleep_init(); +} +CLK_OF_DECLARE(exynos3250_cmu, "samsung,exynos3250-cmu", exynos3250_cmu_init); diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index b4f9672..c4df294 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -428,7 +428,7 @@ static struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata /* fixed rate clocks generated inside the soc */ static struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = { FRATE(0, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000), - FRATE(0, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), + FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000), FRATE(0, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000), }; @@ -903,7 +903,7 @@ static struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { GATE(CLK_AUDSS, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0), GATE(CLK_MDNIE0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0), GATE(CLK_ROTATOR, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0), - GATE(CLK_MDMA2, "mdma2", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0), + GATE(CLK_MDMA, "mdma", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0), GATE(CLK_SMMU_MDMA, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0, 0), GATE(CLK_MIPI_HSI, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0), @@ -1043,7 +1043,7 @@ static unsigned long exynos4_get_xom(void) return xom; } -static void __init exynos4_clk_register_finpll(void) +static void __init exynos4_clk_register_finpll(struct samsung_clk_provider *ctx) { struct samsung_fixed_rate_clock fclk; struct clk *clk; @@ -1066,7 +1066,7 @@ static void __init exynos4_clk_register_finpll(void) fclk.parent_name = NULL; fclk.flags = CLK_IS_ROOT; fclk.fixed_rate = finpll_f; - samsung_clk_register_fixed_rate(&fclk, 1); + samsung_clk_register_fixed_rate(ctx, &fclk, 1); } @@ -1176,22 +1176,25 @@ static struct samsung_pll_clock exynos4x12_plls[nr_plls] __initdata = { static void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc soc) { + struct samsung_clk_provider *ctx; exynos4_soc = soc; reg_base = of_iomap(np, 0); if (!reg_base) panic("%s: failed to map registers\n", __func__); - samsung_clk_init(np, reg_base, CLK_NR_CLKS); + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); - samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks, + samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), ext_clk_match); - exynos4_clk_register_finpll(); + exynos4_clk_register_finpll(ctx); if (exynos4_soc == EXYNOS4210) { - samsung_clk_register_mux(exynos4210_mux_early, + samsung_clk_register_mux(ctx, exynos4210_mux_early, ARRAY_SIZE(exynos4210_mux_early)); if (_get_rate("fin_pll") == 24000000) { @@ -1205,7 +1208,7 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4210_plls[vpll].rate_table = exynos4210_vpll_rates; - samsung_clk_register_pll(exynos4210_plls, + samsung_clk_register_pll(ctx, exynos4210_plls, ARRAY_SIZE(exynos4210_plls), reg_base); } else { if (_get_rate("fin_pll") == 24000000) { @@ -1217,42 +1220,42 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4x12_vpll_rates; } - samsung_clk_register_pll(exynos4x12_plls, + samsung_clk_register_pll(ctx, exynos4x12_plls, ARRAY_SIZE(exynos4x12_plls), reg_base); } - samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks, ARRAY_SIZE(exynos4_fixed_rate_clks)); - samsung_clk_register_mux(exynos4_mux_clks, + samsung_clk_register_mux(ctx, exynos4_mux_clks, ARRAY_SIZE(exynos4_mux_clks)); - samsung_clk_register_div(exynos4_div_clks, + samsung_clk_register_div(ctx, exynos4_div_clks, ARRAY_SIZE(exynos4_div_clks)); - samsung_clk_register_gate(exynos4_gate_clks, + samsung_clk_register_gate(ctx, exynos4_gate_clks, ARRAY_SIZE(exynos4_gate_clks)); if (exynos4_soc == EXYNOS4210) { - samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, exynos4210_fixed_rate_clks, ARRAY_SIZE(exynos4210_fixed_rate_clks)); - samsung_clk_register_mux(exynos4210_mux_clks, + samsung_clk_register_mux(ctx, exynos4210_mux_clks, ARRAY_SIZE(exynos4210_mux_clks)); - samsung_clk_register_div(exynos4210_div_clks, + samsung_clk_register_div(ctx, exynos4210_div_clks, ARRAY_SIZE(exynos4210_div_clks)); - samsung_clk_register_gate(exynos4210_gate_clks, + samsung_clk_register_gate(ctx, exynos4210_gate_clks, ARRAY_SIZE(exynos4210_gate_clks)); - samsung_clk_register_alias(exynos4210_aliases, + samsung_clk_register_alias(ctx, exynos4210_aliases, ARRAY_SIZE(exynos4210_aliases)); } else { - samsung_clk_register_mux(exynos4x12_mux_clks, + samsung_clk_register_mux(ctx, exynos4x12_mux_clks, ARRAY_SIZE(exynos4x12_mux_clks)); - samsung_clk_register_div(exynos4x12_div_clks, + samsung_clk_register_div(ctx, exynos4x12_div_clks, ARRAY_SIZE(exynos4x12_div_clks)); - samsung_clk_register_gate(exynos4x12_gate_clks, + samsung_clk_register_gate(ctx, exynos4x12_gate_clks, ARRAY_SIZE(exynos4x12_gate_clks)); - samsung_clk_register_alias(exynos4x12_aliases, + samsung_clk_register_alias(ctx, exynos4x12_aliases, ARRAY_SIZE(exynos4x12_aliases)); } - samsung_clk_register_alias(exynos4_aliases, + samsung_clk_register_alias(ctx, exynos4_aliases, ARRAY_SIZE(exynos4_aliases)); exynos4_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index e7ee442..870e18b 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -28,6 +28,8 @@ #define MPLL_CON0 0x4100 #define SRC_CORE1 0x4204 #define GATE_IP_ACP 0x8800 +#define GATE_IP_ISP0 0xc800 +#define GATE_IP_ISP1 0xc804 #define CPLL_LOCK 0x10020 #define EPLL_LOCK 0x10030 #define VPLL_LOCK 0x10040 @@ -37,6 +39,7 @@ #define VPLL_CON0 0x10140 #define GPLL_CON0 0x10150 #define SRC_TOP0 0x10210 +#define SRC_TOP1 0x10214 #define SRC_TOP2 0x10218 #define SRC_TOP3 0x1021c #define SRC_GSCL 0x10220 @@ -71,6 +74,7 @@ #define GATE_IP_GSCL 0x10920 #define GATE_IP_DISP1 0x10928 #define GATE_IP_MFC 0x1092c +#define GATE_IP_G3D 0x10930 #define GATE_IP_GEN 0x10934 #define GATE_IP_FSYS 0x10944 #define GATE_IP_PERIC 0x10950 @@ -100,6 +104,7 @@ static unsigned long exynos5250_clk_regs[] __initdata = { DIV_CPU0, SRC_CORE1, SRC_TOP0, + SRC_TOP1, SRC_TOP2, SRC_TOP3, SRC_GSCL, @@ -133,6 +138,7 @@ static unsigned long exynos5250_clk_regs[] __initdata = { DIV_PERIC5, GATE_IP_GSCL, GATE_IP_MFC, + GATE_IP_G3D, GATE_IP_GEN, GATE_IP_FSYS, GATE_IP_PERIC, @@ -141,6 +147,8 @@ static unsigned long exynos5250_clk_regs[] __initdata = { PLL_DIV2_SEL, GATE_IP_DISP1, GATE_IP_ACP, + GATE_IP_ISP0, + GATE_IP_ISP1, }; static int exynos5250_clk_suspend(void) @@ -189,13 +197,16 @@ PNAME(mout_vpllsrc_p) = { "fin_pll", "sclk_hdmi27m" }; PNAME(mout_vpll_p) = { "mout_vpllsrc", "fout_vpll" }; PNAME(mout_cpll_p) = { "fin_pll", "fout_cpll" }; PNAME(mout_epll_p) = { "fin_pll", "fout_epll" }; +PNAME(mout_gpll_p) = { "fin_pll", "fout_gpll" }; PNAME(mout_mpll_user_p) = { "fin_pll", "mout_mpll" }; PNAME(mout_bpll_user_p) = { "fin_pll", "mout_bpll" }; PNAME(mout_aclk166_p) = { "mout_cpll", "mout_mpll_user" }; PNAME(mout_aclk200_p) = { "mout_mpll_user", "mout_bpll_user" }; +PNAME(mout_aclk400_p) = { "mout_aclk400_g3d_mid", "mout_gpll" }; PNAME(mout_aclk200_sub_p) = { "fin_pll", "div_aclk200" }; PNAME(mout_aclk266_sub_p) = { "fin_pll", "div_aclk266" }; PNAME(mout_aclk333_sub_p) = { "fin_pll", "div_aclk333" }; +PNAME(mout_aclk400_isp_sub_p) = { "fin_pll", "div_aclk400_isp" }; PNAME(mout_hdmi_p) = { "div_hdmi_pixel", "sclk_hdmiphy" }; PNAME(mout_usb3_p) = { "mout_mpll_user", "mout_cpll" }; PNAME(mout_group1_p) = { "fin_pll", "fin_pll", "sclk_hdmi27m", @@ -273,15 +284,23 @@ static struct samsung_mux_clock exynos5250_mux_clks[] __initdata = { MUX(0, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1), MUX(0, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1), MUX(0, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1), + MUX(0, "mout_aclk400_g3d_mid", mout_aclk200_p, SRC_TOP0, 20, 1), + + MUX(0, "mout_aclk400_isp", mout_aclk200_p, SRC_TOP1, 24, 1), + MUX(0, "mout_aclk400_g3d", mout_aclk400_p, SRC_TOP1, 28, 1), MUX(0, "mout_cpll", mout_cpll_p, SRC_TOP2, 8, 1), MUX(0, "mout_epll", mout_epll_p, SRC_TOP2, 12, 1), MUX(0, "mout_vpll", mout_vpll_p, SRC_TOP2, 16, 1), MUX(0, "mout_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1), MUX(0, "mout_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1), + MUX(CLK_MOUT_GPLL, "mout_gpll", mout_gpll_p, SRC_TOP2, 28, 1), MUX(0, "mout_aclk200_disp1_sub", mout_aclk200_sub_p, SRC_TOP3, 4, 1), MUX(0, "mout_aclk266_gscl_sub", mout_aclk266_sub_p, SRC_TOP3, 8, 1), + MUX(0, "mout_aclk_266_isp_sub", mout_aclk266_sub_p, SRC_TOP3, 16, 1), + MUX(0, "mout_aclk_400_isp_sub", mout_aclk400_isp_sub_p, + SRC_TOP3, 20, 1), MUX(0, "mout_aclk333_sub", mout_aclk333_sub_p, SRC_TOP3, 24, 1), MUX(0, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4), @@ -351,7 +370,10 @@ static struct samsung_div_clock exynos5250_div_clks[] __initdata = { DIV(0, "div_aclk200", "mout_aclk200", DIV_TOP0, 12, 3), DIV(0, "div_aclk266", "mout_mpll_user", DIV_TOP0, 16, 3), DIV(0, "div_aclk333", "mout_aclk333", DIV_TOP0, 20, 3), + DIV(0, "div_aclk400_g3d", "mout_aclk400_g3d", DIV_TOP0, + 24, 3), + DIV(0, "div_aclk400_isp", "mout_aclk400_isp", DIV_TOP1, 20, 3), DIV(0, "div_aclk66_pre", "mout_mpll_user", DIV_TOP1, 24, 3), DIV(0, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4), @@ -428,6 +450,7 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { * CMU_ACP */ GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0), + GATE(CLK_SSS, "sss", "div_aclk266", GATE_IP_ACP, 2, 0, 0), GATE(CLK_G2D, "g2d", "div_aclk200", GATE_IP_ACP, 3, 0, 0), GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "div_aclk266", GATE_IP_ACP, 5, 0, 0), @@ -533,7 +556,8 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { 0), GATE(CLK_SMMU_MFCL, "smmu_mfcl", "mout_aclk333_sub", GATE_IP_MFC, 2, 0, 0), - + GATE(CLK_G3D, "g3d", "div_aclk400_g3d", GATE_IP_G3D, 0, + CLK_SET_RATE_PARENT, 0), GATE(CLK_ROTATOR, "rotator", "div_aclk266", GATE_IP_GEN, 1, 0, 0), GATE(CLK_JPEG, "jpeg", "div_aclk166", GATE_IP_GEN, 2, 0, 0), GATE(CLK_MDMA1, "mdma1", "div_aclk266", GATE_IP_GEN, 4, 0, 0), @@ -615,6 +639,31 @@ static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { GATE(CLK_WDT, "wdt", "div_aclk66", GATE_IP_PERIS, 19, 0, 0), GATE(CLK_RTC, "rtc", "div_aclk66", GATE_IP_PERIS, 20, 0, 0), GATE(CLK_TMU, "tmu", "div_aclk66", GATE_IP_PERIS, 21, 0, 0), + GATE(CLK_SMMU_TV, "smmu_tv", "mout_aclk200_disp1_sub", + GATE_IP_DISP1, 2, 0, 0), + GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "mout_aclk200_disp1_sub", + GATE_IP_DISP1, 8, 0, 0), + GATE(CLK_SMMU_2D, "smmu_2d", "div_aclk200", GATE_IP_ACP, 7, 0, 0), + GATE(CLK_SMMU_FIMC_ISP, "smmu_fimc_isp", "mout_aclk_266_isp_sub", + GATE_IP_ISP0, 8, 0, 0), + GATE(CLK_SMMU_FIMC_DRC, "smmu_fimc_drc", "mout_aclk_266_isp_sub", + GATE_IP_ISP0, 9, 0, 0), + GATE(CLK_SMMU_FIMC_FD, "smmu_fimc_fd", "mout_aclk_266_isp_sub", + GATE_IP_ISP0, 10, 0, 0), + GATE(CLK_SMMU_FIMC_SCC, "smmu_fimc_scc", "mout_aclk_266_isp_sub", + GATE_IP_ISP0, 11, 0, 0), + GATE(CLK_SMMU_FIMC_SCP, "smmu_fimc_scp", "mout_aclk_266_isp_sub", + GATE_IP_ISP0, 12, 0, 0), + GATE(CLK_SMMU_FIMC_MCU, "smmu_fimc_mcu", "mout_aclk_400_isp_sub", + GATE_IP_ISP0, 13, 0, 0), + GATE(CLK_SMMU_FIMC_ODC, "smmu_fimc_odc", "mout_aclk_266_isp_sub", + GATE_IP_ISP1, 4, 0, 0), + GATE(CLK_SMMU_FIMC_DIS0, "smmu_fimc_dis0", "mout_aclk_266_isp_sub", + GATE_IP_ISP1, 5, 0, 0), + GATE(CLK_SMMU_FIMC_DIS1, "smmu_fimc_dis1", "mout_aclk_266_isp_sub", + GATE_IP_ISP1, 6, 0, 0), + GATE(CLK_SMMU_FIMC_3DNR, "smmu_fimc_3dnr", "mout_aclk_266_isp_sub", + GATE_IP_ISP1, 7, 0, 0), }; static struct samsung_pll_rate_table vpll_24mhz_tbl[] __initdata = { @@ -686,6 +735,8 @@ static struct of_device_id ext_clk_match[] __initdata = { /* register exynox5250 clocks */ static void __init exynos5250_clk_init(struct device_node *np) { + struct samsung_clk_provider *ctx; + if (np) { reg_base = of_iomap(np, 0); if (!reg_base) @@ -694,11 +745,13 @@ static void __init exynos5250_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS); - samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks, + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), ext_clk_match); - samsung_clk_register_mux(exynos5250_pll_pmux_clks, + samsung_clk_register_mux(ctx, exynos5250_pll_pmux_clks, ARRAY_SIZE(exynos5250_pll_pmux_clks)); if (_get_rate("fin_pll") == 24 * MHZ) { @@ -709,17 +762,18 @@ static void __init exynos5250_clk_init(struct device_node *np) if (_get_rate("mout_vpllsrc") == 24 * MHZ) exynos5250_plls[vpll].rate_table = vpll_24mhz_tbl; - samsung_clk_register_pll(exynos5250_plls, ARRAY_SIZE(exynos5250_plls), - reg_base); - samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks, + samsung_clk_register_pll(ctx, exynos5250_plls, + ARRAY_SIZE(exynos5250_plls), + reg_base); + samsung_clk_register_fixed_rate(ctx, exynos5250_fixed_rate_clks, ARRAY_SIZE(exynos5250_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks, + samsung_clk_register_fixed_factor(ctx, exynos5250_fixed_factor_clks, ARRAY_SIZE(exynos5250_fixed_factor_clks)); - samsung_clk_register_mux(exynos5250_mux_clks, + samsung_clk_register_mux(ctx, exynos5250_mux_clks, ARRAY_SIZE(exynos5250_mux_clks)); - samsung_clk_register_div(exynos5250_div_clks, + samsung_clk_register_div(ctx, exynos5250_div_clks, ARRAY_SIZE(exynos5250_div_clks)); - samsung_clk_register_gate(exynos5250_gate_clks, + samsung_clk_register_gate(ctx, exynos5250_gate_clks, ARRAY_SIZE(exynos5250_gate_clks)); exynos5250_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c new file mode 100644 index 0000000..64596ba --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5260.c @@ -0,0 +1,1980 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Rahul Sharma <rahul.sharma@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for Exynos5260 SoC. + */ + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/syscore_ops.h> + +#include "clk-exynos5260.h" +#include "clk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/exynos5260-clk.h> + +static LIST_HEAD(clock_reg_cache_list); + +struct exynos5260_clock_reg_cache { + struct list_head node; + void __iomem *reg_base; + struct samsung_clk_reg_dump *rdump; + unsigned int rd_num; +}; + +struct exynos5260_cmu_info { + /* list of pll clocks and respective count */ + struct samsung_pll_clock *pll_clks; + unsigned int nr_pll_clks; + /* list of mux clocks and respective count */ + struct samsung_mux_clock *mux_clks; + unsigned int nr_mux_clks; + /* list of div clocks and respective count */ + struct samsung_div_clock *div_clks; + unsigned int nr_div_clks; + /* list of gate clocks and respective count */ + struct samsung_gate_clock *gate_clks; + unsigned int nr_gate_clks; + /* list of fixed clocks and respective count */ + struct samsung_fixed_rate_clock *fixed_clks; + unsigned int nr_fixed_clks; + /* total number of clocks with IDs assigned*/ + unsigned int nr_clk_ids; + + /* list and number of clocks registers */ + unsigned long *clk_regs; + unsigned int nr_clk_regs; +}; + +/* + * Applicable for all 2550 Type PLLS for Exynos5260, listed below + * DISP_PLL, EGL_PLL, KFC_PLL, MEM_PLL, BUS_PLL, MEDIA_PLL, G3D_PLL. + */ +static struct samsung_pll_rate_table pll2550_24mhz_tbl[] __initdata = { + PLL_35XX_RATE(1700000000, 425, 6, 0), + PLL_35XX_RATE(1600000000, 200, 3, 0), + PLL_35XX_RATE(1500000000, 250, 4, 0), + PLL_35XX_RATE(1400000000, 175, 3, 0), + PLL_35XX_RATE(1300000000, 325, 6, 0), + PLL_35XX_RATE(1200000000, 400, 4, 1), + PLL_35XX_RATE(1100000000, 275, 3, 1), + PLL_35XX_RATE(1000000000, 250, 3, 1), + PLL_35XX_RATE(933000000, 311, 4, 1), + PLL_35XX_RATE(900000000, 300, 4, 1), + PLL_35XX_RATE(800000000, 200, 3, 1), + PLL_35XX_RATE(733000000, 733, 12, 1), + PLL_35XX_RATE(700000000, 175, 3, 1), + PLL_35XX_RATE(667000000, 667, 12, 1), + PLL_35XX_RATE(633000000, 211, 4, 1), + PLL_35XX_RATE(620000000, 310, 3, 2), + PLL_35XX_RATE(600000000, 400, 4, 2), + PLL_35XX_RATE(543000000, 362, 4, 2), + PLL_35XX_RATE(533000000, 533, 6, 2), + PLL_35XX_RATE(500000000, 250, 3, 2), + PLL_35XX_RATE(450000000, 300, 4, 2), + PLL_35XX_RATE(400000000, 200, 3, 2), + PLL_35XX_RATE(350000000, 175, 3, 2), + PLL_35XX_RATE(300000000, 400, 4, 3), + PLL_35XX_RATE(266000000, 266, 3, 3), + PLL_35XX_RATE(200000000, 200, 3, 3), + PLL_35XX_RATE(160000000, 160, 3, 3), +}; + +/* + * Applicable for 2650 Type PLL for AUD_PLL. + */ +static struct samsung_pll_rate_table pll2650_24mhz_tbl[] __initdata = { + PLL_36XX_RATE(1600000000, 200, 3, 0, 0), + PLL_36XX_RATE(1200000000, 100, 2, 0, 0), + PLL_36XX_RATE(1000000000, 250, 3, 1, 0), + PLL_36XX_RATE(800000000, 200, 3, 1, 0), + PLL_36XX_RATE(600000000, 100, 2, 1, 0), + PLL_36XX_RATE(532000000, 266, 3, 2, 0), + PLL_36XX_RATE(480000000, 160, 2, 2, 0), + PLL_36XX_RATE(432000000, 144, 2, 2, 0), + PLL_36XX_RATE(400000000, 200, 3, 2, 0), + PLL_36XX_RATE(394073130, 459, 7, 2, 49282), + PLL_36XX_RATE(333000000, 111, 2, 2, 0), + PLL_36XX_RATE(300000000, 100, 2, 2, 0), + PLL_36XX_RATE(266000000, 266, 3, 3, 0), + PLL_36XX_RATE(200000000, 200, 3, 3, 0), + PLL_36XX_RATE(166000000, 166, 3, 3, 0), + PLL_36XX_RATE(133000000, 266, 3, 4, 0), + PLL_36XX_RATE(100000000, 200, 3, 4, 0), + PLL_36XX_RATE(66000000, 176, 2, 5, 0), +}; + +#ifdef CONFIG_PM_SLEEP + +static int exynos5260_clk_suspend(void) +{ + struct exynos5260_clock_reg_cache *cache; + + list_for_each_entry(cache, &clock_reg_cache_list, node) + samsung_clk_save(cache->reg_base, cache->rdump, + cache->rd_num); + + return 0; +} + +static void exynos5260_clk_resume(void) +{ + struct exynos5260_clock_reg_cache *cache; + + list_for_each_entry(cache, &clock_reg_cache_list, node) + samsung_clk_restore(cache->reg_base, cache->rdump, + cache->rd_num); +} + +static struct syscore_ops exynos5260_clk_syscore_ops = { + .suspend = exynos5260_clk_suspend, + .resume = exynos5260_clk_resume, +}; + +static void exynos5260_clk_sleep_init(void __iomem *reg_base, + unsigned long *rdump, + unsigned long nr_rdump) +{ + struct exynos5260_clock_reg_cache *reg_cache; + + reg_cache = kzalloc(sizeof(struct exynos5260_clock_reg_cache), + GFP_KERNEL); + if (!reg_cache) + panic("could not allocate register cache.\n"); + + reg_cache->rdump = samsung_clk_alloc_reg_dump(rdump, nr_rdump); + + if (!reg_cache->rdump) + panic("could not allocate register dump storage.\n"); + + if (list_empty(&clock_reg_cache_list)) + register_syscore_ops(&exynos5260_clk_syscore_ops); + + reg_cache->rd_num = nr_rdump; + reg_cache->reg_base = reg_base; + list_add_tail(®_cache->node, &clock_reg_cache_list); +} + +#else +static void exynos5260_clk_sleep_init(void __iomem *reg_base, + unsigned long *rdump, + unsigned long nr_rdump){} +#endif + +/* + * Common function which registers plls, muxes, dividers and gates + * for each CMU. It also add CMU register list to register cache. + */ + +void __init exynos5260_cmu_register_one(struct device_node *np, + struct exynos5260_cmu_info *cmu) +{ + void __iomem *reg_base; + struct samsung_clk_provider *ctx; + + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + ctx = samsung_clk_init(np, reg_base, cmu->nr_clk_ids); + if (!ctx) + panic("%s: unable to alllocate ctx\n", __func__); + + if (cmu->pll_clks) + samsung_clk_register_pll(ctx, cmu->pll_clks, cmu->nr_pll_clks, + reg_base); + if (cmu->mux_clks) + samsung_clk_register_mux(ctx, cmu->mux_clks, + cmu->nr_mux_clks); + if (cmu->div_clks) + samsung_clk_register_div(ctx, cmu->div_clks, cmu->nr_div_clks); + if (cmu->gate_clks) + samsung_clk_register_gate(ctx, cmu->gate_clks, + cmu->nr_gate_clks); + if (cmu->fixed_clks) + samsung_clk_register_fixed_rate(ctx, cmu->fixed_clks, + cmu->nr_fixed_clks); + if (cmu->clk_regs) + exynos5260_clk_sleep_init(reg_base, cmu->clk_regs, + cmu->nr_clk_regs); +} + + +/* CMU_AUD */ + +static unsigned long aud_clk_regs[] __initdata = { + MUX_SEL_AUD, + DIV_AUD0, + DIV_AUD1, + EN_ACLK_AUD, + EN_PCLK_AUD, + EN_SCLK_AUD, + EN_IP_AUD, +}; + +PNAME(mout_aud_pll_user_p) = {"fin_pll", "fout_aud_pll"}; +PNAME(mout_sclk_aud_i2s_p) = {"mout_aud_pll_user", "ioclk_i2s_cdclk"}; +PNAME(mout_sclk_aud_pcm_p) = {"mout_aud_pll_user", "ioclk_pcm_extclk"}; + +struct samsung_mux_clock aud_mux_clks[] __initdata = { + MUX(AUD_MOUT_AUD_PLL_USER, "mout_aud_pll_user", mout_aud_pll_user_p, + MUX_SEL_AUD, 0, 1), + MUX(AUD_MOUT_SCLK_AUD_I2S, "mout_sclk_aud_i2s", mout_sclk_aud_i2s_p, + MUX_SEL_AUD, 4, 1), + MUX(AUD_MOUT_SCLK_AUD_PCM, "mout_sclk_aud_pcm", mout_sclk_aud_pcm_p, + MUX_SEL_AUD, 8, 1), +}; + +struct samsung_div_clock aud_div_clks[] __initdata = { + DIV(AUD_DOUT_ACLK_AUD_131, "dout_aclk_aud_131", "mout_aud_pll_user", + DIV_AUD0, 0, 4), + + DIV(AUD_DOUT_SCLK_AUD_I2S, "dout_sclk_aud_i2s", "mout_sclk_aud_i2s", + DIV_AUD1, 0, 4), + DIV(AUD_DOUT_SCLK_AUD_PCM, "dout_sclk_aud_pcm", "mout_sclk_aud_pcm", + DIV_AUD1, 4, 8), + DIV(AUD_DOUT_SCLK_AUD_UART, "dout_sclk_aud_uart", "mout_aud_pll_user", + DIV_AUD1, 12, 4), +}; + +struct samsung_gate_clock aud_gate_clks[] __initdata = { + GATE(AUD_SCLK_I2S, "sclk_aud_i2s", "dout_sclk_aud_i2s", + EN_SCLK_AUD, 0, CLK_SET_RATE_PARENT, 0), + GATE(AUD_SCLK_PCM, "sclk_aud_pcm", "dout_sclk_aud_pcm", + EN_SCLK_AUD, 1, CLK_SET_RATE_PARENT, 0), + GATE(AUD_SCLK_AUD_UART, "sclk_aud_uart", "dout_sclk_aud_uart", + EN_SCLK_AUD, 2, CLK_SET_RATE_PARENT, 0), + + GATE(AUD_CLK_SRAMC, "clk_sramc", "dout_aclk_aud_131", EN_IP_AUD, + 0, 0, 0), + GATE(AUD_CLK_DMAC, "clk_dmac", "dout_aclk_aud_131", + EN_IP_AUD, 1, 0, 0), + GATE(AUD_CLK_I2S, "clk_i2s", "dout_aclk_aud_131", EN_IP_AUD, 2, 0, 0), + GATE(AUD_CLK_PCM, "clk_pcm", "dout_aclk_aud_131", EN_IP_AUD, 3, 0, 0), + GATE(AUD_CLK_AUD_UART, "clk_aud_uart", "dout_aclk_aud_131", + EN_IP_AUD, 4, 0, 0), +}; + +static void __init exynos5260_clk_aud_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = aud_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(aud_mux_clks); + cmu.div_clks = aud_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(aud_div_clks); + cmu.gate_clks = aud_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(aud_gate_clks); + cmu.nr_clk_ids = AUD_NR_CLK; + cmu.clk_regs = aud_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(aud_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_aud, "samsung,exynos5260-clock-aud", + exynos5260_clk_aud_init); + + +/* CMU_DISP */ + +static unsigned long disp_clk_regs[] __initdata = { + MUX_SEL_DISP0, + MUX_SEL_DISP1, + MUX_SEL_DISP2, + MUX_SEL_DISP3, + MUX_SEL_DISP4, + DIV_DISP, + EN_ACLK_DISP, + EN_PCLK_DISP, + EN_SCLK_DISP0, + EN_SCLK_DISP1, + EN_IP_DISP, + EN_IP_DISP_BUS, +}; + +PNAME(mout_phyclk_dptx_phy_ch3_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch3_txd_clk"}; +PNAME(mout_phyclk_dptx_phy_ch2_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch2_txd_clk"}; +PNAME(mout_phyclk_dptx_phy_ch1_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch1_txd_clk"}; +PNAME(mout_phyclk_dptx_phy_ch0_txd_clk_user_p) = {"fin_pll", + "phyclk_dptx_phy_ch0_txd_clk"}; +PNAME(mout_aclk_disp_222_user_p) = {"fin_pll", "dout_aclk_disp_222"}; +PNAME(mout_sclk_disp_pixel_user_p) = {"fin_pll", "dout_sclk_disp_pixel"}; +PNAME(mout_aclk_disp_333_user_p) = {"fin_pll", "dout_aclk_disp_333"}; +PNAME(mout_phyclk_hdmi_phy_tmds_clko_user_p) = {"fin_pll", + "phyclk_hdmi_phy_tmds_clko"}; +PNAME(mout_phyclk_hdmi_phy_ref_clko_user_p) = {"fin_pll", + "phyclk_hdmi_phy_ref_clko"}; +PNAME(mout_phyclk_hdmi_phy_pixel_clko_user_p) = {"fin_pll", + "phyclk_hdmi_phy_pixel_clko"}; +PNAME(mout_phyclk_hdmi_link_o_tmds_clkhi_user_p) = {"fin_pll", + "phyclk_hdmi_link_o_tmds_clkhi"}; +PNAME(mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs_p) = {"fin_pll", + "phyclk_mipi_dphy_4l_m_txbyte_clkhs"}; +PNAME(mout_phyclk_dptx_phy_o_ref_clk_24m_user_p) = {"fin_pll", + "phyclk_dptx_phy_o_ref_clk_24m"}; +PNAME(mout_phyclk_dptx_phy_clk_div2_user_p) = {"fin_pll", + "phyclk_dptx_phy_clk_div2"}; +PNAME(mout_sclk_hdmi_pixel_p) = {"mout_sclk_disp_pixel_user", + "mout_aclk_disp_222_user"}; +PNAME(mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p) = {"fin_pll", + "phyclk_mipi_dphy_4l_m_rxclkesc0"}; +PNAME(mout_sclk_hdmi_spdif_p) = {"fin_pll", "ioclk_spdif_extclk", + "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; + +struct samsung_mux_clock disp_mux_clks[] __initdata = { + MUX(DISP_MOUT_ACLK_DISP_333_USER, "mout_aclk_disp_333_user", + mout_aclk_disp_333_user_p, + MUX_SEL_DISP0, 0, 1), + MUX(DISP_MOUT_SCLK_DISP_PIXEL_USER, "mout_sclk_disp_pixel_user", + mout_sclk_disp_pixel_user_p, + MUX_SEL_DISP0, 4, 1), + MUX(DISP_MOUT_ACLK_DISP_222_USER, "mout_aclk_disp_222_user", + mout_aclk_disp_222_user_p, + MUX_SEL_DISP0, 8, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH0_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch0_txd_clk_user", + mout_phyclk_dptx_phy_ch0_txd_clk_user_p, + MUX_SEL_DISP0, 16, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH1_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch1_txd_clk_user", + mout_phyclk_dptx_phy_ch1_txd_clk_user_p, + MUX_SEL_DISP0, 20, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH2_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch2_txd_clk_user", + mout_phyclk_dptx_phy_ch2_txd_clk_user_p, + MUX_SEL_DISP0, 24, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CH3_TXD_CLK_USER, + "mout_phyclk_dptx_phy_ch3_txd_clk_user", + mout_phyclk_dptx_phy_ch3_txd_clk_user_p, + MUX_SEL_DISP0, 28, 1), + + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_CLK_DIV2_USER, + "mout_phyclk_dptx_phy_clk_div2_user", + mout_phyclk_dptx_phy_clk_div2_user_p, + MUX_SEL_DISP1, 0, 1), + MUX(DISP_MOUT_PHYCLK_DPTX_PHY_O_REF_CLK_24M_USER, + "mout_phyclk_dptx_phy_o_ref_clk_24m_user", + mout_phyclk_dptx_phy_o_ref_clk_24m_user_p, + MUX_SEL_DISP1, 4, 1), + MUX(DISP_MOUT_PHYCLK_MIPI_DPHY_4L_M_TXBYTE_CLKHS, + "mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs", + mout_phyclk_mipi_dphy_4l_m_txbyte_clkhs_p, + MUX_SEL_DISP1, 8, 1), + MUX(DISP_MOUT_PHYCLK_HDMI_LINK_O_TMDS_CLKHI_USER, + "mout_phyclk_hdmi_link_o_tmds_clkhi_user", + mout_phyclk_hdmi_link_o_tmds_clkhi_user_p, + MUX_SEL_DISP1, 16, 1), + MUX(DISP_MOUT_HDMI_PHY_PIXEL, + "mout_phyclk_hdmi_phy_pixel_clko_user", + mout_phyclk_hdmi_phy_pixel_clko_user_p, + MUX_SEL_DISP1, 20, 1), + MUX(DISP_MOUT_PHYCLK_HDMI_PHY_REF_CLKO_USER, + "mout_phyclk_hdmi_phy_ref_clko_user", + mout_phyclk_hdmi_phy_ref_clko_user_p, + MUX_SEL_DISP1, 24, 1), + MUX(DISP_MOUT_PHYCLK_HDMI_PHY_TMDS_CLKO_USER, + "mout_phyclk_hdmi_phy_tmds_clko_user", + mout_phyclk_hdmi_phy_tmds_clko_user_p, + MUX_SEL_DISP1, 28, 1), + + MUX(DISP_MOUT_PHYCLK_MIPI_DPHY_4LMRXCLK_ESC0_USER, + "mout_phyclk_mipi_dphy_4lmrxclk_esc0_user", + mout_phyclk_mipi_dphy_4lmrxclk_esc0_user_p, + MUX_SEL_DISP2, 0, 1), + MUX(DISP_MOUT_SCLK_HDMI_PIXEL, "mout_sclk_hdmi_pixel", + mout_sclk_hdmi_pixel_p, + MUX_SEL_DISP2, 4, 1), + + MUX(DISP_MOUT_SCLK_HDMI_SPDIF, "mout_sclk_hdmi_spdif", + mout_sclk_hdmi_spdif_p, + MUX_SEL_DISP4, 4, 2), +}; + +struct samsung_div_clock disp_div_clks[] __initdata = { + DIV(DISP_DOUT_PCLK_DISP_111, "dout_pclk_disp_111", + "mout_aclk_disp_222_user", + DIV_DISP, 8, 4), + DIV(DISP_DOUT_SCLK_FIMD1_EXTCLKPLL, "dout_sclk_fimd1_extclkpll", + "mout_sclk_disp_pixel_user", + DIV_DISP, 12, 4), + DIV(DISP_DOUT_SCLK_HDMI_PHY_PIXEL_CLKI, + "dout_sclk_hdmi_phy_pixel_clki", + "mout_sclk_hdmi_pixel", + DIV_DISP, 16, 4), +}; + +struct samsung_gate_clock disp_gate_clks[] __initdata = { + GATE(DISP_MOUT_HDMI_PHY_PIXEL_USER, "sclk_hdmi_link_i_pixel", + "mout_phyclk_hdmi_phy_pixel_clko_user", + EN_SCLK_DISP0, 26, CLK_SET_RATE_PARENT, 0), + GATE(DISP_SCLK_PIXEL, "sclk_hdmi_phy_pixel_clki", + "dout_sclk_hdmi_phy_pixel_clki", + EN_SCLK_DISP0, 29, CLK_SET_RATE_PARENT, 0), + + GATE(DISP_CLK_DP, "clk_dptx_link", "mout_aclk_disp_222_user", + EN_IP_DISP, 4, 0, 0), + GATE(DISP_CLK_DPPHY, "clk_dptx_phy", "mout_aclk_disp_222_user", + EN_IP_DISP, 5, 0, 0), + GATE(DISP_CLK_DSIM1, "clk_dsim1", "mout_aclk_disp_222_user", + EN_IP_DISP, 6, 0, 0), + GATE(DISP_CLK_FIMD1, "clk_fimd1", "mout_aclk_disp_222_user", + EN_IP_DISP, 7, 0, 0), + GATE(DISP_CLK_HDMI, "clk_hdmi", "mout_aclk_disp_222_user", + EN_IP_DISP, 8, 0, 0), + GATE(DISP_CLK_HDMIPHY, "clk_hdmiphy", "mout_aclk_disp_222_user", + EN_IP_DISP, 9, 0, 0), + GATE(DISP_CLK_MIPIPHY, "clk_mipi_dphy", "mout_aclk_disp_222_user", + EN_IP_DISP, 10, 0, 0), + GATE(DISP_CLK_MIXER, "clk_mixer", "mout_aclk_disp_222_user", + EN_IP_DISP, 11, 0, 0), + GATE(DISP_CLK_PIXEL_DISP, "clk_pixel_disp", "mout_aclk_disp_222_user", + EN_IP_DISP, 12, CLK_IGNORE_UNUSED, 0), + GATE(DISP_CLK_PIXEL_MIXER, "clk_pixel_mixer", "mout_aclk_disp_222_user", + EN_IP_DISP, 13, CLK_IGNORE_UNUSED, 0), + GATE(DISP_CLK_SMMU_FIMD1M0, "clk_smmu3_fimd1m0", + "mout_aclk_disp_222_user", + EN_IP_DISP, 22, 0, 0), + GATE(DISP_CLK_SMMU_FIMD1M1, "clk_smmu3_fimd1m1", + "mout_aclk_disp_222_user", + EN_IP_DISP, 23, 0, 0), + GATE(DISP_CLK_SMMU_TV, "clk_smmu3_tv", "mout_aclk_disp_222_user", + EN_IP_DISP, 25, 0, 0), +}; + +static void __init exynos5260_clk_disp_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = disp_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(disp_mux_clks); + cmu.div_clks = disp_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(disp_div_clks); + cmu.gate_clks = disp_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(disp_gate_clks); + cmu.nr_clk_ids = DISP_NR_CLK; + cmu.clk_regs = disp_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(disp_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_disp, "samsung,exynos5260-clock-disp", + exynos5260_clk_disp_init); + + +/* CMU_EGL */ + +static unsigned long egl_clk_regs[] __initdata = { + EGL_PLL_LOCK, + EGL_PLL_CON0, + EGL_PLL_CON1, + EGL_PLL_FREQ_DET, + MUX_SEL_EGL, + MUX_ENABLE_EGL, + DIV_EGL, + DIV_EGL_PLL_FDET, + EN_ACLK_EGL, + EN_PCLK_EGL, + EN_SCLK_EGL, +}; + +PNAME(mout_egl_b_p) = {"mout_egl_pll", "dout_bus_pll"}; +PNAME(mout_egl_pll_p) = {"fin_pll", "fout_egl_pll"}; + +struct samsung_mux_clock egl_mux_clks[] __initdata = { + MUX(EGL_MOUT_EGL_PLL, "mout_egl_pll", mout_egl_pll_p, + MUX_SEL_EGL, 4, 1), + MUX(EGL_MOUT_EGL_B, "mout_egl_b", mout_egl_b_p, MUX_SEL_EGL, 16, 1), +}; + +struct samsung_div_clock egl_div_clks[] __initdata = { + DIV(EGL_DOUT_EGL1, "dout_egl1", "mout_egl_b", DIV_EGL, 0, 3), + DIV(EGL_DOUT_EGL2, "dout_egl2", "dout_egl1", DIV_EGL, 4, 3), + DIV(EGL_DOUT_ACLK_EGL, "dout_aclk_egl", "dout_egl2", DIV_EGL, 8, 3), + DIV(EGL_DOUT_PCLK_EGL, "dout_pclk_egl", "dout_egl_atclk", + DIV_EGL, 12, 3), + DIV(EGL_DOUT_EGL_ATCLK, "dout_egl_atclk", "dout_egl2", DIV_EGL, 16, 3), + DIV(EGL_DOUT_EGL_PCLK_DBG, "dout_egl_pclk_dbg", "dout_egl_atclk", + DIV_EGL, 20, 3), + DIV(EGL_DOUT_EGL_PLL, "dout_egl_pll", "mout_egl_b", DIV_EGL, 24, 3), +}; + +static struct samsung_pll_clock egl_pll_clks[] __initdata = { + PLL(pll_2550xx, EGL_FOUT_EGL_PLL, "fout_egl_pll", "fin_pll", + EGL_PLL_LOCK, EGL_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_egl_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.pll_clks = egl_pll_clks; + cmu.nr_pll_clks = ARRAY_SIZE(egl_pll_clks); + cmu.mux_clks = egl_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(egl_mux_clks); + cmu.div_clks = egl_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(egl_div_clks); + cmu.nr_clk_ids = EGL_NR_CLK; + cmu.clk_regs = egl_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(egl_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_egl, "samsung,exynos5260-clock-egl", + exynos5260_clk_egl_init); + + +/* CMU_FSYS */ + +static unsigned long fsys_clk_regs[] __initdata = { + MUX_SEL_FSYS0, + MUX_SEL_FSYS1, + EN_ACLK_FSYS, + EN_ACLK_FSYS_SECURE_RTIC, + EN_ACLK_FSYS_SECURE_SMMU_RTIC, + EN_SCLK_FSYS, + EN_IP_FSYS, + EN_IP_FSYS_SECURE_RTIC, + EN_IP_FSYS_SECURE_SMMU_RTIC, +}; + +PNAME(mout_phyclk_usbhost20_phyclk_user_p) = {"fin_pll", + "phyclk_usbhost20_phy_phyclock"}; +PNAME(mout_phyclk_usbhost20_freeclk_user_p) = {"fin_pll", + "phyclk_usbhost20_phy_freeclk"}; +PNAME(mout_phyclk_usbhost20_clk48mohci_user_p) = {"fin_pll", + "phyclk_usbhost20_phy_clk48mohci"}; +PNAME(mout_phyclk_usbdrd30_pipe_pclk_user_p) = {"fin_pll", + "phyclk_usbdrd30_udrd30_pipe_pclk"}; +PNAME(mout_phyclk_usbdrd30_phyclock_user_p) = {"fin_pll", + "phyclk_usbdrd30_udrd30_phyclock"}; + +struct samsung_mux_clock fsys_mux_clks[] __initdata = { + MUX(FSYS_MOUT_PHYCLK_USBDRD30_PHYCLOCK_USER, + "mout_phyclk_usbdrd30_phyclock_user", + mout_phyclk_usbdrd30_phyclock_user_p, + MUX_SEL_FSYS1, 0, 1), + MUX(FSYS_MOUT_PHYCLK_USBDRD30_PIPE_PCLK_USER, + "mout_phyclk_usbdrd30_pipe_pclk_user", + mout_phyclk_usbdrd30_pipe_pclk_user_p, + MUX_SEL_FSYS1, 4, 1), + MUX(FSYS_MOUT_PHYCLK_USBHOST20_CLK48MOHCI_USER, + "mout_phyclk_usbhost20_clk48mohci_user", + mout_phyclk_usbhost20_clk48mohci_user_p, + MUX_SEL_FSYS1, 8, 1), + MUX(FSYS_MOUT_PHYCLK_USBHOST20_FREECLK_USER, + "mout_phyclk_usbhost20_freeclk_user", + mout_phyclk_usbhost20_freeclk_user_p, + MUX_SEL_FSYS1, 12, 1), + MUX(FSYS_MOUT_PHYCLK_USBHOST20_PHYCLK_USER, + "mout_phyclk_usbhost20_phyclk_user", + mout_phyclk_usbhost20_phyclk_user_p, + MUX_SEL_FSYS1, 16, 1), +}; + +struct samsung_gate_clock fsys_gate_clks[] __initdata = { + GATE(FSYS_PHYCLK_USBHOST20, "phyclk_usbhost20_phyclock", + "mout_phyclk_usbdrd30_phyclock_user", + EN_SCLK_FSYS, 1, 0, 0), + GATE(FSYS_PHYCLK_USBDRD30, "phyclk_usbdrd30_udrd30_phyclock_g", + "mout_phyclk_usbdrd30_phyclock_user", + EN_SCLK_FSYS, 7, 0, 0), + + GATE(FSYS_CLK_MMC0, "clk_mmc0", "dout_aclk_fsys_200", + EN_IP_FSYS, 6, 0, 0), + GATE(FSYS_CLK_MMC1, "clk_mmc1", "dout_aclk_fsys_200", + EN_IP_FSYS, 7, 0, 0), + GATE(FSYS_CLK_MMC2, "clk_mmc2", "dout_aclk_fsys_200", + EN_IP_FSYS, 8, 0, 0), + GATE(FSYS_CLK_PDMA, "clk_pdma", "dout_aclk_fsys_200", + EN_IP_FSYS, 9, 0, 0), + GATE(FSYS_CLK_SROMC, "clk_sromc", "dout_aclk_fsys_200", + EN_IP_FSYS, 13, 0, 0), + GATE(FSYS_CLK_USBDRD30, "clk_usbdrd30", "dout_aclk_fsys_200", + EN_IP_FSYS, 14, 0, 0), + GATE(FSYS_CLK_USBHOST20, "clk_usbhost20", "dout_aclk_fsys_200", + EN_IP_FSYS, 15, 0, 0), + GATE(FSYS_CLK_USBLINK, "clk_usblink", "dout_aclk_fsys_200", + EN_IP_FSYS, 18, 0, 0), + GATE(FSYS_CLK_TSI, "clk_tsi", "dout_aclk_fsys_200", + EN_IP_FSYS, 20, 0, 0), + + GATE(FSYS_CLK_RTIC, "clk_rtic", "dout_aclk_fsys_200", + EN_IP_FSYS_SECURE_RTIC, 11, 0, 0), + GATE(FSYS_CLK_SMMU_RTIC, "clk_smmu_rtic", "dout_aclk_fsys_200", + EN_IP_FSYS_SECURE_SMMU_RTIC, 12, 0, 0), +}; + +static void __init exynos5260_clk_fsys_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = fsys_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(fsys_mux_clks); + cmu.gate_clks = fsys_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(fsys_gate_clks); + cmu.nr_clk_ids = FSYS_NR_CLK; + cmu.clk_regs = fsys_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(fsys_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_fsys, "samsung,exynos5260-clock-fsys", + exynos5260_clk_fsys_init); + + +/* CMU_G2D */ + +static unsigned long g2d_clk_regs[] __initdata = { + MUX_SEL_G2D, + MUX_STAT_G2D, + DIV_G2D, + EN_ACLK_G2D, + EN_ACLK_G2D_SECURE_SSS, + EN_ACLK_G2D_SECURE_SLIM_SSS, + EN_ACLK_G2D_SECURE_SMMU_SLIM_SSS, + EN_ACLK_G2D_SECURE_SMMU_SSS, + EN_ACLK_G2D_SECURE_SMMU_MDMA, + EN_ACLK_G2D_SECURE_SMMU_G2D, + EN_PCLK_G2D, + EN_PCLK_G2D_SECURE_SMMU_SLIM_SSS, + EN_PCLK_G2D_SECURE_SMMU_SSS, + EN_PCLK_G2D_SECURE_SMMU_MDMA, + EN_PCLK_G2D_SECURE_SMMU_G2D, + EN_IP_G2D, + EN_IP_G2D_SECURE_SSS, + EN_IP_G2D_SECURE_SLIM_SSS, + EN_IP_G2D_SECURE_SMMU_SLIM_SSS, + EN_IP_G2D_SECURE_SMMU_SSS, + EN_IP_G2D_SECURE_SMMU_MDMA, + EN_IP_G2D_SECURE_SMMU_G2D, +}; + +PNAME(mout_aclk_g2d_333_user_p) = {"fin_pll", "dout_aclk_g2d_333"}; + +struct samsung_mux_clock g2d_mux_clks[] __initdata = { + MUX(G2D_MOUT_ACLK_G2D_333_USER, "mout_aclk_g2d_333_user", + mout_aclk_g2d_333_user_p, + MUX_SEL_G2D, 0, 1), +}; + +struct samsung_div_clock g2d_div_clks[] __initdata = { + DIV(G2D_DOUT_PCLK_G2D_83, "dout_pclk_g2d_83", "mout_aclk_g2d_333_user", + DIV_G2D, 0, 3), +}; + +struct samsung_gate_clock g2d_gate_clks[] __initdata = { + GATE(G2D_CLK_G2D, "clk_g2d", "mout_aclk_g2d_333_user", + EN_IP_G2D, 4, 0, 0), + GATE(G2D_CLK_JPEG, "clk_jpeg", "mout_aclk_g2d_333_user", + EN_IP_G2D, 5, 0, 0), + GATE(G2D_CLK_MDMA, "clk_mdma", "mout_aclk_g2d_333_user", + EN_IP_G2D, 6, 0, 0), + GATE(G2D_CLK_SMMU3_JPEG, "clk_smmu3_jpeg", "mout_aclk_g2d_333_user", + EN_IP_G2D, 16, 0, 0), + + GATE(G2D_CLK_SSS, "clk_sss", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SSS, 17, 0, 0), + + GATE(G2D_CLK_SLIM_SSS, "clk_slim_sss", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SLIM_SSS, 11, 0, 0), + + GATE(G2D_CLK_SMMU_SLIM_SSS, "clk_smmu_slim_sss", + "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_SLIM_SSS, 13, 0, 0), + + GATE(G2D_CLK_SMMU_SSS, "clk_smmu_sss", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_SSS, 14, 0, 0), + + GATE(G2D_CLK_SMMU_MDMA, "clk_smmu_mdma", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_MDMA, 12, 0, 0), + + GATE(G2D_CLK_SMMU3_G2D, "clk_smmu3_g2d", "mout_aclk_g2d_333_user", + EN_IP_G2D_SECURE_SMMU_G2D, 15, 0, 0), +}; + +static void __init exynos5260_clk_g2d_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = g2d_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(g2d_mux_clks); + cmu.div_clks = g2d_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(g2d_div_clks); + cmu.gate_clks = g2d_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(g2d_gate_clks); + cmu.nr_clk_ids = G2D_NR_CLK; + cmu.clk_regs = g2d_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(g2d_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_g2d, "samsung,exynos5260-clock-g2d", + exynos5260_clk_g2d_init); + + +/* CMU_G3D */ + +static unsigned long g3d_clk_regs[] __initdata = { + G3D_PLL_LOCK, + G3D_PLL_CON0, + G3D_PLL_CON1, + G3D_PLL_FDET, + MUX_SEL_G3D, + DIV_G3D, + DIV_G3D_PLL_FDET, + EN_ACLK_G3D, + EN_PCLK_G3D, + EN_SCLK_G3D, + EN_IP_G3D, +}; + +PNAME(mout_g3d_pll_p) = {"fin_pll", "fout_g3d_pll"}; + +struct samsung_mux_clock g3d_mux_clks[] __initdata = { + MUX(G3D_MOUT_G3D_PLL, "mout_g3d_pll", mout_g3d_pll_p, + MUX_SEL_G3D, 0, 1), +}; + +struct samsung_div_clock g3d_div_clks[] __initdata = { + DIV(G3D_DOUT_PCLK_G3D, "dout_pclk_g3d", "dout_aclk_g3d", DIV_G3D, 0, 3), + DIV(G3D_DOUT_ACLK_G3D, "dout_aclk_g3d", "mout_g3d_pll", DIV_G3D, 4, 3), +}; + +struct samsung_gate_clock g3d_gate_clks[] __initdata = { + GATE(G3D_CLK_G3D, "clk_g3d", "dout_aclk_g3d", EN_IP_G3D, 2, 0, 0), + GATE(G3D_CLK_G3D_HPM, "clk_g3d_hpm", "dout_aclk_g3d", + EN_IP_G3D, 3, 0, 0), +}; + +static struct samsung_pll_clock g3d_pll_clks[] __initdata = { + PLL(pll_2550, G3D_FOUT_G3D_PLL, "fout_g3d_pll", "fin_pll", + G3D_PLL_LOCK, G3D_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_g3d_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.pll_clks = g3d_pll_clks; + cmu.nr_pll_clks = ARRAY_SIZE(g3d_pll_clks); + cmu.mux_clks = g3d_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(g3d_mux_clks); + cmu.div_clks = g3d_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(g3d_div_clks); + cmu.gate_clks = g3d_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(g3d_gate_clks); + cmu.nr_clk_ids = G3D_NR_CLK; + cmu.clk_regs = g3d_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(g3d_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_g3d, "samsung,exynos5260-clock-g3d", + exynos5260_clk_g3d_init); + + +/* CMU_GSCL */ + +static unsigned long gscl_clk_regs[] __initdata = { + MUX_SEL_GSCL, + DIV_GSCL, + EN_ACLK_GSCL, + EN_ACLK_GSCL_FIMC, + EN_ACLK_GSCL_SECURE_SMMU_GSCL0, + EN_ACLK_GSCL_SECURE_SMMU_GSCL1, + EN_ACLK_GSCL_SECURE_SMMU_MSCL0, + EN_ACLK_GSCL_SECURE_SMMU_MSCL1, + EN_PCLK_GSCL, + EN_PCLK_GSCL_FIMC, + EN_PCLK_GSCL_SECURE_SMMU_GSCL0, + EN_PCLK_GSCL_SECURE_SMMU_GSCL1, + EN_PCLK_GSCL_SECURE_SMMU_MSCL0, + EN_PCLK_GSCL_SECURE_SMMU_MSCL1, + EN_SCLK_GSCL, + EN_SCLK_GSCL_FIMC, + EN_IP_GSCL, + EN_IP_GSCL_FIMC, + EN_IP_GSCL_SECURE_SMMU_GSCL0, + EN_IP_GSCL_SECURE_SMMU_GSCL1, + EN_IP_GSCL_SECURE_SMMU_MSCL0, + EN_IP_GSCL_SECURE_SMMU_MSCL1, +}; + +PNAME(mout_aclk_gscl_333_user_p) = {"fin_pll", "dout_aclk_gscl_333"}; +PNAME(mout_aclk_m2m_400_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; +PNAME(mout_aclk_gscl_fimc_user_p) = {"fin_pll", "dout_aclk_gscl_400"}; +PNAME(mout_aclk_csis_p) = {"dout_aclk_csis_200", "mout_aclk_gscl_fimc_user"}; + +struct samsung_mux_clock gscl_mux_clks[] __initdata = { + MUX(GSCL_MOUT_ACLK_GSCL_333_USER, "mout_aclk_gscl_333_user", + mout_aclk_gscl_333_user_p, + MUX_SEL_GSCL, 0, 1), + MUX(GSCL_MOUT_ACLK_M2M_400_USER, "mout_aclk_m2m_400_user", + mout_aclk_m2m_400_user_p, + MUX_SEL_GSCL, 4, 1), + MUX(GSCL_MOUT_ACLK_GSCL_FIMC_USER, "mout_aclk_gscl_fimc_user", + mout_aclk_gscl_fimc_user_p, + MUX_SEL_GSCL, 8, 1), + MUX(GSCL_MOUT_ACLK_CSIS, "mout_aclk_csis", mout_aclk_csis_p, + MUX_SEL_GSCL, 24, 1), +}; + +struct samsung_div_clock gscl_div_clks[] __initdata = { + DIV(GSCL_DOUT_PCLK_M2M_100, "dout_pclk_m2m_100", + "mout_aclk_m2m_400_user", + DIV_GSCL, 0, 3), + DIV(GSCL_DOUT_ACLK_CSIS_200, "dout_aclk_csis_200", + "mout_aclk_m2m_400_user", + DIV_GSCL, 4, 3), +}; + +struct samsung_gate_clock gscl_gate_clks[] __initdata = { + GATE(GSCL_SCLK_CSIS0_WRAP, "sclk_csis0_wrap", "dout_aclk_csis_200", + EN_SCLK_GSCL_FIMC, 0, CLK_SET_RATE_PARENT, 0), + GATE(GSCL_SCLK_CSIS1_WRAP, "sclk_csis1_wrap", "dout_aclk_csis_200", + EN_SCLK_GSCL_FIMC, 1, CLK_SET_RATE_PARENT, 0), + + GATE(GSCL_CLK_GSCL0, "clk_gscl0", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 2, 0, 0), + GATE(GSCL_CLK_GSCL1, "clk_gscl1", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 3, 0, 0), + GATE(GSCL_CLK_MSCL0, "clk_mscl0", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 4, 0, 0), + GATE(GSCL_CLK_MSCL1, "clk_mscl1", "mout_aclk_gscl_333_user", + EN_IP_GSCL, 5, 0, 0), + GATE(GSCL_CLK_PIXEL_GSCL0, "clk_pixel_gscl0", + "mout_aclk_gscl_333_user", + EN_IP_GSCL, 8, 0, 0), + GATE(GSCL_CLK_PIXEL_GSCL1, "clk_pixel_gscl1", + "mout_aclk_gscl_333_user", + EN_IP_GSCL, 9, 0, 0), + + GATE(GSCL_CLK_SMMU3_LITE_A, "clk_smmu3_lite_a", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 5, 0, 0), + GATE(GSCL_CLK_SMMU3_LITE_B, "clk_smmu3_lite_b", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 6, 0, 0), + GATE(GSCL_CLK_SMMU3_LITE_D, "clk_smmu3_lite_d", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 7, 0, 0), + GATE(GSCL_CLK_CSIS0, "clk_csis0", "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 8, 0, 0), + GATE(GSCL_CLK_CSIS1, "clk_csis1", "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 9, 0, 0), + GATE(GSCL_CLK_FIMC_LITE_A, "clk_fimc_lite_a", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 10, 0, 0), + GATE(GSCL_CLK_FIMC_LITE_B, "clk_fimc_lite_b", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 11, 0, 0), + GATE(GSCL_CLK_FIMC_LITE_D, "clk_fimc_lite_d", + "mout_aclk_gscl_fimc_user", + EN_IP_GSCL_FIMC, 12, 0, 0), + + GATE(GSCL_CLK_SMMU3_GSCL0, "clk_smmu3_gscl0", + "mout_aclk_gscl_333_user", + EN_IP_GSCL_SECURE_SMMU_GSCL0, 17, 0, 0), + GATE(GSCL_CLK_SMMU3_GSCL1, "clk_smmu3_gscl1", "mout_aclk_gscl_333_user", + EN_IP_GSCL_SECURE_SMMU_GSCL1, 18, 0, 0), + GATE(GSCL_CLK_SMMU3_MSCL0, "clk_smmu3_mscl0", + "mout_aclk_m2m_400_user", + EN_IP_GSCL_SECURE_SMMU_MSCL0, 19, 0, 0), + GATE(GSCL_CLK_SMMU3_MSCL1, "clk_smmu3_mscl1", + "mout_aclk_m2m_400_user", + EN_IP_GSCL_SECURE_SMMU_MSCL1, 20, 0, 0), +}; + +static void __init exynos5260_clk_gscl_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = gscl_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(gscl_mux_clks); + cmu.div_clks = gscl_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(gscl_div_clks); + cmu.gate_clks = gscl_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(gscl_gate_clks); + cmu.nr_clk_ids = GSCL_NR_CLK; + cmu.clk_regs = gscl_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(gscl_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_gscl, "samsung,exynos5260-clock-gscl", + exynos5260_clk_gscl_init); + + +/* CMU_ISP */ + +static unsigned long isp_clk_regs[] __initdata = { + MUX_SEL_ISP0, + MUX_SEL_ISP1, + DIV_ISP, + EN_ACLK_ISP0, + EN_ACLK_ISP1, + EN_PCLK_ISP0, + EN_PCLK_ISP1, + EN_SCLK_ISP, + EN_IP_ISP0, + EN_IP_ISP1, +}; + +PNAME(mout_isp_400_user_p) = {"fin_pll", "dout_aclk_isp1_400"}; +PNAME(mout_isp_266_user_p) = {"fin_pll", "dout_aclk_isp1_266"}; + +struct samsung_mux_clock isp_mux_clks[] __initdata = { + MUX(ISP_MOUT_ISP_266_USER, "mout_isp_266_user", mout_isp_266_user_p, + MUX_SEL_ISP0, 0, 1), + MUX(ISP_MOUT_ISP_400_USER, "mout_isp_400_user", mout_isp_400_user_p, + MUX_SEL_ISP0, 4, 1), +}; + +struct samsung_div_clock isp_div_clks[] __initdata = { + DIV(ISP_DOUT_PCLK_ISP_66, "dout_pclk_isp_66", "mout_kfc", + DIV_ISP, 0, 3), + DIV(ISP_DOUT_PCLK_ISP_133, "dout_pclk_isp_133", "mout_kfc", + DIV_ISP, 4, 4), + DIV(ISP_DOUT_CA5_ATCLKIN, "dout_ca5_atclkin", "mout_kfc", + DIV_ISP, 12, 3), + DIV(ISP_DOUT_CA5_PCLKDBG, "dout_ca5_pclkdbg", "mout_kfc", + DIV_ISP, 16, 4), + DIV(ISP_DOUT_SCLK_MPWM, "dout_sclk_mpwm", "mout_kfc", DIV_ISP, 20, 2), +}; + +struct samsung_gate_clock isp_gate_clks[] __initdata = { + GATE(ISP_CLK_GIC, "clk_isp_gic", "mout_aclk_isp1_266", + EN_IP_ISP0, 15, 0, 0), + + GATE(ISP_CLK_CA5, "clk_isp_ca5", "mout_aclk_isp1_266", + EN_IP_ISP1, 1, 0, 0), + GATE(ISP_CLK_FIMC_DRC, "clk_isp_fimc_drc", "mout_aclk_isp1_266", + EN_IP_ISP1, 2, 0, 0), + GATE(ISP_CLK_FIMC_FD, "clk_isp_fimc_fd", "mout_aclk_isp1_266", + EN_IP_ISP1, 3, 0, 0), + GATE(ISP_CLK_FIMC, "clk_isp_fimc", "mout_aclk_isp1_266", + EN_IP_ISP1, 4, 0, 0), + GATE(ISP_CLK_FIMC_SCALERC, "clk_isp_fimc_scalerc", + "mout_aclk_isp1_266", + EN_IP_ISP1, 5, 0, 0), + GATE(ISP_CLK_FIMC_SCALERP, "clk_isp_fimc_scalerp", + "mout_aclk_isp1_266", + EN_IP_ISP1, 6, 0, 0), + GATE(ISP_CLK_I2C0, "clk_isp_i2c0", "mout_aclk_isp1_266", + EN_IP_ISP1, 7, 0, 0), + GATE(ISP_CLK_I2C1, "clk_isp_i2c1", "mout_aclk_isp1_266", + EN_IP_ISP1, 8, 0, 0), + GATE(ISP_CLK_MCUCTL, "clk_isp_mcuctl", "mout_aclk_isp1_266", + EN_IP_ISP1, 9, 0, 0), + GATE(ISP_CLK_MPWM, "clk_isp_mpwm", "mout_aclk_isp1_266", + EN_IP_ISP1, 10, 0, 0), + GATE(ISP_CLK_MTCADC, "clk_isp_mtcadc", "mout_aclk_isp1_266", + EN_IP_ISP1, 11, 0, 0), + GATE(ISP_CLK_PWM, "clk_isp_pwm", "mout_aclk_isp1_266", + EN_IP_ISP1, 14, 0, 0), + GATE(ISP_CLK_SMMU_DRC, "clk_smmu_drc", "mout_aclk_isp1_266", + EN_IP_ISP1, 21, 0, 0), + GATE(ISP_CLK_SMMU_FD, "clk_smmu_fd", "mout_aclk_isp1_266", + EN_IP_ISP1, 22, 0, 0), + GATE(ISP_CLK_SMMU_ISP, "clk_smmu_isp", "mout_aclk_isp1_266", + EN_IP_ISP1, 23, 0, 0), + GATE(ISP_CLK_SMMU_ISPCX, "clk_smmu_ispcx", "mout_aclk_isp1_266", + EN_IP_ISP1, 24, 0, 0), + GATE(ISP_CLK_SMMU_SCALERC, "clk_isp_smmu_scalerc", + "mout_aclk_isp1_266", + EN_IP_ISP1, 25, 0, 0), + GATE(ISP_CLK_SMMU_SCALERP, "clk_isp_smmu_scalerp", + "mout_aclk_isp1_266", + EN_IP_ISP1, 26, 0, 0), + GATE(ISP_CLK_SPI0, "clk_isp_spi0", "mout_aclk_isp1_266", + EN_IP_ISP1, 27, 0, 0), + GATE(ISP_CLK_SPI1, "clk_isp_spi1", "mout_aclk_isp1_266", + EN_IP_ISP1, 28, 0, 0), + GATE(ISP_CLK_WDT, "clk_isp_wdt", "mout_aclk_isp1_266", + EN_IP_ISP1, 31, 0, 0), + GATE(ISP_CLK_UART, "clk_isp_uart", "mout_aclk_isp1_266", + EN_IP_ISP1, 30, 0, 0), + + GATE(ISP_SCLK_UART_EXT, "sclk_isp_uart_ext", "fin_pll", + EN_SCLK_ISP, 7, CLK_SET_RATE_PARENT, 0), + GATE(ISP_SCLK_SPI1_EXT, "sclk_isp_spi1_ext", "fin_pll", + EN_SCLK_ISP, 8, CLK_SET_RATE_PARENT, 0), + GATE(ISP_SCLK_SPI0_EXT, "sclk_isp_spi0_ext", "fin_pll", + EN_SCLK_ISP, 9, CLK_SET_RATE_PARENT, 0), +}; + +static void __init exynos5260_clk_isp_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = isp_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(isp_mux_clks); + cmu.div_clks = isp_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(isp_div_clks); + cmu.gate_clks = isp_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(isp_gate_clks); + cmu.nr_clk_ids = ISP_NR_CLK; + cmu.clk_regs = isp_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(isp_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_isp, "samsung,exynos5260-clock-isp", + exynos5260_clk_isp_init); + + +/* CMU_KFC */ + +static unsigned long kfc_clk_regs[] __initdata = { + KFC_PLL_LOCK, + KFC_PLL_CON0, + KFC_PLL_CON1, + KFC_PLL_FDET, + MUX_SEL_KFC0, + MUX_SEL_KFC2, + DIV_KFC, + DIV_KFC_PLL_FDET, + EN_ACLK_KFC, + EN_PCLK_KFC, + EN_SCLK_KFC, + EN_IP_KFC, +}; + +PNAME(mout_kfc_pll_p) = {"fin_pll", "fout_kfc_pll"}; +PNAME(mout_kfc_p) = {"mout_kfc_pll", "dout_media_pll"}; + +struct samsung_mux_clock kfc_mux_clks[] __initdata = { + MUX(KFC_MOUT_KFC_PLL, "mout_kfc_pll", mout_kfc_pll_p, + MUX_SEL_KFC0, 0, 1), + MUX(KFC_MOUT_KFC, "mout_kfc", mout_kfc_p, MUX_SEL_KFC2, 0, 1), +}; + +struct samsung_div_clock kfc_div_clks[] __initdata = { + DIV(KFC_DOUT_KFC1, "dout_kfc1", "mout_kfc", DIV_KFC, 0, 3), + DIV(KFC_DOUT_KFC2, "dout_kfc2", "dout_kfc1", DIV_KFC, 4, 3), + DIV(KFC_DOUT_KFC_ATCLK, "dout_kfc_atclk", "dout_kfc2", DIV_KFC, 8, 3), + DIV(KFC_DOUT_KFC_PCLK_DBG, "dout_kfc_pclk_dbg", "dout_kfc2", + DIV_KFC, 12, 3), + DIV(KFC_DOUT_ACLK_KFC, "dout_aclk_kfc", "dout_kfc2", DIV_KFC, 16, 3), + DIV(KFC_DOUT_PCLK_KFC, "dout_pclk_kfc", "dout_kfc2", DIV_KFC, 20, 3), + DIV(KFC_DOUT_KFC_PLL, "dout_kfc_pll", "mout_kfc", DIV_KFC, 24, 3), +}; + +static struct samsung_pll_clock kfc_pll_clks[] __initdata = { + PLL(pll_2550xx, KFC_FOUT_KFC_PLL, "fout_kfc_pll", "fin_pll", + KFC_PLL_LOCK, KFC_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_kfc_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.pll_clks = kfc_pll_clks; + cmu.nr_pll_clks = ARRAY_SIZE(kfc_pll_clks); + cmu.mux_clks = kfc_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(kfc_mux_clks); + cmu.div_clks = kfc_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(kfc_div_clks); + cmu.nr_clk_ids = KFC_NR_CLK; + cmu.clk_regs = kfc_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(kfc_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_kfc, "samsung,exynos5260-clock-kfc", + exynos5260_clk_kfc_init); + + +/* CMU_MFC */ + +static unsigned long mfc_clk_regs[] __initdata = { + MUX_SEL_MFC, + DIV_MFC, + EN_ACLK_MFC, + EN_ACLK_SECURE_SMMU2_MFC, + EN_PCLK_MFC, + EN_PCLK_SECURE_SMMU2_MFC, + EN_IP_MFC, + EN_IP_MFC_SECURE_SMMU2_MFC, +}; + +PNAME(mout_aclk_mfc_333_user_p) = {"fin_pll", "dout_aclk_mfc_333"}; + +struct samsung_mux_clock mfc_mux_clks[] __initdata = { + MUX(MFC_MOUT_ACLK_MFC_333_USER, "mout_aclk_mfc_333_user", + mout_aclk_mfc_333_user_p, + MUX_SEL_MFC, 0, 1), +}; + +struct samsung_div_clock mfc_div_clks[] __initdata = { + DIV(MFC_DOUT_PCLK_MFC_83, "dout_pclk_mfc_83", "mout_aclk_mfc_333_user", + DIV_MFC, 0, 3), +}; + +struct samsung_gate_clock mfc_gate_clks[] __initdata = { + GATE(MFC_CLK_MFC, "clk_mfc", "mout_aclk_mfc_333_user", + EN_IP_MFC, 1, 0, 0), + GATE(MFC_CLK_SMMU2_MFCM0, "clk_smmu2_mfcm0", "mout_aclk_mfc_333_user", + EN_IP_MFC_SECURE_SMMU2_MFC, 6, 0, 0), + GATE(MFC_CLK_SMMU2_MFCM1, "clk_smmu2_mfcm1", "mout_aclk_mfc_333_user", + EN_IP_MFC_SECURE_SMMU2_MFC, 7, 0, 0), +}; + +static void __init exynos5260_clk_mfc_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = mfc_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(mfc_mux_clks); + cmu.div_clks = mfc_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(mfc_div_clks); + cmu.gate_clks = mfc_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(mfc_gate_clks); + cmu.nr_clk_ids = MFC_NR_CLK; + cmu.clk_regs = mfc_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(mfc_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_mfc, "samsung,exynos5260-clock-mfc", + exynos5260_clk_mfc_init); + + +/* CMU_MIF */ + +static unsigned long mif_clk_regs[] __initdata = { + MEM_PLL_LOCK, + BUS_PLL_LOCK, + MEDIA_PLL_LOCK, + MEM_PLL_CON0, + MEM_PLL_CON1, + MEM_PLL_FDET, + BUS_PLL_CON0, + BUS_PLL_CON1, + BUS_PLL_FDET, + MEDIA_PLL_CON0, + MEDIA_PLL_CON1, + MEDIA_PLL_FDET, + MUX_SEL_MIF, + DIV_MIF, + DIV_MIF_PLL_FDET, + EN_ACLK_MIF, + EN_ACLK_MIF_SECURE_DREX1_TZ, + EN_ACLK_MIF_SECURE_DREX0_TZ, + EN_ACLK_MIF_SECURE_INTMEM, + EN_PCLK_MIF, + EN_PCLK_MIF_SECURE_MONOCNT, + EN_PCLK_MIF_SECURE_RTC_APBIF, + EN_PCLK_MIF_SECURE_DREX1_TZ, + EN_PCLK_MIF_SECURE_DREX0_TZ, + EN_SCLK_MIF, + EN_IP_MIF, + EN_IP_MIF_SECURE_MONOCNT, + EN_IP_MIF_SECURE_RTC_APBIF, + EN_IP_MIF_SECURE_DREX1_TZ, + EN_IP_MIF_SECURE_DREX0_TZ, + EN_IP_MIF_SECURE_INTEMEM, +}; + +PNAME(mout_mem_pll_p) = {"fin_pll", "fout_mem_pll"}; +PNAME(mout_bus_pll_p) = {"fin_pll", "fout_bus_pll"}; +PNAME(mout_media_pll_p) = {"fin_pll", "fout_media_pll"}; +PNAME(mout_mif_drex_p) = {"dout_mem_pll", "dout_bus_pll"}; +PNAME(mout_mif_drex2x_p) = {"dout_mem_pll", "dout_bus_pll"}; +PNAME(mout_clkm_phy_p) = {"mout_mif_drex", "dout_media_pll"}; +PNAME(mout_clk2x_phy_p) = {"mout_mif_drex2x", "dout_media_pll"}; + +struct samsung_mux_clock mif_mux_clks[] __initdata = { + MUX(MIF_MOUT_MEM_PLL, "mout_mem_pll", mout_mem_pll_p, + MUX_SEL_MIF, 0, 1), + MUX(MIF_MOUT_BUS_PLL, "mout_bus_pll", mout_bus_pll_p, + MUX_SEL_MIF, 4, 1), + MUX(MIF_MOUT_MEDIA_PLL, "mout_media_pll", mout_media_pll_p, + MUX_SEL_MIF, 8, 1), + MUX(MIF_MOUT_MIF_DREX, "mout_mif_drex", mout_mif_drex_p, + MUX_SEL_MIF, 12, 1), + MUX(MIF_MOUT_CLKM_PHY, "mout_clkm_phy", mout_clkm_phy_p, + MUX_SEL_MIF, 16, 1), + MUX(MIF_MOUT_MIF_DREX2X, "mout_mif_drex2x", mout_mif_drex2x_p, + MUX_SEL_MIF, 20, 1), + MUX(MIF_MOUT_CLK2X_PHY, "mout_clk2x_phy", mout_clk2x_phy_p, + MUX_SEL_MIF, 24, 1), +}; + +struct samsung_div_clock mif_div_clks[] __initdata = { + DIV(MIF_DOUT_MEDIA_PLL, "dout_media_pll", "mout_media_pll", + DIV_MIF, 0, 3), + DIV(MIF_DOUT_MEM_PLL, "dout_mem_pll", "mout_mem_pll", + DIV_MIF, 4, 3), + DIV(MIF_DOUT_BUS_PLL, "dout_bus_pll", "mout_bus_pll", + DIV_MIF, 8, 3), + DIV(MIF_DOUT_CLKM_PHY, "dout_clkm_phy", "mout_clkm_phy", + DIV_MIF, 12, 3), + DIV(MIF_DOUT_CLK2X_PHY, "dout_clk2x_phy", "mout_clk2x_phy", + DIV_MIF, 16, 4), + DIV(MIF_DOUT_ACLK_MIF_466, "dout_aclk_mif_466", "dout_clk2x_phy", + DIV_MIF, 20, 3), + DIV(MIF_DOUT_ACLK_BUS_200, "dout_aclk_bus_200", "dout_bus_pll", + DIV_MIF, 24, 3), + DIV(MIF_DOUT_ACLK_BUS_100, "dout_aclk_bus_100", "dout_bus_pll", + DIV_MIF, 28, 4), +}; + +struct samsung_gate_clock mif_gate_clks[] __initdata = { + GATE(MIF_CLK_LPDDR3PHY_WRAP0, "clk_lpddr3phy_wrap0", "dout_clk2x_phy", + EN_IP_MIF, 12, CLK_IGNORE_UNUSED, 0), + GATE(MIF_CLK_LPDDR3PHY_WRAP1, "clk_lpddr3phy_wrap1", "dout_clk2x_phy", + EN_IP_MIF, 13, CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_MONOCNT, "clk_monocnt", "dout_aclk_bus_100", + EN_IP_MIF_SECURE_MONOCNT, 22, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_MIF_RTC, "clk_mif_rtc", "dout_aclk_bus_100", + EN_IP_MIF_SECURE_RTC_APBIF, 23, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_DREX1, "clk_drex1", "dout_aclk_mif_466", + EN_IP_MIF_SECURE_DREX1_TZ, 9, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_DREX0, "clk_drex0", "dout_aclk_mif_466", + EN_IP_MIF_SECURE_DREX0_TZ, 9, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_CLK_INTMEM, "clk_intmem", "dout_aclk_bus_200", + EN_IP_MIF_SECURE_INTEMEM, 11, + CLK_IGNORE_UNUSED, 0), + + GATE(MIF_SCLK_LPDDR3PHY_WRAP_U0, "sclk_lpddr3phy_wrap_u0", + "dout_clkm_phy", EN_SCLK_MIF, 0, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), + GATE(MIF_SCLK_LPDDR3PHY_WRAP_U1, "sclk_lpddr3phy_wrap_u1", + "dout_clkm_phy", EN_SCLK_MIF, 1, + CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0), +}; + +static struct samsung_pll_clock mif_pll_clks[] __initdata = { + PLL(pll_2550xx, MIF_FOUT_MEM_PLL, "fout_mem_pll", "fin_pll", + MEM_PLL_LOCK, MEM_PLL_CON0, + pll2550_24mhz_tbl), + PLL(pll_2550xx, MIF_FOUT_BUS_PLL, "fout_bus_pll", "fin_pll", + BUS_PLL_LOCK, BUS_PLL_CON0, + pll2550_24mhz_tbl), + PLL(pll_2550xx, MIF_FOUT_MEDIA_PLL, "fout_media_pll", "fin_pll", + MEDIA_PLL_LOCK, MEDIA_PLL_CON0, + pll2550_24mhz_tbl), +}; + +static void __init exynos5260_clk_mif_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.pll_clks = mif_pll_clks; + cmu.nr_pll_clks = ARRAY_SIZE(mif_pll_clks); + cmu.mux_clks = mif_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(mif_mux_clks); + cmu.div_clks = mif_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(mif_div_clks); + cmu.gate_clks = mif_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(mif_gate_clks); + cmu.nr_clk_ids = MIF_NR_CLK; + cmu.clk_regs = mif_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(mif_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_mif, "samsung,exynos5260-clock-mif", + exynos5260_clk_mif_init); + + +/* CMU_PERI */ + +static unsigned long peri_clk_regs[] __initdata = { + MUX_SEL_PERI, + MUX_SEL_PERI1, + DIV_PERI, + EN_PCLK_PERI0, + EN_PCLK_PERI1, + EN_PCLK_PERI2, + EN_PCLK_PERI3, + EN_PCLK_PERI_SECURE_CHIPID, + EN_PCLK_PERI_SECURE_PROVKEY0, + EN_PCLK_PERI_SECURE_PROVKEY1, + EN_PCLK_PERI_SECURE_SECKEY, + EN_PCLK_PERI_SECURE_ANTIRBKCNT, + EN_PCLK_PERI_SECURE_TOP_RTC, + EN_PCLK_PERI_SECURE_TZPC, + EN_SCLK_PERI, + EN_SCLK_PERI_SECURE_TOP_RTC, + EN_IP_PERI0, + EN_IP_PERI1, + EN_IP_PERI2, + EN_IP_PERI_SECURE_CHIPID, + EN_IP_PERI_SECURE_PROVKEY0, + EN_IP_PERI_SECURE_PROVKEY1, + EN_IP_PERI_SECURE_SECKEY, + EN_IP_PERI_SECURE_ANTIRBKCNT, + EN_IP_PERI_SECURE_TOP_RTC, + EN_IP_PERI_SECURE_TZPC, +}; + +PNAME(mout_sclk_pcm_p) = {"ioclk_pcm_extclk", "fin_pll", "dout_aclk_peri_aud", + "phyclk_hdmi_phy_ref_cko"}; +PNAME(mout_sclk_i2scod_p) = {"ioclk_i2s_cdclk", "fin_pll", "dout_aclk_peri_aud", + "phyclk_hdmi_phy_ref_cko"}; +PNAME(mout_sclk_spdif_p) = {"ioclk_spdif_extclk", "fin_pll", + "dout_aclk_peri_aud", "phyclk_hdmi_phy_ref_cko"}; + +struct samsung_mux_clock peri_mux_clks[] __initdata = { + MUX(PERI_MOUT_SCLK_PCM, "mout_sclk_pcm", mout_sclk_pcm_p, + MUX_SEL_PERI1, 4, 2), + MUX(PERI_MOUT_SCLK_I2SCOD, "mout_sclk_i2scod", mout_sclk_i2scod_p, + MUX_SEL_PERI1, 12, 2), + MUX(PERI_MOUT_SCLK_SPDIF, "mout_sclk_spdif", mout_sclk_spdif_p, + MUX_SEL_PERI1, 20, 2), +}; + +struct samsung_div_clock peri_div_clks[] __initdata = { + DIV(PERI_DOUT_PCM, "dout_pcm", "mout_sclk_pcm", DIV_PERI, 0, 8), + DIV(PERI_DOUT_I2S, "dout_i2s", "mout_sclk_i2scod", DIV_PERI, 8, 6), +}; + +struct samsung_gate_clock peri_gate_clks[] __initdata = { + GATE(PERI_SCLK_PCM1, "sclk_pcm1", "dout_pcm", EN_SCLK_PERI, 0, + CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_I2S, "sclk_i2s", "dout_i2s", EN_SCLK_PERI, 1, + CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPDIF, "sclk_spdif", "dout_sclk_peri_spi0_b", + EN_SCLK_PERI, 2, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPI0, "sclk_spi0", "dout_sclk_peri_spi0_b", + EN_SCLK_PERI, 7, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPI1, "sclk_spi1", "dout_sclk_peri_spi1_b", + EN_SCLK_PERI, 8, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_SPI2, "sclk_spi2", "dout_sclk_peri_spi2_b", + EN_SCLK_PERI, 9, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_UART0, "sclk_uart0", "dout_sclk_peri_uart0", + EN_SCLK_PERI, 10, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_UART1, "sclk_uart1", "dout_sclk_peri_uart1", + EN_SCLK_PERI, 11, CLK_SET_RATE_PARENT, 0), + GATE(PERI_SCLK_UART2, "sclk_uart2", "dout_sclk_peri_uart2", + EN_SCLK_PERI, 12, CLK_SET_RATE_PARENT, 0), + + GATE(PERI_CLK_ABB, "clk_abb", "dout_aclk_peri_66", + EN_IP_PERI0, 1, 0, 0), + GATE(PERI_CLK_EFUSE_WRITER, "clk_efuse_writer", "dout_aclk_peri_66", + EN_IP_PERI0, 5, 0, 0), + GATE(PERI_CLK_HDMICEC, "clk_hdmicec", "dout_aclk_peri_66", + EN_IP_PERI0, 6, 0, 0), + GATE(PERI_CLK_I2C10, "clk_i2c10", "dout_aclk_peri_66", + EN_IP_PERI0, 7, 0, 0), + GATE(PERI_CLK_I2C11, "clk_i2c11", "dout_aclk_peri_66", + EN_IP_PERI0, 8, 0, 0), + GATE(PERI_CLK_I2C8, "clk_i2c8", "dout_aclk_peri_66", + EN_IP_PERI0, 9, 0, 0), + GATE(PERI_CLK_I2C9, "clk_i2c9", "dout_aclk_peri_66", + EN_IP_PERI0, 10, 0, 0), + GATE(PERI_CLK_I2C4, "clk_i2c4", "dout_aclk_peri_66", + EN_IP_PERI0, 11, 0, 0), + GATE(PERI_CLK_I2C5, "clk_i2c5", "dout_aclk_peri_66", + EN_IP_PERI0, 12, 0, 0), + GATE(PERI_CLK_I2C6, "clk_i2c6", "dout_aclk_peri_66", + EN_IP_PERI0, 13, 0, 0), + GATE(PERI_CLK_I2C7, "clk_i2c7", "dout_aclk_peri_66", + EN_IP_PERI0, 14, 0, 0), + GATE(PERI_CLK_I2CHDMI, "clk_i2chdmi", "dout_aclk_peri_66", + EN_IP_PERI0, 15, 0, 0), + GATE(PERI_CLK_I2S, "clk_peri_i2s", "dout_aclk_peri_66", + EN_IP_PERI0, 16, 0, 0), + GATE(PERI_CLK_MCT, "clk_mct", "dout_aclk_peri_66", + EN_IP_PERI0, 17, 0, 0), + GATE(PERI_CLK_PCM, "clk_peri_pcm", "dout_aclk_peri_66", + EN_IP_PERI0, 18, 0, 0), + GATE(PERI_CLK_HSIC0, "clk_hsic0", "dout_aclk_peri_66", + EN_IP_PERI0, 20, 0, 0), + GATE(PERI_CLK_HSIC1, "clk_hsic1", "dout_aclk_peri_66", + EN_IP_PERI0, 21, 0, 0), + GATE(PERI_CLK_HSIC2, "clk_hsic2", "dout_aclk_peri_66", + EN_IP_PERI0, 22, 0, 0), + GATE(PERI_CLK_HSIC3, "clk_hsic3", "dout_aclk_peri_66", + EN_IP_PERI0, 23, 0, 0), + GATE(PERI_CLK_WDT_EGL, "clk_wdt_egl", "dout_aclk_peri_66", + EN_IP_PERI0, 24, 0, 0), + GATE(PERI_CLK_WDT_KFC, "clk_wdt_kfc", "dout_aclk_peri_66", + EN_IP_PERI0, 25, 0, 0), + + GATE(PERI_CLK_UART4, "clk_uart4", "dout_aclk_peri_66", + EN_IP_PERI2, 0, 0, 0), + GATE(PERI_CLK_PWM, "clk_pwm", "dout_aclk_peri_66", + EN_IP_PERI2, 3, 0, 0), + GATE(PERI_CLK_SPDIF, "clk_spdif", "dout_aclk_peri_66", + EN_IP_PERI2, 6, 0, 0), + GATE(PERI_CLK_SPI0, "clk_spi0", "dout_aclk_peri_66", + EN_IP_PERI2, 7, 0, 0), + GATE(PERI_CLK_SPI1, "clk_spi1", "dout_aclk_peri_66", + EN_IP_PERI2, 8, 0, 0), + GATE(PERI_CLK_SPI2, "clk_spi2", "dout_aclk_peri_66", + EN_IP_PERI2, 9, 0, 0), + GATE(PERI_CLK_TMU0, "clk_tmu0", "dout_aclk_peri_66", + EN_IP_PERI2, 10, 0, 0), + GATE(PERI_CLK_TMU1, "clk_tmu1", "dout_aclk_peri_66", + EN_IP_PERI2, 11, 0, 0), + GATE(PERI_CLK_TMU2, "clk_tmu2", "dout_aclk_peri_66", + EN_IP_PERI2, 12, 0, 0), + GATE(PERI_CLK_TMU3, "clk_tmu3", "dout_aclk_peri_66", + EN_IP_PERI2, 13, 0, 0), + GATE(PERI_CLK_TMU4, "clk_tmu4", "dout_aclk_peri_66", + EN_IP_PERI2, 14, 0, 0), + GATE(PERI_CLK_ADC, "clk_adc", "dout_aclk_peri_66", + EN_IP_PERI2, 18, 0, 0), + GATE(PERI_CLK_UART0, "clk_uart0", "dout_aclk_peri_66", + EN_IP_PERI2, 19, 0, 0), + GATE(PERI_CLK_UART1, "clk_uart1", "dout_aclk_peri_66", + EN_IP_PERI2, 20, 0, 0), + GATE(PERI_CLK_UART2, "clk_uart2", "dout_aclk_peri_66", + EN_IP_PERI2, 21, 0, 0), + + GATE(PERI_CLK_CHIPID, "clk_chipid", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_CHIPID, 2, 0, 0), + + GATE(PERI_CLK_PROVKEY0, "clk_provkey0", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_PROVKEY0, 1, 0, 0), + + GATE(PERI_CLK_PROVKEY1, "clk_provkey1", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_PROVKEY1, 2, 0, 0), + + GATE(PERI_CLK_SECKEY, "clk_seckey", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_SECKEY, 5, 0, 0), + + GATE(PERI_CLK_TOP_RTC, "clk_top_rtc", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TOP_RTC, 5, 0, 0), + + GATE(PERI_CLK_TZPC0, "clk_tzpc0", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 10, 0, 0), + GATE(PERI_CLK_TZPC1, "clk_tzpc1", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 11, 0, 0), + GATE(PERI_CLK_TZPC2, "clk_tzpc2", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 12, 0, 0), + GATE(PERI_CLK_TZPC3, "clk_tzpc3", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 13, 0, 0), + GATE(PERI_CLK_TZPC4, "clk_tzpc4", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 14, 0, 0), + GATE(PERI_CLK_TZPC5, "clk_tzpc5", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 15, 0, 0), + GATE(PERI_CLK_TZPC6, "clk_tzpc6", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 16, 0, 0), + GATE(PERI_CLK_TZPC7, "clk_tzpc7", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 17, 0, 0), + GATE(PERI_CLK_TZPC8, "clk_tzpc8", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 18, 0, 0), + GATE(PERI_CLK_TZPC9, "clk_tzpc9", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 19, 0, 0), + GATE(PERI_CLK_TZPC10, "clk_tzpc10", "dout_aclk_peri_66", + EN_IP_PERI_SECURE_TZPC, 20, 0, 0), +}; + +static void __init exynos5260_clk_peri_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.mux_clks = peri_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(peri_mux_clks); + cmu.div_clks = peri_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(peri_div_clks); + cmu.gate_clks = peri_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(peri_gate_clks); + cmu.nr_clk_ids = PERI_NR_CLK; + cmu.clk_regs = peri_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(peri_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_peri, "samsung,exynos5260-clock-peri", + exynos5260_clk_peri_init); + + +/* CMU_TOP */ + +static unsigned long top_clk_regs[] __initdata = { + DISP_PLL_LOCK, + AUD_PLL_LOCK, + DISP_PLL_CON0, + DISP_PLL_CON1, + DISP_PLL_FDET, + AUD_PLL_CON0, + AUD_PLL_CON1, + AUD_PLL_CON2, + AUD_PLL_FDET, + MUX_SEL_TOP_PLL0, + MUX_SEL_TOP_MFC, + MUX_SEL_TOP_G2D, + MUX_SEL_TOP_GSCL, + MUX_SEL_TOP_ISP10, + MUX_SEL_TOP_ISP11, + MUX_SEL_TOP_DISP0, + MUX_SEL_TOP_DISP1, + MUX_SEL_TOP_BUS, + MUX_SEL_TOP_PERI0, + MUX_SEL_TOP_PERI1, + MUX_SEL_TOP_FSYS, + DIV_TOP_G2D_MFC, + DIV_TOP_GSCL_ISP0, + DIV_TOP_ISP10, + DIV_TOP_ISP11, + DIV_TOP_DISP, + DIV_TOP_BUS, + DIV_TOP_PERI0, + DIV_TOP_PERI1, + DIV_TOP_PERI2, + DIV_TOP_FSYS0, + DIV_TOP_FSYS1, + DIV_TOP_HPM, + DIV_TOP_PLL_FDET, + EN_ACLK_TOP, + EN_SCLK_TOP, + EN_IP_TOP, +}; + +/* fixed rate clocks generated inside the soc */ +struct samsung_fixed_rate_clock fixed_rate_clks[] __initdata = { + FRATE(PHYCLK_DPTX_PHY_CH3_TXD_CLK, "phyclk_dptx_phy_ch3_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(PHYCLK_DPTX_PHY_CH2_TXD_CLK, "phyclk_dptx_phy_ch2_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(PHYCLK_DPTX_PHY_CH1_TXD_CLK, "phyclk_dptx_phy_ch1_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(PHYCLK_DPTX_PHY_CH0_TXD_CLK, "phyclk_dptx_phy_ch0_txd_clk", NULL, + CLK_IS_ROOT, 270000000), + FRATE(phyclk_hdmi_phy_tmds_clko, "phyclk_hdmi_phy_tmds_clko", NULL, + CLK_IS_ROOT, 250000000), + FRATE(PHYCLK_HDMI_PHY_PIXEL_CLKO, "phyclk_hdmi_phy_pixel_clko", NULL, + CLK_IS_ROOT, 1660000000), + FRATE(PHYCLK_HDMI_LINK_O_TMDS_CLKHI, "phyclk_hdmi_link_o_tmds_clkhi", + NULL, CLK_IS_ROOT, 125000000), + FRATE(PHYCLK_MIPI_DPHY_4L_M_TXBYTECLKHS, + "phyclk_mipi_dphy_4l_m_txbyteclkhs" , NULL, + CLK_IS_ROOT, 187500000), + FRATE(PHYCLK_DPTX_PHY_O_REF_CLK_24M, "phyclk_dptx_phy_o_ref_clk_24m", + NULL, CLK_IS_ROOT, 24000000), + FRATE(PHYCLK_DPTX_PHY_CLK_DIV2, "phyclk_dptx_phy_clk_div2", NULL, + CLK_IS_ROOT, 135000000), + FRATE(PHYCLK_MIPI_DPHY_4L_M_RXCLKESC0, + "phyclk_mipi_dphy_4l_m_rxclkesc0", NULL, + CLK_IS_ROOT, 20000000), + FRATE(PHYCLK_USBHOST20_PHY_PHYCLOCK, "phyclk_usbhost20_phy_phyclock", + NULL, CLK_IS_ROOT, 60000000), + FRATE(PHYCLK_USBHOST20_PHY_FREECLK, "phyclk_usbhost20_phy_freeclk", + NULL, CLK_IS_ROOT, 60000000), + FRATE(PHYCLK_USBHOST20_PHY_CLK48MOHCI, + "phyclk_usbhost20_phy_clk48mohci", + NULL, CLK_IS_ROOT, 48000000), + FRATE(PHYCLK_USBDRD30_UDRD30_PIPE_PCLK, + "phyclk_usbdrd30_udrd30_pipe_pclk", NULL, + CLK_IS_ROOT, 125000000), + FRATE(PHYCLK_USBDRD30_UDRD30_PHYCLOCK, + "phyclk_usbdrd30_udrd30_phyclock", NULL, + CLK_IS_ROOT, 60000000), +}; + +PNAME(mout_memtop_pll_user_p) = {"fin_pll", "dout_mem_pll"}; +PNAME(mout_bustop_pll_user_p) = {"fin_pll", "dout_bus_pll"}; +PNAME(mout_mediatop_pll_user_p) = {"fin_pll", "dout_media_pll"}; +PNAME(mout_audtop_pll_user_p) = {"fin_pll", "mout_aud_pll"}; +PNAME(mout_aud_pll_p) = {"fin_pll", "fout_aud_pll"}; +PNAME(mout_disp_pll_p) = {"fin_pll", "fout_disp_pll"}; +PNAME(mout_mfc_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_mfc_333_p) = {"mout_mediatop_pll_user", "mout_mfc_bustop_333"}; +PNAME(mout_g2d_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_g2d_333_p) = {"mout_mediatop_pll_user", "mout_g2d_bustop_333"}; +PNAME(mout_gscl_bustop_333_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_gscl_333_p) = {"mout_mediatop_pll_user", + "mout_gscl_bustop_333"}; +PNAME(mout_m2m_mediatop_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_gscl_400_p) = {"mout_bustop_pll_user", + "mout_m2m_mediatop_400"}; +PNAME(mout_gscl_bustop_fimc_p) = {"mout_bustop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_gscl_fimc_p) = {"mout_mediatop_pll_user", + "mout_gscl_bustop_fimc"}; +PNAME(mout_isp1_media_266_p) = {"mout_mediatop_pll_user", + "mout_memtop_pll_user"}; +PNAME(mout_aclk_isp1_266_p) = {"mout_bustop_pll_user", "mout_isp1_media_266"}; +PNAME(mout_isp1_media_400_p) = {"mout_mediatop_pll_user", "mout_disp_pll"}; +PNAME(mout_aclk_isp1_400_p) = {"mout_bustop_pll_user", "mout_isp1_media_400"}; +PNAME(mout_sclk_isp_spi_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_isp_uart_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_isp_sensor_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_disp_disp_333_p) = {"mout_disp_pll", "mout_bustop_pll_user"}; +PNAME(mout_aclk_disp_333_p) = {"mout_mediatop_pll_user", "mout_disp_disp_333"}; +PNAME(mout_disp_disp_222_p) = {"mout_disp_pll", "mout_bustop_pll_user"}; +PNAME(mout_aclk_disp_222_p) = {"mout_mediatop_pll_user", "mout_disp_disp_222"}; +PNAME(mout_disp_media_pixel_p) = {"mout_mediatop_pll_user", + "mout_bustop_pll_user"}; +PNAME(mout_sclk_disp_pixel_p) = {"mout_disp_pll", "mout_disp_media_pixel"}; +PNAME(mout_bus_bustop_400_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"}; +PNAME(mout_bus_bustop_100_p) = {"mout_bustop_pll_user", "mout_memtop_pll_user"}; +PNAME(mout_sclk_peri_spi_clk_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_peri_uart_uclk_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_fsys_usb_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_fsys_mmc_sdclkin_a_p) = {"fin_pll", "mout_bustop_pll_user"}; +PNAME(mout_sclk_fsys_mmc0_sdclkin_b_p) = {"mout_sclk_fsys_mmc0_sdclkin_a", + "mout_mediatop_pll_user"}; +PNAME(mout_sclk_fsys_mmc1_sdclkin_b_p) = {"mout_sclk_fsys_mmc1_sdclkin_a", + "mout_mediatop_pll_user"}; +PNAME(mout_sclk_fsys_mmc2_sdclkin_b_p) = {"mout_sclk_fsys_mmc2_sdclkin_a", + "mout_mediatop_pll_user"}; + +struct samsung_mux_clock top_mux_clks[] __initdata = { + MUX(TOP_MOUT_MEDIATOP_PLL_USER, "mout_mediatop_pll_user", + mout_mediatop_pll_user_p, + MUX_SEL_TOP_PLL0, 0, 1), + MUX(TOP_MOUT_MEMTOP_PLL_USER, "mout_memtop_pll_user", + mout_memtop_pll_user_p, + MUX_SEL_TOP_PLL0, 4, 1), + MUX(TOP_MOUT_BUSTOP_PLL_USER, "mout_bustop_pll_user", + mout_bustop_pll_user_p, + MUX_SEL_TOP_PLL0, 8, 1), + MUX(TOP_MOUT_DISP_PLL, "mout_disp_pll", mout_disp_pll_p, + MUX_SEL_TOP_PLL0, 12, 1), + MUX(TOP_MOUT_AUD_PLL, "mout_aud_pll", mout_aud_pll_p, + MUX_SEL_TOP_PLL0, 16, 1), + MUX(TOP_MOUT_AUDTOP_PLL_USER, "mout_audtop_pll_user", + mout_audtop_pll_user_p, + MUX_SEL_TOP_PLL0, 24, 1), + + MUX(TOP_MOUT_DISP_DISP_333, "mout_disp_disp_333", mout_disp_disp_333_p, + MUX_SEL_TOP_DISP0, 0, 1), + MUX(TOP_MOUT_ACLK_DISP_333, "mout_aclk_disp_333", mout_aclk_disp_333_p, + MUX_SEL_TOP_DISP0, 8, 1), + MUX(TOP_MOUT_DISP_DISP_222, "mout_disp_disp_222", mout_disp_disp_222_p, + MUX_SEL_TOP_DISP0, 12, 1), + MUX(TOP_MOUT_ACLK_DISP_222, "mout_aclk_disp_222", mout_aclk_disp_222_p, + MUX_SEL_TOP_DISP0, 20, 1), + + MUX(TOP_MOUT_FIMD1, "mout_sclk_disp_pixel", mout_sclk_disp_pixel_p, + MUX_SEL_TOP_DISP1, 0, 1), + MUX(TOP_MOUT_DISP_MEDIA_PIXEL, "mout_disp_media_pixel", + mout_disp_media_pixel_p, + MUX_SEL_TOP_DISP1, 8, 1), + + MUX(TOP_MOUT_SCLK_PERI_SPI2_CLK, "mout_sclk_peri_spi2_clk", + mout_sclk_peri_spi_clk_p, + MUX_SEL_TOP_PERI1, 0, 1), + MUX(TOP_MOUT_SCLK_PERI_SPI1_CLK, "mout_sclk_peri_spi1_clk", + mout_sclk_peri_spi_clk_p, + MUX_SEL_TOP_PERI1, 4, 1), + MUX(TOP_MOUT_SCLK_PERI_SPI0_CLK, "mout_sclk_peri_spi0_clk", + mout_sclk_peri_spi_clk_p, + MUX_SEL_TOP_PERI1, 8, 1), + MUX(TOP_MOUT_SCLK_PERI_UART1_UCLK, "mout_sclk_peri_uart1_uclk", + mout_sclk_peri_uart_uclk_p, + MUX_SEL_TOP_PERI1, 12, 1), + MUX(TOP_MOUT_SCLK_PERI_UART2_UCLK, "mout_sclk_peri_uart2_uclk", + mout_sclk_peri_uart_uclk_p, + MUX_SEL_TOP_PERI1, 16, 1), + MUX(TOP_MOUT_SCLK_PERI_UART0_UCLK, "mout_sclk_peri_uart0_uclk", + mout_sclk_peri_uart_uclk_p, + MUX_SEL_TOP_PERI1, 20, 1), + + + MUX(TOP_MOUT_BUS1_BUSTOP_400, "mout_bus1_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 0, 1), + MUX(TOP_MOUT_BUS1_BUSTOP_100, "mout_bus1_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 4, 1), + MUX(TOP_MOUT_BUS2_BUSTOP_100, "mout_bus2_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 8, 1), + MUX(TOP_MOUT_BUS2_BUSTOP_400, "mout_bus2_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 12, 1), + MUX(TOP_MOUT_BUS3_BUSTOP_400, "mout_bus3_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 16, 1), + MUX(TOP_MOUT_BUS3_BUSTOP_100, "mout_bus3_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 20, 1), + MUX(TOP_MOUT_BUS4_BUSTOP_400, "mout_bus4_bustop_400", + mout_bus_bustop_400_p, + MUX_SEL_TOP_BUS, 24, 1), + MUX(TOP_MOUT_BUS4_BUSTOP_100, "mout_bus4_bustop_100", + mout_bus_bustop_100_p, + MUX_SEL_TOP_BUS, 28, 1), + + MUX(TOP_MOUT_SCLK_FSYS_USB, "mout_sclk_fsys_usb", + mout_sclk_fsys_usb_p, + MUX_SEL_TOP_FSYS, 0, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_A, "mout_sclk_fsys_mmc2_sdclkin_a", + mout_sclk_fsys_mmc_sdclkin_a_p, + MUX_SEL_TOP_FSYS, 4, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC2_SDCLKIN_B, "mout_sclk_fsys_mmc2_sdclkin_b", + mout_sclk_fsys_mmc2_sdclkin_b_p, + MUX_SEL_TOP_FSYS, 8, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_A, "mout_sclk_fsys_mmc1_sdclkin_a", + mout_sclk_fsys_mmc_sdclkin_a_p, + MUX_SEL_TOP_FSYS, 12, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC1_SDCLKIN_B, "mout_sclk_fsys_mmc1_sdclkin_b", + mout_sclk_fsys_mmc1_sdclkin_b_p, + MUX_SEL_TOP_FSYS, 16, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_A, "mout_sclk_fsys_mmc0_sdclkin_a", + mout_sclk_fsys_mmc_sdclkin_a_p, + MUX_SEL_TOP_FSYS, 20, 1), + MUX(TOP_MOUT_SCLK_FSYS_MMC0_SDCLKIN_B, "mout_sclk_fsys_mmc0_sdclkin_b", + mout_sclk_fsys_mmc0_sdclkin_b_p, + MUX_SEL_TOP_FSYS, 24, 1), + + MUX(TOP_MOUT_ISP1_MEDIA_400, "mout_isp1_media_400", + mout_isp1_media_400_p, + MUX_SEL_TOP_ISP10, 4, 1), + MUX(TOP_MOUT_ACLK_ISP1_400, "mout_aclk_isp1_400", mout_aclk_isp1_400_p, + MUX_SEL_TOP_ISP10, 8 , 1), + MUX(TOP_MOUT_ISP1_MEDIA_266, "mout_isp1_media_266", + mout_isp1_media_266_p, + MUX_SEL_TOP_ISP10, 16, 1), + MUX(TOP_MOUT_ACLK_ISP1_266, "mout_aclk_isp1_266", mout_aclk_isp1_266_p, + MUX_SEL_TOP_ISP10, 20, 1), + + MUX(TOP_MOUT_SCLK_ISP1_SPI0, "mout_sclk_isp1_spi0", mout_sclk_isp_spi_p, + MUX_SEL_TOP_ISP11, 4, 1), + MUX(TOP_MOUT_SCLK_ISP1_SPI1, "mout_sclk_isp1_spi1", mout_sclk_isp_spi_p, + MUX_SEL_TOP_ISP11, 8, 1), + MUX(TOP_MOUT_SCLK_ISP1_UART, "mout_sclk_isp1_uart", + mout_sclk_isp_uart_p, + MUX_SEL_TOP_ISP11, 12, 1), + MUX(TOP_MOUT_SCLK_ISP1_SENSOR0, "mout_sclk_isp1_sensor0", + mout_sclk_isp_sensor_p, + MUX_SEL_TOP_ISP11, 16, 1), + MUX(TOP_MOUT_SCLK_ISP1_SENSOR1, "mout_sclk_isp1_sensor1", + mout_sclk_isp_sensor_p, + MUX_SEL_TOP_ISP11, 20, 1), + MUX(TOP_MOUT_SCLK_ISP1_SENSOR2, "mout_sclk_isp1_sensor2", + mout_sclk_isp_sensor_p, + MUX_SEL_TOP_ISP11, 24, 1), + + MUX(TOP_MOUT_MFC_BUSTOP_333, "mout_mfc_bustop_333", + mout_mfc_bustop_333_p, + MUX_SEL_TOP_MFC, 4, 1), + MUX(TOP_MOUT_ACLK_MFC_333, "mout_aclk_mfc_333", mout_aclk_mfc_333_p, + MUX_SEL_TOP_MFC, 8, 1), + + MUX(TOP_MOUT_G2D_BUSTOP_333, "mout_g2d_bustop_333", + mout_g2d_bustop_333_p, + MUX_SEL_TOP_G2D, 4, 1), + MUX(TOP_MOUT_ACLK_G2D_333, "mout_aclk_g2d_333", mout_aclk_g2d_333_p, + MUX_SEL_TOP_G2D, 8, 1), + + MUX(TOP_MOUT_M2M_MEDIATOP_400, "mout_m2m_mediatop_400", + mout_m2m_mediatop_400_p, + MUX_SEL_TOP_GSCL, 0, 1), + MUX(TOP_MOUT_ACLK_GSCL_400, "mout_aclk_gscl_400", + mout_aclk_gscl_400_p, + MUX_SEL_TOP_GSCL, 4, 1), + MUX(TOP_MOUT_GSCL_BUSTOP_333, "mout_gscl_bustop_333", + mout_gscl_bustop_333_p, + MUX_SEL_TOP_GSCL, 8, 1), + MUX(TOP_MOUT_ACLK_GSCL_333, "mout_aclk_gscl_333", + mout_aclk_gscl_333_p, + MUX_SEL_TOP_GSCL, 12, 1), + MUX(TOP_MOUT_GSCL_BUSTOP_FIMC, "mout_gscl_bustop_fimc", + mout_gscl_bustop_fimc_p, + MUX_SEL_TOP_GSCL, 16, 1), + MUX(TOP_MOUT_ACLK_GSCL_FIMC, "mout_aclk_gscl_fimc", + mout_aclk_gscl_fimc_p, + MUX_SEL_TOP_GSCL, 20, 1), +}; + +struct samsung_div_clock top_div_clks[] __initdata = { + DIV(TOP_DOUT_ACLK_G2D_333, "dout_aclk_g2d_333", "mout_aclk_g2d_333", + DIV_TOP_G2D_MFC, 0, 3), + DIV(TOP_DOUT_ACLK_MFC_333, "dout_aclk_mfc_333", "mout_aclk_mfc_333", + DIV_TOP_G2D_MFC, 4, 3), + + DIV(TOP_DOUT_ACLK_GSCL_333, "dout_aclk_gscl_333", "mout_aclk_gscl_333", + DIV_TOP_GSCL_ISP0, 0, 3), + DIV(TOP_DOUT_ACLK_GSCL_400, "dout_aclk_gscl_400", "mout_aclk_gscl_400", + DIV_TOP_GSCL_ISP0, 4, 3), + DIV(TOP_DOUT_ACLK_GSCL_FIMC, "dout_aclk_gscl_fimc", + "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 8, 3), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR0_A, "dout_sclk_isp1_sensor0_a", + "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 16, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR1_A, "dout_sclk_isp1_sensor1_a", + "mout_aclk_gscl_400", DIV_TOP_GSCL_ISP0, 20, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR2_A, "dout_sclk_isp1_sensor2_a", + "mout_aclk_gscl_fimc", DIV_TOP_GSCL_ISP0, 24, 4), + + DIV(TOP_DOUT_ACLK_ISP1_266, "dout_aclk_isp1_266", "mout_aclk_isp1_266", + DIV_TOP_ISP10, 0, 3), + DIV(TOP_DOUT_ACLK_ISP1_400, "dout_aclk_isp1_400", "mout_aclk_isp1_400", + DIV_TOP_ISP10, 4, 3), + DIV(TOP_DOUT_SCLK_ISP1_SPI0_A, "dout_sclk_isp1_spi0_a", + "mout_sclk_isp1_spi0", DIV_TOP_ISP10, 12, 4), + DIV(TOP_DOUT_SCLK_ISP1_SPI0_B, "dout_sclk_isp1_spi0_b", + "dout_sclk_isp1_spi0_a", DIV_TOP_ISP10, 16, 8), + + DIV(TOP_DOUT_SCLK_ISP1_SPI1_A, "dout_sclk_isp1_spi1_a", + "mout_sclk_isp1_spi1", DIV_TOP_ISP11, 0, 4), + DIV(TOP_DOUT_SCLK_ISP1_SPI1_B, "dout_sclk_isp1_spi1_b", + "dout_sclk_isp1_spi1_a", DIV_TOP_ISP11, 4, 8), + DIV(TOP_DOUT_SCLK_ISP1_UART, "dout_sclk_isp1_uart", + "mout_sclk_isp1_uart", DIV_TOP_ISP11, 12, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR0_B, "dout_sclk_isp1_sensor0_b", + "dout_sclk_isp1_sensor0_a", DIV_TOP_ISP11, 16, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR1_B, "dout_sclk_isp1_sensor1_b", + "dout_sclk_isp1_sensor1_a", DIV_TOP_ISP11, 20, 4), + DIV(TOP_DOUT_SCLK_ISP1_SENSOR2_B, "dout_sclk_isp1_sensor2_b", + "dout_sclk_isp1_sensor2_a", DIV_TOP_ISP11, 24, 4), + + DIV(TOP_DOUTTOP__SCLK_HPM_TARGETCLK, "dout_sclk_hpm_targetclk", + "mout_bustop_pll_user", DIV_TOP_HPM, 0, 3), + + DIV(TOP_DOUT_ACLK_DISP_333, "dout_aclk_disp_333", "mout_aclk_disp_333", + DIV_TOP_DISP, 0, 3), + DIV(TOP_DOUT_ACLK_DISP_222, "dout_aclk_disp_222", "mout_aclk_disp_222", + DIV_TOP_DISP, 4, 3), + DIV(TOP_DOUT_SCLK_DISP_PIXEL, "dout_sclk_disp_pixel", + "mout_sclk_disp_pixel", DIV_TOP_DISP, 8, 3), + + DIV(TOP_DOUT_ACLK_BUS1_400, "dout_aclk_bus1_400", + "mout_bus1_bustop_400", DIV_TOP_BUS, 0, 3), + DIV(TOP_DOUT_ACLK_BUS1_100, "dout_aclk_bus1_100", + "mout_bus1_bustop_100", DIV_TOP_BUS, 4, 4), + DIV(TOP_DOUT_ACLK_BUS2_400, "dout_aclk_bus2_400", + "mout_bus2_bustop_400", DIV_TOP_BUS, 8, 3), + DIV(TOP_DOUT_ACLK_BUS2_100, "dout_aclk_bus2_100", + "mout_bus2_bustop_100", DIV_TOP_BUS, 12, 4), + DIV(TOP_DOUT_ACLK_BUS3_400, "dout_aclk_bus3_400", + "mout_bus3_bustop_400", DIV_TOP_BUS, 16, 3), + DIV(TOP_DOUT_ACLK_BUS3_100, "dout_aclk_bus3_100", + "mout_bus3_bustop_100", DIV_TOP_BUS, 20, 4), + DIV(TOP_DOUT_ACLK_BUS4_400, "dout_aclk_bus4_400", + "mout_bus4_bustop_400", DIV_TOP_BUS, 24, 3), + DIV(TOP_DOUT_ACLK_BUS4_100, "dout_aclk_bus4_100", + "mout_bus4_bustop_100", DIV_TOP_BUS, 28, 4), + + DIV(TOP_DOUT_SCLK_PERI_SPI0_A, "dout_sclk_peri_spi0_a", + "mout_sclk_peri_spi0_clk", DIV_TOP_PERI0, 4, 4), + DIV(TOP_DOUT_SCLK_PERI_SPI0_B, "dout_sclk_peri_spi0_b", + "dout_sclk_peri_spi0_a", DIV_TOP_PERI0, 8, 8), + DIV(TOP_DOUT_SCLK_PERI_SPI1_A, "dout_sclk_peri_spi1_a", + "mout_sclk_peri_spi1_clk", DIV_TOP_PERI0, 16, 4), + DIV(TOP_DOUT_SCLK_PERI_SPI1_B, "dout_sclk_peri_spi1_b", + "dout_sclk_peri_spi1_a", DIV_TOP_PERI0, 20, 8), + + DIV(TOP_DOUT_SCLK_PERI_SPI2_A, "dout_sclk_peri_spi2_a", + "mout_sclk_peri_spi2_clk", DIV_TOP_PERI1, 0, 4), + DIV(TOP_DOUT_SCLK_PERI_SPI2_B, "dout_sclk_peri_spi2_b", + "dout_sclk_peri_spi2_a", DIV_TOP_PERI1, 4, 8), + DIV(TOP_DOUT_SCLK_PERI_UART1, "dout_sclk_peri_uart1", + "mout_sclk_peri_uart1_uclk", DIV_TOP_PERI1, 16, 4), + DIV(TOP_DOUT_SCLK_PERI_UART2, "dout_sclk_peri_uart2", + "mout_sclk_peri_uart2_uclk", DIV_TOP_PERI1, 20, 4), + DIV(TOP_DOUT_SCLK_PERI_UART0, "dout_sclk_peri_uart0", + "mout_sclk_peri_uart0_uclk", DIV_TOP_PERI1, 24, 4), + + DIV(TOP_DOUT_ACLK_PERI_66, "dout_aclk_peri_66", "mout_bustop_pll_user", + DIV_TOP_PERI2, 20, 4), + DIV(TOP_DOUT_ACLK_PERI_AUD, "dout_aclk_peri_aud", + "mout_audtop_pll_user", DIV_TOP_PERI2, 24, 3), + + DIV(TOP_DOUT_ACLK_FSYS_200, "dout_aclk_fsys_200", + "mout_bustop_pll_user", DIV_TOP_FSYS0, 0, 3), + DIV(TOP_DOUT_SCLK_FSYS_USBDRD30_SUSPEND_CLK, + "dout_sclk_fsys_usbdrd30_suspend_clk", + "mout_sclk_fsys_usb", DIV_TOP_FSYS0, 4, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC0_SDCLKIN_A, "dout_sclk_fsys_mmc0_sdclkin_a", + "mout_sclk_fsys_mmc0_sdclkin_b", + DIV_TOP_FSYS0, 12, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC0_SDCLKIN_B, "dout_sclk_fsys_mmc0_sdclkin_b", + "dout_sclk_fsys_mmc0_sdclkin_a", + DIV_TOP_FSYS0, 16, 8), + + + DIV(TOP_DOUT_SCLK_FSYS_MMC1_SDCLKIN_A, "dout_sclk_fsys_mmc1_sdclkin_a", + "mout_sclk_fsys_mmc1_sdclkin_b", + DIV_TOP_FSYS1, 0, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC1_SDCLKIN_B, "dout_sclk_fsys_mmc1_sdclkin_b", + "dout_sclk_fsys_mmc1_sdclkin_a", + DIV_TOP_FSYS1, 4, 8), + DIV(TOP_DOUT_SCLK_FSYS_MMC2_SDCLKIN_A, "dout_sclk_fsys_mmc2_sdclkin_a", + "mout_sclk_fsys_mmc2_sdclkin_b", + DIV_TOP_FSYS1, 12, 4), + DIV(TOP_DOUT_SCLK_FSYS_MMC2_SDCLKIN_B, "dout_sclk_fsys_mmc2_sdclkin_b", + "dout_sclk_fsys_mmc2_sdclkin_a", + DIV_TOP_FSYS1, 16, 8), + +}; + +struct samsung_gate_clock top_gate_clks[] __initdata = { + GATE(TOP_SCLK_MMC0, "sclk_fsys_mmc0_sdclkin", + "dout_sclk_fsys_mmc0_sdclkin_b", + EN_SCLK_TOP, 7, CLK_SET_RATE_PARENT, 0), + GATE(TOP_SCLK_MMC1, "sclk_fsys_mmc1_sdclkin", + "dout_sclk_fsys_mmc1_sdclkin_b", + EN_SCLK_TOP, 8, CLK_SET_RATE_PARENT, 0), + GATE(TOP_SCLK_MMC2, "sclk_fsys_mmc2_sdclkin", + "dout_sclk_fsys_mmc2_sdclkin_b", + EN_SCLK_TOP, 9, CLK_SET_RATE_PARENT, 0), + GATE(TOP_SCLK_FIMD1, "sclk_disp_pixel", "dout_sclk_disp_pixel", + EN_ACLK_TOP, 10, CLK_IGNORE_UNUSED | + CLK_SET_RATE_PARENT, 0), +}; + +static struct samsung_pll_clock top_pll_clks[] __initdata = { + PLL(pll_2550xx, TOP_FOUT_DISP_PLL, "fout_disp_pll", "fin_pll", + DISP_PLL_LOCK, DISP_PLL_CON0, + pll2550_24mhz_tbl), + PLL(pll_2650xx, TOP_FOUT_AUD_PLL, "fout_aud_pll", "fin_pll", + AUD_PLL_LOCK, AUD_PLL_CON0, + pll2650_24mhz_tbl), +}; + +static void __init exynos5260_clk_top_init(struct device_node *np) +{ + struct exynos5260_cmu_info cmu = {0}; + + cmu.pll_clks = top_pll_clks; + cmu.nr_pll_clks = ARRAY_SIZE(top_pll_clks); + cmu.mux_clks = top_mux_clks; + cmu.nr_mux_clks = ARRAY_SIZE(top_mux_clks); + cmu.div_clks = top_div_clks; + cmu.nr_div_clks = ARRAY_SIZE(top_div_clks); + cmu.gate_clks = top_gate_clks; + cmu.nr_gate_clks = ARRAY_SIZE(top_gate_clks); + cmu.fixed_clks = fixed_rate_clks; + cmu.nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks); + cmu.nr_clk_ids = TOP_NR_CLK; + cmu.clk_regs = top_clk_regs; + cmu.nr_clk_regs = ARRAY_SIZE(top_clk_regs); + + exynos5260_cmu_register_one(np, &cmu); +} + +CLK_OF_DECLARE(exynos5260_clk_top, "samsung,exynos5260-clock-top", + exynos5260_clk_top_init); diff --git a/drivers/clk/samsung/clk-exynos5260.h b/drivers/clk/samsung/clk-exynos5260.h new file mode 100644 index 0000000..d739716 --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5260.h @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Rahul Sharma <rahul.sharma@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for Exynos5260 SoC. + */ + +#ifndef __CLK_EXYNOS5260_H +#define __CLK_EXYNOS5260_H + +/* +*Registers for CMU_AUD +*/ +#define MUX_SEL_AUD 0x0200 +#define MUX_ENABLE_AUD 0x0300 +#define MUX_STAT_AUD 0x0400 +#define MUX_IGNORE_AUD 0x0500 +#define DIV_AUD0 0x0600 +#define DIV_AUD1 0x0604 +#define DIV_STAT_AUD0 0x0700 +#define DIV_STAT_AUD1 0x0704 +#define EN_ACLK_AUD 0x0800 +#define EN_PCLK_AUD 0x0900 +#define EN_SCLK_AUD 0x0a00 +#define EN_IP_AUD 0x0b00 + +/* +*Registers for CMU_DISP +*/ +#define MUX_SEL_DISP0 0x0200 +#define MUX_SEL_DISP1 0x0204 +#define MUX_SEL_DISP2 0x0208 +#define MUX_SEL_DISP3 0x020C +#define MUX_SEL_DISP4 0x0210 +#define MUX_ENABLE_DISP0 0x0300 +#define MUX_ENABLE_DISP1 0x0304 +#define MUX_ENABLE_DISP2 0x0308 +#define MUX_ENABLE_DISP3 0x030c +#define MUX_ENABLE_DISP4 0x0310 +#define MUX_STAT_DISP0 0x0400 +#define MUX_STAT_DISP1 0x0404 +#define MUX_STAT_DISP2 0x0408 +#define MUX_STAT_DISP3 0x040c +#define MUX_STAT_DISP4 0x0410 +#define MUX_IGNORE_DISP0 0x0500 +#define MUX_IGNORE_DISP1 0x0504 +#define MUX_IGNORE_DISP2 0x0508 +#define MUX_IGNORE_DISP3 0x050c +#define MUX_IGNORE_DISP4 0x0510 +#define DIV_DISP 0x0600 +#define DIV_STAT_DISP 0x0700 +#define EN_ACLK_DISP 0x0800 +#define EN_PCLK_DISP 0x0900 +#define EN_SCLK_DISP0 0x0a00 +#define EN_SCLK_DISP1 0x0a04 +#define EN_IP_DISP 0x0b00 +#define EN_IP_DISP_BUS 0x0b04 + + +/* +*Registers for CMU_EGL +*/ +#define EGL_PLL_LOCK 0x0000 +#define EGL_DPLL_LOCK 0x0004 +#define EGL_PLL_CON0 0x0100 +#define EGL_PLL_CON1 0x0104 +#define EGL_PLL_FREQ_DET 0x010c +#define EGL_DPLL_CON0 0x0110 +#define EGL_DPLL_CON1 0x0114 +#define EGL_DPLL_FREQ_DET 0x011c +#define MUX_SEL_EGL 0x0200 +#define MUX_ENABLE_EGL 0x0300 +#define MUX_STAT_EGL 0x0400 +#define DIV_EGL 0x0600 +#define DIV_EGL_PLL_FDET 0x0604 +#define DIV_STAT_EGL 0x0700 +#define DIV_STAT_EGL_PLL_FDET 0x0704 +#define EN_ACLK_EGL 0x0800 +#define EN_PCLK_EGL 0x0900 +#define EN_SCLK_EGL 0x0a00 +#define EN_IP_EGL 0x0b00 +#define CLKOUT_CMU_EGL 0x0c00 +#define CLKOUT_CMU_EGL_DIV_STAT 0x0c04 +#define ARMCLK_STOPCTRL 0x1000 +#define EAGLE_EMA_CTRL 0x1008 +#define EAGLE_EMA_STATUS 0x100c +#define PWR_CTRL 0x1020 +#define PWR_CTRL2 0x1024 +#define CLKSTOP_CTRL 0x1028 +#define INTR_SPREAD_EN 0x1080 +#define INTR_SPREAD_USE_STANDBYWFI 0x1084 +#define INTR_SPREAD_BLOCKING_DURATION 0x1088 +#define CMU_EGL_SPARE0 0x2000 +#define CMU_EGL_SPARE1 0x2004 +#define CMU_EGL_SPARE2 0x2008 +#define CMU_EGL_SPARE3 0x200c +#define CMU_EGL_SPARE4 0x2010 + +/* +*Registers for CMU_FSYS +*/ + +#define MUX_SEL_FSYS0 0x0200 +#define MUX_SEL_FSYS1 0x0204 +#define MUX_ENABLE_FSYS0 0x0300 +#define MUX_ENABLE_FSYS1 0x0304 +#define MUX_STAT_FSYS0 0x0400 +#define MUX_STAT_FSYS1 0x0404 +#define MUX_IGNORE_FSYS0 0x0500 +#define MUX_IGNORE_FSYS1 0x0504 +#define EN_ACLK_FSYS 0x0800 +#define EN_ACLK_FSYS_SECURE_RTIC 0x0804 +#define EN_ACLK_FSYS_SECURE_SMMU_RTIC 0x0808 +#define EN_PCLK_FSYS 0x0900 +#define EN_SCLK_FSYS 0x0a00 +#define EN_IP_FSYS 0x0b00 +#define EN_IP_FSYS_SECURE_RTIC 0x0b04 +#define EN_IP_FSYS_SECURE_SMMU_RTIC 0x0b08 + +/* +*Registers for CMU_G2D +*/ + +#define MUX_SEL_G2D 0x0200 +#define MUX_ENABLE_G2D 0x0300 +#define MUX_STAT_G2D 0x0400 +#define DIV_G2D 0x0600 +#define DIV_STAT_G2D 0x0700 +#define EN_ACLK_G2D 0x0800 +#define EN_ACLK_G2D_SECURE_SSS 0x0804 +#define EN_ACLK_G2D_SECURE_SLIM_SSS 0x0808 +#define EN_ACLK_G2D_SECURE_SMMU_SLIM_SSS 0x080c +#define EN_ACLK_G2D_SECURE_SMMU_SSS 0x0810 +#define EN_ACLK_G2D_SECURE_SMMU_MDMA 0x0814 +#define EN_ACLK_G2D_SECURE_SMMU_G2D 0x0818 +#define EN_PCLK_G2D 0x0900 +#define EN_PCLK_G2D_SECURE_SMMU_SLIM_SSS 0x0904 +#define EN_PCLK_G2D_SECURE_SMMU_SSS 0x0908 +#define EN_PCLK_G2D_SECURE_SMMU_MDMA 0x090c +#define EN_PCLK_G2D_SECURE_SMMU_G2D 0x0910 +#define EN_IP_G2D 0x0b00 +#define EN_IP_G2D_SECURE_SSS 0x0b04 +#define EN_IP_G2D_SECURE_SLIM_SSS 0x0b08 +#define EN_IP_G2D_SECURE_SMMU_SLIM_SSS 0x0b0c +#define EN_IP_G2D_SECURE_SMMU_SSS 0x0b10 +#define EN_IP_G2D_SECURE_SMMU_MDMA 0x0b14 +#define EN_IP_G2D_SECURE_SMMU_G2D 0x0b18 + +/* +*Registers for CMU_G3D +*/ + +#define G3D_PLL_LOCK 0x0000 +#define G3D_PLL_CON0 0x0100 +#define G3D_PLL_CON1 0x0104 +#define G3D_PLL_FDET 0x010c +#define MUX_SEL_G3D 0x0200 +#define MUX_EN_G3D 0x0300 +#define MUX_STAT_G3D 0x0400 +#define MUX_IGNORE_G3D 0x0500 +#define DIV_G3D 0x0600 +#define DIV_G3D_PLL_FDET 0x0604 +#define DIV_STAT_G3D 0x0700 +#define DIV_STAT_G3D_PLL_FDET 0x0704 +#define EN_ACLK_G3D 0x0800 +#define EN_PCLK_G3D 0x0900 +#define EN_SCLK_G3D 0x0a00 +#define EN_IP_G3D 0x0b00 +#define CLKOUT_CMU_G3D 0x0c00 +#define CLKOUT_CMU_G3D_DIV_STAT 0x0c04 +#define G3DCLK_STOPCTRL 0x1000 +#define G3D_EMA_CTRL 0x1008 +#define G3D_EMA_STATUS 0x100c + +/* +*Registers for CMU_GSCL +*/ + +#define MUX_SEL_GSCL 0x0200 +#define MUX_EN_GSCL 0x0300 +#define MUX_STAT_GSCL 0x0400 +#define MUX_IGNORE_GSCL 0x0500 +#define DIV_GSCL 0x0600 +#define DIV_STAT_GSCL 0x0700 +#define EN_ACLK_GSCL 0x0800 +#define EN_ACLK_GSCL_FIMC 0x0804 +#define EN_ACLK_GSCL_SECURE_SMMU_GSCL0 0x0808 +#define EN_ACLK_GSCL_SECURE_SMMU_GSCL1 0x080c +#define EN_ACLK_GSCL_SECURE_SMMU_MSCL0 0x0810 +#define EN_ACLK_GSCL_SECURE_SMMU_MSCL1 0x0814 +#define EN_PCLK_GSCL 0x0900 +#define EN_PCLK_GSCL_FIMC 0x0904 +#define EN_PCLK_GSCL_SECURE_SMMU_GSCL0 0x0908 +#define EN_PCLK_GSCL_SECURE_SMMU_GSCL1 0x090c +#define EN_PCLK_GSCL_SECURE_SMMU_MSCL0 0x0910 +#define EN_PCLK_GSCL_SECURE_SMMU_MSCL1 0x0914 +#define EN_SCLK_GSCL 0x0a00 +#define EN_SCLK_GSCL_FIMC 0x0a04 +#define EN_IP_GSCL 0x0b00 +#define EN_IP_GSCL_FIMC 0x0b04 +#define EN_IP_GSCL_SECURE_SMMU_GSCL0 0x0b08 +#define EN_IP_GSCL_SECURE_SMMU_GSCL1 0x0b0c +#define EN_IP_GSCL_SECURE_SMMU_MSCL0 0x0b10 +#define EN_IP_GSCL_SECURE_SMMU_MSCL1 0x0b14 + +/* +*Registers for CMU_ISP +*/ +#define MUX_SEL_ISP0 0x0200 +#define MUX_SEL_ISP1 0x0204 +#define MUX_ENABLE_ISP0 0x0300 +#define MUX_ENABLE_ISP1 0x0304 +#define MUX_STAT_ISP0 0x0400 +#define MUX_STAT_ISP1 0x0404 +#define MUX_IGNORE_ISP0 0x0500 +#define MUX_IGNORE_ISP1 0x0504 +#define DIV_ISP 0x0600 +#define DIV_STAT_ISP 0x0700 +#define EN_ACLK_ISP0 0x0800 +#define EN_ACLK_ISP1 0x0804 +#define EN_PCLK_ISP0 0x0900 +#define EN_PCLK_ISP1 0x0904 +#define EN_SCLK_ISP 0x0a00 +#define EN_IP_ISP0 0x0b00 +#define EN_IP_ISP1 0x0b04 + +/* +*Registers for CMU_KFC +*/ +#define KFC_PLL_LOCK 0x0000 +#define KFC_PLL_CON0 0x0100 +#define KFC_PLL_CON1 0x0104 +#define KFC_PLL_FDET 0x010c +#define MUX_SEL_KFC0 0x0200 +#define MUX_SEL_KFC2 0x0208 +#define MUX_ENABLE_KFC0 0x0300 +#define MUX_ENABLE_KFC2 0x0308 +#define MUX_STAT_KFC0 0x0400 +#define MUX_STAT_KFC2 0x0408 +#define DIV_KFC 0x0600 +#define DIV_KFC_PLL_FDET 0x0604 +#define DIV_STAT_KFC 0x0700 +#define DIV_STAT_KFC_PLL_FDET 0x0704 +#define EN_ACLK_KFC 0x0800 +#define EN_PCLK_KFC 0x0900 +#define EN_SCLK_KFC 0x0a00 +#define EN_IP_KFC 0x0b00 +#define CLKOUT_CMU_KFC 0x0c00 +#define CLKOUT_CMU_KFC_DIV_STAT 0x0c04 +#define ARMCLK_STOPCTRL_KFC 0x1000 +#define ARM_EMA_CTRL 0x1008 +#define ARM_EMA_STATUS 0x100c +#define PWR_CTRL_KFC 0x1020 +#define PWR_CTRL2_KFC 0x1024 +#define CLKSTOP_CTRL_KFC 0x1028 +#define INTR_SPREAD_ENABLE_KFC 0x1080 +#define INTR_SPREAD_USE_STANDBYWFI_KFC 0x1084 +#define INTR_SPREAD_BLOCKING_DURATION_KFC 0x1088 +#define CMU_KFC_SPARE0 0x2000 +#define CMU_KFC_SPARE1 0x2004 +#define CMU_KFC_SPARE2 0x2008 +#define CMU_KFC_SPARE3 0x200c +#define CMU_KFC_SPARE4 0x2010 + +/* +*Registers for CMU_MFC +*/ +#define MUX_SEL_MFC 0x0200 +#define MUX_ENABLE_MFC 0x0300 +#define MUX_STAT_MFC 0x0400 +#define DIV_MFC 0x0600 +#define DIV_STAT_MFC 0x0700 +#define EN_ACLK_MFC 0x0800 +#define EN_ACLK_SECURE_SMMU2_MFC 0x0804 +#define EN_PCLK_MFC 0x0900 +#define EN_PCLK_SECURE_SMMU2_MFC 0x0904 +#define EN_IP_MFC 0x0b00 +#define EN_IP_MFC_SECURE_SMMU2_MFC 0x0b04 + +/* +*Registers for CMU_MIF +*/ +#define MEM_PLL_LOCK 0x0000 +#define BUS_PLL_LOCK 0x0004 +#define MEDIA_PLL_LOCK 0x0008 +#define MEM_PLL_CON0 0x0100 +#define MEM_PLL_CON1 0x0104 +#define MEM_PLL_FDET 0x010c +#define BUS_PLL_CON0 0x0110 +#define BUS_PLL_CON1 0x0114 +#define BUS_PLL_FDET 0x011c +#define MEDIA_PLL_CON0 0x0120 +#define MEDIA_PLL_CON1 0x0124 +#define MEDIA_PLL_FDET 0x012c +#define MUX_SEL_MIF 0x0200 +#define MUX_ENABLE_MIF 0x0300 +#define MUX_STAT_MIF 0x0400 +#define MUX_IGNORE_MIF 0x0500 +#define DIV_MIF 0x0600 +#define DIV_MIF_PLL_FDET 0x0604 +#define DIV_STAT_MIF 0x0700 +#define DIV_STAT_MIF_PLL_FDET 0x0704 +#define EN_ACLK_MIF 0x0800 +#define EN_ACLK_MIF_SECURE_DREX1_TZ 0x0804 +#define EN_ACLK_MIF_SECURE_DREX0_TZ 0x0808 +#define EN_ACLK_MIF_SECURE_INTMEM 0x080c +#define EN_PCLK_MIF 0x0900 +#define EN_PCLK_MIF_SECURE_MONOCNT 0x0904 +#define EN_PCLK_MIF_SECURE_RTC_APBIF 0x0908 +#define EN_PCLK_MIF_SECURE_DREX1_TZ 0x090c +#define EN_PCLK_MIF_SECURE_DREX0_TZ 0x0910 +#define EN_SCLK_MIF 0x0a00 +#define EN_IP_MIF 0x0b00 +#define EN_IP_MIF_SECURE_MONOCNT 0x0b04 +#define EN_IP_MIF_SECURE_RTC_APBIF 0x0b08 +#define EN_IP_MIF_SECURE_DREX1_TZ 0x0b0c +#define EN_IP_MIF_SECURE_DREX0_TZ 0x0b10 +#define EN_IP_MIF_SECURE_INTEMEM 0x0b14 +#define CLKOUT_CMU_MIF_DIV_STAT 0x0c04 +#define DREX_FREQ_CTRL 0x1000 +#define PAUSE 0x1004 +#define DDRPHY_LOCK_CTRL 0x1008 +#define CLKOUT_CMU_MIF 0xcb00 + +/* +*Registers for CMU_PERI +*/ +#define MUX_SEL_PERI 0x0200 +#define MUX_SEL_PERI1 0x0204 +#define MUX_ENABLE_PERI 0x0300 +#define MUX_ENABLE_PERI1 0x0304 +#define MUX_STAT_PERI 0x0400 +#define MUX_STAT_PERI1 0x0404 +#define MUX_IGNORE_PERI 0x0500 +#define MUX_IGNORE_PERI1 0x0504 +#define DIV_PERI 0x0600 +#define DIV_STAT_PERI 0x0700 +#define EN_PCLK_PERI0 0x0800 +#define EN_PCLK_PERI1 0x0804 +#define EN_PCLK_PERI2 0x0808 +#define EN_PCLK_PERI3 0x080c +#define EN_PCLK_PERI_SECURE_CHIPID 0x0810 +#define EN_PCLK_PERI_SECURE_PROVKEY0 0x0814 +#define EN_PCLK_PERI_SECURE_PROVKEY1 0x0818 +#define EN_PCLK_PERI_SECURE_SECKEY 0x081c +#define EN_PCLK_PERI_SECURE_ANTIRBKCNT 0x0820 +#define EN_PCLK_PERI_SECURE_TOP_RTC 0x0824 +#define EN_PCLK_PERI_SECURE_TZPC 0x0828 +#define EN_SCLK_PERI 0x0a00 +#define EN_SCLK_PERI_SECURE_TOP_RTC 0x0a04 +#define EN_IP_PERI0 0x0b00 +#define EN_IP_PERI1 0x0b04 +#define EN_IP_PERI2 0x0b08 +#define EN_IP_PERI_SECURE_CHIPID 0x0b0c +#define EN_IP_PERI_SECURE_PROVKEY0 0x0b10 +#define EN_IP_PERI_SECURE_PROVKEY1 0x0b14 +#define EN_IP_PERI_SECURE_SECKEY 0x0b18 +#define EN_IP_PERI_SECURE_ANTIRBKCNT 0x0b1c +#define EN_IP_PERI_SECURE_TOP_RTC 0x0b20 +#define EN_IP_PERI_SECURE_TZPC 0x0b24 + +/* +*Registers for CMU_TOP +*/ +#define DISP_PLL_LOCK 0x0000 +#define AUD_PLL_LOCK 0x0004 +#define DISP_PLL_CON0 0x0100 +#define DISP_PLL_CON1 0x0104 +#define DISP_PLL_FDET 0x0108 +#define AUD_PLL_CON0 0x0110 +#define AUD_PLL_CON1 0x0114 +#define AUD_PLL_CON2 0x0118 +#define AUD_PLL_FDET 0x011c +#define MUX_SEL_TOP_PLL0 0x0200 +#define MUX_SEL_TOP_MFC 0x0204 +#define MUX_SEL_TOP_G2D 0x0208 +#define MUX_SEL_TOP_GSCL 0x020c +#define MUX_SEL_TOP_ISP10 0x0214 +#define MUX_SEL_TOP_ISP11 0x0218 +#define MUX_SEL_TOP_DISP0 0x021c +#define MUX_SEL_TOP_DISP1 0x0220 +#define MUX_SEL_TOP_BUS 0x0224 +#define MUX_SEL_TOP_PERI0 0x0228 +#define MUX_SEL_TOP_PERI1 0x022c +#define MUX_SEL_TOP_FSYS 0x0230 +#define MUX_ENABLE_TOP_PLL0 0x0300 +#define MUX_ENABLE_TOP_MFC 0x0304 +#define MUX_ENABLE_TOP_G2D 0x0308 +#define MUX_ENABLE_TOP_GSCL 0x030c +#define MUX_ENABLE_TOP_ISP10 0x0314 +#define MUX_ENABLE_TOP_ISP11 0x0318 +#define MUX_ENABLE_TOP_DISP0 0x031c +#define MUX_ENABLE_TOP_DISP1 0x0320 +#define MUX_ENABLE_TOP_BUS 0x0324 +#define MUX_ENABLE_TOP_PERI0 0x0328 +#define MUX_ENABLE_TOP_PERI1 0x032c +#define MUX_ENABLE_TOP_FSYS 0x0330 +#define MUX_STAT_TOP_PLL0 0x0400 +#define MUX_STAT_TOP_MFC 0x0404 +#define MUX_STAT_TOP_G2D 0x0408 +#define MUX_STAT_TOP_GSCL 0x040c +#define MUX_STAT_TOP_ISP10 0x0414 +#define MUX_STAT_TOP_ISP11 0x0418 +#define MUX_STAT_TOP_DISP0 0x041c +#define MUX_STAT_TOP_DISP1 0x0420 +#define MUX_STAT_TOP_BUS 0x0424 +#define MUX_STAT_TOP_PERI0 0x0428 +#define MUX_STAT_TOP_PERI1 0x042c +#define MUX_STAT_TOP_FSYS 0x0430 +#define MUX_IGNORE_TOP_PLL0 0x0500 +#define MUX_IGNORE_TOP_MFC 0x0504 +#define MUX_IGNORE_TOP_G2D 0x0508 +#define MUX_IGNORE_TOP_GSCL 0x050c +#define MUX_IGNORE_TOP_ISP10 0x0514 +#define MUX_IGNORE_TOP_ISP11 0x0518 +#define MUX_IGNORE_TOP_DISP0 0x051c +#define MUX_IGNORE_TOP_DISP1 0x0520 +#define MUX_IGNORE_TOP_BUS 0x0524 +#define MUX_IGNORE_TOP_PERI0 0x0528 +#define MUX_IGNORE_TOP_PERI1 0x052c +#define MUX_IGNORE_TOP_FSYS 0x0530 +#define DIV_TOP_G2D_MFC 0x0600 +#define DIV_TOP_GSCL_ISP0 0x0604 +#define DIV_TOP_ISP10 0x0608 +#define DIV_TOP_ISP11 0x060c +#define DIV_TOP_DISP 0x0610 +#define DIV_TOP_BUS 0x0614 +#define DIV_TOP_PERI0 0x0618 +#define DIV_TOP_PERI1 0x061c +#define DIV_TOP_PERI2 0x0620 +#define DIV_TOP_FSYS0 0x0624 +#define DIV_TOP_FSYS1 0x0628 +#define DIV_TOP_HPM 0x062c +#define DIV_TOP_PLL_FDET 0x0630 +#define DIV_STAT_TOP_G2D_MFC 0x0700 +#define DIV_STAT_TOP_GSCL_ISP0 0x0704 +#define DIV_STAT_TOP_ISP10 0x0708 +#define DIV_STAT_TOP_ISP11 0x070c +#define DIV_STAT_TOP_DISP 0x0710 +#define DIV_STAT_TOP_BUS 0x0714 +#define DIV_STAT_TOP_PERI0 0x0718 +#define DIV_STAT_TOP_PERI1 0x071c +#define DIV_STAT_TOP_PERI2 0x0720 +#define DIV_STAT_TOP_FSYS0 0x0724 +#define DIV_STAT_TOP_FSYS1 0x0728 +#define DIV_STAT_TOP_HPM 0x072c +#define DIV_STAT_TOP_PLL_FDET 0x0730 +#define EN_ACLK_TOP 0x0800 +#define EN_SCLK_TOP 0x0a00 +#define EN_IP_TOP 0x0b00 +#define CLKOUT_CMU_TOP 0x0c00 +#define CLKOUT_CMU_TOP_DIV_STAT 0x0c04 + +#endif /*__CLK_EXYNOS5260_H */ + diff --git a/drivers/clk/samsung/clk-exynos5410.c b/drivers/clk/samsung/clk-exynos5410.c new file mode 100644 index 0000000..c9505ab --- /dev/null +++ b/drivers/clk/samsung/clk-exynos5410.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2013 Samsung Electronics Co., Ltd. + * Author: Tarek Dakhran <t.dakhran@samsung.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Common Clock Framework support for Exynos5410 SoC. +*/ + +#include <dt-bindings/clock/exynos5410.h> + +#include <linux/clk.h> +#include <linux/clkdev.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include "clk.h" + +#define APLL_LOCK 0x0 +#define APLL_CON0 0x100 +#define CPLL_LOCK 0x10020 +#define CPLL_CON0 0x10120 +#define MPLL_LOCK 0x4000 +#define MPLL_CON0 0x4100 +#define BPLL_LOCK 0x20010 +#define BPLL_CON0 0x20110 +#define KPLL_LOCK 0x28000 +#define KPLL_CON0 0x28100 + +#define SRC_CPU 0x200 +#define DIV_CPU0 0x500 +#define SRC_CPERI1 0x4204 +#define DIV_TOP0 0x10510 +#define DIV_TOP1 0x10514 +#define DIV_FSYS1 0x1054c +#define DIV_FSYS2 0x10550 +#define DIV_PERIC0 0x10558 +#define SRC_TOP0 0x10210 +#define SRC_TOP1 0x10214 +#define SRC_TOP2 0x10218 +#define SRC_FSYS 0x10244 +#define SRC_PERIC0 0x10250 +#define SRC_MASK_FSYS 0x10340 +#define SRC_MASK_PERIC0 0x10350 +#define GATE_BUS_FSYS0 0x10740 +#define GATE_IP_FSYS 0x10944 +#define GATE_IP_PERIC 0x10950 +#define GATE_IP_PERIS 0x10960 +#define SRC_CDREX 0x20200 +#define SRC_KFC 0x28200 +#define DIV_KFC0 0x28500 + +/* list of PLLs */ +enum exynos5410_plls { + apll, cpll, mpll, + bpll, kpll, + nr_plls /* number of PLLs */ +}; + +/* list of all parent clocks */ +PNAME(apll_p) = { "fin_pll", "fout_apll", }; +PNAME(bpll_p) = { "fin_pll", "fout_bpll", }; +PNAME(cpll_p) = { "fin_pll", "fout_cpll" }; +PNAME(mpll_p) = { "fin_pll", "fout_mpll", }; +PNAME(kpll_p) = { "fin_pll", "fout_kpll", }; + +PNAME(mout_cpu_p) = { "mout_apll", "sclk_mpll", }; +PNAME(mout_kfc_p) = { "mout_kpll", "sclk_mpll", }; + +PNAME(mpll_user_p) = { "fin_pll", "sclk_mpll", }; +PNAME(bpll_user_p) = { "fin_pll", "sclk_bpll", }; +PNAME(mpll_bpll_p) = { "sclk_mpll_muxed", "sclk_bpll_muxed", }; + +PNAME(group2_p) = { "fin_pll", "fin_pll", "none", "none", + "none", "none", "sclk_mpll_bpll", + "none", "none", "sclk_cpll" }; + +static struct samsung_mux_clock exynos5410_mux_clks[] __initdata = { + MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1), + MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), + + MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1), + MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1), + + MUX(0, "sclk_mpll", mpll_p, SRC_CPERI1, 8, 1), + MUX(0, "sclk_mpll_muxed", mpll_user_p, SRC_TOP2, 20, 1), + + MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1), + MUX(0, "sclk_bpll_muxed", bpll_user_p, SRC_TOP2, 24, 1), + + MUX(0, "sclk_cpll", cpll_p, SRC_TOP2, 8, 1), + + MUX(0, "sclk_mpll_bpll", mpll_bpll_p, SRC_TOP1, 20, 1), + + MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 0, 4), + MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 4, 4), + MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 8, 4), + + MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 0, 4), + MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 4, 4), + MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 8, 4), + + MUX(0, "mout_aclk200", mpll_bpll_p, SRC_TOP0, 12, 1), + MUX(0, "mout_aclk400", mpll_bpll_p, SRC_TOP0, 20, 1), +}; + +static struct samsung_div_clock exynos5410_div_clks[] __initdata = { + DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), + DIV(0, "div_arm2", "div_arm", DIV_CPU0, 28, 3), + + DIV(0, "div_acp", "div_arm2", DIV_CPU0, 8, 3), + DIV(0, "div_cpud", "div_arm2", DIV_CPU0, 4, 3), + DIV(0, "div_atb", "div_arm2", DIV_CPU0, 16, 3), + DIV(0, "pclk_dbg", "div_arm2", DIV_CPU0, 20, 3), + + DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3), + DIV(0, "div_aclk", "div_kfc", DIV_KFC0, 4, 3), + DIV(0, "div_pclk", "div_kfc", DIV_KFC0, 20, 3), + + DIV(0, "aclk66_pre", "sclk_mpll_muxed", DIV_TOP1, 24, 3), + DIV(0, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3), + + DIV(0, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4), + DIV(0, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4), + DIV(0, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4), + + DIV_F(0, "div_mmc_pre0", "div_mmc0", + DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0), + DIV_F(0, "div_mmc_pre1", "div_mmc1", + DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0), + DIV_F(0, "div_mmc_pre2", "div_mmc2", + DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0), + + DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4), + DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4), + DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4), + DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4), + + DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3), + DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3), +}; + +static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { + GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0), + + GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0", + SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1", + SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2", + SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0), + + GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0), + GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0), + GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0), + + GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0), + GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0), + GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0), + + GATE(CLK_SCLK_UART0, "sclk_uart0", "div_uart0", + SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART1, "sclk_uart1", "div_uart1", + SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_UART2, "sclk_uart2", "div_uart2", + SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0), +}; + +static struct samsung_pll_clock exynos5410_plls[nr_plls] __initdata = { + [apll] = PLL(pll_35xx, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, + APLL_CON0, NULL), + [cpll] = PLL(pll_35xx, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, + CPLL_CON0, NULL), + [mpll] = PLL(pll_35xx, CLK_FOUT_MPLL, "fout_mpll", "fin_pll", MPLL_LOCK, + MPLL_CON0, NULL), + [bpll] = PLL(pll_35xx, CLK_FOUT_BPLL, "fout_bpll", "fin_pll", BPLL_LOCK, + BPLL_CON0, NULL), + [kpll] = PLL(pll_35xx, CLK_FOUT_KPLL, "fout_kpll", "fin_pll", KPLL_LOCK, + KPLL_CON0, NULL), +}; + +/* register exynos5410 clocks */ +static void __init exynos5410_clk_init(struct device_node *np) +{ + struct samsung_clk_provider *ctx; + void __iomem *reg_base; + + reg_base = of_iomap(np, 0); + if (!reg_base) + panic("%s: failed to map registers\n", __func__); + + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + + samsung_clk_register_pll(ctx, exynos5410_plls, + ARRAY_SIZE(exynos5410_plls), reg_base); + + samsung_clk_register_mux(ctx, exynos5410_mux_clks, + ARRAY_SIZE(exynos5410_mux_clks)); + samsung_clk_register_div(ctx, exynos5410_div_clks, + ARRAY_SIZE(exynos5410_div_clks)); + samsung_clk_register_gate(ctx, exynos5410_gate_clks, + ARRAY_SIZE(exynos5410_gate_clks)); + + pr_debug("Exynos5410: clock setup completed.\n"); +} +CLK_OF_DECLARE(exynos5410_clk, "samsung,exynos5410-clock", exynos5410_clk_init); diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 60b2681..9d7d7ee 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -27,18 +27,24 @@ #define DIV_CPU1 0x504 #define GATE_BUS_CPU 0x700 #define GATE_SCLK_CPU 0x800 +#define CLKOUT_CMU_CPU 0xa00 +#define GATE_IP_G2D 0x8800 #define CPLL_LOCK 0x10020 #define DPLL_LOCK 0x10030 #define EPLL_LOCK 0x10040 #define RPLL_LOCK 0x10050 #define IPLL_LOCK 0x10060 #define SPLL_LOCK 0x10070 -#define VPLL_LOCK 0x10070 +#define VPLL_LOCK 0x10080 #define MPLL_LOCK 0x10090 #define CPLL_CON0 0x10120 #define DPLL_CON0 0x10128 #define EPLL_CON0 0x10130 +#define EPLL_CON1 0x10134 +#define EPLL_CON2 0x10138 #define RPLL_CON0 0x10140 +#define RPLL_CON1 0x10144 +#define RPLL_CON2 0x10148 #define IPLL_CON0 0x10150 #define SPLL_CON0 0x10160 #define VPLL_CON0 0x10170 @@ -51,21 +57,31 @@ #define SRC_TOP5 0x10214 #define SRC_TOP6 0x10218 #define SRC_TOP7 0x1021c +#define SRC_TOP8 0x10220 /* 5800 specific */ +#define SRC_TOP9 0x10224 /* 5800 specific */ #define SRC_DISP10 0x1022c #define SRC_MAU 0x10240 #define SRC_FSYS 0x10244 #define SRC_PERIC0 0x10250 #define SRC_PERIC1 0x10254 +#define SRC_ISP 0x10270 +#define SRC_CAM 0x10274 /* 5800 specific */ #define SRC_TOP10 0x10280 #define SRC_TOP11 0x10284 #define SRC_TOP12 0x10288 -#define SRC_MASK_DISP10 0x1032c +#define SRC_TOP13 0x1028c /* 5800 specific */ +#define SRC_MASK_TOP2 0x10308 +#define SRC_MASK_TOP7 0x1031c +#define SRC_MASK_DISP10 0x1032c +#define SRC_MASK_MAU 0x10334 #define SRC_MASK_FSYS 0x10340 #define SRC_MASK_PERIC0 0x10350 #define SRC_MASK_PERIC1 0x10354 #define DIV_TOP0 0x10500 #define DIV_TOP1 0x10504 #define DIV_TOP2 0x10508 +#define DIV_TOP8 0x10520 /* 5800 specific */ +#define DIV_TOP9 0x10524 /* 5800 specific */ #define DIV_DISP10 0x1052c #define DIV_MAU 0x10544 #define DIV_FSYS0 0x10548 @@ -76,54 +92,82 @@ #define DIV_PERIC2 0x10560 #define DIV_PERIC3 0x10564 #define DIV_PERIC4 0x10568 +#define DIV_CAM 0x10574 /* 5800 specific */ +#define SCLK_DIV_ISP0 0x10580 +#define SCLK_DIV_ISP1 0x10584 +#define DIV2_RATIO0 0x10590 +#define DIV4_RATIO 0x105a0 #define GATE_BUS_TOP 0x10700 +#define GATE_BUS_GEN 0x1073c #define GATE_BUS_FSYS0 0x10740 +#define GATE_BUS_FSYS2 0x10748 #define GATE_BUS_PERIC 0x10750 #define GATE_BUS_PERIC1 0x10754 #define GATE_BUS_PERIS0 0x10760 #define GATE_BUS_PERIS1 0x10764 +#define GATE_BUS_NOC 0x10770 +#define GATE_TOP_SCLK_ISP 0x10870 #define GATE_IP_GSCL0 0x10910 #define GATE_IP_GSCL1 0x10920 +#define GATE_IP_CAM 0x10924 /* 5800 specific */ #define GATE_IP_MFC 0x1092c #define GATE_IP_DISP1 0x10928 #define GATE_IP_G3D 0x10930 #define GATE_IP_GEN 0x10934 +#define GATE_IP_FSYS 0x10944 +#define GATE_IP_PERIC 0x10950 +#define GATE_IP_PERIS 0x10960 #define GATE_IP_MSCL 0x10970 #define GATE_TOP_SCLK_GSCL 0x10820 #define GATE_TOP_SCLK_DISP1 0x10828 #define GATE_TOP_SCLK_MAU 0x1083c #define GATE_TOP_SCLK_FSYS 0x10840 #define GATE_TOP_SCLK_PERIC 0x10850 +#define TOP_SPARE2 0x10b08 #define BPLL_LOCK 0x20010 #define BPLL_CON0 0x20110 -#define SRC_CDREX 0x20200 #define KPLL_LOCK 0x28000 #define KPLL_CON0 0x28100 #define SRC_KFC 0x28200 #define DIV_KFC0 0x28500 +/* Exynos5x SoC type */ +enum exynos5x_soc { + EXYNOS5420, + EXYNOS5800, +}; + /* list of PLLs */ -enum exynos5420_plls { +enum exynos5x_plls { apll, cpll, dpll, epll, rpll, ipll, spll, vpll, mpll, bpll, kpll, nr_plls /* number of PLLs */ }; static void __iomem *reg_base; +static enum exynos5x_soc exynos5x_soc; #ifdef CONFIG_PM_SLEEP -static struct samsung_clk_reg_dump *exynos5420_save; +static struct samsung_clk_reg_dump *exynos5x_save; +static struct samsung_clk_reg_dump *exynos5800_save; /* * list of controller registers to be saved and restored during a * suspend/resume cycle. */ -static unsigned long exynos5420_clk_regs[] __initdata = { +static unsigned long exynos5x_clk_regs[] __initdata = { SRC_CPU, DIV_CPU0, DIV_CPU1, GATE_BUS_CPU, GATE_SCLK_CPU, + CLKOUT_CMU_CPU, + EPLL_CON0, + EPLL_CON1, + EPLL_CON2, + RPLL_CON0, + RPLL_CON1, + RPLL_CON2, SRC_TOP0, SRC_TOP1, SRC_TOP2, @@ -140,10 +184,13 @@ static unsigned long exynos5420_clk_regs[] __initdata = { SRC_TOP10, SRC_TOP11, SRC_TOP12, + SRC_MASK_TOP2, + SRC_MASK_TOP7, SRC_MASK_DISP10, SRC_MASK_FSYS, SRC_MASK_PERIC0, SRC_MASK_PERIC1, + SRC_ISP, DIV_TOP0, DIV_TOP1, DIV_TOP2, @@ -157,41 +204,71 @@ static unsigned long exynos5420_clk_regs[] __initdata = { DIV_PERIC2, DIV_PERIC3, DIV_PERIC4, + SCLK_DIV_ISP0, + SCLK_DIV_ISP1, + DIV2_RATIO0, + DIV4_RATIO, GATE_BUS_TOP, + GATE_BUS_GEN, GATE_BUS_FSYS0, + GATE_BUS_FSYS2, GATE_BUS_PERIC, GATE_BUS_PERIC1, GATE_BUS_PERIS0, GATE_BUS_PERIS1, + GATE_BUS_NOC, + GATE_TOP_SCLK_ISP, GATE_IP_GSCL0, GATE_IP_GSCL1, GATE_IP_MFC, GATE_IP_DISP1, GATE_IP_G3D, GATE_IP_GEN, + GATE_IP_FSYS, + GATE_IP_PERIC, + GATE_IP_PERIS, GATE_IP_MSCL, GATE_TOP_SCLK_GSCL, GATE_TOP_SCLK_DISP1, GATE_TOP_SCLK_MAU, GATE_TOP_SCLK_FSYS, GATE_TOP_SCLK_PERIC, - SRC_CDREX, + TOP_SPARE2, SRC_KFC, DIV_KFC0, }; +static unsigned long exynos5800_clk_regs[] __initdata = { + SRC_TOP8, + SRC_TOP9, + SRC_CAM, + SRC_TOP1, + DIV_TOP8, + DIV_TOP9, + DIV_CAM, + GATE_IP_CAM, +}; + static int exynos5420_clk_suspend(void) { - samsung_clk_save(reg_base, exynos5420_save, - ARRAY_SIZE(exynos5420_clk_regs)); + samsung_clk_save(reg_base, exynos5x_save, + ARRAY_SIZE(exynos5x_clk_regs)); + + if (exynos5x_soc == EXYNOS5800) + samsung_clk_save(reg_base, exynos5800_save, + ARRAY_SIZE(exynos5800_clk_regs)); return 0; } static void exynos5420_clk_resume(void) { - samsung_clk_restore(reg_base, exynos5420_save, - ARRAY_SIZE(exynos5420_clk_regs)); + samsung_clk_restore(reg_base, exynos5x_save, + ARRAY_SIZE(exynos5x_clk_regs)); + + if (exynos5x_soc == EXYNOS5800) + samsung_clk_restore(reg_base, exynos5800_save, + ARRAY_SIZE(exynos5800_clk_regs)); } static struct syscore_ops exynos5420_clk_syscore_ops = { @@ -201,108 +278,183 @@ static struct syscore_ops exynos5420_clk_syscore_ops = { static void exynos5420_clk_sleep_init(void) { - exynos5420_save = samsung_clk_alloc_reg_dump(exynos5420_clk_regs, - ARRAY_SIZE(exynos5420_clk_regs)); - if (!exynos5420_save) { + exynos5x_save = samsung_clk_alloc_reg_dump(exynos5x_clk_regs, + ARRAY_SIZE(exynos5x_clk_regs)); + if (!exynos5x_save) { pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", __func__); return; } + if (exynos5x_soc == EXYNOS5800) { + exynos5800_save = + samsung_clk_alloc_reg_dump(exynos5800_clk_regs, + ARRAY_SIZE(exynos5800_clk_regs)); + if (!exynos5800_save) + goto err_soc; + } + register_syscore_ops(&exynos5420_clk_syscore_ops); + return; +err_soc: + kfree(exynos5x_save); + pr_warn("%s: failed to allocate sleep save data, no sleep support!\n", + __func__); + return; } #else static void exynos5420_clk_sleep_init(void) {} #endif /* list of all parent clocks */ -PNAME(mspll_cpu_p) = { "sclk_cpll", "sclk_dpll", - "sclk_mpll", "sclk_spll" }; -PNAME(cpu_p) = { "mout_apll" , "mout_mspll_cpu" }; -PNAME(kfc_p) = { "mout_kpll" , "mout_mspll_kfc" }; -PNAME(apll_p) = { "fin_pll", "fout_apll", }; -PNAME(bpll_p) = { "fin_pll", "fout_bpll", }; -PNAME(cpll_p) = { "fin_pll", "fout_cpll", }; -PNAME(dpll_p) = { "fin_pll", "fout_dpll", }; -PNAME(epll_p) = { "fin_pll", "fout_epll", }; -PNAME(ipll_p) = { "fin_pll", "fout_ipll", }; -PNAME(kpll_p) = { "fin_pll", "fout_kpll", }; -PNAME(mpll_p) = { "fin_pll", "fout_mpll", }; -PNAME(rpll_p) = { "fin_pll", "fout_rpll", }; -PNAME(spll_p) = { "fin_pll", "fout_spll", }; -PNAME(vpll_p) = { "fin_pll", "fout_vpll", }; - -PNAME(group1_p) = { "sclk_cpll", "sclk_dpll", "sclk_mpll" }; -PNAME(group2_p) = { "fin_pll", "sclk_cpll", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(group3_p) = { "sclk_rpll", "sclk_spll" }; -PNAME(group4_p) = { "sclk_ipll", "sclk_dpll", "sclk_mpll" }; -PNAME(group5_p) = { "sclk_vpll", "sclk_dpll" }; - -PNAME(sw_aclk66_p) = { "dout_aclk66", "sclk_spll" }; -PNAME(aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66" }; - -PNAME(sw_aclk200_fsys_p) = { "dout_aclk200_fsys", "sclk_spll"}; -PNAME(user_aclk200_fsys_p) = { "fin_pll", "mout_sw_aclk200_fsys" }; - -PNAME(sw_aclk200_fsys2_p) = { "dout_aclk200_fsys2", "sclk_spll"}; -PNAME(user_aclk200_fsys2_p) = { "fin_pll", "mout_sw_aclk200_fsys2" }; - -PNAME(sw_aclk200_p) = { "dout_aclk200", "sclk_spll"}; -PNAME(aclk200_disp1_p) = { "fin_pll", "mout_sw_aclk200" }; - -PNAME(sw_aclk400_mscl_p) = { "dout_aclk400_mscl", "sclk_spll"}; -PNAME(user_aclk400_mscl_p) = { "fin_pll", "mout_sw_aclk400_mscl" }; - -PNAME(sw_aclk333_p) = { "dout_aclk333", "sclk_spll"}; -PNAME(user_aclk333_p) = { "fin_pll", "mout_sw_aclk333" }; - -PNAME(sw_aclk166_p) = { "dout_aclk166", "sclk_spll"}; -PNAME(user_aclk166_p) = { "fin_pll", "mout_sw_aclk166" }; - -PNAME(sw_aclk266_p) = { "dout_aclk266", "sclk_spll"}; -PNAME(user_aclk266_p) = { "fin_pll", "mout_sw_aclk266" }; - -PNAME(sw_aclk333_432_gscl_p) = { "dout_aclk333_432_gscl", "sclk_spll"}; -PNAME(user_aclk333_432_gscl_p) = { "fin_pll", "mout_sw_aclk333_432_gscl" }; - -PNAME(sw_aclk300_gscl_p) = { "dout_aclk300_gscl", "sclk_spll"}; -PNAME(user_aclk300_gscl_p) = { "fin_pll", "mout_sw_aclk300_gscl" }; - -PNAME(sw_aclk300_disp1_p) = { "dout_aclk300_disp1", "sclk_spll"}; -PNAME(user_aclk300_disp1_p) = { "fin_pll", "mout_sw_aclk300_disp1" }; - -PNAME(sw_aclk300_jpeg_p) = { "dout_aclk300_jpeg", "sclk_spll"}; -PNAME(user_aclk300_jpeg_p) = { "fin_pll", "mout_sw_aclk300_jpeg" }; - -PNAME(sw_aclk_g3d_p) = { "dout_aclk_g3d", "sclk_spll"}; -PNAME(user_aclk_g3d_p) = { "fin_pll", "mout_sw_aclk_g3d" }; - -PNAME(sw_aclk266_g2d_p) = { "dout_aclk266_g2d", "sclk_spll"}; -PNAME(user_aclk266_g2d_p) = { "fin_pll", "mout_sw_aclk266_g2d" }; - -PNAME(sw_aclk333_g2d_p) = { "dout_aclk333_g2d", "sclk_spll"}; -PNAME(user_aclk333_g2d_p) = { "fin_pll", "mout_sw_aclk333_g2d" }; - -PNAME(audio0_p) = { "fin_pll", "cdclk0", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(audio1_p) = { "fin_pll", "cdclk1", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(audio2_p) = { "fin_pll", "cdclk2", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(spdif_p) = { "fin_pll", "dout_audio0", "dout_audio1", "dout_audio2", - "spdif_extclk", "sclk_ipll", "sclk_epll", "sclk_rpll" }; -PNAME(hdmi_p) = { "dout_hdmi_pixel", "sclk_hdmiphy" }; -PNAME(maudio0_p) = { "fin_pll", "maudio_clk", "sclk_dpll", "sclk_mpll", - "sclk_spll", "sclk_ipll", "sclk_epll", "sclk_rpll" }; +PNAME(mout_mspll_cpu_p) = {"mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll"}; +PNAME(mout_cpu_p) = {"mout_apll" , "mout_mspll_cpu"}; +PNAME(mout_kfc_p) = {"mout_kpll" , "mout_mspll_kfc"}; +PNAME(mout_apll_p) = {"fin_pll", "fout_apll"}; +PNAME(mout_bpll_p) = {"fin_pll", "fout_bpll"}; +PNAME(mout_cpll_p) = {"fin_pll", "fout_cpll"}; +PNAME(mout_dpll_p) = {"fin_pll", "fout_dpll"}; +PNAME(mout_epll_p) = {"fin_pll", "fout_epll"}; +PNAME(mout_ipll_p) = {"fin_pll", "fout_ipll"}; +PNAME(mout_kpll_p) = {"fin_pll", "fout_kpll"}; +PNAME(mout_mpll_p) = {"fin_pll", "fout_mpll"}; +PNAME(mout_rpll_p) = {"fin_pll", "fout_rpll"}; +PNAME(mout_spll_p) = {"fin_pll", "fout_spll"}; +PNAME(mout_vpll_p) = {"fin_pll", "fout_vpll"}; + +PNAME(mout_group1_p) = {"mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll"}; +PNAME(mout_group2_p) = {"fin_pll", "mout_sclk_cpll", + "mout_sclk_dpll", "mout_sclk_mpll", "mout_sclk_spll", + "mout_sclk_ipll", "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_group3_p) = {"mout_sclk_rpll", "mout_sclk_spll"}; +PNAME(mout_group4_p) = {"mout_sclk_ipll", "mout_sclk_dpll", "mout_sclk_mpll"}; +PNAME(mout_group5_p) = {"mout_sclk_vpll", "mout_sclk_dpll"}; + +PNAME(mout_fimd1_final_p) = {"mout_fimd1", "mout_fimd1_opt"}; +PNAME(mout_sw_aclk66_p) = {"dout_aclk66", "mout_sclk_spll"}; +PNAME(mout_user_aclk66_peric_p) = { "fin_pll", "mout_sw_aclk66"}; +PNAME(mout_user_pclk66_gpio_p) = {"mout_sw_aclk66", "ff_sw_aclk66"}; + +PNAME(mout_sw_aclk200_fsys_p) = {"dout_aclk200_fsys", "mout_sclk_spll"}; +PNAME(mout_sw_pclk200_fsys_p) = {"dout_pclk200_fsys", "mout_sclk_spll"}; +PNAME(mout_user_pclk200_fsys_p) = {"fin_pll", "mout_sw_pclk200_fsys"}; +PNAME(mout_user_aclk200_fsys_p) = {"fin_pll", "mout_sw_aclk200_fsys"}; + +PNAME(mout_sw_aclk200_fsys2_p) = {"dout_aclk200_fsys2", "mout_sclk_spll"}; +PNAME(mout_user_aclk200_fsys2_p) = {"fin_pll", "mout_sw_aclk200_fsys2"}; +PNAME(mout_sw_aclk100_noc_p) = {"dout_aclk100_noc", "mout_sclk_spll"}; +PNAME(mout_user_aclk100_noc_p) = {"fin_pll", "mout_sw_aclk100_noc"}; + +PNAME(mout_sw_aclk400_wcore_p) = {"dout_aclk400_wcore", "mout_sclk_spll"}; +PNAME(mout_aclk400_wcore_bpll_p) = {"mout_aclk400_wcore", "sclk_bpll"}; +PNAME(mout_user_aclk400_wcore_p) = {"fin_pll", "mout_sw_aclk400_wcore"}; + +PNAME(mout_sw_aclk400_isp_p) = {"dout_aclk400_isp", "mout_sclk_spll"}; +PNAME(mout_user_aclk400_isp_p) = {"fin_pll", "mout_sw_aclk400_isp"}; + +PNAME(mout_sw_aclk333_432_isp0_p) = {"dout_aclk333_432_isp0", + "mout_sclk_spll"}; +PNAME(mout_user_aclk333_432_isp0_p) = {"fin_pll", "mout_sw_aclk333_432_isp0"}; + +PNAME(mout_sw_aclk333_432_isp_p) = {"dout_aclk333_432_isp", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_432_isp_p) = {"fin_pll", "mout_sw_aclk333_432_isp"}; + +PNAME(mout_sw_aclk200_p) = {"dout_aclk200", "mout_sclk_spll"}; +PNAME(mout_user_aclk200_disp1_p) = {"fin_pll", "mout_sw_aclk200"}; + +PNAME(mout_sw_aclk400_mscl_p) = {"dout_aclk400_mscl", "mout_sclk_spll"}; +PNAME(mout_user_aclk400_mscl_p) = {"fin_pll", "mout_sw_aclk400_mscl"}; + +PNAME(mout_sw_aclk333_p) = {"dout_aclk333", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_p) = {"fin_pll", "mout_sw_aclk333"}; + +PNAME(mout_sw_aclk166_p) = {"dout_aclk166", "mout_sclk_spll"}; +PNAME(mout_user_aclk166_p) = {"fin_pll", "mout_sw_aclk166"}; + +PNAME(mout_sw_aclk266_p) = {"dout_aclk266", "mout_sclk_spll"}; +PNAME(mout_user_aclk266_p) = {"fin_pll", "mout_sw_aclk266"}; +PNAME(mout_user_aclk266_isp_p) = {"fin_pll", "mout_sw_aclk266"}; + +PNAME(mout_sw_aclk333_432_gscl_p) = {"dout_aclk333_432_gscl", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_432_gscl_p) = {"fin_pll", "mout_sw_aclk333_432_gscl"}; + +PNAME(mout_sw_aclk300_gscl_p) = {"dout_aclk300_gscl", "mout_sclk_spll"}; +PNAME(mout_user_aclk300_gscl_p) = {"fin_pll", "mout_sw_aclk300_gscl"}; + +PNAME(mout_sw_aclk300_disp1_p) = {"dout_aclk300_disp1", "mout_sclk_spll"}; +PNAME(mout_sw_aclk400_disp1_p) = {"dout_aclk400_disp1", "mout_sclk_spll"}; +PNAME(mout_user_aclk300_disp1_p) = {"fin_pll", "mout_sw_aclk300_disp1"}; +PNAME(mout_user_aclk400_disp1_p) = {"fin_pll", "mout_sw_aclk400_disp1"}; + +PNAME(mout_sw_aclk300_jpeg_p) = {"dout_aclk300_jpeg", "mout_sclk_spll"}; +PNAME(mout_user_aclk300_jpeg_p) = {"fin_pll", "mout_sw_aclk300_jpeg"}; + +PNAME(mout_sw_aclk_g3d_p) = {"dout_aclk_g3d", "mout_sclk_spll"}; +PNAME(mout_user_aclk_g3d_p) = {"fin_pll", "mout_sw_aclk_g3d"}; + +PNAME(mout_sw_aclk266_g2d_p) = {"dout_aclk266_g2d", "mout_sclk_spll"}; +PNAME(mout_user_aclk266_g2d_p) = {"fin_pll", "mout_sw_aclk266_g2d"}; + +PNAME(mout_sw_aclk333_g2d_p) = {"dout_aclk333_g2d", "mout_sclk_spll"}; +PNAME(mout_user_aclk333_g2d_p) = {"fin_pll", "mout_sw_aclk333_g2d"}; + +PNAME(mout_audio0_p) = {"fin_pll", "cdclk0", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_audio1_p) = {"fin_pll", "cdclk1", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_audio2_p) = {"fin_pll", "cdclk2", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_spdif_p) = {"fin_pll", "dout_audio0", "dout_audio1", + "dout_audio2", "spdif_extclk", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_hdmi_p) = {"dout_hdmi_pixel", "sclk_hdmiphy"}; +PNAME(mout_maudio0_p) = {"fin_pll", "maudio_clk", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", "mout_sclk_ipll", + "mout_sclk_epll", "mout_sclk_rpll"}; +PNAME(mout_mau_epll_clk_p) = {"mout_sclk_epll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll"}; +/* List of parents specific to exynos5800 */ +PNAME(mout_epll2_5800_p) = { "mout_sclk_epll", "ff_dout_epll2" }; +PNAME(mout_group1_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2" }; +PNAME(mout_group2_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2", + "mout_epll2", "mout_sclk_ipll" }; +PNAME(mout_group3_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2", + "mout_epll2" }; +PNAME(mout_group5_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll" }; +PNAME(mout_group6_5800_p) = { "mout_sclk_ipll", "mout_sclk_dpll", + "mout_sclk_mpll", "ff_dout_spll2" }; +PNAME(mout_group7_5800_p) = { "mout_sclk_cpll", "mout_sclk_dpll", + "mout_sclk_mpll", "mout_sclk_spll", + "mout_epll2", "mout_sclk_ipll" }; +PNAME(mout_mau_epll_clk_5800_p) = { "mout_sclk_epll", "mout_sclk_dpll", + "mout_sclk_mpll", + "ff_dout_spll2" }; +PNAME(mout_group8_5800_p) = { "dout_aclk432_scaler", "dout_sclk_sw" }; +PNAME(mout_group9_5800_p) = { "dout_osc_div", "mout_sw_aclk432_scaler" }; +PNAME(mout_group10_5800_p) = { "dout_aclk432_cam", "dout_sclk_sw" }; +PNAME(mout_group11_5800_p) = { "dout_osc_div", "mout_sw_aclk432_cam" }; +PNAME(mout_group12_5800_p) = { "dout_aclkfl1_550_cam", "dout_sclk_sw" }; +PNAME(mout_group13_5800_p) = { "dout_osc_div", "mout_sw_aclkfl1_550_cam" }; +PNAME(mout_group14_5800_p) = { "dout_aclk550_cam", "dout_sclk_sw" }; +PNAME(mout_group15_5800_p) = { "dout_osc_div", "mout_sw_aclk550_cam" }; /* fixed rate clocks generated outside the soc */ -static struct samsung_fixed_rate_clock exynos5420_fixed_rate_ext_clks[] __initdata = { +static struct samsung_fixed_rate_clock + exynos5x_fixed_rate_ext_clks[] __initdata = { FRATE(CLK_FIN_PLL, "fin_pll", NULL, CLK_IS_ROOT, 0), }; /* fixed rate clocks generated inside the soc */ -static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = { +static struct samsung_fixed_rate_clock exynos5x_fixed_rate_clks[] __initdata = { FRATE(CLK_SCLK_HDMIPHY, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000), FRATE(0, "sclk_pwi", NULL, CLK_IS_ROOT, 24000000), FRATE(0, "sclk_usbh20", NULL, CLK_IS_ROOT, 48000000), @@ -310,146 +462,309 @@ static struct samsung_fixed_rate_clock exynos5420_fixed_rate_clks[] __initdata = FRATE(0, "sclk_usbh20_scan_clk", NULL, CLK_IS_ROOT, 480000000), }; -static struct samsung_fixed_factor_clock exynos5420_fixed_factor_clks[] __initdata = { - FFACTOR(0, "sclk_hsic_12m", "fin_pll", 1, 2, 0), +static struct samsung_fixed_factor_clock + exynos5x_fixed_factor_clks[] __initdata = { + FFACTOR(0, "ff_hsic_12m", "fin_pll", 1, 2, 0), + FFACTOR(0, "ff_sw_aclk66", "mout_sw_aclk66", 1, 2, 0), }; -static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { - MUX(0, "mout_mspll_kfc", mspll_cpu_p, SRC_TOP7, 8, 2), - MUX(0, "mout_mspll_cpu", mspll_cpu_p, SRC_TOP7, 12, 2), - MUX(0, "mout_apll", apll_p, SRC_CPU, 0, 1), - MUX(0, "mout_cpu", cpu_p, SRC_CPU, 16, 1), - MUX(0, "mout_kpll", kpll_p, SRC_KFC, 0, 1), - MUX(0, "mout_cpu_kfc", kfc_p, SRC_KFC, 16, 1), - - MUX(0, "sclk_bpll", bpll_p, SRC_CDREX, 0, 1), - - MUX_A(0, "mout_aclk400_mscl", group1_p, - SRC_TOP0, 4, 2, "aclk400_mscl"), - MUX(0, "mout_aclk200", group1_p, SRC_TOP0, 8, 2), - MUX(0, "mout_aclk200_fsys2", group1_p, SRC_TOP0, 12, 2), - MUX(0, "mout_aclk200_fsys", group1_p, SRC_TOP0, 28, 2), - - MUX(0, "mout_aclk333_432_gscl", group4_p, SRC_TOP1, 0, 2), - MUX(0, "mout_aclk66", group1_p, SRC_TOP1, 8, 2), - MUX(0, "mout_aclk266", group1_p, SRC_TOP1, 20, 2), - MUX(0, "mout_aclk166", group1_p, SRC_TOP1, 24, 2), - MUX(0, "mout_aclk333", group1_p, SRC_TOP1, 28, 2), - - MUX(0, "mout_aclk333_g2d", group1_p, SRC_TOP2, 8, 2), - MUX(0, "mout_aclk266_g2d", group1_p, SRC_TOP2, 12, 2), - MUX(0, "mout_aclk_g3d", group5_p, SRC_TOP2, 16, 1), - MUX(0, "mout_aclk300_jpeg", group1_p, SRC_TOP2, 20, 2), - MUX(0, "mout_aclk300_disp1", group1_p, SRC_TOP2, 24, 2), - MUX(0, "mout_aclk300_gscl", group1_p, SRC_TOP2, 28, 2), - - MUX(0, "mout_user_aclk400_mscl", user_aclk400_mscl_p, +static struct samsung_fixed_factor_clock + exynos5800_fixed_factor_clks[] __initdata = { + FFACTOR(0, "ff_dout_epll2", "mout_sclk_epll", 1, 2, 0), + FFACTOR(0, "ff_dout_spll2", "mout_sclk_spll", 1, 2, 0), +}; + +struct samsung_mux_clock exynos5800_mux_clks[] __initdata = { + MUX(0, "mout_aclk400_isp", mout_group3_5800_p, SRC_TOP0, 0, 3), + MUX(0, "mout_aclk400_mscl", mout_group3_5800_p, SRC_TOP0, 4, 3), + MUX(0, "mout_aclk400_wcore", mout_group2_5800_p, SRC_TOP0, 16, 3), + MUX(0, "mout_aclk100_noc", mout_group1_5800_p, SRC_TOP0, 20, 2), + + MUX(0, "mout_aclk333_432_gscl", mout_group6_5800_p, SRC_TOP1, 0, 2), + MUX(0, "mout_aclk333_432_isp", mout_group6_5800_p, SRC_TOP1, 4, 2), + MUX(0, "mout_aclk333_432_isp0", mout_group6_5800_p, SRC_TOP1, 12, 2), + MUX(0, "mout_aclk266", mout_group5_5800_p, SRC_TOP1, 20, 2), + MUX(0, "mout_aclk333", mout_group1_5800_p, SRC_TOP1, 28, 2), + + MUX(0, "mout_aclk400_disp1", mout_group7_5800_p, SRC_TOP2, 4, 3), + MUX(0, "mout_aclk333_g2d", mout_group5_5800_p, SRC_TOP2, 8, 2), + MUX(0, "mout_aclk266_g2d", mout_group5_5800_p, SRC_TOP2, 12, 2), + MUX(0, "mout_aclk300_jpeg", mout_group5_5800_p, SRC_TOP2, 20, 2), + MUX(0, "mout_aclk300_disp1", mout_group5_5800_p, SRC_TOP2, 24, 2), + MUX(0, "mout_aclk300_gscl", mout_group5_5800_p, SRC_TOP2, 28, 2), + + MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, SRC_TOP7, + 20, 2), + MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1), + MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1), + + MUX(0, "mout_aclk550_cam", mout_group3_5800_p, SRC_TOP8, 16, 3), + MUX(0, "mout_aclkfl1_550_cam", mout_group3_5800_p, SRC_TOP8, 20, 3), + MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2), + MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2), + + MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p, + SRC_TOP9, 16, 1), + MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p, + SRC_TOP9, 20, 1), + MUX(0, "mout_user_aclk432_cam", mout_group11_5800_p, + SRC_TOP9, 24, 1), + MUX(0, "mout_user_aclk432_scaler", mout_group9_5800_p, + SRC_TOP9, 28, 1), + + MUX(0, "mout_sw_aclk550_cam", mout_group14_5800_p, SRC_TOP13, 16, 1), + MUX(0, "mout_sw_aclkfl1_550_cam", mout_group12_5800_p, + SRC_TOP13, 20, 1), + MUX(0, "mout_sw_aclk432_cam", mout_group10_5800_p, + SRC_TOP13, 24, 1), + MUX(0, "mout_sw_aclk432_scaler", mout_group8_5800_p, + SRC_TOP13, 28, 1), + + MUX(0, "mout_fimd1", mout_group2_p, SRC_DISP10, 4, 3), +}; + +struct samsung_div_clock exynos5800_div_clks[] __initdata = { + DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore", DIV_TOP0, 16, 3), + + DIV(0, "dout_aclk550_cam", "mout_aclk550_cam", + DIV_TOP8, 16, 3), + DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam", + DIV_TOP8, 20, 3), + DIV(0, "dout_aclk432_cam", "mout_aclk432_cam", + DIV_TOP8, 24, 3), + DIV(0, "dout_aclk432_scaler", "mout_aclk432_scaler", + DIV_TOP8, 28, 3), + + DIV(0, "dout_osc_div", "fin_pll", DIV_TOP9, 20, 3), + DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6), +}; + +struct samsung_gate_clock exynos5800_gate_clks[] __initdata = { + GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam", + GATE_BUS_TOP, 24, 0, 0), + GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler", + GATE_BUS_TOP, 27, 0, 0), +}; + +struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { + MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1), + MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p, + TOP_SPARE2, 4, 1), + + MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2), + MUX_A(0, "mout_aclk400_mscl", mout_group1_p, + SRC_TOP0, 4, 2, "aclk400_mscl"), + MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2), + MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2), + + MUX(0, "mout_aclk333_432_gscl", mout_group4_p, SRC_TOP1, 0, 2), + MUX(0, "mout_aclk333_432_isp", mout_group4_p, + SRC_TOP1, 4, 2), + MUX(0, "mout_aclk333_432_isp0", mout_group4_p, SRC_TOP1, 12, 2), + MUX(0, "mout_aclk266", mout_group1_p, SRC_TOP1, 20, 2), + MUX(0, "mout_aclk333", mout_group1_p, SRC_TOP1, 28, 2), + + MUX(0, "mout_aclk400_disp1", mout_group1_p, SRC_TOP2, 4, 2), + MUX(0, "mout_aclk333_g2d", mout_group1_p, SRC_TOP2, 8, 2), + MUX(0, "mout_aclk266_g2d", mout_group1_p, SRC_TOP2, 12, 2), + MUX(0, "mout_aclk300_jpeg", mout_group1_p, SRC_TOP2, 20, 2), + MUX(0, "mout_aclk300_disp1", mout_group1_p, SRC_TOP2, 24, 2), + MUX(0, "mout_aclk300_gscl", mout_group1_p, SRC_TOP2, 28, 2), + + MUX(0, "mout_mau_epll_clk", mout_mau_epll_clk_p, SRC_TOP7, 20, 2), + + MUX(0, "mout_fimd1", mout_group3_p, SRC_DISP10, 4, 1), +}; + +struct samsung_div_clock exynos5420_div_clks[] __initdata = { + DIV(0, "dout_aclk400_wcore", "mout_aclk400_wcore_bpll", + DIV_TOP0, 16, 3), +}; + +static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = { + MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p, + SRC_TOP7, 4, 1), + MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2), + MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2), + + MUX(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1), + MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), + MUX(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1), + MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1), + + MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2), + MUX(0, "mout_aclk200_fsys2", mout_group1_p, SRC_TOP0, 12, 2), + MUX(0, "mout_pclk200_fsys", mout_group1_p, SRC_TOP0, 24, 2), + MUX(0, "mout_aclk200_fsys", mout_group1_p, SRC_TOP0, 28, 2), + + MUX(0, "mout_aclk66", mout_group1_p, SRC_TOP1, 8, 2), + MUX(0, "mout_aclk166", mout_group1_p, SRC_TOP1, 24, 2), + + MUX(0, "mout_aclk_g3d", mout_group5_p, SRC_TOP2, 16, 1), + + MUX(0, "mout_user_aclk400_isp", mout_user_aclk400_isp_p, + SRC_TOP3, 0, 1), + MUX(0, "mout_user_aclk400_mscl", mout_user_aclk400_mscl_p, SRC_TOP3, 4, 1), - MUX_A(0, "mout_aclk200_disp1", aclk200_disp1_p, - SRC_TOP3, 8, 1, "aclk200_disp1"), - MUX(0, "mout_user_aclk200_fsys2", user_aclk200_fsys2_p, + MUX(0, "mout_user_aclk200_disp1", mout_user_aclk200_disp1_p, + SRC_TOP3, 8, 1), + MUX(0, "mout_user_aclk200_fsys2", mout_user_aclk200_fsys2_p, SRC_TOP3, 12, 1), - MUX(0, "mout_user_aclk200_fsys", user_aclk200_fsys_p, + MUX(0, "mout_user_aclk400_wcore", mout_user_aclk400_wcore_p, + SRC_TOP3, 16, 1), + MUX(0, "mout_user_aclk100_noc", mout_user_aclk100_noc_p, + SRC_TOP3, 20, 1), + MUX(0, "mout_user_pclk200_fsys", mout_user_pclk200_fsys_p, + SRC_TOP3, 24, 1), + MUX(0, "mout_user_aclk200_fsys", mout_user_aclk200_fsys_p, SRC_TOP3, 28, 1), - MUX(0, "mout_user_aclk333_432_gscl", user_aclk333_432_gscl_p, + MUX(0, "mout_user_aclk333_432_gscl", mout_user_aclk333_432_gscl_p, SRC_TOP4, 0, 1), - MUX(0, "mout_aclk66_peric", aclk66_peric_p, SRC_TOP4, 8, 1), - MUX(0, "mout_user_aclk266", user_aclk266_p, SRC_TOP4, 20, 1), - MUX(0, "mout_user_aclk166", user_aclk166_p, SRC_TOP4, 24, 1), - MUX(0, "mout_user_aclk333", user_aclk333_p, SRC_TOP4, 28, 1), - - MUX(0, "mout_aclk66_psgen", aclk66_peric_p, SRC_TOP5, 4, 1), - MUX(0, "mout_user_aclk333_g2d", user_aclk333_g2d_p, SRC_TOP5, 8, 1), - MUX(0, "mout_user_aclk266_g2d", user_aclk266_g2d_p, SRC_TOP5, 12, 1), - MUX_A(0, "mout_user_aclk_g3d", user_aclk_g3d_p, - SRC_TOP5, 16, 1, "aclkg3d"), - MUX(0, "mout_user_aclk300_jpeg", user_aclk300_jpeg_p, + MUX(0, "mout_user_aclk333_432_isp", mout_user_aclk333_432_isp_p, + SRC_TOP4, 4, 1), + MUX(0, "mout_user_aclk66_peric", mout_user_aclk66_peric_p, + SRC_TOP4, 8, 1), + MUX(0, "mout_user_aclk333_432_isp0", mout_user_aclk333_432_isp0_p, + SRC_TOP4, 12, 1), + MUX(0, "mout_user_aclk266_isp", mout_user_aclk266_isp_p, + SRC_TOP4, 16, 1), + MUX(0, "mout_user_aclk266", mout_user_aclk266_p, SRC_TOP4, 20, 1), + MUX(0, "mout_user_aclk166", mout_user_aclk166_p, SRC_TOP4, 24, 1), + MUX(0, "mout_user_aclk333", mout_user_aclk333_p, SRC_TOP4, 28, 1), + + MUX(0, "mout_user_aclk400_disp1", mout_user_aclk400_disp1_p, + SRC_TOP5, 0, 1), + MUX(0, "mout_user_aclk66_psgen", mout_user_aclk66_peric_p, + SRC_TOP5, 4, 1), + MUX(0, "mout_user_aclk333_g2d", mout_user_aclk333_g2d_p, + SRC_TOP5, 8, 1), + MUX(0, "mout_user_aclk266_g2d", mout_user_aclk266_g2d_p, + SRC_TOP5, 12, 1), + MUX(CLK_MOUT_G3D, "mout_user_aclk_g3d", mout_user_aclk_g3d_p, + SRC_TOP5, 16, 1), + MUX(0, "mout_user_aclk300_jpeg", mout_user_aclk300_jpeg_p, SRC_TOP5, 20, 1), - MUX(0, "mout_user_aclk300_disp1", user_aclk300_disp1_p, + MUX(0, "mout_user_aclk300_disp1", mout_user_aclk300_disp1_p, SRC_TOP5, 24, 1), - MUX(0, "mout_user_aclk300_gscl", user_aclk300_gscl_p, + MUX(0, "mout_user_aclk300_gscl", mout_user_aclk300_gscl_p, SRC_TOP5, 28, 1), - MUX(0, "sclk_mpll", mpll_p, SRC_TOP6, 0, 1), - MUX(0, "sclk_vpll", vpll_p, SRC_TOP6, 4, 1), - MUX(0, "sclk_spll", spll_p, SRC_TOP6, 8, 1), - MUX(0, "sclk_ipll", ipll_p, SRC_TOP6, 12, 1), - MUX(0, "sclk_rpll", rpll_p, SRC_TOP6, 16, 1), - MUX(0, "sclk_epll", epll_p, SRC_TOP6, 20, 1), - MUX(0, "sclk_dpll", dpll_p, SRC_TOP6, 24, 1), - MUX(0, "sclk_cpll", cpll_p, SRC_TOP6, 28, 1), - - MUX(0, "mout_sw_aclk400_mscl", sw_aclk400_mscl_p, SRC_TOP10, 4, 1), - MUX(0, "mout_sw_aclk200", sw_aclk200_p, SRC_TOP10, 8, 1), - MUX(0, "mout_sw_aclk200_fsys2", sw_aclk200_fsys2_p, + MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1), + MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1), + MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1), + MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1), + MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1), + MUX(0, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1), + MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1), + MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1), + + MUX(0, "mout_sw_aclk400_isp", mout_sw_aclk400_isp_p, + SRC_TOP10, 0, 1), + MUX(0, "mout_sw_aclk400_mscl", mout_sw_aclk400_mscl_p, + SRC_TOP10, 4, 1), + MUX(0, "mout_sw_aclk200", mout_sw_aclk200_p, SRC_TOP10, 8, 1), + MUX(0, "mout_sw_aclk200_fsys2", mout_sw_aclk200_fsys2_p, SRC_TOP10, 12, 1), - MUX(0, "mout_sw_aclk200_fsys", sw_aclk200_fsys_p, SRC_TOP10, 28, 1), - - MUX(0, "mout_sw_aclk333_432_gscl", sw_aclk333_432_gscl_p, + MUX(0, "mout_sw_aclk400_wcore", mout_sw_aclk400_wcore_p, + SRC_TOP10, 16, 1), + MUX(0, "mout_sw_aclk100_noc", mout_sw_aclk100_noc_p, + SRC_TOP10, 20, 1), + MUX(0, "mout_sw_pclk200_fsys", mout_sw_pclk200_fsys_p, + SRC_TOP10, 24, 1), + MUX(0, "mout_sw_aclk200_fsys", mout_sw_aclk200_fsys_p, + SRC_TOP10, 28, 1), + + MUX(0, "mout_sw_aclk333_432_gscl", mout_sw_aclk333_432_gscl_p, SRC_TOP11, 0, 1), - MUX(0, "mout_sw_aclk66", sw_aclk66_p, SRC_TOP11, 8, 1), - MUX(0, "mout_sw_aclk266", sw_aclk266_p, SRC_TOP11, 20, 1), - MUX(0, "mout_sw_aclk166", sw_aclk166_p, SRC_TOP11, 24, 1), - MUX(0, "mout_sw_aclk333", sw_aclk333_p, SRC_TOP11, 28, 1), - - MUX(0, "mout_sw_aclk333_g2d", sw_aclk333_g2d_p, SRC_TOP12, 8, 1), - MUX(0, "mout_sw_aclk266_g2d", sw_aclk266_g2d_p, SRC_TOP12, 12, 1), - MUX(0, "mout_sw_aclk_g3d", sw_aclk_g3d_p, SRC_TOP12, 16, 1), - MUX(0, "mout_sw_aclk300_jpeg", sw_aclk300_jpeg_p, SRC_TOP12, 20, 1), - MUX(0, "mout_sw_aclk300_disp1", sw_aclk300_disp1_p, + MUX(0, "mout_sw_aclk333_432_isp", mout_sw_aclk333_432_isp_p, + SRC_TOP11, 4, 1), + MUX(0, "mout_sw_aclk66", mout_sw_aclk66_p, SRC_TOP11, 8, 1), + MUX(0, "mout_sw_aclk333_432_isp0", mout_sw_aclk333_432_isp0_p, + SRC_TOP11, 12, 1), + MUX(0, "mout_sw_aclk266", mout_sw_aclk266_p, SRC_TOP11, 20, 1), + MUX(0, "mout_sw_aclk166", mout_sw_aclk166_p, SRC_TOP11, 24, 1), + MUX(0, "mout_sw_aclk333", mout_sw_aclk333_p, SRC_TOP11, 28, 1), + + MUX(0, "mout_sw_aclk400_disp1", mout_sw_aclk400_disp1_p, + SRC_TOP12, 4, 1), + MUX(0, "mout_sw_aclk333_g2d", mout_sw_aclk333_g2d_p, + SRC_TOP12, 8, 1), + MUX(0, "mout_sw_aclk266_g2d", mout_sw_aclk266_g2d_p, + SRC_TOP12, 12, 1), + MUX(0, "mout_sw_aclk_g3d", mout_sw_aclk_g3d_p, SRC_TOP12, 16, 1), + MUX(0, "mout_sw_aclk300_jpeg", mout_sw_aclk300_jpeg_p, + SRC_TOP12, 20, 1), + MUX(0, "mout_sw_aclk300_disp1", mout_sw_aclk300_disp1_p, SRC_TOP12, 24, 1), - MUX(0, "mout_sw_aclk300_gscl", sw_aclk300_gscl_p, SRC_TOP12, 28, 1), + MUX(0, "mout_sw_aclk300_gscl", mout_sw_aclk300_gscl_p, + SRC_TOP12, 28, 1), /* DISP1 Block */ - MUX(0, "mout_fimd1", group3_p, SRC_DISP10, 4, 1), - MUX(0, "mout_mipi1", group2_p, SRC_DISP10, 16, 3), - MUX(0, "mout_dp1", group2_p, SRC_DISP10, 20, 3), - MUX(0, "mout_pixel", group2_p, SRC_DISP10, 24, 3), - MUX(CLK_MOUT_HDMI, "mout_hdmi", hdmi_p, SRC_DISP10, 28, 1), + MUX(0, "mout_mipi1", mout_group2_p, SRC_DISP10, 16, 3), + MUX(0, "mout_dp1", mout_group2_p, SRC_DISP10, 20, 3), + MUX(0, "mout_pixel", mout_group2_p, SRC_DISP10, 24, 3), + MUX(CLK_MOUT_HDMI, "mout_hdmi", mout_hdmi_p, SRC_DISP10, 28, 1), + MUX(0, "mout_fimd1_opt", mout_group2_p, SRC_DISP10, 8, 3), + + MUX(0, "mout_fimd1_final", mout_fimd1_final_p, TOP_SPARE2, 8, 1), /* MAU Block */ - MUX(0, "mout_maudio0", maudio0_p, SRC_MAU, 28, 3), + MUX(CLK_MOUT_MAUDIO0, "mout_maudio0", mout_maudio0_p, SRC_MAU, 28, 3), /* FSYS Block */ - MUX(0, "mout_usbd301", group2_p, SRC_FSYS, 4, 3), - MUX(0, "mout_mmc0", group2_p, SRC_FSYS, 8, 3), - MUX(0, "mout_mmc1", group2_p, SRC_FSYS, 12, 3), - MUX(0, "mout_mmc2", group2_p, SRC_FSYS, 16, 3), - MUX(0, "mout_usbd300", group2_p, SRC_FSYS, 20, 3), - MUX(0, "mout_unipro", group2_p, SRC_FSYS, 24, 3), + MUX(0, "mout_usbd301", mout_group2_p, SRC_FSYS, 4, 3), + MUX(0, "mout_mmc0", mout_group2_p, SRC_FSYS, 8, 3), + MUX(0, "mout_mmc1", mout_group2_p, SRC_FSYS, 12, 3), + MUX(0, "mout_mmc2", mout_group2_p, SRC_FSYS, 16, 3), + MUX(0, "mout_usbd300", mout_group2_p, SRC_FSYS, 20, 3), + MUX(0, "mout_unipro", mout_group2_p, SRC_FSYS, 24, 3), + MUX(0, "mout_mphy_refclk", mout_group2_p, SRC_FSYS, 28, 3), /* PERIC Block */ - MUX(0, "mout_uart0", group2_p, SRC_PERIC0, 4, 3), - MUX(0, "mout_uart1", group2_p, SRC_PERIC0, 8, 3), - MUX(0, "mout_uart2", group2_p, SRC_PERIC0, 12, 3), - MUX(0, "mout_uart3", group2_p, SRC_PERIC0, 16, 3), - MUX(0, "mout_pwm", group2_p, SRC_PERIC0, 24, 3), - MUX(0, "mout_spdif", spdif_p, SRC_PERIC0, 28, 3), - MUX(0, "mout_audio0", audio0_p, SRC_PERIC1, 8, 3), - MUX(0, "mout_audio1", audio1_p, SRC_PERIC1, 12, 3), - MUX(0, "mout_audio2", audio2_p, SRC_PERIC1, 16, 3), - MUX(0, "mout_spi0", group2_p, SRC_PERIC1, 20, 3), - MUX(0, "mout_spi1", group2_p, SRC_PERIC1, 24, 3), - MUX(0, "mout_spi2", group2_p, SRC_PERIC1, 28, 3), + MUX(0, "mout_uart0", mout_group2_p, SRC_PERIC0, 4, 3), + MUX(0, "mout_uart1", mout_group2_p, SRC_PERIC0, 8, 3), + MUX(0, "mout_uart2", mout_group2_p, SRC_PERIC0, 12, 3), + MUX(0, "mout_uart3", mout_group2_p, SRC_PERIC0, 16, 3), + MUX(0, "mout_pwm", mout_group2_p, SRC_PERIC0, 24, 3), + MUX(0, "mout_spdif", mout_spdif_p, SRC_PERIC0, 28, 3), + MUX(0, "mout_audio0", mout_audio0_p, SRC_PERIC1, 8, 3), + MUX(0, "mout_audio1", mout_audio1_p, SRC_PERIC1, 12, 3), + MUX(0, "mout_audio2", mout_audio2_p, SRC_PERIC1, 16, 3), + MUX(0, "mout_spi0", mout_group2_p, SRC_PERIC1, 20, 3), + MUX(0, "mout_spi1", mout_group2_p, SRC_PERIC1, 24, 3), + MUX(0, "mout_spi2", mout_group2_p, SRC_PERIC1, 28, 3), + + /* ISP Block */ + MUX(0, "mout_pwm_isp", mout_group2_p, SRC_ISP, 24, 3), + MUX(0, "mout_uart_isp", mout_group2_p, SRC_ISP, 20, 3), + MUX(0, "mout_spi0_isp", mout_group2_p, SRC_ISP, 12, 3), + MUX(0, "mout_spi1_isp", mout_group2_p, SRC_ISP, 16, 3), + MUX(0, "mout_isp_sensor", mout_group2_p, SRC_ISP, 28, 3), }; -static struct samsung_div_clock exynos5420_div_clks[] __initdata = { +static struct samsung_div_clock exynos5x_div_clks[] __initdata = { DIV(0, "div_arm", "mout_cpu", DIV_CPU0, 0, 3), DIV(0, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3), DIV(0, "armclk2", "div_arm", DIV_CPU0, 28, 3), - DIV(0, "div_kfc", "mout_cpu_kfc", DIV_KFC0, 0, 3), + DIV(0, "div_kfc", "mout_kfc", DIV_KFC0, 0, 3), DIV(0, "sclk_kpll", "mout_kpll", DIV_KFC0, 24, 3), + DIV(0, "dout_aclk400_isp", "mout_aclk400_isp", DIV_TOP0, 0, 3), DIV(0, "dout_aclk400_mscl", "mout_aclk400_mscl", DIV_TOP0, 4, 3), DIV(0, "dout_aclk200", "mout_aclk200", DIV_TOP0, 8, 3), DIV(0, "dout_aclk200_fsys2", "mout_aclk200_fsys2", DIV_TOP0, 12, 3), + DIV(0, "dout_aclk100_noc", "mout_aclk100_noc", DIV_TOP0, 20, 3), DIV(0, "dout_pclk200_fsys", "mout_pclk200_fsys", DIV_TOP0, 24, 3), DIV(0, "dout_aclk200_fsys", "mout_aclk200_fsys", DIV_TOP0, 28, 3), DIV(0, "dout_aclk333_432_gscl", "mout_aclk333_432_gscl", DIV_TOP1, 0, 3), + DIV(0, "dout_aclk333_432_isp", "mout_aclk333_432_isp", + DIV_TOP1, 4, 3), DIV(0, "dout_aclk66", "mout_aclk66", DIV_TOP1, 8, 6), + DIV(0, "dout_aclk333_432_isp0", "mout_aclk333_432_isp0", + DIV_TOP1, 16, 3), DIV(0, "dout_aclk266", "mout_aclk266", DIV_TOP1, 20, 3), DIV(0, "dout_aclk166", "mout_aclk166", DIV_TOP1, 24, 3), DIV(0, "dout_aclk333", "mout_aclk333", DIV_TOP1, 28, 3), @@ -458,15 +773,16 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_aclk266_g2d", "mout_aclk266_g2d", DIV_TOP2, 12, 3), DIV(0, "dout_aclk_g3d", "mout_aclk_g3d", DIV_TOP2, 16, 3), DIV(0, "dout_aclk300_jpeg", "mout_aclk300_jpeg", DIV_TOP2, 20, 3), - DIV_A(0, "dout_aclk300_disp1", "mout_aclk300_disp1", - DIV_TOP2, 24, 3, "aclk300_disp1"), + DIV(0, "dout_aclk300_disp1", "mout_aclk300_disp1", DIV_TOP2, 24, 3), DIV(0, "dout_aclk300_gscl", "mout_aclk300_gscl", DIV_TOP2, 28, 3), /* DISP1 Block */ - DIV(0, "dout_fimd1", "mout_fimd1", DIV_DISP10, 0, 4), + DIV(0, "dout_fimd1", "mout_fimd1_final", DIV_DISP10, 0, 4), DIV(0, "dout_mipi1", "mout_mipi1", DIV_DISP10, 16, 8), DIV(0, "dout_dp1", "mout_dp1", DIV_DISP10, 24, 4), DIV(CLK_DOUT_PIXEL, "dout_hdmi_pixel", "mout_pixel", DIV_DISP10, 28, 4), + DIV(0, "dout_disp1_blk", "aclk200_disp1", DIV2_RATIO0, 16, 2), + DIV(0, "dout_aclk400_disp1", "mout_aclk400_disp1", DIV_TOP2, 4, 3), /* Audio Block */ DIV(0, "dout_maudio0", "mout_maudio0", DIV_MAU, 20, 4), @@ -484,6 +800,7 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_mmc2", "mout_mmc2", DIV_FSYS1, 20, 10), DIV(0, "dout_unipro", "mout_unipro", DIV_FSYS2, 24, 8), + DIV(0, "dout_mphy_refclk", "mout_mphy_refclk", DIV_FSYS2, 16, 8), /* UART and PWM */ DIV(0, "dout_uart0", "mout_uart0", DIV_PERIC0, 8, 4), @@ -497,6 +814,9 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_spi1", "mout_spi1", DIV_PERIC1, 24, 4), DIV(0, "dout_spi2", "mout_spi2", DIV_PERIC1, 28, 4), + /* Mfc Block */ + DIV(0, "dout_mfc_blk", "mout_user_aclk333", DIV4_RATIO, 0, 2), + /* PCM */ DIV(0, "dout_pcm1", "dout_audio1", DIV_PERIC2, 16, 8), DIV(0, "dout_pcm2", "dout_audio2", DIV_PERIC2, 24, 8), @@ -509,15 +829,43 @@ static struct samsung_div_clock exynos5420_div_clks[] __initdata = { DIV(0, "dout_audio2", "mout_audio2", DIV_PERIC3, 28, 4), /* SPI Pre-Ratio */ - DIV(0, "dout_pre_spi0", "dout_spi0", DIV_PERIC4, 8, 8), - DIV(0, "dout_pre_spi1", "dout_spi1", DIV_PERIC4, 16, 8), - DIV(0, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8), + DIV(0, "dout_spi0_pre", "dout_spi0", DIV_PERIC4, 8, 8), + DIV(0, "dout_spi1_pre", "dout_spi1", DIV_PERIC4, 16, 8), + DIV(0, "dout_spi2_pre", "dout_spi2", DIV_PERIC4, 24, 8), + + /* GSCL Block */ + DIV(0, "dout_gscl_blk_300", "mout_user_aclk300_gscl", + DIV2_RATIO0, 4, 2), + DIV(0, "dout_gscl_blk_333", "aclk333_432_gscl", DIV2_RATIO0, 6, 2), + + /* MSCL Block */ + DIV(0, "dout_mscl_blk", "aclk400_mscl", DIV2_RATIO0, 28, 2), + + /* PSGEN */ + DIV(0, "dout_gen_blk", "mout_user_aclk266", DIV2_RATIO0, 8, 1), + DIV(0, "dout_jpg_blk", "aclk166", DIV2_RATIO0, 20, 1), + + /* ISP Block */ + DIV(0, "dout_isp_sensor0", "mout_isp_sensor", SCLK_DIV_ISP0, 8, 8), + DIV(0, "dout_isp_sensor1", "mout_isp_sensor", SCLK_DIV_ISP0, 16, 8), + DIV(0, "dout_isp_sensor2", "mout_isp_sensor", SCLK_DIV_ISP0, 24, 8), + DIV(0, "dout_pwm_isp", "mout_pwm_isp", SCLK_DIV_ISP1, 28, 4), + DIV(0, "dout_uart_isp", "mout_uart_isp", SCLK_DIV_ISP1, 24, 4), + DIV(0, "dout_spi0_isp", "mout_spi0_isp", SCLK_DIV_ISP1, 16, 4), + DIV(0, "dout_spi1_isp", "mout_spi1_isp", SCLK_DIV_ISP1, 20, 4), + DIV_F(0, "dout_spi0_isp_pre", "dout_spi0_isp", SCLK_DIV_ISP1, 0, 8, + CLK_SET_RATE_PARENT, 0), + DIV_F(0, "dout_spi1_isp_pre", "dout_spi1_isp", SCLK_DIV_ISP1, 8, 8, + CLK_SET_RATE_PARENT, 0), }; -static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { - /* TODO: Re-verify the CG bits for all the gate clocks */ - GATE_A(CLK_MCT, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, - "mct"), +static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = { + /* G2D */ + GATE(CLK_MDMA0, "mdma0", "aclk266_g2d", GATE_IP_G2D, 1, 0, 0), + GATE(CLK_SSS, "sss", "aclk266_g2d", GATE_IP_G2D, 2, 0, 0), + GATE(CLK_G2D, "g2d", "aclk333_g2d", GATE_IP_G2D, 3, 0, 0), + GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "aclk266_g2d", GATE_IP_G2D, 5, 0, 0), + GATE(CLK_SMMU_G2D, "smmu_g2d", "aclk333_g2d", GATE_IP_G2D, 7, 0, 0), GATE(0, "aclk200_fsys", "mout_user_aclk200_fsys", GATE_BUS_FSYS0, 9, CLK_IGNORE_UNUSED, 0), @@ -530,20 +878,42 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE_BUS_TOP, 1, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg", GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0), + GATE(0, "aclk333_432_isp0", "mout_user_aclk333_432_isp0", + GATE_BUS_TOP, 5, 0, 0), GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl", GATE_BUS_TOP, 6, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl", GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0), - GATE(0, "pclk66_gpio", "mout_sw_aclk66", + GATE(0, "aclk333_432_isp", "mout_user_aclk333_432_isp", + GATE_BUS_TOP, 8, 0, 0), + GATE(CLK_PCLK66_GPIO, "pclk66_gpio", "mout_user_pclk66_gpio", GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0), - GATE(0, "aclk66_psgen", "mout_aclk66_psgen", + GATE(0, "aclk66_psgen", "mout_user_aclk66_psgen", GATE_BUS_TOP, 10, CLK_IGNORE_UNUSED, 0), - GATE(0, "aclk66_peric", "mout_aclk66_peric", - GATE_BUS_TOP, 11, 0, 0), + GATE(CLK_ACLK66_PERIC, "aclk66_peric", "mout_user_aclk66_peric", + GATE_BUS_TOP, 11, CLK_IGNORE_UNUSED, 0), + GATE(0, "aclk266_isp", "mout_user_aclk266_isp", + GATE_BUS_TOP, 13, 0, 0), GATE(0, "aclk166", "mout_user_aclk166", GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk333", "mout_aclk333", GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0), + GATE(0, "aclk400_isp", "mout_user_aclk400_isp", + GATE_BUS_TOP, 16, 0, 0), + GATE(0, "aclk400_mscl", "mout_user_aclk400_mscl", + GATE_BUS_TOP, 17, 0, 0), + GATE(0, "aclk200_disp1", "mout_user_aclk200_disp1", + GATE_BUS_TOP, 18, 0, 0), + GATE(CLK_SCLK_MPHY_IXTAL24, "sclk_mphy_ixtal24", "mphy_refclk_ixtal24", + GATE_BUS_TOP, 28, 0, 0), + GATE(CLK_SCLK_HSIC_12M, "sclk_hsic_12m", "ff_hsic_12m", + GATE_BUS_TOP, 29, 0, 0), + + GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1", + SRC_MASK_TOP2, 24, 0, 0), + + GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk", + SRC_MASK_TOP7, 20, 0, 0), /* sclk */ GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_uart0", @@ -554,11 +924,11 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE_TOP_SCLK_PERIC, 2, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_uart3", GATE_TOP_SCLK_PERIC, 3, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI0, "sclk_spi0", "dout_pre_spi0", + GATE(CLK_SCLK_SPI0, "sclk_spi0", "dout_spi0_pre", GATE_TOP_SCLK_PERIC, 6, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI1, "sclk_spi1", "dout_pre_spi1", + GATE(CLK_SCLK_SPI1, "sclk_spi1", "dout_spi1_pre", GATE_TOP_SCLK_PERIC, 7, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_SPI2, "sclk_spi2", "dout_pre_spi2", + GATE(CLK_SCLK_SPI2, "sclk_spi2", "dout_spi2_pre", GATE_TOP_SCLK_PERIC, 8, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_SPDIF, "sclk_spdif", "mout_spdif", GATE_TOP_SCLK_PERIC, 9, CLK_SET_RATE_PARENT, 0), @@ -588,164 +958,191 @@ static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { GATE(CLK_SCLK_USBD301, "sclk_usbd301", "dout_usbd301", GATE_TOP_SCLK_FSYS, 10, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_USBD301, "sclk_unipro", "dout_unipro", - SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0), - - GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "aclK333_432_gscl", - GATE_TOP_SCLK_GSCL, 6, CLK_SET_RATE_PARENT, 0), - GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "aclk333_432_gscl", - GATE_TOP_SCLK_GSCL, 7, CLK_SET_RATE_PARENT, 0), - /* Display */ GATE(CLK_SCLK_FIMD1, "sclk_fimd1", "dout_fimd1", - GATE_TOP_SCLK_DISP1, 0, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MIPI1, "sclk_mipi1", "dout_mipi1", - GATE_TOP_SCLK_DISP1, 3, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 3, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_HDMI, "sclk_hdmi", "mout_hdmi", - GATE_TOP_SCLK_DISP1, 9, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 9, 0, 0), GATE(CLK_SCLK_PIXEL, "sclk_pixel", "dout_hdmi_pixel", - GATE_TOP_SCLK_DISP1, 10, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 10, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_DP1, "sclk_dp1", "dout_dp1", - GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0), + GATE_TOP_SCLK_DISP1, 20, CLK_SET_RATE_PARENT, 0), /* Maudio Block */ GATE(CLK_SCLK_MAUDIO0, "sclk_maudio0", "dout_maudio0", GATE_TOP_SCLK_MAU, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MAUPCM0, "sclk_maupcm0", "dout_maupcm0", GATE_TOP_SCLK_MAU, 1, CLK_SET_RATE_PARENT, 0), - /* FSYS */ + + /* FSYS Block */ GATE(CLK_TSI, "tsi", "aclk200_fsys", GATE_BUS_FSYS0, 0, 0, 0), GATE(CLK_PDMA0, "pdma0", "aclk200_fsys", GATE_BUS_FSYS0, 1, 0, 0), GATE(CLK_PDMA1, "pdma1", "aclk200_fsys", GATE_BUS_FSYS0, 2, 0, 0), GATE(CLK_UFS, "ufs", "aclk200_fsys2", GATE_BUS_FSYS0, 3, 0, 0), - GATE(CLK_RTIC, "rtic", "aclk200_fsys", GATE_BUS_FSYS0, 5, 0, 0), - GATE(CLK_MMC0, "mmc0", "aclk200_fsys2", GATE_BUS_FSYS0, 12, 0, 0), - GATE(CLK_MMC1, "mmc1", "aclk200_fsys2", GATE_BUS_FSYS0, 13, 0, 0), - GATE(CLK_MMC2, "mmc2", "aclk200_fsys2", GATE_BUS_FSYS0, 14, 0, 0), + GATE(CLK_RTIC, "rtic", "aclk200_fsys", GATE_IP_FSYS, 9, 0, 0), + GATE(CLK_MMC0, "mmc0", "aclk200_fsys2", GATE_IP_FSYS, 12, 0, 0), + GATE(CLK_MMC1, "mmc1", "aclk200_fsys2", GATE_IP_FSYS, 13, 0, 0), + GATE(CLK_MMC2, "mmc2", "aclk200_fsys2", GATE_IP_FSYS, 14, 0, 0), GATE(CLK_SROMC, "sromc", "aclk200_fsys2", - GATE_BUS_FSYS0, 19, CLK_IGNORE_UNUSED, 0), - GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_BUS_FSYS0, 20, 0, 0), - GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_BUS_FSYS0, 21, 0, 0), - GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_BUS_FSYS0, 28, 0, 0), - - /* UART */ - GATE(CLK_UART0, "uart0", "aclk66_peric", GATE_BUS_PERIC, 4, 0, 0), - GATE(CLK_UART1, "uart1", "aclk66_peric", GATE_BUS_PERIC, 5, 0, 0), - GATE_A(CLK_UART2, "uart2", "aclk66_peric", - GATE_BUS_PERIC, 6, CLK_IGNORE_UNUSED, 0, "uart2"), - GATE(CLK_UART3, "uart3", "aclk66_peric", GATE_BUS_PERIC, 7, 0, 0), - /* I2C */ - GATE(CLK_I2C0, "i2c0", "aclk66_peric", GATE_BUS_PERIC, 9, 0, 0), - GATE(CLK_I2C1, "i2c1", "aclk66_peric", GATE_BUS_PERIC, 10, 0, 0), - GATE(CLK_I2C2, "i2c2", "aclk66_peric", GATE_BUS_PERIC, 11, 0, 0), - GATE(CLK_I2C3, "i2c3", "aclk66_peric", GATE_BUS_PERIC, 12, 0, 0), - GATE(CLK_I2C4, "i2c4", "aclk66_peric", GATE_BUS_PERIC, 13, 0, 0), - GATE(CLK_I2C5, "i2c5", "aclk66_peric", GATE_BUS_PERIC, 14, 0, 0), - GATE(CLK_I2C6, "i2c6", "aclk66_peric", GATE_BUS_PERIC, 15, 0, 0), - GATE(CLK_I2C7, "i2c7", "aclk66_peric", GATE_BUS_PERIC, 16, 0, 0), - GATE(CLK_I2C_HDMI, "i2c_hdmi", "aclk66_peric", GATE_BUS_PERIC, 17, 0, - 0), - GATE(CLK_TSADC, "tsadc", "aclk66_peric", GATE_BUS_PERIC, 18, 0, 0), - /* SPI */ - GATE(CLK_SPI0, "spi0", "aclk66_peric", GATE_BUS_PERIC, 19, 0, 0), - GATE(CLK_SPI1, "spi1", "aclk66_peric", GATE_BUS_PERIC, 20, 0, 0), - GATE(CLK_SPI2, "spi2", "aclk66_peric", GATE_BUS_PERIC, 21, 0, 0), - GATE(CLK_KEYIF, "keyif", "aclk66_peric", GATE_BUS_PERIC, 22, 0, 0), - /* I2S */ - GATE(CLK_I2S1, "i2s1", "aclk66_peric", GATE_BUS_PERIC, 23, 0, 0), - GATE(CLK_I2S2, "i2s2", "aclk66_peric", GATE_BUS_PERIC, 24, 0, 0), - /* PCM */ - GATE(CLK_PCM1, "pcm1", "aclk66_peric", GATE_BUS_PERIC, 25, 0, 0), - GATE(CLK_PCM2, "pcm2", "aclk66_peric", GATE_BUS_PERIC, 26, 0, 0), - /* PWM */ - GATE(CLK_PWM, "pwm", "aclk66_peric", GATE_BUS_PERIC, 27, 0, 0), - /* SPDIF */ - GATE(CLK_SPDIF, "spdif", "aclk66_peric", GATE_BUS_PERIC, 29, 0, 0), + GATE_IP_FSYS, 17, CLK_IGNORE_UNUSED, 0), + GATE(CLK_USBH20, "usbh20", "aclk200_fsys", GATE_IP_FSYS, 18, 0, 0), + GATE(CLK_USBD300, "usbd300", "aclk200_fsys", GATE_IP_FSYS, 19, 0, 0), + GATE(CLK_USBD301, "usbd301", "aclk200_fsys", GATE_IP_FSYS, 20, 0, 0), + GATE(CLK_SCLK_UNIPRO, "sclk_unipro", "dout_unipro", + SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0), - GATE(CLK_I2C8, "i2c8", "aclk66_peric", GATE_BUS_PERIC1, 0, 0, 0), - GATE(CLK_I2C9, "i2c9", "aclk66_peric", GATE_BUS_PERIC1, 1, 0, 0), - GATE(CLK_I2C10, "i2c10", "aclk66_peric", GATE_BUS_PERIC1, 2, 0, 0), + /* PERIC Block */ + GATE(CLK_UART0, "uart0", "aclk66_peric", GATE_IP_PERIC, 0, 0, 0), + GATE(CLK_UART1, "uart1", "aclk66_peric", GATE_IP_PERIC, 1, 0, 0), + GATE(CLK_UART2, "uart2", "aclk66_peric", GATE_IP_PERIC, 2, 0, 0), + GATE(CLK_UART3, "uart3", "aclk66_peric", GATE_IP_PERIC, 3, 0, 0), + GATE(CLK_I2C0, "i2c0", "aclk66_peric", GATE_IP_PERIC, 6, 0, 0), + GATE(CLK_I2C1, "i2c1", "aclk66_peric", GATE_IP_PERIC, 7, 0, 0), + GATE(CLK_I2C2, "i2c2", "aclk66_peric", GATE_IP_PERIC, 8, 0, 0), + GATE(CLK_I2C3, "i2c3", "aclk66_peric", GATE_IP_PERIC, 9, 0, 0), + GATE(CLK_USI0, "usi0", "aclk66_peric", GATE_IP_PERIC, 10, 0, 0), + GATE(CLK_USI1, "usi1", "aclk66_peric", GATE_IP_PERIC, 11, 0, 0), + GATE(CLK_USI2, "usi2", "aclk66_peric", GATE_IP_PERIC, 12, 0, 0), + GATE(CLK_USI3, "usi3", "aclk66_peric", GATE_IP_PERIC, 13, 0, 0), + GATE(CLK_I2C_HDMI, "i2c_hdmi", "aclk66_peric", GATE_IP_PERIC, 14, 0, 0), + GATE(CLK_TSADC, "tsadc", "aclk66_peric", GATE_IP_PERIC, 15, 0, 0), + GATE(CLK_SPI0, "spi0", "aclk66_peric", GATE_IP_PERIC, 16, 0, 0), + GATE(CLK_SPI1, "spi1", "aclk66_peric", GATE_IP_PERIC, 17, 0, 0), + GATE(CLK_SPI2, "spi2", "aclk66_peric", GATE_IP_PERIC, 18, 0, 0), + GATE(CLK_I2S1, "i2s1", "aclk66_peric", GATE_IP_PERIC, 20, 0, 0), + GATE(CLK_I2S2, "i2s2", "aclk66_peric", GATE_IP_PERIC, 21, 0, 0), + GATE(CLK_PCM1, "pcm1", "aclk66_peric", GATE_IP_PERIC, 22, 0, 0), + GATE(CLK_PCM2, "pcm2", "aclk66_peric", GATE_IP_PERIC, 23, 0, 0), + GATE(CLK_PWM, "pwm", "aclk66_peric", GATE_IP_PERIC, 24, 0, 0), + GATE(CLK_SPDIF, "spdif", "aclk66_peric", GATE_IP_PERIC, 26, 0, 0), + GATE(CLK_USI4, "usi4", "aclk66_peric", GATE_IP_PERIC, 28, 0, 0), + GATE(CLK_USI5, "usi5", "aclk66_peric", GATE_IP_PERIC, 30, 0, 0), + GATE(CLK_USI6, "usi6", "aclk66_peric", GATE_IP_PERIC, 31, 0, 0), + GATE(CLK_KEYIF, "keyif", "aclk66_peric", GATE_BUS_PERIC, 22, 0, 0), + + /* PERIS Block */ GATE(CLK_CHIPID, "chipid", "aclk66_psgen", - GATE_BUS_PERIS0, 12, CLK_IGNORE_UNUSED, 0), + GATE_IP_PERIS, 0, CLK_IGNORE_UNUSED, 0), GATE(CLK_SYSREG, "sysreg", "aclk66_psgen", - GATE_BUS_PERIS0, 13, CLK_IGNORE_UNUSED, 0), - GATE(CLK_TZPC0, "tzpc0", "aclk66_psgen", GATE_BUS_PERIS0, 18, 0, 0), - GATE(CLK_TZPC1, "tzpc1", "aclk66_psgen", GATE_BUS_PERIS0, 19, 0, 0), - GATE(CLK_TZPC2, "tzpc2", "aclk66_psgen", GATE_BUS_PERIS0, 20, 0, 0), - GATE(CLK_TZPC3, "tzpc3", "aclk66_psgen", GATE_BUS_PERIS0, 21, 0, 0), - GATE(CLK_TZPC4, "tzpc4", "aclk66_psgen", GATE_BUS_PERIS0, 22, 0, 0), - GATE(CLK_TZPC5, "tzpc5", "aclk66_psgen", GATE_BUS_PERIS0, 23, 0, 0), - GATE(CLK_TZPC6, "tzpc6", "aclk66_psgen", GATE_BUS_PERIS0, 24, 0, 0), - GATE(CLK_TZPC7, "tzpc7", "aclk66_psgen", GATE_BUS_PERIS0, 25, 0, 0), - GATE(CLK_TZPC8, "tzpc8", "aclk66_psgen", GATE_BUS_PERIS0, 26, 0, 0), - GATE(CLK_TZPC9, "tzpc9", "aclk66_psgen", GATE_BUS_PERIS0, 27, 0, 0), - - GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk66_psgen", GATE_BUS_PERIS1, 0, 0, - 0), + GATE_IP_PERIS, 1, CLK_IGNORE_UNUSED, 0), + GATE(CLK_TZPC0, "tzpc0", "aclk66_psgen", GATE_IP_PERIS, 6, 0, 0), + GATE(CLK_TZPC1, "tzpc1", "aclk66_psgen", GATE_IP_PERIS, 7, 0, 0), + GATE(CLK_TZPC2, "tzpc2", "aclk66_psgen", GATE_IP_PERIS, 8, 0, 0), + GATE(CLK_TZPC3, "tzpc3", "aclk66_psgen", GATE_IP_PERIS, 9, 0, 0), + GATE(CLK_TZPC4, "tzpc4", "aclk66_psgen", GATE_IP_PERIS, 10, 0, 0), + GATE(CLK_TZPC5, "tzpc5", "aclk66_psgen", GATE_IP_PERIS, 11, 0, 0), + GATE(CLK_TZPC6, "tzpc6", "aclk66_psgen", GATE_IP_PERIS, 12, 0, 0), + GATE(CLK_TZPC7, "tzpc7", "aclk66_psgen", GATE_IP_PERIS, 13, 0, 0), + GATE(CLK_TZPC8, "tzpc8", "aclk66_psgen", GATE_IP_PERIS, 14, 0, 0), + GATE(CLK_TZPC9, "tzpc9", "aclk66_psgen", GATE_IP_PERIS, 15, 0, 0), + GATE(CLK_HDMI_CEC, "hdmi_cec", "aclk66_psgen", GATE_IP_PERIS, 16, 0, 0), + GATE(CLK_MCT, "mct", "aclk66_psgen", GATE_IP_PERIS, 18, 0, 0), + GATE(CLK_WDT, "wdt", "aclk66_psgen", GATE_IP_PERIS, 19, 0, 0), + GATE(CLK_RTC, "rtc", "aclk66_psgen", GATE_IP_PERIS, 20, 0, 0), + GATE(CLK_TMU, "tmu", "aclk66_psgen", GATE_IP_PERIS, 21, 0, 0), + GATE(CLK_TMU_GPU, "tmu_gpu", "aclk66_psgen", GATE_IP_PERIS, 22, 0, 0), + GATE(CLK_SECKEY, "seckey", "aclk66_psgen", GATE_BUS_PERIS1, 1, 0, 0), - GATE(CLK_WDT, "wdt", "aclk66_psgen", GATE_BUS_PERIS1, 3, 0, 0), - GATE(CLK_RTC, "rtc", "aclk66_psgen", GATE_BUS_PERIS1, 4, 0, 0), - GATE(CLK_TMU, "tmu", "aclk66_psgen", GATE_BUS_PERIS1, 5, 0, 0), - GATE(CLK_TMU_GPU, "tmu_gpu", "aclk66_psgen", GATE_BUS_PERIS1, 6, 0, 0), + + /* GEN Block */ + GATE(CLK_ROTATOR, "rotator", "mout_user_aclk266", GATE_IP_GEN, 1, 0, 0), + GATE(CLK_JPEG, "jpeg", "aclk300_jpeg", GATE_IP_GEN, 2, 0, 0), + GATE(CLK_JPEG2, "jpeg2", "aclk300_jpeg", GATE_IP_GEN, 3, 0, 0), + GATE(CLK_MDMA1, "mdma1", "mout_user_aclk266", GATE_IP_GEN, 4, 0, 0), + GATE(CLK_TOP_RTC, "top_rtc", "aclk66_psgen", GATE_IP_GEN, 5, 0, 0), + GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "dout_gen_blk", + GATE_IP_GEN, 6, 0, 0), + GATE(CLK_SMMU_JPEG, "smmu_jpeg", "dout_jpg_blk", GATE_IP_GEN, 7, 0, 0), + GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "dout_gen_blk", + GATE_IP_GEN, 9, 0, 0), + + /* GATE_IP_GEN doesn't list gates for smmu_jpeg2 and mc */ + GATE(CLK_SMMU_JPEG2, "smmu_jpeg2", "dout_jpg_blk", + GATE_BUS_GEN, 28, 0, 0), + GATE(CLK_MC, "mc", "aclk66_psgen", GATE_BUS_GEN, 12, 0, 0), + + /* GSCL Block */ + GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "mout_user_aclk333_432_gscl", + GATE_TOP_SCLK_GSCL, 6, 0, 0), + GATE(CLK_SCLK_GSCL_WB, "sclk_gscl_wb", "mout_user_aclk333_432_gscl", + GATE_TOP_SCLK_GSCL, 7, 0, 0), GATE(CLK_GSCL0, "gscl0", "aclk300_gscl", GATE_IP_GSCL0, 0, 0, 0), GATE(CLK_GSCL1, "gscl1", "aclk300_gscl", GATE_IP_GSCL0, 1, 0, 0), - GATE(CLK_CLK_3AA, "clk_3aa", "aclk300_gscl", GATE_IP_GSCL0, 4, 0, 0), - - GATE(CLK_SMMU_3AA, "smmu_3aa", "aclk333_432_gscl", GATE_IP_GSCL1, 2, 0, - 0), - GATE(CLK_SMMU_FIMCL0, "smmu_fimcl0", "aclk333_432_gscl", + GATE(CLK_FIMC_3AA, "fimc_3aa", "aclk333_432_gscl", + GATE_IP_GSCL0, 4, 0, 0), + GATE(CLK_FIMC_LITE0, "fimc_lite0", "aclk333_432_gscl", + GATE_IP_GSCL0, 5, 0, 0), + GATE(CLK_FIMC_LITE1, "fimc_lite1", "aclk333_432_gscl", + GATE_IP_GSCL0, 6, 0, 0), + + GATE(CLK_SMMU_3AA, "smmu_3aa", "dout_gscl_blk_333", + GATE_IP_GSCL1, 2, 0, 0), + GATE(CLK_SMMU_FIMCL0, "smmu_fimcl0", "dout_gscl_blk_333", GATE_IP_GSCL1, 3, 0, 0), - GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "aclk333_432_gscl", + GATE(CLK_SMMU_FIMCL1, "smmu_fimcl1", "dout_gscl_blk_333", GATE_IP_GSCL1, 4, 0, 0), - GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "aclk300_gscl", GATE_IP_GSCL1, 6, 0, - 0), - GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "aclk300_gscl", GATE_IP_GSCL1, 7, 0, - 0), - GATE(CLK_GSCL_WA, "gscl_wa", "aclk300_gscl", GATE_IP_GSCL1, 12, 0, 0), - GATE(CLK_GSCL_WB, "gscl_wb", "aclk300_gscl", GATE_IP_GSCL1, 13, 0, 0), - GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "aclk333_432_gscl", + GATE(CLK_SMMU_GSCL0, "smmu_gscl0", "dout_gscl_blk_300", + GATE_IP_GSCL1, 6, 0, 0), + GATE(CLK_SMMU_GSCL1, "smmu_gscl1", "dout_gscl_blk_300", + GATE_IP_GSCL1, 7, 0, 0), + GATE(CLK_GSCL_WA, "gscl_wa", "sclk_gscl_wa", GATE_IP_GSCL1, 12, 0, 0), + GATE(CLK_GSCL_WB, "gscl_wb", "sclk_gscl_wb", GATE_IP_GSCL1, 13, 0, 0), + GATE(CLK_SMMU_FIMCL3, "smmu_fimcl3,", "dout_gscl_blk_333", GATE_IP_GSCL1, 16, 0, 0), GATE(CLK_FIMC_LITE3, "fimc_lite3", "aclk333_432_gscl", GATE_IP_GSCL1, 17, 0, 0), + /* MSCL Block */ + GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0), + GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0), + GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0), + GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "dout_mscl_blk", + GATE_IP_MSCL, 8, 0, 0), + GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "dout_mscl_blk", + GATE_IP_MSCL, 9, 0, 0), + GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "dout_mscl_blk", + GATE_IP_MSCL, 10, 0, 0), + GATE(CLK_FIMD1, "fimd1", "aclk300_disp1", GATE_IP_DISP1, 0, 0, 0), GATE(CLK_DSIM1, "dsim1", "aclk200_disp1", GATE_IP_DISP1, 3, 0, 0), GATE(CLK_DP1, "dp1", "aclk200_disp1", GATE_IP_DISP1, 4, 0, 0), - GATE(CLK_MIXER, "mixer", "aclk166", GATE_IP_DISP1, 5, 0, 0), + GATE(CLK_MIXER, "mixer", "aclk200_disp1", GATE_IP_DISP1, 5, 0, 0), GATE(CLK_HDMI, "hdmi", "aclk200_disp1", GATE_IP_DISP1, 6, 0, 0), - GATE(CLK_SMMU_FIMD1, "smmu_fimd1", "aclk300_disp1", GATE_IP_DISP1, 8, 0, - 0), + GATE(CLK_SMMU_FIMD1M0, "smmu_fimd1m0", "dout_disp1_blk", + GATE_IP_DISP1, 7, 0, 0), + GATE(CLK_SMMU_FIMD1M1, "smmu_fimd1m1", "dout_disp1_blk", + GATE_IP_DISP1, 8, 0, 0), + GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1", + GATE_IP_DISP1, 9, 0, 0), + + /* ISP */ + GATE(CLK_SCLK_UART_ISP, "sclk_uart_isp", "dout_uart_isp", + GATE_TOP_SCLK_ISP, 0, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI0_ISP, "sclk_spi0_isp", "dout_spi0_isp_pre", + GATE_TOP_SCLK_ISP, 1, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_SPI1_ISP, "sclk_spi1_isp", "dout_spi1_isp_pre", + GATE_TOP_SCLK_ISP, 2, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_PWM_ISP, "sclk_pwm_isp", "dout_pwm_isp", + GATE_TOP_SCLK_ISP, 3, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_ISP_SENSOR0, "sclk_isp_sensor0", "dout_isp_sensor0", + GATE_TOP_SCLK_ISP, 4, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_ISP_SENSOR1, "sclk_isp_sensor1", "dout_isp_sensor1", + GATE_TOP_SCLK_ISP, 8, CLK_SET_RATE_PARENT, 0), + GATE(CLK_SCLK_ISP_SENSOR2, "sclk_isp_sensor2", "dout_isp_sensor2", + GATE_TOP_SCLK_ISP, 12, CLK_SET_RATE_PARENT, 0), GATE(CLK_MFC, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0), - GATE(CLK_SMMU_MFCL, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0), - GATE(CLK_SMMU_MFCR, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0), - - GATE(CLK_G3D, "g3d", "aclkg3d", GATE_IP_G3D, 9, 0, 0), + GATE(CLK_SMMU_MFCL, "smmu_mfcl", "dout_mfc_blk", GATE_IP_MFC, 1, 0, 0), + GATE(CLK_SMMU_MFCR, "smmu_mfcr", "dout_mfc_blk", GATE_IP_MFC, 2, 0, 0), - GATE(CLK_ROTATOR, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0), - GATE(CLK_JPEG, "jpeg", "aclk300_jpeg", GATE_IP_GEN, 2, 0, 0), - GATE(CLK_JPEG2, "jpeg2", "aclk300_jpeg", GATE_IP_GEN, 3, 0, 0), - GATE(CLK_MDMA1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0), - GATE(CLK_SMMU_ROTATOR, "smmu_rotator", "aclk266", GATE_IP_GEN, 6, 0, 0), - GATE(CLK_SMMU_JPEG, "smmu_jpeg", "aclk300_jpeg", GATE_IP_GEN, 7, 0, 0), - GATE(CLK_SMMU_MDMA1, "smmu_mdma1", "aclk266", GATE_IP_GEN, 9, 0, 0), - - GATE(CLK_MSCL0, "mscl0", "aclk400_mscl", GATE_IP_MSCL, 0, 0, 0), - GATE(CLK_MSCL1, "mscl1", "aclk400_mscl", GATE_IP_MSCL, 1, 0, 0), - GATE(CLK_MSCL2, "mscl2", "aclk400_mscl", GATE_IP_MSCL, 2, 0, 0), - GATE(CLK_SMMU_MSCL0, "smmu_mscl0", "aclk400_mscl", GATE_IP_MSCL, 8, 0, - 0), - GATE(CLK_SMMU_MSCL1, "smmu_mscl1", "aclk400_mscl", GATE_IP_MSCL, 9, 0, - 0), - GATE(CLK_SMMU_MSCL2, "smmu_mscl2", "aclk400_mscl", GATE_IP_MSCL, 10, 0, - 0), - GATE(CLK_SMMU_MIXER, "smmu_mixer", "aclk200_disp1", GATE_IP_DISP1, 9, 0, - 0), + GATE(CLK_G3D, "g3d", "mout_user_aclk_g3d", GATE_IP_G3D, 9, 0, 0), }; -static struct samsung_pll_clock exynos5420_plls[nr_plls] __initdata = { +static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = { [apll] = PLL(pll_2550, CLK_FOUT_APLL, "fout_apll", "fin_pll", APLL_LOCK, APLL_CON0, NULL), [cpll] = PLL(pll_2550, CLK_FOUT_CPLL, "fout_cpll", "fin_pll", CPLL_LOCK, @@ -776,8 +1173,11 @@ static struct of_device_id ext_clk_match[] __initdata = { }; /* register exynos5420 clocks */ -static void __init exynos5420_clk_init(struct device_node *np) +static void __init exynos5x_clk_init(struct device_node *np, + enum exynos5x_soc soc) { + struct samsung_clk_provider *ctx; + if (np) { reg_base = of_iomap(np, 0); if (!reg_base) @@ -786,23 +1186,56 @@ static void __init exynos5420_clk_init(struct device_node *np) panic("%s: unable to determine soc\n", __func__); } - samsung_clk_init(np, reg_base, CLK_NR_CLKS); - samsung_clk_of_register_fixed_ext(exynos5420_fixed_rate_ext_clks, - ARRAY_SIZE(exynos5420_fixed_rate_ext_clks), + exynos5x_soc = soc; + + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks, + ARRAY_SIZE(exynos5x_fixed_rate_ext_clks), ext_clk_match); - samsung_clk_register_pll(exynos5420_plls, ARRAY_SIZE(exynos5420_plls), + samsung_clk_register_pll(ctx, exynos5x_plls, ARRAY_SIZE(exynos5x_plls), reg_base); - samsung_clk_register_fixed_rate(exynos5420_fixed_rate_clks, - ARRAY_SIZE(exynos5420_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5420_fixed_factor_clks, - ARRAY_SIZE(exynos5420_fixed_factor_clks)); - samsung_clk_register_mux(exynos5420_mux_clks, - ARRAY_SIZE(exynos5420_mux_clks)); - samsung_clk_register_div(exynos5420_div_clks, - ARRAY_SIZE(exynos5420_div_clks)); - samsung_clk_register_gate(exynos5420_gate_clks, - ARRAY_SIZE(exynos5420_gate_clks)); + samsung_clk_register_fixed_rate(ctx, exynos5x_fixed_rate_clks, + ARRAY_SIZE(exynos5x_fixed_rate_clks)); + samsung_clk_register_fixed_factor(ctx, exynos5x_fixed_factor_clks, + ARRAY_SIZE(exynos5x_fixed_factor_clks)); + samsung_clk_register_mux(ctx, exynos5x_mux_clks, + ARRAY_SIZE(exynos5x_mux_clks)); + samsung_clk_register_div(ctx, exynos5x_div_clks, + ARRAY_SIZE(exynos5x_div_clks)); + samsung_clk_register_gate(ctx, exynos5x_gate_clks, + ARRAY_SIZE(exynos5x_gate_clks)); + + if (soc == EXYNOS5420) { + samsung_clk_register_mux(ctx, exynos5420_mux_clks, + ARRAY_SIZE(exynos5420_mux_clks)); + samsung_clk_register_div(ctx, exynos5420_div_clks, + ARRAY_SIZE(exynos5420_div_clks)); + } else { + samsung_clk_register_fixed_factor( + ctx, exynos5800_fixed_factor_clks, + ARRAY_SIZE(exynos5800_fixed_factor_clks)); + samsung_clk_register_mux(ctx, exynos5800_mux_clks, + ARRAY_SIZE(exynos5800_mux_clks)); + samsung_clk_register_div(ctx, exynos5800_div_clks, + ARRAY_SIZE(exynos5800_div_clks)); + samsung_clk_register_gate(ctx, exynos5800_gate_clks, + ARRAY_SIZE(exynos5800_gate_clks)); + } exynos5420_clk_sleep_init(); } + +static void __init exynos5420_clk_init(struct device_node *np) +{ + exynos5x_clk_init(np, EXYNOS5420); +} CLK_OF_DECLARE(exynos5420_clk, "samsung,exynos5420-clock", exynos5420_clk_init); + +static void __init exynos5800_clk_init(struct device_node *np) +{ + exynos5x_clk_init(np, EXYNOS5800); +} +CLK_OF_DECLARE(exynos5800_clk, "samsung,exynos5800-clock", exynos5800_clk_init); diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index 2bfad5a..647f144 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c @@ -93,6 +93,7 @@ static struct of_device_id ext_clk_match[] __initdata = { static void __init exynos5440_clk_init(struct device_node *np) { void __iomem *reg_base; + struct samsung_clk_provider *ctx; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -101,22 +102,25 @@ static void __init exynos5440_clk_init(struct device_node *np) return; } - samsung_clk_init(np, reg_base, CLK_NR_CLKS); - samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks, + ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); + + samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks, ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match); samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10); samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10); - samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks, ARRAY_SIZE(exynos5440_fixed_rate_clks)); - samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks, + samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks, ARRAY_SIZE(exynos5440_fixed_factor_clks)); - samsung_clk_register_mux(exynos5440_mux_clks, + samsung_clk_register_mux(ctx, exynos5440_mux_clks, ARRAY_SIZE(exynos5440_mux_clks)); - samsung_clk_register_div(exynos5440_div_clks, + samsung_clk_register_div(ctx, exynos5440_div_clks, ARRAY_SIZE(exynos5440_div_clks)); - samsung_clk_register_gate(exynos5440_gate_clks, + samsung_clk_register_gate(ctx, exynos5440_gate_clks, ARRAY_SIZE(exynos5440_gate_clks)); pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk")); diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 7fb0a28..b07fad2 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -947,8 +947,206 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name, return clk; } -static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, - void __iomem *base) +/* + * PLL2550xx Clock Type + */ + +/* Maximum lock time can be 270 * PDIV cycles */ +#define PLL2550XX_LOCK_FACTOR 270 + +#define PLL2550XX_M_MASK 0x3FF +#define PLL2550XX_P_MASK 0x3F +#define PLL2550XX_S_MASK 0x7 +#define PLL2550XX_LOCK_STAT_MASK 0x1 +#define PLL2550XX_M_SHIFT 9 +#define PLL2550XX_P_SHIFT 3 +#define PLL2550XX_S_SHIFT 0 +#define PLL2550XX_LOCK_STAT_SHIFT 21 + +static unsigned long samsung_pll2550xx_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 mdiv, pdiv, sdiv, pll_con; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->con_reg); + mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK; + pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK; + sdiv = (pll_con >> PLL2550XX_S_SHIFT) & PLL2550XX_S_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +static inline bool samsung_pll2550xx_mp_change(u32 mdiv, u32 pdiv, u32 pll_con) +{ + u32 old_mdiv, old_pdiv; + + old_mdiv = (pll_con >> PLL2550XX_M_SHIFT) & PLL2550XX_M_MASK; + old_pdiv = (pll_con >> PLL2550XX_P_SHIFT) & PLL2550XX_P_MASK; + + return mdiv != old_mdiv || pdiv != old_pdiv; +} + +static int samsung_pll2550xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long prate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + const struct samsung_pll_rate_table *rate; + u32 tmp; + + /* Get required rate settings from table */ + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + tmp = __raw_readl(pll->con_reg); + + if (!(samsung_pll2550xx_mp_change(rate->mdiv, rate->pdiv, tmp))) { + /* If only s change, change just s value only*/ + tmp &= ~(PLL2550XX_S_MASK << PLL2550XX_S_SHIFT); + tmp |= rate->sdiv << PLL2550XX_S_SHIFT; + __raw_writel(tmp, pll->con_reg); + + return 0; + } + + /* Set PLL lock time. */ + __raw_writel(rate->pdiv * PLL2550XX_LOCK_FACTOR, pll->lock_reg); + + /* Change PLL PMS values */ + tmp &= ~((PLL2550XX_M_MASK << PLL2550XX_M_SHIFT) | + (PLL2550XX_P_MASK << PLL2550XX_P_SHIFT) | + (PLL2550XX_S_MASK << PLL2550XX_S_SHIFT)); + tmp |= (rate->mdiv << PLL2550XX_M_SHIFT) | + (rate->pdiv << PLL2550XX_P_SHIFT) | + (rate->sdiv << PLL2550XX_S_SHIFT); + __raw_writel(tmp, pll->con_reg); + + /* wait_lock_time */ + do { + cpu_relax(); + tmp = __raw_readl(pll->con_reg); + } while (!(tmp & (PLL2550XX_LOCK_STAT_MASK + << PLL2550XX_LOCK_STAT_SHIFT))); + + return 0; +} + +static const struct clk_ops samsung_pll2550xx_clk_ops = { + .recalc_rate = samsung_pll2550xx_recalc_rate, + .round_rate = samsung_pll_round_rate, + .set_rate = samsung_pll2550xx_set_rate, +}; + +static const struct clk_ops samsung_pll2550xx_clk_min_ops = { + .recalc_rate = samsung_pll2550xx_recalc_rate, +}; + +/* + * PLL2650XX Clock Type + */ + +/* Maximum lock time can be 3000 * PDIV cycles */ +#define PLL2650XX_LOCK_FACTOR 3000 + +#define PLL2650XX_MDIV_SHIFT 9 +#define PLL2650XX_PDIV_SHIFT 3 +#define PLL2650XX_SDIV_SHIFT 0 +#define PLL2650XX_KDIV_SHIFT 0 +#define PLL2650XX_MDIV_MASK 0x1ff +#define PLL2650XX_PDIV_MASK 0x3f +#define PLL2650XX_SDIV_MASK 0x7 +#define PLL2650XX_KDIV_MASK 0xffff +#define PLL2650XX_PLL_ENABLE_SHIFT 23 +#define PLL2650XX_PLL_LOCKTIME_SHIFT 21 +#define PLL2650XX_PLL_FOUTMASK_SHIFT 31 + +static unsigned long samsung_pll2650xx_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 mdiv, pdiv, sdiv, pll_con0, pll_con2; + s16 kdiv; + u64 fvco = parent_rate; + + pll_con0 = __raw_readl(pll->con_reg); + pll_con2 = __raw_readl(pll->con_reg + 8); + mdiv = (pll_con0 >> PLL2650XX_MDIV_SHIFT) & PLL2650XX_MDIV_MASK; + pdiv = (pll_con0 >> PLL2650XX_PDIV_SHIFT) & PLL2650XX_PDIV_MASK; + sdiv = (pll_con0 >> PLL2650XX_SDIV_SHIFT) & PLL2650XX_SDIV_MASK; + kdiv = (s16)(pll_con2 & PLL2650XX_KDIV_MASK); + + fvco *= (mdiv << 16) + kdiv; + do_div(fvco, (pdiv << sdiv)); + fvco >>= 16; + + return (unsigned long)fvco; +} + +static int samsung_pll2650xx_set_rate(struct clk_hw *hw, unsigned long drate, + unsigned long parent_rate) +{ + struct samsung_clk_pll *pll = to_clk_pll(hw); + u32 tmp, pll_con0, pll_con2; + const struct samsung_pll_rate_table *rate; + + rate = samsung_get_pll_settings(pll, drate); + if (!rate) { + pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, + drate, __clk_get_name(hw->clk)); + return -EINVAL; + } + + pll_con0 = __raw_readl(pll->con_reg); + pll_con2 = __raw_readl(pll->con_reg + 8); + + /* Change PLL PMS values */ + pll_con0 &= ~(PLL2650XX_MDIV_MASK << PLL2650XX_MDIV_SHIFT | + PLL2650XX_PDIV_MASK << PLL2650XX_PDIV_SHIFT | + PLL2650XX_SDIV_MASK << PLL2650XX_SDIV_SHIFT); + pll_con0 |= rate->mdiv << PLL2650XX_MDIV_SHIFT; + pll_con0 |= rate->pdiv << PLL2650XX_PDIV_SHIFT; + pll_con0 |= rate->sdiv << PLL2650XX_SDIV_SHIFT; + pll_con0 |= 1 << PLL2650XX_PLL_ENABLE_SHIFT; + pll_con0 |= 1 << PLL2650XX_PLL_FOUTMASK_SHIFT; + + pll_con2 &= ~(PLL2650XX_KDIV_MASK << PLL2650XX_KDIV_SHIFT); + pll_con2 |= ((~(rate->kdiv) + 1) & PLL2650XX_KDIV_MASK) + << PLL2650XX_KDIV_SHIFT; + + /* Set PLL lock time. */ + __raw_writel(PLL2650XX_LOCK_FACTOR * rate->pdiv, pll->lock_reg); + + __raw_writel(pll_con0, pll->con_reg); + __raw_writel(pll_con2, pll->con_reg + 8); + + do { + tmp = __raw_readl(pll->con_reg); + } while (!(tmp & (0x1 << PLL2650XX_PLL_LOCKTIME_SHIFT))); + + return 0; +} + +static const struct clk_ops samsung_pll2650xx_clk_ops = { + .recalc_rate = samsung_pll2650xx_recalc_rate, + .set_rate = samsung_pll2650xx_set_rate, + .round_rate = samsung_pll_round_rate, +}; + +static const struct clk_ops samsung_pll2650xx_clk_min_ops = { + .recalc_rate = samsung_pll2650xx_recalc_rate, +}; + +static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx, + struct samsung_pll_clock *pll_clk, + void __iomem *base) { struct samsung_clk_pll *pll; struct clk *clk; @@ -1048,6 +1246,18 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, else init.ops = &samsung_s3c2440_mpll_clk_ops; break; + case pll_2550xx: + if (!pll->rate_table) + init.ops = &samsung_pll2550xx_clk_min_ops; + else + init.ops = &samsung_pll2550xx_clk_ops; + break; + case pll_2650xx: + if (!pll->rate_table) + init.ops = &samsung_pll2650xx_clk_min_ops; + else + init.ops = &samsung_pll2650xx_clk_ops; + break; default: pr_warn("%s: Unknown pll type for pll clk %s\n", __func__, pll_clk->name); @@ -1066,7 +1276,7 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, return; } - samsung_clk_add_lookup(clk, pll_clk->id); + samsung_clk_add_lookup(ctx, clk, pll_clk->id); if (!pll_clk->alias) return; @@ -1077,11 +1287,12 @@ static void __init _samsung_clk_register_pll(struct samsung_pll_clock *pll_clk, __func__, pll_clk->name, ret); } -void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, - unsigned int nr_pll, void __iomem *base) +void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, + struct samsung_pll_clock *pll_list, + unsigned int nr_pll, void __iomem *base) { int cnt; for (cnt = 0; cnt < nr_pll; cnt++) - _samsung_clk_register_pll(&pll_list[cnt], base); + _samsung_clk_register_pll(ctx, &pll_list[cnt], base); } diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index 6428bcc6..c0ed4d4 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -31,6 +31,8 @@ enum samsung_pll_type { pll_s3c2410_mpll, pll_s3c2410_upll, pll_s3c2440_mpll, + pll_2550xx, + pll_2650xx, }; #define PLL_35XX_RATE(_rate, _m, _p, _s) \ diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c index 7b41821..ba07168 100644 --- a/drivers/clk/samsung/clk-s3c2410.c +++ b/drivers/clk/samsung/clk-s3c2410.c @@ -344,21 +344,24 @@ struct samsung_fixed_rate_clock s3c2410_common_frate_clks[] __initdata = { FRATE(XTI, "xti", NULL, CLK_IS_ROOT, 0), }; -static void __init s3c2410_common_clk_register_fixed_ext(unsigned long xti_f) +static void __init s3c2410_common_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, + unsigned long xti_f) { struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); s3c2410_common_frate_clks[0].fixed_rate = xti_f; - samsung_clk_register_fixed_rate(s3c2410_common_frate_clks, + samsung_clk_register_fixed_rate(ctx, s3c2410_common_frate_clks, ARRAY_SIZE(s3c2410_common_frate_clks)); - samsung_clk_register_alias(&xti_alias, 1); + samsung_clk_register_alias(ctx, &xti_alias, 1); } void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, int current_soc, void __iomem *base) { + struct samsung_clk_provider *ctx; reg_base = base; if (np) { @@ -367,11 +370,13 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, panic("%s: failed to map registers\n", __func__); } - samsung_clk_init(np, reg_base, NR_CLKS); + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); /* Register external clocks only in non-dt cases */ if (!np) - s3c2410_common_clk_register_fixed_ext(xti_f); + s3c2410_common_clk_register_fixed_ext(ctx, xti_f); if (current_soc == 2410) { if (_get_rate("xti") == 12 * MHZ) { @@ -380,7 +385,7 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, } /* Register PLLs. */ - samsung_clk_register_pll(s3c2410_plls, + samsung_clk_register_pll(ctx, s3c2410_plls, ARRAY_SIZE(s3c2410_plls), reg_base); } else { /* S3C2440, S3C2442 */ @@ -396,49 +401,49 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, } /* Register PLLs. */ - samsung_clk_register_pll(s3c244x_common_plls, + samsung_clk_register_pll(ctx, s3c244x_common_plls, ARRAY_SIZE(s3c244x_common_plls), reg_base); } /* Register common internal clocks. */ - samsung_clk_register_mux(s3c2410_common_muxes, + samsung_clk_register_mux(ctx, s3c2410_common_muxes, ARRAY_SIZE(s3c2410_common_muxes)); - samsung_clk_register_div(s3c2410_common_dividers, + samsung_clk_register_div(ctx, s3c2410_common_dividers, ARRAY_SIZE(s3c2410_common_dividers)); - samsung_clk_register_gate(s3c2410_common_gates, + samsung_clk_register_gate(ctx, s3c2410_common_gates, ARRAY_SIZE(s3c2410_common_gates)); if (current_soc == S3C2440 || current_soc == S3C2442) { - samsung_clk_register_div(s3c244x_common_dividers, + samsung_clk_register_div(ctx, s3c244x_common_dividers, ARRAY_SIZE(s3c244x_common_dividers)); - samsung_clk_register_gate(s3c244x_common_gates, + samsung_clk_register_gate(ctx, s3c244x_common_gates, ARRAY_SIZE(s3c244x_common_gates)); - samsung_clk_register_mux(s3c244x_common_muxes, + samsung_clk_register_mux(ctx, s3c244x_common_muxes, ARRAY_SIZE(s3c244x_common_muxes)); - samsung_clk_register_fixed_factor(s3c244x_common_ffactor, + samsung_clk_register_fixed_factor(ctx, s3c244x_common_ffactor, ARRAY_SIZE(s3c244x_common_ffactor)); } /* Register SoC-specific clocks. */ switch (current_soc) { case S3C2410: - samsung_clk_register_div(s3c2410_dividers, + samsung_clk_register_div(ctx, s3c2410_dividers, ARRAY_SIZE(s3c2410_dividers)); - samsung_clk_register_fixed_factor(s3c2410_ffactor, + samsung_clk_register_fixed_factor(ctx, s3c2410_ffactor, ARRAY_SIZE(s3c2410_ffactor)); - samsung_clk_register_alias(s3c2410_aliases, + samsung_clk_register_alias(ctx, s3c2410_aliases, ARRAY_SIZE(s3c2410_common_aliases)); break; case S3C2440: - samsung_clk_register_mux(s3c2440_muxes, + samsung_clk_register_mux(ctx, s3c2440_muxes, ARRAY_SIZE(s3c2440_muxes)); - samsung_clk_register_gate(s3c2440_gates, + samsung_clk_register_gate(ctx, s3c2440_gates, ARRAY_SIZE(s3c2440_gates)); break; case S3C2442: - samsung_clk_register_mux(s3c2442_muxes, + samsung_clk_register_mux(ctx, s3c2442_muxes, ARRAY_SIZE(s3c2442_muxes)); - samsung_clk_register_fixed_factor(s3c2442_ffactor, + samsung_clk_register_fixed_factor(ctx, s3c2442_ffactor, ARRAY_SIZE(s3c2442_ffactor)); break; } @@ -447,11 +452,11 @@ void __init s3c2410_common_clk_init(struct device_node *np, unsigned long xti_f, * Register common aliases at the end, as some of the aliased clocks * are SoC specific. */ - samsung_clk_register_alias(s3c2410_common_aliases, + samsung_clk_register_alias(ctx, s3c2410_common_aliases, ARRAY_SIZE(s3c2410_common_aliases)); if (current_soc == S3C2440 || current_soc == S3C2442) { - samsung_clk_register_alias(s3c244x_common_aliases, + samsung_clk_register_alias(ctx, s3c244x_common_aliases, ARRAY_SIZE(s3c244x_common_aliases)); } diff --git a/drivers/clk/samsung/clk-s3c2412.c b/drivers/clk/samsung/clk-s3c2412.c index 0f11a07..23e4313 100644 --- a/drivers/clk/samsung/clk-s3c2412.c +++ b/drivers/clk/samsung/clk-s3c2412.c @@ -214,23 +214,25 @@ struct samsung_fixed_rate_clock s3c2412_common_frate_clks[] __initdata = { FRATE(0, "ext", NULL, CLK_IS_ROOT, 0), }; -static void __init s3c2412_common_clk_register_fixed_ext(unsigned long xti_f, - unsigned long ext_f) +static void __init s3c2412_common_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, + unsigned long xti_f, unsigned long ext_f) { /* xtal alias is necessary for the current cpufreq driver */ struct samsung_clock_alias xti_alias = ALIAS(XTI, NULL, "xtal"); s3c2412_common_frate_clks[0].fixed_rate = xti_f; s3c2412_common_frate_clks[1].fixed_rate = ext_f; - samsung_clk_register_fixed_rate(s3c2412_common_frate_clks, + samsung_clk_register_fixed_rate(ctx, s3c2412_common_frate_clks, ARRAY_SIZE(s3c2412_common_frate_clks)); - samsung_clk_register_alias(&xti_alias, 1); + samsung_clk_register_alias(ctx, &xti_alias, 1); } void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, unsigned long ext_f, void __iomem *base) { + struct samsung_clk_provider *ctx; reg_base = base; if (np) { @@ -239,24 +241,27 @@ void __init s3c2412_common_clk_init(struct device_node *np, unsigned long xti_f, panic("%s: failed to map registers\n", __func__); } - samsung_clk_init(np, reg_base, NR_CLKS); + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); /* Register external clocks only in non-dt cases */ if (!np) - s3c2412_common_clk_register_fixed_ext(xti_f, ext_f); + s3c2412_common_clk_register_fixed_ext(ctx, xti_f, ext_f); /* Register PLLs. */ - samsung_clk_register_pll(s3c2412_plls, ARRAY_SIZE(s3c2412_plls), + samsung_clk_register_pll(ctx, s3c2412_plls, ARRAY_SIZE(s3c2412_plls), reg_base); /* Register common internal clocks. */ - samsung_clk_register_mux(s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes)); - samsung_clk_register_div(s3c2412_dividers, + samsung_clk_register_mux(ctx, s3c2412_muxes, ARRAY_SIZE(s3c2412_muxes)); + samsung_clk_register_div(ctx, s3c2412_dividers, ARRAY_SIZE(s3c2412_dividers)); - samsung_clk_register_gate(s3c2412_gates, ARRAY_SIZE(s3c2412_gates)); - samsung_clk_register_fixed_factor(s3c2412_ffactor, + samsung_clk_register_gate(ctx, s3c2412_gates, + ARRAY_SIZE(s3c2412_gates)); + samsung_clk_register_fixed_factor(ctx, s3c2412_ffactor, ARRAY_SIZE(s3c2412_ffactor)); - samsung_clk_register_alias(s3c2412_aliases, + samsung_clk_register_alias(ctx, s3c2412_aliases, ARRAY_SIZE(s3c2412_aliases)); s3c2412_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk-s3c2443.c b/drivers/clk/samsung/clk-s3c2443.c index 8e4f451..c4bbdab 100644 --- a/drivers/clk/samsung/clk-s3c2443.c +++ b/drivers/clk/samsung/clk-s3c2443.c @@ -365,10 +365,11 @@ struct samsung_fixed_rate_clock s3c2443_common_frate_clks[] __initdata = { FRATE(0, "ext_uart", NULL, CLK_IS_ROOT, 0), }; -static void __init s3c2443_common_clk_register_fixed_ext(unsigned long xti_f) +static void __init s3c2443_common_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, unsigned long xti_f) { s3c2443_common_frate_clks[0].fixed_rate = xti_f; - samsung_clk_register_fixed_rate(s3c2443_common_frate_clks, + samsung_clk_register_fixed_rate(ctx, s3c2443_common_frate_clks, ARRAY_SIZE(s3c2443_common_frate_clks)); } @@ -376,6 +377,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, int current_soc, void __iomem *base) { + struct samsung_clk_provider *ctx; reg_base = base; if (np) { @@ -384,58 +386,60 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f, panic("%s: failed to map registers\n", __func__); } - samsung_clk_init(np, reg_base, NR_CLKS); + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); /* Register external clocks only in non-dt cases */ if (!np) - s3c2443_common_clk_register_fixed_ext(xti_f); + s3c2443_common_clk_register_fixed_ext(ctx, xti_f); /* Register PLLs. */ if (current_soc == S3C2416 || current_soc == S3C2450) - samsung_clk_register_pll(s3c2416_pll_clks, + samsung_clk_register_pll(ctx, s3c2416_pll_clks, ARRAY_SIZE(s3c2416_pll_clks), reg_base); else - samsung_clk_register_pll(s3c2443_pll_clks, + samsung_clk_register_pll(ctx, s3c2443_pll_clks, ARRAY_SIZE(s3c2443_pll_clks), reg_base); /* Register common internal clocks. */ - samsung_clk_register_mux(s3c2443_common_muxes, + samsung_clk_register_mux(ctx, s3c2443_common_muxes, ARRAY_SIZE(s3c2443_common_muxes)); - samsung_clk_register_div(s3c2443_common_dividers, + samsung_clk_register_div(ctx, s3c2443_common_dividers, ARRAY_SIZE(s3c2443_common_dividers)); - samsung_clk_register_gate(s3c2443_common_gates, + samsung_clk_register_gate(ctx, s3c2443_common_gates, ARRAY_SIZE(s3c2443_common_gates)); - samsung_clk_register_alias(s3c2443_common_aliases, + samsung_clk_register_alias(ctx, s3c2443_common_aliases, ARRAY_SIZE(s3c2443_common_aliases)); /* Register SoC-specific clocks. */ switch (current_soc) { case S3C2450: - samsung_clk_register_div(s3c2450_dividers, + samsung_clk_register_div(ctx, s3c2450_dividers, ARRAY_SIZE(s3c2450_dividers)); - samsung_clk_register_mux(s3c2450_muxes, + samsung_clk_register_mux(ctx, s3c2450_muxes, ARRAY_SIZE(s3c2450_muxes)); - samsung_clk_register_gate(s3c2450_gates, + samsung_clk_register_gate(ctx, s3c2450_gates, ARRAY_SIZE(s3c2450_gates)); - samsung_clk_register_alias(s3c2450_aliases, + samsung_clk_register_alias(ctx, s3c2450_aliases, ARRAY_SIZE(s3c2450_aliases)); /* fall through, as s3c2450 extends the s3c2416 clocks */ case S3C2416: - samsung_clk_register_div(s3c2416_dividers, + samsung_clk_register_div(ctx, s3c2416_dividers, ARRAY_SIZE(s3c2416_dividers)); - samsung_clk_register_mux(s3c2416_muxes, + samsung_clk_register_mux(ctx, s3c2416_muxes, ARRAY_SIZE(s3c2416_muxes)); - samsung_clk_register_gate(s3c2416_gates, + samsung_clk_register_gate(ctx, s3c2416_gates, ARRAY_SIZE(s3c2416_gates)); - samsung_clk_register_alias(s3c2416_aliases, + samsung_clk_register_alias(ctx, s3c2416_aliases, ARRAY_SIZE(s3c2416_aliases)); break; case S3C2443: - samsung_clk_register_div(s3c2443_dividers, + samsung_clk_register_div(ctx, s3c2443_dividers, ARRAY_SIZE(s3c2443_dividers)); - samsung_clk_register_gate(s3c2443_gates, + samsung_clk_register_gate(ctx, s3c2443_gates, ARRAY_SIZE(s3c2443_gates)); - samsung_clk_register_alias(s3c2443_aliases, + samsung_clk_register_alias(ctx, s3c2443_aliases, ARRAY_SIZE(s3c2443_aliases)); break; } diff --git a/drivers/clk/samsung/clk-s3c64xx.c b/drivers/clk/samsung/clk-s3c64xx.c index 8bda658..efa16ee 100644 --- a/drivers/clk/samsung/clk-s3c64xx.c +++ b/drivers/clk/samsung/clk-s3c64xx.c @@ -442,12 +442,14 @@ static struct samsung_clock_alias s3c6410_clock_aliases[] = { ALIAS(MEM0_SROM, NULL, "srom"), }; -static void __init s3c64xx_clk_register_fixed_ext(unsigned long fin_pll_f, - unsigned long xusbxti_f) +static void __init s3c64xx_clk_register_fixed_ext( + struct samsung_clk_provider *ctx, + unsigned long fin_pll_f, + unsigned long xusbxti_f) { s3c64xx_fixed_rate_ext_clks[0].fixed_rate = fin_pll_f; s3c64xx_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f; - samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_ext_clks, + samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_ext_clks, ARRAY_SIZE(s3c64xx_fixed_rate_ext_clks)); } @@ -456,6 +458,8 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, unsigned long xusbxti_f, bool s3c6400, void __iomem *base) { + struct samsung_clk_provider *ctx; + reg_base = base; is_s3c6400 = s3c6400; @@ -465,48 +469,50 @@ void __init s3c64xx_clk_init(struct device_node *np, unsigned long xtal_f, panic("%s: failed to map registers\n", __func__); } - samsung_clk_init(np, reg_base, NR_CLKS); + ctx = samsung_clk_init(np, reg_base, NR_CLKS); + if (!ctx) + panic("%s: unable to allocate context.\n", __func__); /* Register external clocks. */ if (!np) - s3c64xx_clk_register_fixed_ext(xtal_f, xusbxti_f); + s3c64xx_clk_register_fixed_ext(ctx, xtal_f, xusbxti_f); /* Register PLLs. */ - samsung_clk_register_pll(s3c64xx_pll_clks, + samsung_clk_register_pll(ctx, s3c64xx_pll_clks, ARRAY_SIZE(s3c64xx_pll_clks), reg_base); /* Register common internal clocks. */ - samsung_clk_register_fixed_rate(s3c64xx_fixed_rate_clks, + samsung_clk_register_fixed_rate(ctx, s3c64xx_fixed_rate_clks, ARRAY_SIZE(s3c64xx_fixed_rate_clks)); - samsung_clk_register_mux(s3c64xx_mux_clks, + samsung_clk_register_mux(ctx, s3c64xx_mux_clks, ARRAY_SIZE(s3c64xx_mux_clks)); - samsung_clk_register_div(s3c64xx_div_clks, + samsung_clk_register_div(ctx, s3c64xx_div_clks, ARRAY_SIZE(s3c64xx_div_clks)); - samsung_clk_register_gate(s3c64xx_gate_clks, + samsung_clk_register_gate(ctx, s3c64xx_gate_clks, ARRAY_SIZE(s3c64xx_gate_clks)); /* Register SoC-specific clocks. */ if (is_s3c6400) { - samsung_clk_register_mux(s3c6400_mux_clks, + samsung_clk_register_mux(ctx, s3c6400_mux_clks, ARRAY_SIZE(s3c6400_mux_clks)); - samsung_clk_register_div(s3c6400_div_clks, + samsung_clk_register_div(ctx, s3c6400_div_clks, ARRAY_SIZE(s3c6400_div_clks)); - samsung_clk_register_gate(s3c6400_gate_clks, + samsung_clk_register_gate(ctx, s3c6400_gate_clks, ARRAY_SIZE(s3c6400_gate_clks)); - samsung_clk_register_alias(s3c6400_clock_aliases, + samsung_clk_register_alias(ctx, s3c6400_clock_aliases, ARRAY_SIZE(s3c6400_clock_aliases)); } else { - samsung_clk_register_mux(s3c6410_mux_clks, + samsung_clk_register_mux(ctx, s3c6410_mux_clks, ARRAY_SIZE(s3c6410_mux_clks)); - samsung_clk_register_div(s3c6410_div_clks, + samsung_clk_register_div(ctx, s3c6410_div_clks, ARRAY_SIZE(s3c6410_div_clks)); - samsung_clk_register_gate(s3c6410_gate_clks, + samsung_clk_register_gate(ctx, s3c6410_gate_clks, ARRAY_SIZE(s3c6410_gate_clks)); - samsung_clk_register_alias(s3c6410_clock_aliases, + samsung_clk_register_alias(ctx, s3c6410_clock_aliases, ARRAY_SIZE(s3c6410_clock_aliases)); } - samsung_clk_register_alias(s3c64xx_clock_aliases, + samsung_clk_register_alias(ctx, s3c64xx_clock_aliases, ARRAY_SIZE(s3c64xx_clock_aliases)); s3c64xx_clk_sleep_init(); diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c index 91bec3e..49629c7 100644 --- a/drivers/clk/samsung/clk.c +++ b/drivers/clk/samsung/clk.c @@ -14,13 +14,6 @@ #include <linux/syscore_ops.h> #include "clk.h" -static DEFINE_SPINLOCK(lock); -static struct clk **clk_table; -static void __iomem *reg_base; -#ifdef CONFIG_OF -static struct clk_onecell_data clk_data; -#endif - void samsung_clk_save(void __iomem *base, struct samsung_clk_reg_dump *rd, unsigned int num_regs) @@ -55,40 +48,58 @@ struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( } /* setup the essentials required to support clock lookup using ccf */ -void __init samsung_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks) +struct samsung_clk_provider *__init samsung_clk_init(struct device_node *np, + void __iomem *base, unsigned long nr_clks) { - reg_base = base; + struct samsung_clk_provider *ctx; + struct clk **clk_table; + int ret; + int i; - clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL); + ctx = kzalloc(sizeof(struct samsung_clk_provider), GFP_KERNEL); + if (!ctx) + panic("could not allocate clock provider context.\n"); + + clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); if (!clk_table) panic("could not allocate clock lookup table\n"); + for (i = 0; i < nr_clks; ++i) + clk_table[i] = ERR_PTR(-ENOENT); + + ctx->reg_base = base; + ctx->clk_data.clks = clk_table; + ctx->clk_data.clk_num = nr_clks; + spin_lock_init(&ctx->lock); + if (!np) - return; + return ctx; -#ifdef CONFIG_OF - clk_data.clks = clk_table; - clk_data.clk_num = nr_clks; - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); -#endif + ret = of_clk_add_provider(np, of_clk_src_onecell_get, + &ctx->clk_data); + if (ret) + panic("could not register clock provide\n"); + + return ctx; } /* add a clock instance to the clock lookup table used for dt based lookup */ -void samsung_clk_add_lookup(struct clk *clk, unsigned int id) +void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, struct clk *clk, + unsigned int id) { - if (clk_table && id) - clk_table[id] = clk; + if (ctx->clk_data.clks && id) + ctx->clk_data.clks[id] = clk; } /* register a list of aliases */ -void __init samsung_clk_register_alias(struct samsung_clock_alias *list, - unsigned int nr_clk) +void __init samsung_clk_register_alias(struct samsung_clk_provider *ctx, + struct samsung_clock_alias *list, + unsigned int nr_clk) { struct clk *clk; unsigned int idx, ret; - if (!clk_table) { + if (!ctx->clk_data.clks) { pr_err("%s: clock table missing\n", __func__); return; } @@ -100,7 +111,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, continue; } - clk = clk_table[list->id]; + clk = ctx->clk_data.clks[list->id]; if (!clk) { pr_err("%s: failed to find clock %d\n", __func__, list->id); @@ -115,7 +126,7 @@ void __init samsung_clk_register_alias(struct samsung_clock_alias *list, } /* register a list of fixed clocks */ -void __init samsung_clk_register_fixed_rate( +void __init samsung_clk_register_fixed_rate(struct samsung_clk_provider *ctx, struct samsung_fixed_rate_clock *list, unsigned int nr_clk) { struct clk *clk; @@ -130,7 +141,7 @@ void __init samsung_clk_register_fixed_rate( continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); /* * Unconditionally add a clock lookup for the fixed rate clocks. @@ -144,7 +155,7 @@ void __init samsung_clk_register_fixed_rate( } /* register a list of fixed factor clocks */ -void __init samsung_clk_register_fixed_factor( +void __init samsung_clk_register_fixed_factor(struct samsung_clk_provider *ctx, struct samsung_fixed_factor_clock *list, unsigned int nr_clk) { struct clk *clk; @@ -159,28 +170,30 @@ void __init samsung_clk_register_fixed_factor( continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); } } /* register a list of mux clocks */ -void __init samsung_clk_register_mux(struct samsung_mux_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, + struct samsung_mux_clock *list, + unsigned int nr_clk) { struct clk *clk; unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { clk = clk_register_mux(NULL, list->name, list->parent_names, - list->num_parents, list->flags, reg_base + list->offset, - list->shift, list->width, list->mux_flags, &lock); + list->num_parents, list->flags, + ctx->reg_base + list->offset, + list->shift, list->width, list->mux_flags, &ctx->lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); /* register a clock lookup only if a clock alias is specified */ if (list->alias) { @@ -194,8 +207,9 @@ void __init samsung_clk_register_mux(struct samsung_mux_clock *list, } /* register a list of div clocks */ -void __init samsung_clk_register_div(struct samsung_div_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, + struct samsung_div_clock *list, + unsigned int nr_clk) { struct clk *clk; unsigned int idx, ret; @@ -203,22 +217,22 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list, for (idx = 0; idx < nr_clk; idx++, list++) { if (list->table) clk = clk_register_divider_table(NULL, list->name, - list->parent_name, list->flags, - reg_base + list->offset, list->shift, - list->width, list->div_flags, - list->table, &lock); + list->parent_name, list->flags, + ctx->reg_base + list->offset, + list->shift, list->width, list->div_flags, + list->table, &ctx->lock); else clk = clk_register_divider(NULL, list->name, - list->parent_name, list->flags, - reg_base + list->offset, list->shift, - list->width, list->div_flags, &lock); + list->parent_name, list->flags, + ctx->reg_base + list->offset, list->shift, + list->width, list->div_flags, &ctx->lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); continue; } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); /* register a clock lookup only if a clock alias is specified */ if (list->alias) { @@ -232,16 +246,17 @@ void __init samsung_clk_register_div(struct samsung_div_clock *list, } /* register a list of gate clocks */ -void __init samsung_clk_register_gate(struct samsung_gate_clock *list, - unsigned int nr_clk) +void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, + struct samsung_gate_clock *list, + unsigned int nr_clk) { struct clk *clk; unsigned int idx, ret; for (idx = 0; idx < nr_clk; idx++, list++) { clk = clk_register_gate(NULL, list->name, list->parent_name, - list->flags, reg_base + list->offset, - list->bit_idx, list->gate_flags, &lock); + list->flags, ctx->reg_base + list->offset, + list->bit_idx, list->gate_flags, &ctx->lock); if (IS_ERR(clk)) { pr_err("%s: failed to register clock %s\n", __func__, list->name); @@ -257,7 +272,7 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, __func__, list->alias); } - samsung_clk_add_lookup(clk, list->id); + samsung_clk_add_lookup(ctx, clk, list->id); } } @@ -266,21 +281,21 @@ void __init samsung_clk_register_gate(struct samsung_gate_clock *list, * tree and register it */ #ifdef CONFIG_OF -void __init samsung_clk_of_register_fixed_ext( +void __init samsung_clk_of_register_fixed_ext(struct samsung_clk_provider *ctx, struct samsung_fixed_rate_clock *fixed_rate_clk, unsigned int nr_fixed_rate_clk, struct of_device_id *clk_matches) { const struct of_device_id *match; - struct device_node *np; + struct device_node *clk_np; u32 freq; - for_each_matching_node_and_match(np, clk_matches, &match) { - if (of_property_read_u32(np, "clock-frequency", &freq)) + for_each_matching_node_and_match(clk_np, clk_matches, &match) { + if (of_property_read_u32(clk_np, "clock-frequency", &freq)) continue; - fixed_rate_clk[(u32)match->data].fixed_rate = freq; + fixed_rate_clk[(unsigned long)match->data].fixed_rate = freq; } - samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk); + samsung_clk_register_fixed_rate(ctx, fixed_rate_clk, nr_fixed_rate_clk); } #endif diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index c7141ba..9693b80 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h @@ -22,6 +22,18 @@ #include "clk-pll.h" /** + * struct samsung_clk_provider: information about clock provider + * @reg_base: virtual address for the register base. + * @clk_data: holds clock related data like clk* and number of clocks. + * @lock: maintains exclusion bwtween callbacks for a given clock-provider. + */ +struct samsung_clk_provider { + void __iomem *reg_base; + struct clk_onecell_data clk_data; + spinlock_t lock; +}; + +/** * struct samsung_clock_alias: information about mux clock * @id: platform specific id of the clock. * @dev_name: name of the device to which this clock belongs. @@ -312,40 +324,52 @@ struct samsung_pll_clock { __PLL(_typ, _id, NULL, _name, _pname, CLK_GET_RATE_NOCACHE, \ _lock, _con, _rtable, _alias) -extern void __init samsung_clk_init(struct device_node *np, void __iomem *base, - unsigned long nr_clks); +extern struct samsung_clk_provider *__init samsung_clk_init( + struct device_node *np, void __iomem *base, + unsigned long nr_clks); extern void __init samsung_clk_of_register_fixed_ext( - struct samsung_fixed_rate_clock *fixed_rate_clk, - unsigned int nr_fixed_rate_clk, - struct of_device_id *clk_matches); + struct samsung_clk_provider *ctx, + struct samsung_fixed_rate_clock *fixed_rate_clk, + unsigned int nr_fixed_rate_clk, + struct of_device_id *clk_matches); -extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id); +extern void samsung_clk_add_lookup(struct samsung_clk_provider *ctx, + struct clk *clk, unsigned int id); -extern void samsung_clk_register_alias(struct samsung_clock_alias *list, - unsigned int nr_clk); +extern void samsung_clk_register_alias(struct samsung_clk_provider *ctx, + struct samsung_clock_alias *list, + unsigned int nr_clk); extern void __init samsung_clk_register_fixed_rate( - struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk); + struct samsung_clk_provider *ctx, + struct samsung_fixed_rate_clock *clk_list, + unsigned int nr_clk); extern void __init samsung_clk_register_fixed_factor( - struct samsung_fixed_factor_clock *list, unsigned int nr_clk); -extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list, - unsigned int nr_clk); -extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list, - unsigned int nr_clk); -extern void __init samsung_clk_register_gate( - struct samsung_gate_clock *clk_list, unsigned int nr_clk); -extern void __init samsung_clk_register_pll(struct samsung_pll_clock *pll_list, - unsigned int nr_clk, void __iomem *base); + struct samsung_clk_provider *ctx, + struct samsung_fixed_factor_clock *list, + unsigned int nr_clk); +extern void __init samsung_clk_register_mux(struct samsung_clk_provider *ctx, + struct samsung_mux_clock *clk_list, + unsigned int nr_clk); +extern void __init samsung_clk_register_div(struct samsung_clk_provider *ctx, + struct samsung_div_clock *clk_list, + unsigned int nr_clk); +extern void __init samsung_clk_register_gate(struct samsung_clk_provider *ctx, + struct samsung_gate_clock *clk_list, + unsigned int nr_clk); +extern void __init samsung_clk_register_pll(struct samsung_clk_provider *ctx, + struct samsung_pll_clock *pll_list, + unsigned int nr_clk, void __iomem *base); extern unsigned long _get_rate(const char *clk_name); extern void samsung_clk_save(void __iomem *base, - struct samsung_clk_reg_dump *rd, - unsigned int num_regs); + struct samsung_clk_reg_dump *rd, + unsigned int num_regs); extern void samsung_clk_restore(void __iomem *base, - const struct samsung_clk_reg_dump *rd, - unsigned int num_regs); + const struct samsung_clk_reg_dump *rd, + unsigned int num_regs); extern struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump( - const unsigned long *rdump, - unsigned long nr_rdump); + const unsigned long *rdump, + unsigned long nr_rdump); #endif /* __SAMSUNG_CLK_H */ diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c index 49fbe28..7a08811 100644 --- a/drivers/clocksource/cadence_ttc_timer.c +++ b/drivers/clocksource/cadence_ttc_timer.c @@ -118,11 +118,11 @@ static void ttc_set_interval(struct ttc_timer *timer, u32 ctrl_reg; /* Disable the counter, set the counter value and re-enable counter */ - ctrl_reg = __raw_readl(timer->base_addr + TTC_CNT_CNTRL_OFFSET); + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; - __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); - __raw_writel(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); + writel_relaxed(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); /* * Reset the counter (0x10) so that it starts from 0, one-shot @@ -130,7 +130,7 @@ static void ttc_set_interval(struct ttc_timer *timer, */ ctrl_reg |= CNT_CNTRL_RESET; ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; - __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); } /** @@ -147,7 +147,7 @@ static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id) struct ttc_timer *timer = &ttce->ttc; /* Acknowledge the interrupt and call event handler */ - __raw_readl(timer->base_addr + TTC_ISR_OFFSET); + readl_relaxed(timer->base_addr + TTC_ISR_OFFSET); ttce->ce.event_handler(&ttce->ce); @@ -163,13 +163,13 @@ static cycle_t __ttc_clocksource_read(struct clocksource *cs) { struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; - return (cycle_t)__raw_readl(timer->base_addr + + return (cycle_t)readl_relaxed(timer->base_addr + TTC_COUNT_VAL_OFFSET); } static u64 notrace ttc_sched_clock_read(void) { - return __raw_readl(ttc_sched_clock_val_reg); + return readl_relaxed(ttc_sched_clock_val_reg); } /** @@ -211,17 +211,17 @@ static void ttc_set_mode(enum clock_event_mode mode, case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - ctrl_reg = __raw_readl(timer->base_addr + + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; - __raw_writel(ctrl_reg, + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); break; case CLOCK_EVT_MODE_RESUME: - ctrl_reg = __raw_readl(timer->base_addr + + ctrl_reg = readl_relaxed(timer->base_addr + TTC_CNT_CNTRL_OFFSET); ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; - __raw_writel(ctrl_reg, + writel_relaxed(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); break; } @@ -266,8 +266,8 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, * of an abort. */ ttccs->scale_clk_ctrl_reg_old = - __raw_readl(ttccs->ttc.base_addr + - TTC_CLK_CNTRL_OFFSET); + readl_relaxed(ttccs->ttc.base_addr + + TTC_CLK_CNTRL_OFFSET); psv = (ttccs->scale_clk_ctrl_reg_old & TTC_CLK_CNTRL_PSV_MASK) >> @@ -291,8 +291,8 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, return NOTIFY_DONE; /* scale up: adjust divider now - before frequency change */ - __raw_writel(ttccs->scale_clk_ctrl_reg_new, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + writel_relaxed(ttccs->scale_clk_ctrl_reg_new, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); break; } case POST_RATE_CHANGE: @@ -301,8 +301,8 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, return NOTIFY_OK; /* scale down: adjust divider now - after frequency change */ - __raw_writel(ttccs->scale_clk_ctrl_reg_new, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + writel_relaxed(ttccs->scale_clk_ctrl_reg_new, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); break; case ABORT_RATE_CHANGE: @@ -311,8 +311,8 @@ static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, return NOTIFY_OK; /* restore original register value */ - __raw_writel(ttccs->scale_clk_ctrl_reg_old, - ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); + writel_relaxed(ttccs->scale_clk_ctrl_reg_old, + ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); /* fall through */ default: return NOTIFY_DONE; @@ -359,10 +359,10 @@ static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) * with no interrupt and it rolls over at 0xFFFF. Pre-scale * it by 32 also. Let it start running now. */ - __raw_writel(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); - __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, + writel_relaxed(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); + writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - __raw_writel(CNT_CNTRL_RESET, + writel_relaxed(CNT_CNTRL_RESET, ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); err = clocksource_register_hz(&ttccs->cs, ttccs->ttc.freq / PRESCALE); @@ -438,10 +438,10 @@ static void __init ttc_setup_clockevent(struct clk *clk, * is prescaled by 32 using the interval interrupt. Leave it * disabled for now. */ - __raw_writel(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); - __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, + writel_relaxed(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); + writel_relaxed(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); - __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); + writel_relaxed(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); err = request_irq(irq, ttc_clock_event_interrupt, IRQF_TIMER, ttcce->ce.name, ttcce); @@ -490,7 +490,7 @@ static void __init ttc_timer_init(struct device_node *timer) BUG(); } - clksel = __raw_readl(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); + clksel = readl_relaxed(timer_baseaddr + TTC_CLK_CNTRL_OFFSET); clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); clk_cs = of_clk_get(timer, clksel); if (IS_ERR(clk_cs)) { @@ -498,7 +498,7 @@ static void __init ttc_timer_init(struct device_node *timer) BUG(); } - clksel = __raw_readl(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); + clksel = readl_relaxed(timer_baseaddr + 4 + TTC_CLK_CNTRL_OFFSET); clksel = !!(clksel & TTC_CLK_CNTRL_CSRC_MASK); clk_ce = of_clk_get(timer, clksel); if (IS_ERR(clk_ce)) { diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 97ccc31..5bb9478 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -1,6 +1,11 @@ # # ARM CPU Idle drivers # +config ARM_ARMADA_370_XP_CPUIDLE + bool "CPU Idle Driver for Armada 370/XP family processors" + depends on ARCH_MVEBU + help + Select this to enable cpuidle on Armada 370/XP processors. config ARM_BIG_LITTLE_CPUIDLE bool "Support for ARM big.LITTLE processors" diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index f71ae1b..9902d05 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -7,6 +7,7 @@ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o ################################################################################## # ARM SoC drivers +obj-$(CONFIG_ARM_ARMADA_370_XP_CPUIDLE) += cpuidle-armada-370-xp.o obj-$(CONFIG_ARM_BIG_LITTLE_CPUIDLE) += cpuidle-big_little.o obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o diff --git a/drivers/cpuidle/cpuidle-armada-370-xp.c b/drivers/cpuidle/cpuidle-armada-370-xp.c new file mode 100644 index 0000000..28587d0 --- /dev/null +++ b/drivers/cpuidle/cpuidle-armada-370-xp.c @@ -0,0 +1,93 @@ +/* + * Marvell Armada 370 and Armada XP SoC cpuidle driver + * + * Copyright (C) 2014 Marvell + * + * Nadav Haklai <nadavh@marvell.com> + * Gregory CLEMENT <gregory.clement@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + * + * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com> + */ + +#include <linux/cpu_pm.h> +#include <linux/cpuidle.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/suspend.h> +#include <linux/platform_device.h> +#include <asm/cpuidle.h> + +#define ARMADA_370_XP_MAX_STATES 3 +#define ARMADA_370_XP_FLAG_DEEP_IDLE 0x10000 + +static int (*armada_370_xp_cpu_suspend)(int); + +static int armada_370_xp_enter_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int index) +{ + int ret; + bool deepidle = false; + cpu_pm_enter(); + + if (drv->states[index].flags & ARMADA_370_XP_FLAG_DEEP_IDLE) + deepidle = true; + + ret = armada_370_xp_cpu_suspend(deepidle); + if (ret) + return ret; + + cpu_pm_exit(); + + return index; +} + +static struct cpuidle_driver armada_370_xp_idle_driver = { + .name = "armada_370_xp_idle", + .states[0] = ARM_CPUIDLE_WFI_STATE, + .states[1] = { + .enter = armada_370_xp_enter_idle, + .exit_latency = 10, + .power_usage = 50, + .target_residency = 100, + .flags = CPUIDLE_FLAG_TIME_VALID, + .name = "MV CPU IDLE", + .desc = "CPU power down", + }, + .states[2] = { + .enter = armada_370_xp_enter_idle, + .exit_latency = 100, + .power_usage = 5, + .target_residency = 1000, + .flags = CPUIDLE_FLAG_TIME_VALID | + ARMADA_370_XP_FLAG_DEEP_IDLE, + .name = "MV CPU DEEP IDLE", + .desc = "CPU and L2 Fabric power down", + }, + .state_count = ARMADA_370_XP_MAX_STATES, +}; + +static int armada_370_xp_cpuidle_probe(struct platform_device *pdev) +{ + + armada_370_xp_cpu_suspend = (void *)(pdev->dev.platform_data); + return cpuidle_register(&armada_370_xp_idle_driver, NULL); +} + +static struct platform_driver armada_370_xp_cpuidle_plat_driver = { + .driver = { + .name = "cpuidle-armada-370-xp", + .owner = THIS_MODULE, + }, + .probe = armada_370_xp_cpuidle_probe, +}; + +module_platform_driver(armada_370_xp_cpuidle_plat_driver); + +MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>"); +MODULE_DESCRIPTION("Armada 370/XP cpu idle driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 89777ed..3b5bacd 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c @@ -31,7 +31,108 @@ #include <linux/iio/trigger_consumer.h> #include <linux/iio/triggered_buffer.h> -#include <mach/at91_adc.h> +/* Registers */ +#define AT91_ADC_CR 0x00 /* Control Register */ +#define AT91_ADC_SWRST (1 << 0) /* Software Reset */ +#define AT91_ADC_START (1 << 1) /* Start Conversion */ + +#define AT91_ADC_MR 0x04 /* Mode Register */ +#define AT91_ADC_TSAMOD (3 << 0) /* ADC mode */ +#define AT91_ADC_TSAMOD_ADC_ONLY_MODE (0 << 0) /* ADC Mode */ +#define AT91_ADC_TSAMOD_TS_ONLY_MODE (1 << 0) /* Touch Screen Only Mode */ +#define AT91_ADC_TRGEN (1 << 0) /* Trigger Enable */ +#define AT91_ADC_TRGSEL (7 << 1) /* Trigger Selection */ +#define AT91_ADC_TRGSEL_TC0 (0 << 1) +#define AT91_ADC_TRGSEL_TC1 (1 << 1) +#define AT91_ADC_TRGSEL_TC2 (2 << 1) +#define AT91_ADC_TRGSEL_EXTERNAL (6 << 1) +#define AT91_ADC_LOWRES (1 << 4) /* Low Resolution */ +#define AT91_ADC_SLEEP (1 << 5) /* Sleep Mode */ +#define AT91_ADC_PENDET (1 << 6) /* Pen contact detection enable */ +#define AT91_ADC_PRESCAL_9260 (0x3f << 8) /* Prescalar Rate Selection */ +#define AT91_ADC_PRESCAL_9G45 (0xff << 8) +#define AT91_ADC_PRESCAL_(x) ((x) << 8) +#define AT91_ADC_STARTUP_9260 (0x1f << 16) /* Startup Up Time */ +#define AT91_ADC_STARTUP_9G45 (0x7f << 16) +#define AT91_ADC_STARTUP_9X5 (0xf << 16) +#define AT91_ADC_STARTUP_(x) ((x) << 16) +#define AT91_ADC_SHTIM (0xf << 24) /* Sample & Hold Time */ +#define AT91_ADC_SHTIM_(x) ((x) << 24) +#define AT91_ADC_PENDBC (0x0f << 28) /* Pen Debounce time */ +#define AT91_ADC_PENDBC_(x) ((x) << 28) + +#define AT91_ADC_TSR 0x0C +#define AT91_ADC_TSR_SHTIM (0xf << 24) /* Sample & Hold Time */ +#define AT91_ADC_TSR_SHTIM_(x) ((x) << 24) + +#define AT91_ADC_CHER 0x10 /* Channel Enable Register */ +#define AT91_ADC_CHDR 0x14 /* Channel Disable Register */ +#define AT91_ADC_CHSR 0x18 /* Channel Status Register */ +#define AT91_ADC_CH(n) (1 << (n)) /* Channel Number */ + +#define AT91_ADC_SR 0x1C /* Status Register */ +#define AT91_ADC_EOC(n) (1 << (n)) /* End of Conversion on Channel N */ +#define AT91_ADC_OVRE(n) (1 << ((n) + 8))/* Overrun Error on Channel N */ +#define AT91_ADC_DRDY (1 << 16) /* Data Ready */ +#define AT91_ADC_GOVRE (1 << 17) /* General Overrun Error */ +#define AT91_ADC_ENDRX (1 << 18) /* End of RX Buffer */ +#define AT91_ADC_RXFUFF (1 << 19) /* RX Buffer Full */ + +#define AT91_ADC_SR_9X5 0x30 /* Status Register for 9x5 */ +#define AT91_ADC_SR_DRDY_9X5 (1 << 24) /* Data Ready */ + +#define AT91_ADC_LCDR 0x20 /* Last Converted Data Register */ +#define AT91_ADC_LDATA (0x3ff) + +#define AT91_ADC_IER 0x24 /* Interrupt Enable Register */ +#define AT91_ADC_IDR 0x28 /* Interrupt Disable Register */ +#define AT91_ADC_IMR 0x2C /* Interrupt Mask Register */ +#define AT91RL_ADC_IER_PEN (1 << 20) +#define AT91RL_ADC_IER_NOPEN (1 << 21) +#define AT91_ADC_IER_PEN (1 << 29) +#define AT91_ADC_IER_NOPEN (1 << 30) +#define AT91_ADC_IER_XRDY (1 << 20) +#define AT91_ADC_IER_YRDY (1 << 21) +#define AT91_ADC_IER_PRDY (1 << 22) +#define AT91_ADC_ISR_PENS (1 << 31) + +#define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */ +#define AT91_ADC_DATA (0x3ff) + +#define AT91_ADC_CDR0_9X5 (0x50) /* Channel Data Register 0 for 9X5 */ + +#define AT91_ADC_ACR 0x94 /* Analog Control Register */ +#define AT91_ADC_ACR_PENDETSENS (0x3 << 0) /* pull-up resistor */ + +#define AT91_ADC_TSMR 0xB0 +#define AT91_ADC_TSMR_TSMODE (3 << 0) /* Touch Screen Mode */ +#define AT91_ADC_TSMR_TSMODE_NONE (0 << 0) +#define AT91_ADC_TSMR_TSMODE_4WIRE_NO_PRESS (1 << 0) +#define AT91_ADC_TSMR_TSMODE_4WIRE_PRESS (2 << 0) +#define AT91_ADC_TSMR_TSMODE_5WIRE (3 << 0) +#define AT91_ADC_TSMR_TSAV (3 << 4) /* Averages samples */ +#define AT91_ADC_TSMR_TSAV_(x) ((x) << 4) +#define AT91_ADC_TSMR_SCTIM (0x0f << 16) /* Switch closure time */ +#define AT91_ADC_TSMR_PENDBC (0x0f << 28) /* Pen Debounce time */ +#define AT91_ADC_TSMR_PENDBC_(x) ((x) << 28) +#define AT91_ADC_TSMR_NOTSDMA (1 << 22) /* No Touchscreen DMA */ +#define AT91_ADC_TSMR_PENDET_DIS (0 << 24) /* Pen contact detection disable */ +#define AT91_ADC_TSMR_PENDET_ENA (1 << 24) /* Pen contact detection enable */ + +#define AT91_ADC_TSXPOSR 0xB4 +#define AT91_ADC_TSYPOSR 0xB8 +#define AT91_ADC_TSPRESSR 0xBC + +#define AT91_ADC_TRGR_9260 AT91_ADC_MR +#define AT91_ADC_TRGR_9G45 0x08 +#define AT91_ADC_TRGR_9X5 0xC0 + +/* Trigger Register bit field */ +#define AT91_ADC_TRGR_TRGPER (0xffff << 16) +#define AT91_ADC_TRGR_TRGPER_(x) ((x) << 16) +#define AT91_ADC_TRGR_TRGMOD (0x7 << 0) +#define AT91_ADC_TRGR_NONE (0 << 0) +#define AT91_ADC_TRGR_MOD_PERIOD_TRIG (5 << 0) #define AT91_ADC_CHAN(st, ch) \ (st->registers->channel_base + (ch * 4)) @@ -46,6 +147,29 @@ #define TOUCH_SAMPLE_PERIOD_US 2000 /* 2ms */ #define TOUCH_PEN_DETECT_DEBOUNCE_US 200 +#define MAX_RLPOS_BITS 10 +#define TOUCH_SAMPLE_PERIOD_US_RL 10000 /* 10ms, the SoC can't keep up with 2ms */ +#define TOUCH_SHTIM 0xa + +/** + * struct at91_adc_reg_desc - Various informations relative to registers + * @channel_base: Base offset for the channel data registers + * @drdy_mask: Mask of the DRDY field in the relevant registers + (Interruptions registers mostly) + * @status_register: Offset of the Interrupt Status Register + * @trigger_register: Offset of the Trigger setup register + * @mr_prescal_mask: Mask of the PRESCAL field in the adc MR register + * @mr_startup_mask: Mask of the STARTUP field in the adc MR register + */ +struct at91_adc_reg_desc { + u8 channel_base; + u32 drdy_mask; + u8 status_register; + u8 trigger_register; + u32 mr_prescal_mask; + u32 mr_startup_mask; +}; + struct at91_adc_caps { bool has_ts; /* Support touch screen */ bool has_tsmr; /* only at91sam9x5, sama5d3 have TSMR reg */ @@ -64,12 +188,6 @@ struct at91_adc_caps { struct at91_adc_reg_desc registers; }; -enum atmel_adc_ts_type { - ATMEL_ADC_TOUCHSCREEN_NONE = 0, - ATMEL_ADC_TOUCHSCREEN_4WIRE = 4, - ATMEL_ADC_TOUCHSCREEN_5WIRE = 5, -}; - struct at91_adc_state { struct clk *adc_clk; u16 *buffer; @@ -114,6 +232,11 @@ struct at91_adc_state { u16 ts_sample_period_val; u32 ts_pressure_threshold; + u16 ts_pendbc; + + bool ts_bufferedmeasure; + u32 ts_prev_absx; + u32 ts_prev_absy; }; static irqreturn_t at91_adc_trigger_handler(int irq, void *p) @@ -220,7 +343,72 @@ static int at91_ts_sample(struct at91_adc_state *st) return 0; } -static irqreturn_t at91_adc_interrupt(int irq, void *private) +static irqreturn_t at91_adc_rl_interrupt(int irq, void *private) +{ + struct iio_dev *idev = private; + struct at91_adc_state *st = iio_priv(idev); + u32 status = at91_adc_readl(st, st->registers->status_register); + unsigned int reg; + + status &= at91_adc_readl(st, AT91_ADC_IMR); + if (status & st->registers->drdy_mask) + handle_adc_eoc_trigger(irq, idev); + + if (status & AT91RL_ADC_IER_PEN) { + /* Disabling pen debounce is required to get a NOPEN irq */ + reg = at91_adc_readl(st, AT91_ADC_MR); + reg &= ~AT91_ADC_PENDBC; + at91_adc_writel(st, AT91_ADC_MR, reg); + + at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN); + at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_NOPEN + | AT91_ADC_EOC(3)); + /* Set up period trigger for sampling */ + at91_adc_writel(st, st->registers->trigger_register, + AT91_ADC_TRGR_MOD_PERIOD_TRIG | + AT91_ADC_TRGR_TRGPER_(st->ts_sample_period_val)); + } else if (status & AT91RL_ADC_IER_NOPEN) { + reg = at91_adc_readl(st, AT91_ADC_MR); + reg |= AT91_ADC_PENDBC_(st->ts_pendbc) & AT91_ADC_PENDBC; + at91_adc_writel(st, AT91_ADC_MR, reg); + at91_adc_writel(st, st->registers->trigger_register, + AT91_ADC_TRGR_NONE); + + at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_NOPEN + | AT91_ADC_EOC(3)); + at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_PEN); + st->ts_bufferedmeasure = false; + input_report_key(st->ts_input, BTN_TOUCH, 0); + input_sync(st->ts_input); + } else if (status & AT91_ADC_EOC(3)) { + /* Conversion finished */ + if (st->ts_bufferedmeasure) { + /* + * Last measurement is always discarded, since it can + * be erroneous. + * Always report previous measurement + */ + input_report_abs(st->ts_input, ABS_X, st->ts_prev_absx); + input_report_abs(st->ts_input, ABS_Y, st->ts_prev_absy); + input_report_key(st->ts_input, BTN_TOUCH, 1); + input_sync(st->ts_input); + } else + st->ts_bufferedmeasure = true; + + /* Now make new measurement */ + st->ts_prev_absx = at91_adc_readl(st, AT91_ADC_CHAN(st, 3)) + << MAX_RLPOS_BITS; + st->ts_prev_absx /= at91_adc_readl(st, AT91_ADC_CHAN(st, 2)); + + st->ts_prev_absy = at91_adc_readl(st, AT91_ADC_CHAN(st, 1)) + << MAX_RLPOS_BITS; + st->ts_prev_absy /= at91_adc_readl(st, AT91_ADC_CHAN(st, 0)); + } + + return IRQ_HANDLED; +} + +static irqreturn_t at91_adc_9x5_interrupt(int irq, void *private) { struct iio_dev *idev = private; struct at91_adc_state *st = iio_priv(idev); @@ -653,6 +841,8 @@ static int at91_adc_probe_dt_ts(struct device_node *node, return -EINVAL; } + if (!st->caps->has_tsmr) + return 0; prop = 0; of_property_read_u32(node, "atmel,adc-ts-pressure-threshold", &prop); st->ts_pressure_threshold = prop; @@ -776,6 +966,7 @@ static int at91_adc_probe_pdata(struct at91_adc_state *st, st->trigger_number = pdata->trigger_number; st->trigger_list = pdata->trigger_list; st->registers = &st->caps->registers; + st->touchscreen_type = pdata->touchscreen_type; return 0; } @@ -790,7 +981,10 @@ static int atmel_ts_open(struct input_dev *dev) { struct at91_adc_state *st = input_get_drvdata(dev); - at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN); + if (st->caps->has_tsmr) + at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN); + else + at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_PEN); return 0; } @@ -798,45 +992,61 @@ static void atmel_ts_close(struct input_dev *dev) { struct at91_adc_state *st = input_get_drvdata(dev); - at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN); + if (st->caps->has_tsmr) + at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN); + else + at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN); } static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) { - u32 reg = 0, pendbc; + u32 reg = 0; int i = 0; - if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE) - reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS; - else - reg = AT91_ADC_TSMR_TSMODE_5WIRE; - /* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid * pen detect noise. * The formula is : Pen Detect Debounce Time = (2 ^ pendbc) / ADCClock */ - pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz / 1000, 1); + st->ts_pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz / + 1000, 1); - while (pendbc >> ++i) + while (st->ts_pendbc >> ++i) ; /* Empty! Find the shift offset */ - if (abs(pendbc - (1 << i)) < abs(pendbc - (1 << (i - 1)))) - pendbc = i; + if (abs(st->ts_pendbc - (1 << i)) < abs(st->ts_pendbc - (1 << (i - 1)))) + st->ts_pendbc = i; else - pendbc = i - 1; + st->ts_pendbc = i - 1; - if (st->caps->has_tsmr) { - reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average) - & AT91_ADC_TSMR_TSAV; - reg |= AT91_ADC_TSMR_PENDBC_(pendbc) & AT91_ADC_TSMR_PENDBC; - reg |= AT91_ADC_TSMR_NOTSDMA; - reg |= AT91_ADC_TSMR_PENDET_ENA; - reg |= 0x03 << 8; /* TSFREQ, need bigger than TSAV */ - - at91_adc_writel(st, AT91_ADC_TSMR, reg); - } else { - /* TODO: for 9g45 which has no TSMR */ + if (!st->caps->has_tsmr) { + reg = at91_adc_readl(st, AT91_ADC_MR); + reg |= AT91_ADC_TSAMOD_TS_ONLY_MODE | AT91_ADC_PENDET; + + reg |= AT91_ADC_PENDBC_(st->ts_pendbc) & AT91_ADC_PENDBC; + at91_adc_writel(st, AT91_ADC_MR, reg); + + reg = AT91_ADC_TSR_SHTIM_(TOUCH_SHTIM) & AT91_ADC_TSR_SHTIM; + at91_adc_writel(st, AT91_ADC_TSR, reg); + + st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US_RL * + adc_clk_khz / 1000) - 1, 1); + + return 0; } + if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE) + reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS; + else + reg = AT91_ADC_TSMR_TSMODE_5WIRE; + + reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average) + & AT91_ADC_TSMR_TSAV; + reg |= AT91_ADC_TSMR_PENDBC_(st->ts_pendbc) & AT91_ADC_TSMR_PENDBC; + reg |= AT91_ADC_TSMR_NOTSDMA; + reg |= AT91_ADC_TSMR_PENDET_ENA; + reg |= 0x03 << 8; /* TSFREQ, needs to be bigger than TSAV */ + + at91_adc_writel(st, AT91_ADC_TSMR, reg); + /* Change adc internal resistor value for better pen detection, * default value is 100 kOhm. * 0 = 200 kOhm, 1 = 150 kOhm, 2 = 100 kOhm, 3 = 50 kOhm @@ -845,7 +1055,7 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz) at91_adc_writel(st, AT91_ADC_ACR, st->caps->ts_pen_detect_sensitivity & AT91_ADC_ACR_PENDETSENS); - /* Sample Peroid Time = (TRGPER + 1) / ADCClock */ + /* Sample Period Time = (TRGPER + 1) / ADCClock */ st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US * adc_clk_khz / 1000) - 1, 1); @@ -874,18 +1084,38 @@ static int at91_ts_register(struct at91_adc_state *st, __set_bit(EV_ABS, input->evbit); __set_bit(EV_KEY, input->evbit); __set_bit(BTN_TOUCH, input->keybit); - input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1, 0, 0); - input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1, 0, 0); - input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0); + if (st->caps->has_tsmr) { + input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1, + 0, 0); + input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1, + 0, 0); + input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0); + } else { + if (st->touchscreen_type != ATMEL_ADC_TOUCHSCREEN_4WIRE) { + dev_err(&pdev->dev, + "This touchscreen controller only support 4 wires\n"); + ret = -EINVAL; + goto err; + } + + input_set_abs_params(input, ABS_X, 0, (1 << MAX_RLPOS_BITS) - 1, + 0, 0); + input_set_abs_params(input, ABS_Y, 0, (1 << MAX_RLPOS_BITS) - 1, + 0, 0); + } st->ts_input = input; input_set_drvdata(input, st); ret = input_register_device(input); if (ret) - input_free_device(st->ts_input); + goto err; return ret; + +err: + input_free_device(st->ts_input); + return ret; } static void at91_ts_unregister(struct at91_adc_state *st) @@ -943,11 +1173,13 @@ static int at91_adc_probe(struct platform_device *pdev) */ at91_adc_writel(st, AT91_ADC_CR, AT91_ADC_SWRST); at91_adc_writel(st, AT91_ADC_IDR, 0xFFFFFFFF); - ret = request_irq(st->irq, - at91_adc_interrupt, - 0, - pdev->dev.driver->name, - idev); + + if (st->caps->has_tsmr) + ret = request_irq(st->irq, at91_adc_9x5_interrupt, 0, + pdev->dev.driver->name, idev); + else + ret = request_irq(st->irq, at91_adc_rl_interrupt, 0, + pdev->dev.driver->name, idev); if (ret) { dev_err(&pdev->dev, "Failed to allocate IRQ.\n"); return ret; @@ -1051,12 +1283,6 @@ static int at91_adc_probe(struct platform_device *pdev) goto error_disable_adc_clk; } } else { - if (!st->caps->has_tsmr) { - dev_err(&pdev->dev, "We don't support non-TSMR adc\n"); - ret = -ENODEV; - goto error_disable_adc_clk; - } - ret = at91_ts_register(st, pdev); if (ret) goto error_disable_adc_clk; @@ -1120,6 +1346,20 @@ static struct at91_adc_caps at91sam9260_caps = { }, }; +static struct at91_adc_caps at91sam9rl_caps = { + .has_ts = true, + .calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */ + .num_channels = 6, + .registers = { + .channel_base = AT91_ADC_CHR(0), + .drdy_mask = AT91_ADC_DRDY, + .status_register = AT91_ADC_SR, + .trigger_register = AT91_ADC_TRGR_9G45, + .mr_prescal_mask = AT91_ADC_PRESCAL_9260, + .mr_startup_mask = AT91_ADC_STARTUP_9G45, + }, +}; + static struct at91_adc_caps at91sam9g45_caps = { .has_ts = true, .calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */ @@ -1154,6 +1394,7 @@ static struct at91_adc_caps at91sam9x5_caps = { static const struct of_device_id at91_adc_dt_ids[] = { { .compatible = "atmel,at91sam9260-adc", .data = &at91sam9260_caps }, + { .compatible = "atmel,at91sam9rl-adc", .data = &at91sam9rl_caps }, { .compatible = "atmel,at91sam9g45-adc", .data = &at91sam9g45_caps }, { .compatible = "atmel,at91sam9x5-adc", .data = &at91sam9x5_caps }, {}, @@ -1165,6 +1406,9 @@ static const struct platform_device_id at91_adc_ids[] = { .name = "at91sam9260-adc", .driver_data = (unsigned long)&at91sam9260_caps, }, { + .name = "at91sam9rl-adc", + .driver_data = (unsigned long)&at91sam9rl_caps, + }, { .name = "at91sam9g45-adc", .driver_data = (unsigned long)&at91sam9g45_caps, }, { diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index b845e93..d4e5ab5 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -550,18 +550,6 @@ config TOUCHSCREEN_TI_AM335X_TSC To compile this driver as a module, choose M here: the module will be called ti_am335x_tsc. -config TOUCHSCREEN_ATMEL_TSADCC - tristate "Atmel Touchscreen Interface" - depends on ARCH_AT91 - help - Say Y here if you have a 4-wire touchscreen connected to the - ADC Controller on your Atmel SoC. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called atmel_tsadcc. - config TOUCHSCREEN_UCB1400 tristate "Philips UCB1400 touchscreen" depends on AC97_BUS diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 4bc954b..03f12a1 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -13,7 +13,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C) += ad7879-i2c.o obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI) += ad7879-spi.o obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT) += atmel_mxt_ts.o -obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR) += auo-pixcir-ts.o obj-$(CONFIG_TOUCHSCREEN_BU21013) += bu21013_ts.o obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110) += cy8ctmg110_ts.o diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c deleted file mode 100644 index a7c9d69..0000000 --- a/drivers/input/touchscreen/atmel_tsadcc.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Atmel Touch Screen Driver - * - * Copyright (c) 2008 ATMEL - * Copyright (c) 2008 Dan Liang - * Copyright (c) 2008 TimeSys Corporation - * Copyright (c) 2008 Justin Waters - * - * Based on touchscreen code from Atmel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/err.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/input.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/platform_data/atmel.h> -#include <mach/cpu.h> - -/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */ - -#define ATMEL_TSADCC_CR 0x00 /* Control register */ -#define ATMEL_TSADCC_SWRST (1 << 0) /* Software Reset*/ -#define ATMEL_TSADCC_START (1 << 1) /* Start conversion */ - -#define ATMEL_TSADCC_MR 0x04 /* Mode register */ -#define ATMEL_TSADCC_TSAMOD (3 << 0) /* ADC mode */ -#define ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE (0x0) /* ADC Mode */ -#define ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE (0x1) /* Touch Screen Only Mode */ -#define ATMEL_TSADCC_LOWRES (1 << 4) /* Resolution selection */ -#define ATMEL_TSADCC_SLEEP (1 << 5) /* Sleep mode */ -#define ATMEL_TSADCC_PENDET (1 << 6) /* Pen Detect selection */ -#define ATMEL_TSADCC_PRES (1 << 7) /* Pressure Measurement Selection */ -#define ATMEL_TSADCC_PRESCAL (0x3f << 8) /* Prescalar Rate Selection */ -#define ATMEL_TSADCC_EPRESCAL (0xff << 8) /* Prescalar Rate Selection (Extended) */ -#define ATMEL_TSADCC_STARTUP (0x7f << 16) /* Start Up time */ -#define ATMEL_TSADCC_SHTIM (0xf << 24) /* Sample & Hold time */ -#define ATMEL_TSADCC_PENDBC (0xf << 28) /* Pen Detect debouncing time */ - -#define ATMEL_TSADCC_TRGR 0x08 /* Trigger register */ -#define ATMEL_TSADCC_TRGMOD (7 << 0) /* Trigger mode */ -#define ATMEL_TSADCC_TRGMOD_NONE (0 << 0) -#define ATMEL_TSADCC_TRGMOD_EXT_RISING (1 << 0) -#define ATMEL_TSADCC_TRGMOD_EXT_FALLING (2 << 0) -#define ATMEL_TSADCC_TRGMOD_EXT_ANY (3 << 0) -#define ATMEL_TSADCC_TRGMOD_PENDET (4 << 0) -#define ATMEL_TSADCC_TRGMOD_PERIOD (5 << 0) -#define ATMEL_TSADCC_TRGMOD_CONTINUOUS (6 << 0) -#define ATMEL_TSADCC_TRGPER (0xffff << 16) /* Trigger period */ - -#define ATMEL_TSADCC_TSR 0x0C /* Touch Screen register */ -#define ATMEL_TSADCC_TSFREQ (0xf << 0) /* TS Frequency in Interleaved mode */ -#define ATMEL_TSADCC_TSSHTIM (0xf << 24) /* Sample & Hold time */ - -#define ATMEL_TSADCC_CHER 0x10 /* Channel Enable register */ -#define ATMEL_TSADCC_CHDR 0x14 /* Channel Disable register */ -#define ATMEL_TSADCC_CHSR 0x18 /* Channel Status register */ -#define ATMEL_TSADCC_CH(n) (1 << (n)) /* Channel number */ - -#define ATMEL_TSADCC_SR 0x1C /* Status register */ -#define ATMEL_TSADCC_EOC(n) (1 << ((n)+0)) /* End of conversion for channel N */ -#define ATMEL_TSADCC_OVRE(n) (1 << ((n)+8)) /* Overrun error for channel N */ -#define ATMEL_TSADCC_DRDY (1 << 16) /* Data Ready */ -#define ATMEL_TSADCC_GOVRE (1 << 17) /* General Overrun Error */ -#define ATMEL_TSADCC_ENDRX (1 << 18) /* End of RX Buffer */ -#define ATMEL_TSADCC_RXBUFF (1 << 19) /* TX Buffer full */ -#define ATMEL_TSADCC_PENCNT (1 << 20) /* Pen contact */ -#define ATMEL_TSADCC_NOCNT (1 << 21) /* No contact */ - -#define ATMEL_TSADCC_LCDR 0x20 /* Last Converted Data register */ -#define ATMEL_TSADCC_DATA (0x3ff << 0) /* Channel data */ - -#define ATMEL_TSADCC_IER 0x24 /* Interrupt Enable register */ -#define ATMEL_TSADCC_IDR 0x28 /* Interrupt Disable register */ -#define ATMEL_TSADCC_IMR 0x2C /* Interrupt Mask register */ -#define ATMEL_TSADCC_CDR0 0x30 /* Channel Data 0 */ -#define ATMEL_TSADCC_CDR1 0x34 /* Channel Data 1 */ -#define ATMEL_TSADCC_CDR2 0x38 /* Channel Data 2 */ -#define ATMEL_TSADCC_CDR3 0x3C /* Channel Data 3 */ -#define ATMEL_TSADCC_CDR4 0x40 /* Channel Data 4 */ -#define ATMEL_TSADCC_CDR5 0x44 /* Channel Data 5 */ - -#define ATMEL_TSADCC_XPOS 0x50 -#define ATMEL_TSADCC_Z1DAT 0x54 -#define ATMEL_TSADCC_Z2DAT 0x58 - -#define PRESCALER_VAL(x) ((x) >> 8) - -#define ADC_DEFAULT_CLOCK 100000 - -struct atmel_tsadcc { - struct input_dev *input; - char phys[32]; - struct clk *clk; - int irq; - unsigned int prev_absx; - unsigned int prev_absy; - unsigned char bufferedmeasure; -}; - -static void __iomem *tsc_base; - -#define atmel_tsadcc_read(reg) __raw_readl(tsc_base + (reg)) -#define atmel_tsadcc_write(reg, val) __raw_writel((val), tsc_base + (reg)) - -static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev) -{ - struct atmel_tsadcc *ts_dev = (struct atmel_tsadcc *)dev; - struct input_dev *input_dev = ts_dev->input; - - unsigned int status; - unsigned int reg; - - status = atmel_tsadcc_read(ATMEL_TSADCC_SR); - status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR); - - if (status & ATMEL_TSADCC_NOCNT) { - /* Contact lost */ - reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC; - - atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); - atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); - atmel_tsadcc_write(ATMEL_TSADCC_IDR, - ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT); - atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); - - input_report_key(input_dev, BTN_TOUCH, 0); - ts_dev->bufferedmeasure = 0; - input_sync(input_dev); - - } else if (status & ATMEL_TSADCC_PENCNT) { - /* Pen detected */ - reg = atmel_tsadcc_read(ATMEL_TSADCC_MR); - reg &= ~ATMEL_TSADCC_PENDBC; - - atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT); - atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); - atmel_tsadcc_write(ATMEL_TSADCC_IER, - ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT); - atmel_tsadcc_write(ATMEL_TSADCC_TRGR, - ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16)); - - } else if (status & ATMEL_TSADCC_EOC(3)) { - /* Conversion finished */ - - if (ts_dev->bufferedmeasure) { - /* Last measurement is always discarded, since it can - * be erroneous. - * Always report previous measurement */ - input_report_abs(input_dev, ABS_X, ts_dev->prev_absx); - input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy); - input_report_key(input_dev, BTN_TOUCH, 1); - input_sync(input_dev); - } else - ts_dev->bufferedmeasure = 1; - - /* Now make new measurement */ - ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10; - ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2); - - ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10; - ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0); - } - - return IRQ_HANDLED; -} - -/* - * The functions for inserting/removing us as a module. - */ - -static int atmel_tsadcc_probe(struct platform_device *pdev) -{ - struct atmel_tsadcc *ts_dev; - struct input_dev *input_dev; - struct resource *res; - struct at91_tsadcc_data *pdata = dev_get_platdata(&pdev->dev); - int err; - unsigned int prsc; - unsigned int reg; - - if (!pdata) - return -EINVAL; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mmio resource defined.\n"); - return -ENXIO; - } - - /* Allocate memory for device */ - ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL); - if (!ts_dev) { - dev_err(&pdev->dev, "failed to allocate memory.\n"); - return -ENOMEM; - } - platform_set_drvdata(pdev, ts_dev); - - input_dev = input_allocate_device(); - if (!input_dev) { - dev_err(&pdev->dev, "failed to allocate input device.\n"); - err = -EBUSY; - goto err_free_mem; - } - - ts_dev->irq = platform_get_irq(pdev, 0); - if (ts_dev->irq < 0) { - dev_err(&pdev->dev, "no irq ID is designated.\n"); - err = -ENODEV; - goto err_free_dev; - } - - if (!request_mem_region(res->start, resource_size(res), - "atmel tsadcc regs")) { - dev_err(&pdev->dev, "resources is unavailable.\n"); - err = -EBUSY; - goto err_free_dev; - } - - tsc_base = ioremap(res->start, resource_size(res)); - if (!tsc_base) { - dev_err(&pdev->dev, "failed to map registers.\n"); - err = -ENOMEM; - goto err_release_mem; - } - - err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0, - pdev->dev.driver->name, ts_dev); - if (err) { - dev_err(&pdev->dev, "failed to allocate irq.\n"); - goto err_unmap_regs; - } - - ts_dev->clk = clk_get(&pdev->dev, "tsc_clk"); - if (IS_ERR(ts_dev->clk)) { - dev_err(&pdev->dev, "failed to get ts_clk\n"); - err = PTR_ERR(ts_dev->clk); - goto err_free_irq; - } - - ts_dev->input = input_dev; - ts_dev->bufferedmeasure = 0; - - snprintf(ts_dev->phys, sizeof(ts_dev->phys), - "%s/input0", dev_name(&pdev->dev)); - - input_dev->name = "atmel touch screen controller"; - input_dev->phys = ts_dev->phys; - input_dev->dev.parent = &pdev->dev; - - __set_bit(EV_ABS, input_dev->evbit); - input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0); - - input_set_capability(input_dev, EV_KEY, BTN_TOUCH); - - /* clk_enable() always returns 0, no need to check it */ - clk_enable(ts_dev->clk); - - prsc = clk_get_rate(ts_dev->clk); - dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc); - - if (!pdata->adc_clock) - pdata->adc_clock = ADC_DEFAULT_CLOCK; - - prsc = (prsc / (2 * pdata->adc_clock)) - 1; - - /* saturate if this value is too high */ - if (cpu_is_at91sam9rl()) { - if (prsc > PRESCALER_VAL(ATMEL_TSADCC_PRESCAL)) - prsc = PRESCALER_VAL(ATMEL_TSADCC_PRESCAL); - } else { - if (prsc > PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL)) - prsc = PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL); - } - - dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc); - - reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE | - ((0x00 << 5) & ATMEL_TSADCC_SLEEP) | /* Normal Mode */ - ((0x01 << 6) & ATMEL_TSADCC_PENDET) | /* Enable Pen Detect */ - (prsc << 8) | - ((0x26 << 16) & ATMEL_TSADCC_STARTUP) | - ((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC); - - atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST); - atmel_tsadcc_write(ATMEL_TSADCC_MR, reg); - atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE); - atmel_tsadcc_write(ATMEL_TSADCC_TSR, - (pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM); - - atmel_tsadcc_read(ATMEL_TSADCC_SR); - atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT); - - /* All went ok, so register to the input system */ - err = input_register_device(input_dev); - if (err) - goto err_fail; - - return 0; - -err_fail: - clk_disable(ts_dev->clk); - clk_put(ts_dev->clk); -err_free_irq: - free_irq(ts_dev->irq, ts_dev); -err_unmap_regs: - iounmap(tsc_base); -err_release_mem: - release_mem_region(res->start, resource_size(res)); -err_free_dev: - input_free_device(input_dev); -err_free_mem: - kfree(ts_dev); - return err; -} - -static int atmel_tsadcc_remove(struct platform_device *pdev) -{ - struct atmel_tsadcc *ts_dev = platform_get_drvdata(pdev); - struct resource *res; - - free_irq(ts_dev->irq, ts_dev); - - input_unregister_device(ts_dev->input); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(tsc_base); - release_mem_region(res->start, resource_size(res)); - - clk_disable(ts_dev->clk); - clk_put(ts_dev->clk); - - kfree(ts_dev); - - return 0; -} - -static struct platform_driver atmel_tsadcc_driver = { - .probe = atmel_tsadcc_probe, - .remove = atmel_tsadcc_remove, - .driver = { - .name = "atmel_tsadcc", - }, -}; -module_platform_driver(atmel_tsadcc_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atmel TouchScreen Driver"); -MODULE_AUTHOR("Dan Liang <dan.liang@atmel.com>"); - diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c index 3899ba7..c887e6e 100644 --- a/drivers/irqchip/irq-armada-370-xp.c +++ b/drivers/irqchip/irq-armada-370-xp.c @@ -19,6 +19,7 @@ #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/irqchip/chained_irq.h> +#include <linux/cpu.h> #include <linux/io.h> #include <linux/of_address.h> #include <linux/of_irq.h> @@ -310,7 +311,8 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h, } #ifdef CONFIG_SMP -void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq) +static void armada_mpic_send_doorbell(const struct cpumask *mask, + unsigned int irq) { int cpu; unsigned long map = 0; @@ -330,7 +332,7 @@ void armada_mpic_send_doorbell(const struct cpumask *mask, unsigned int irq) ARMADA_370_XP_SW_TRIG_INT_OFFS); } -void armada_xp_mpic_smp_cpu_init(void) +static void armada_xp_mpic_smp_cpu_init(void) { /* Clear pending IPIs */ writel(0, per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS); @@ -342,6 +344,20 @@ void armada_xp_mpic_smp_cpu_init(void) /* Unmask IPI interrupt */ writel(0, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); } + +static int armada_xp_mpic_secondary_init(struct notifier_block *nfb, + unsigned long action, void *hcpu) +{ + if (action == CPU_STARTING || action == CPU_STARTING_FROZEN) + armada_xp_mpic_smp_cpu_init(); + return NOTIFY_OK; +} + +static struct notifier_block armada_370_xp_mpic_cpu_notifier = { + .notifier_call = armada_xp_mpic_secondary_init, + .priority = 100, +}; + #endif /* CONFIG_SMP */ static struct irq_domain_ops armada_370_xp_mpic_irq_ops = { @@ -497,6 +513,10 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node, if (parent_irq <= 0) { irq_set_default_host(armada_370_xp_mpic_domain); set_handle_irq(armada_370_xp_handle_irq); +#ifdef CONFIG_SMP + set_smp_cross_call(armada_mpic_send_doorbell); + register_cpu_notifier(&armada_370_xp_mpic_cpu_notifier); +#endif } else { irq_set_chained_handler(parent_irq, armada_370_xp_mpic_handle_cascade_irq); diff --git a/drivers/irqchip/irq-orion.c b/drivers/irqchip/irq-orion.c index e25f246..34d18b4 100644 --- a/drivers/irqchip/irq-orion.c +++ b/drivers/irqchip/irq-orion.c @@ -42,7 +42,7 @@ __exception_irq_entry orion_handle_irq(struct pt_regs *regs) u32 stat = readl_relaxed(gc->reg_base + ORION_IRQ_CAUSE) & gc->mask_cache; while (stat) { - u32 hwirq = ffs(stat) - 1; + u32 hwirq = __fls(stat); u32 irq = irq_find_mapping(orion_irq_domain, gc->irq_base + hwirq); handle_IRQ(irq, regs); @@ -117,7 +117,7 @@ static void orion_bridge_irq_handler(unsigned int irq, struct irq_desc *desc) gc->mask_cache; while (stat) { - u32 hwirq = ffs(stat) - 1; + u32 hwirq = __fls(stat); generic_handle_irq(irq_find_mapping(d, gc->irq_base + hwirq)); stat &= ~(1 << hwirq); diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index e87140b..db11b4f 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -98,7 +98,11 @@ #define TWL4030_BASEADD_BACKUP 0x0014 #define TWL4030_BASEADD_INT 0x002E #define TWL4030_BASEADD_PM_MASTER 0x0036 + #define TWL4030_BASEADD_PM_RECEIVER 0x005B +#define TWL4030_DCDC_GLOBAL_CFG 0x06 +#define SMARTREFLEX_ENABLE BIT(3) + #define TWL4030_BASEADD_RTC 0x001C #define TWL4030_BASEADD_SECURED_REG 0x0000 @@ -1204,6 +1208,11 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface. * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0, * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0. + * + * Also, always enable SmartReflex bit as that's needed for omaps to + * to do anything over I2C4 for voltage scaling even if SmartReflex + * is disabled. Without the SmartReflex bit omap sys_clkreq idle + * signal will never trigger for retention idle. */ if (twl_class_is_4030()) { u8 temp; @@ -1212,6 +1221,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \ I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU); twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); + + twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp, + TWL4030_DCDC_GLOBAL_CFG); + temp |= SMARTREFLEX_ENABLE; + twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp, + TWL4030_DCDC_GLOBAL_CFG); } if (node) { diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig index fa0e4e0..49b46e6 100644 --- a/drivers/power/reset/Kconfig +++ b/drivers/power/reset/Kconfig @@ -12,6 +12,14 @@ config POWER_RESET_AS3722 help This driver supports turning off board via a ams AS3722 power-off. +config POWER_RESET_AXXIA + bool "LSI Axxia reset driver" + depends on POWER_RESET && ARCH_AXXIA + help + This driver supports restart for Axxia SoC. + + Say Y if you have an Axxia family SoC. + config POWER_RESET_GPIO bool "GPIO power-off driver" depends on OF_GPIO && POWER_RESET diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile index a5b4a77..16c0516 100644 --- a/drivers/power/reset/Makefile +++ b/drivers/power/reset/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_POWER_RESET_AS3722) += as3722-poweroff.o +obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o diff --git a/drivers/power/reset/axxia-reset.c b/drivers/power/reset/axxia-reset.c new file mode 100644 index 0000000..3b1f8d6 --- /dev/null +++ b/drivers/power/reset/axxia-reset.c @@ -0,0 +1,88 @@ +/* + * Reset driver for Axxia devices + * + * Copyright (C) 2014 LSI + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <linux/init.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/reboot.h> +#include <linux/regmap.h> + +#include <asm/system_misc.h> + + +#define SC_CRIT_WRITE_KEY 0x1000 +#define SC_LATCH_ON_RESET 0x1004 +#define SC_RESET_CONTROL 0x1008 +#define RSTCTL_RST_ZERO (1<<3) +#define RSTCTL_RST_FAB (1<<2) +#define RSTCTL_RST_CHIP (1<<1) +#define RSTCTL_RST_SYS (1<<0) +#define SC_EFUSE_INT_STATUS 0x180c +#define EFUSE_READ_DONE (1<<31) + +static struct regmap *syscon; + +static void do_axxia_restart(enum reboot_mode reboot_mode, const char *cmd) +{ + /* Access Key (0xab) */ + regmap_write(syscon, SC_CRIT_WRITE_KEY, 0xab); + /* Select internal boot from 0xffff0000 */ + regmap_write(syscon, SC_LATCH_ON_RESET, 0x00000040); + /* Assert ResetReadDone (to avoid hanging in boot ROM) */ + regmap_write(syscon, SC_EFUSE_INT_STATUS, EFUSE_READ_DONE); + /* Assert chip reset */ + regmap_update_bits(syscon, SC_RESET_CONTROL, + RSTCTL_RST_CHIP, RSTCTL_RST_CHIP); +} + +static int axxia_reset_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + + syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon"); + if (IS_ERR(syscon)) { + pr_err("%s: syscon lookup failed\n", dev->of_node->name); + return PTR_ERR(syscon); + } + + arm_pm_restart = do_axxia_restart; + + return 0; +} + +static const struct of_device_id of_axxia_reset_match[] = { + { .compatible = "lsi,axm55xx-reset", }, + {}, +}; +MODULE_DEVICE_TABLE(of, of_axxia_reset_match); + +static struct platform_driver axxia_reset_driver = { + .probe = axxia_reset_probe, + .driver = { + .name = "axxia-reset", + .of_match_table = of_match_ptr(of_axxia_reset_match), + }, +}; + +static int __init axxia_reset_init(void) +{ + return platform_driver_register(&axxia_reset_driver); +} +device_initcall(axxia_reset_init); |