Path: blob/master/arch/sh/kernel/cpu/sh4a/clock-sh7722.c
26498 views
// SPDX-License-Identifier: GPL-2.01/*2* arch/sh/kernel/cpu/sh4a/clock-sh7722.c3*4* SH7722 clock framework support5*6* Copyright (C) 2009 Magnus Damm7*/8#include <linux/init.h>9#include <linux/kernel.h>10#include <linux/io.h>11#include <linux/clkdev.h>12#include <linux/sh_clk.h>13#include <asm/clock.h>14#include <cpu/sh7722.h>1516/* SH7722 registers */17#define FRQCR 0xa415000018#define VCLKCR 0xa415000419#define SCLKACR 0xa415000820#define SCLKBCR 0xa415000c21#define IRDACLKCR 0xa415001822#define PLLCR 0xa415002423#define MSTPCR0 0xa415003024#define MSTPCR1 0xa415003425#define MSTPCR2 0xa415003826#define DLLFRQ 0xa41500502728/* Fixed 32 KHz root clock for RTC and Power Management purposes */29static struct clk r_clk = {30.rate = 32768,31};3233/*34* Default rate for the root input clock, reset this with clk_set_rate()35* from the platform code.36*/37struct clk extal_clk = {38.rate = 33333333,39};4041/* The dll block multiplies the 32khz r_clk, may be used instead of extal */42static unsigned long dll_recalc(struct clk *clk)43{44unsigned long mult;4546if (__raw_readl(PLLCR) & 0x1000)47mult = __raw_readl(DLLFRQ);48else49mult = 0;5051return clk->parent->rate * mult;52}5354static struct sh_clk_ops dll_clk_ops = {55.recalc = dll_recalc,56};5758static struct clk dll_clk = {59.ops = &dll_clk_ops,60.parent = &r_clk,61.flags = CLK_ENABLE_ON_INIT,62};6364static unsigned long pll_recalc(struct clk *clk)65{66unsigned long mult = 1;67unsigned long div = 1;6869if (__raw_readl(PLLCR) & 0x4000)70mult = (((__raw_readl(FRQCR) >> 24) & 0x1f) + 1);71else72div = 2;7374return (clk->parent->rate * mult) / div;75}7677static struct sh_clk_ops pll_clk_ops = {78.recalc = pll_recalc,79};8081static struct clk pll_clk = {82.ops = &pll_clk_ops,83.flags = CLK_ENABLE_ON_INIT,84};8586struct clk *main_clks[] = {87&r_clk,88&extal_clk,89&dll_clk,90&pll_clk,91};9293static int multipliers[] = { 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };94static int divisors[] = { 1, 3, 2, 5, 3, 4, 5, 6, 8, 10, 12, 16, 20 };9596static struct clk_div_mult_table div4_div_mult_table = {97.divisors = divisors,98.nr_divisors = ARRAY_SIZE(divisors),99.multipliers = multipliers,100.nr_multipliers = ARRAY_SIZE(multipliers),101};102103static struct clk_div4_table div4_table = {104.div_mult_table = &div4_div_mult_table,105};106107#define DIV4(_reg, _bit, _mask, _flags) \108SH_CLK_DIV4(&pll_clk, _reg, _bit, _mask, _flags)109110enum { DIV4_I, DIV4_U, DIV4_SH, DIV4_B, DIV4_B3, DIV4_P, DIV4_NR };111112struct clk div4_clks[DIV4_NR] = {113[DIV4_I] = DIV4(FRQCR, 20, 0x1fef, CLK_ENABLE_ON_INIT),114[DIV4_U] = DIV4(FRQCR, 16, 0x1fff, CLK_ENABLE_ON_INIT),115[DIV4_SH] = DIV4(FRQCR, 12, 0x1fff, CLK_ENABLE_ON_INIT),116[DIV4_B] = DIV4(FRQCR, 8, 0x1fff, CLK_ENABLE_ON_INIT),117[DIV4_B3] = DIV4(FRQCR, 4, 0x1fff, CLK_ENABLE_ON_INIT),118[DIV4_P] = DIV4(FRQCR, 0, 0x1fff, 0),119};120121enum { DIV4_IRDA, DIV4_ENABLE_NR };122123struct clk div4_enable_clks[DIV4_ENABLE_NR] = {124[DIV4_IRDA] = DIV4(IRDACLKCR, 0, 0x1fff, 0),125};126127enum { DIV4_SIUA, DIV4_SIUB, DIV4_REPARENT_NR };128129struct clk div4_reparent_clks[DIV4_REPARENT_NR] = {130[DIV4_SIUA] = DIV4(SCLKACR, 0, 0x1fff, 0),131[DIV4_SIUB] = DIV4(SCLKBCR, 0, 0x1fff, 0),132};133134enum { DIV6_V, DIV6_NR };135136struct clk div6_clks[DIV6_NR] = {137[DIV6_V] = SH_CLK_DIV6(&pll_clk, VCLKCR, 0),138};139140static struct clk mstp_clks[HWBLK_NR] = {141[HWBLK_URAM] = SH_CLK_MSTP32(&div4_clks[DIV4_U], MSTPCR0, 28, CLK_ENABLE_ON_INIT),142[HWBLK_XYMEM] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR0, 26, CLK_ENABLE_ON_INIT),143[HWBLK_TMU] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 15, 0),144[HWBLK_CMT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 14, 0),145[HWBLK_RWDT] = SH_CLK_MSTP32(&r_clk, MSTPCR0, 13, 0),146[HWBLK_FLCTL] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 10, 0),147[HWBLK_SCIF0] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 7, 0),148[HWBLK_SCIF1] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 6, 0),149[HWBLK_SCIF2] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 5, 0),150151[HWBLK_IIC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 9, 0),152[HWBLK_RTC] = SH_CLK_MSTP32(&r_clk, MSTPCR1, 8, 0),153154[HWBLK_SDHI] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 18, 0),155[HWBLK_KEYSC] = SH_CLK_MSTP32(&r_clk, MSTPCR2, 14, 0),156[HWBLK_USBF] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 11, 0),157[HWBLK_2DG] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 9, 0),158[HWBLK_SIU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 8, 0),159[HWBLK_JPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 6, 0),160[HWBLK_VOU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 5, 0),161[HWBLK_BEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 4, 0),162[HWBLK_CEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 3, 0),163[HWBLK_VEU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 2, 0),164[HWBLK_VPU] = SH_CLK_MSTP32(&div4_clks[DIV4_B], MSTPCR2, 1, 0),165[HWBLK_LCDC] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 0, 0),166};167168static struct clk_lookup lookups[] = {169/* main clocks */170CLKDEV_CON_ID("rclk", &r_clk),171CLKDEV_CON_ID("extal", &extal_clk),172CLKDEV_CON_ID("dll_clk", &dll_clk),173CLKDEV_CON_ID("pll_clk", &pll_clk),174175/* DIV4 clocks */176CLKDEV_CON_ID("cpu_clk", &div4_clks[DIV4_I]),177CLKDEV_CON_ID("umem_clk", &div4_clks[DIV4_U]),178CLKDEV_CON_ID("shyway_clk", &div4_clks[DIV4_SH]),179CLKDEV_CON_ID("bus_clk", &div4_clks[DIV4_B]),180CLKDEV_CON_ID("b3_clk", &div4_clks[DIV4_B3]),181CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),182CLKDEV_CON_ID("irda_clk", &div4_enable_clks[DIV4_IRDA]),183CLKDEV_CON_ID("siua_clk", &div4_reparent_clks[DIV4_SIUA]),184CLKDEV_CON_ID("siub_clk", &div4_reparent_clks[DIV4_SIUB]),185186/* DIV6 clocks */187CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),188189/* MSTP clocks */190CLKDEV_CON_ID("uram0", &mstp_clks[HWBLK_URAM]),191CLKDEV_CON_ID("xymem0", &mstp_clks[HWBLK_XYMEM]),192193CLKDEV_ICK_ID("fck", "sh-tmu.0", &mstp_clks[HWBLK_TMU]),194195CLKDEV_ICK_ID("fck", "sh-cmt-32.0", &mstp_clks[HWBLK_CMT]),196CLKDEV_DEV_ID("sh-wdt.0", &mstp_clks[HWBLK_RWDT]),197CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),198199CLKDEV_DEV_ID("sh-sci.0", &mstp_clks[HWBLK_SCIF0]),200CLKDEV_DEV_ID("sh-sci.1", &mstp_clks[HWBLK_SCIF1]),201CLKDEV_DEV_ID("sh-sci.2", &mstp_clks[HWBLK_SCIF2]),202203CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[HWBLK_IIC]),204CLKDEV_CON_ID("rtc0", &mstp_clks[HWBLK_RTC]),205CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[HWBLK_SDHI]),206CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[HWBLK_KEYSC]),207CLKDEV_CON_ID("usbf0", &mstp_clks[HWBLK_USBF]),208CLKDEV_CON_ID("2dg0", &mstp_clks[HWBLK_2DG]),209CLKDEV_DEV_ID("siu-pcm-audio", &mstp_clks[HWBLK_SIU]),210CLKDEV_DEV_ID("sh-vou.0", &mstp_clks[HWBLK_VOU]),211CLKDEV_CON_ID("jpu0", &mstp_clks[HWBLK_JPU]),212CLKDEV_CON_ID("beu0", &mstp_clks[HWBLK_BEU]),213CLKDEV_DEV_ID("renesas-ceu.0", &mstp_clks[HWBLK_CEU]),214CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU]),215CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]),216CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[HWBLK_LCDC]),217};218219int __init arch_clk_init(void)220{221int k, ret = 0;222223/* autodetect extal or dll configuration */224if (__raw_readl(PLLCR) & 0x1000)225pll_clk.parent = &dll_clk;226else227pll_clk.parent = &extal_clk;228229for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)230ret = clk_register(main_clks[k]);231232clkdev_add_table(lookups, ARRAY_SIZE(lookups));233234if (!ret)235ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);236237if (!ret)238ret = sh_clk_div4_enable_register(div4_enable_clks,239DIV4_ENABLE_NR, &div4_table);240241if (!ret)242ret = sh_clk_div4_reparent_register(div4_reparent_clks,243DIV4_REPARENT_NR, &div4_table);244245if (!ret)246ret = sh_clk_div6_register(div6_clks, DIV6_NR);247248if (!ret)249ret = sh_clk_mstp_register(mstp_clks, HWBLK_NR);250251return ret;252}253254255