Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Hisilicon Hi3620 clock driver
0004  *
0005  * Copyright (c) 2012-2013 Hisilicon Limited.
0006  * Copyright (c) 2012-2013 Linaro Limited.
0007  *
0008  * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
0009  *     Xin Li <li.xin@linaro.org>
0010  */
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/clk-provider.h>
0014 #include <linux/io.h>
0015 #include <linux/of.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_device.h>
0018 #include <linux/slab.h>
0019 
0020 #include <dt-bindings/clock/hi3620-clock.h>
0021 
0022 #include "clk.h"
0023 
0024 /* clock parent list */
0025 static const char *const timer0_mux_p[] __initconst = { "osc32k", "timerclk01", };
0026 static const char *const timer1_mux_p[] __initconst = { "osc32k", "timerclk01", };
0027 static const char *const timer2_mux_p[] __initconst = { "osc32k", "timerclk23", };
0028 static const char *const timer3_mux_p[] __initconst = { "osc32k", "timerclk23", };
0029 static const char *const timer4_mux_p[] __initconst = { "osc32k", "timerclk45", };
0030 static const char *const timer5_mux_p[] __initconst = { "osc32k", "timerclk45", };
0031 static const char *const timer6_mux_p[] __initconst = { "osc32k", "timerclk67", };
0032 static const char *const timer7_mux_p[] __initconst = { "osc32k", "timerclk67", };
0033 static const char *const timer8_mux_p[] __initconst = { "osc32k", "timerclk89", };
0034 static const char *const timer9_mux_p[] __initconst = { "osc32k", "timerclk89", };
0035 static const char *const uart0_mux_p[] __initconst = { "osc26m", "pclk", };
0036 static const char *const uart1_mux_p[] __initconst = { "osc26m", "pclk", };
0037 static const char *const uart2_mux_p[] __initconst = { "osc26m", "pclk", };
0038 static const char *const uart3_mux_p[] __initconst = { "osc26m", "pclk", };
0039 static const char *const uart4_mux_p[] __initconst = { "osc26m", "pclk", };
0040 static const char *const spi0_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
0041 static const char *const spi1_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
0042 static const char *const spi2_mux_p[] __initconst = { "osc26m", "rclk_cfgaxi", };
0043 /* share axi parent */
0044 static const char *const saxi_mux_p[] __initconst = { "armpll3", "armpll2", };
0045 static const char *const pwm0_mux_p[] __initconst = { "osc32k", "osc26m", };
0046 static const char *const pwm1_mux_p[] __initconst = { "osc32k", "osc26m", };
0047 static const char *const sd_mux_p[] __initconst = { "armpll2", "armpll3", };
0048 static const char *const mmc1_mux_p[] __initconst = { "armpll2", "armpll3", };
0049 static const char *const mmc1_mux2_p[] __initconst = { "osc26m", "mmc1_div", };
0050 static const char *const g2d_mux_p[] __initconst = { "armpll2", "armpll3", };
0051 static const char *const venc_mux_p[] __initconst = { "armpll2", "armpll3", };
0052 static const char *const vdec_mux_p[] __initconst = { "armpll2", "armpll3", };
0053 static const char *const vpp_mux_p[] __initconst = { "armpll2", "armpll3", };
0054 static const char *const edc0_mux_p[] __initconst = { "armpll2", "armpll3", };
0055 static const char *const ldi0_mux_p[] __initconst = { "armpll2", "armpll4",
0056                          "armpll3", "armpll5", };
0057 static const char *const edc1_mux_p[] __initconst = { "armpll2", "armpll3", };
0058 static const char *const ldi1_mux_p[] __initconst = { "armpll2", "armpll4",
0059                          "armpll3", "armpll5", };
0060 static const char *const rclk_hsic_p[] __initconst = { "armpll3", "armpll2", };
0061 static const char *const mmc2_mux_p[] __initconst = { "armpll2", "armpll3", };
0062 static const char *const mmc3_mux_p[] __initconst = { "armpll2", "armpll3", };
0063 
0064 
0065 /* fixed rate clocks */
0066 static struct hisi_fixed_rate_clock hi3620_fixed_rate_clks[] __initdata = {
0067     { HI3620_OSC32K,   "osc32k",   NULL, 0, 32768, },
0068     { HI3620_OSC26M,   "osc26m",   NULL, 0, 26000000, },
0069     { HI3620_PCLK,     "pclk",     NULL, 0, 26000000, },
0070     { HI3620_PLL_ARM0, "armpll0",  NULL, 0, 1600000000, },
0071     { HI3620_PLL_ARM1, "armpll1",  NULL, 0, 1600000000, },
0072     { HI3620_PLL_PERI, "armpll2",  NULL, 0, 1440000000, },
0073     { HI3620_PLL_USB,  "armpll3",  NULL, 0, 1440000000, },
0074     { HI3620_PLL_HDMI, "armpll4",  NULL, 0, 1188000000, },
0075     { HI3620_PLL_GPU,  "armpll5",  NULL, 0, 1300000000, },
0076 };
0077 
0078 /* fixed factor clocks */
0079 static struct hisi_fixed_factor_clock hi3620_fixed_factor_clks[] __initdata = {
0080     { HI3620_RCLK_TCXO,   "rclk_tcxo",   "osc26m",   1, 4,  0, },
0081     { HI3620_RCLK_CFGAXI, "rclk_cfgaxi", "armpll2",  1, 30, 0, },
0082     { HI3620_RCLK_PICO,   "rclk_pico",   "hsic_div", 1, 40, 0, },
0083 };
0084 
0085 static struct hisi_mux_clock hi3620_mux_clks[] __initdata = {
0086     { HI3620_TIMER0_MUX, "timer0_mux", timer0_mux_p, ARRAY_SIZE(timer0_mux_p), CLK_SET_RATE_PARENT, 0,     15, 2, 0,                   },
0087     { HI3620_TIMER1_MUX, "timer1_mux", timer1_mux_p, ARRAY_SIZE(timer1_mux_p), CLK_SET_RATE_PARENT, 0,     17, 2, 0,                   },
0088     { HI3620_TIMER2_MUX, "timer2_mux", timer2_mux_p, ARRAY_SIZE(timer2_mux_p), CLK_SET_RATE_PARENT, 0,     19, 2, 0,                   },
0089     { HI3620_TIMER3_MUX, "timer3_mux", timer3_mux_p, ARRAY_SIZE(timer3_mux_p), CLK_SET_RATE_PARENT, 0,     21, 2, 0,                   },
0090     { HI3620_TIMER4_MUX, "timer4_mux", timer4_mux_p, ARRAY_SIZE(timer4_mux_p), CLK_SET_RATE_PARENT, 0x18,  0,  2, 0,                   },
0091     { HI3620_TIMER5_MUX, "timer5_mux", timer5_mux_p, ARRAY_SIZE(timer5_mux_p), CLK_SET_RATE_PARENT, 0x18,  2,  2, 0,                   },
0092     { HI3620_TIMER6_MUX, "timer6_mux", timer6_mux_p, ARRAY_SIZE(timer6_mux_p), CLK_SET_RATE_PARENT, 0x18,  4,  2, 0,                   },
0093     { HI3620_TIMER7_MUX, "timer7_mux", timer7_mux_p, ARRAY_SIZE(timer7_mux_p), CLK_SET_RATE_PARENT, 0x18,  6,  2, 0,                   },
0094     { HI3620_TIMER8_MUX, "timer8_mux", timer8_mux_p, ARRAY_SIZE(timer8_mux_p), CLK_SET_RATE_PARENT, 0x18,  8,  2, 0,                   },
0095     { HI3620_TIMER9_MUX, "timer9_mux", timer9_mux_p, ARRAY_SIZE(timer9_mux_p), CLK_SET_RATE_PARENT, 0x18,  10, 2, 0,                   },
0096     { HI3620_UART0_MUX,  "uart0_mux",  uart0_mux_p,  ARRAY_SIZE(uart0_mux_p),  CLK_SET_RATE_PARENT, 0x100, 7,  1, CLK_MUX_HIWORD_MASK, },
0097     { HI3620_UART1_MUX,  "uart1_mux",  uart1_mux_p,  ARRAY_SIZE(uart1_mux_p),  CLK_SET_RATE_PARENT, 0x100, 8,  1, CLK_MUX_HIWORD_MASK, },
0098     { HI3620_UART2_MUX,  "uart2_mux",  uart2_mux_p,  ARRAY_SIZE(uart2_mux_p),  CLK_SET_RATE_PARENT, 0x100, 9,  1, CLK_MUX_HIWORD_MASK, },
0099     { HI3620_UART3_MUX,  "uart3_mux",  uart3_mux_p,  ARRAY_SIZE(uart3_mux_p),  CLK_SET_RATE_PARENT, 0x100, 10, 1, CLK_MUX_HIWORD_MASK, },
0100     { HI3620_UART4_MUX,  "uart4_mux",  uart4_mux_p,  ARRAY_SIZE(uart4_mux_p),  CLK_SET_RATE_PARENT, 0x100, 11, 1, CLK_MUX_HIWORD_MASK, },
0101     { HI3620_SPI0_MUX,   "spi0_mux",   spi0_mux_p,   ARRAY_SIZE(spi0_mux_p),   CLK_SET_RATE_PARENT, 0x100, 12, 1, CLK_MUX_HIWORD_MASK, },
0102     { HI3620_SPI1_MUX,   "spi1_mux",   spi1_mux_p,   ARRAY_SIZE(spi1_mux_p),   CLK_SET_RATE_PARENT, 0x100, 13, 1, CLK_MUX_HIWORD_MASK, },
0103     { HI3620_SPI2_MUX,   "spi2_mux",   spi2_mux_p,   ARRAY_SIZE(spi2_mux_p),   CLK_SET_RATE_PARENT, 0x100, 14, 1, CLK_MUX_HIWORD_MASK, },
0104     { HI3620_SAXI_MUX,   "saxi_mux",   saxi_mux_p,   ARRAY_SIZE(saxi_mux_p),   CLK_SET_RATE_PARENT, 0x100, 15, 1, CLK_MUX_HIWORD_MASK, },
0105     { HI3620_PWM0_MUX,   "pwm0_mux",   pwm0_mux_p,   ARRAY_SIZE(pwm0_mux_p),   CLK_SET_RATE_PARENT, 0x104, 10, 1, CLK_MUX_HIWORD_MASK, },
0106     { HI3620_PWM1_MUX,   "pwm1_mux",   pwm1_mux_p,   ARRAY_SIZE(pwm1_mux_p),   CLK_SET_RATE_PARENT, 0x104, 11, 1, CLK_MUX_HIWORD_MASK, },
0107     { HI3620_SD_MUX,     "sd_mux",     sd_mux_p,     ARRAY_SIZE(sd_mux_p),     CLK_SET_RATE_PARENT, 0x108, 4,  1, CLK_MUX_HIWORD_MASK, },
0108     { HI3620_MMC1_MUX,   "mmc1_mux",   mmc1_mux_p,   ARRAY_SIZE(mmc1_mux_p),   CLK_SET_RATE_PARENT, 0x108, 9,  1, CLK_MUX_HIWORD_MASK, },
0109     { HI3620_MMC1_MUX2,  "mmc1_mux2",  mmc1_mux2_p,  ARRAY_SIZE(mmc1_mux2_p),  CLK_SET_RATE_PARENT, 0x108, 10, 1, CLK_MUX_HIWORD_MASK, },
0110     { HI3620_G2D_MUX,    "g2d_mux",    g2d_mux_p,    ARRAY_SIZE(g2d_mux_p),    CLK_SET_RATE_PARENT, 0x10c, 5,  1, CLK_MUX_HIWORD_MASK, },
0111     { HI3620_VENC_MUX,   "venc_mux",   venc_mux_p,   ARRAY_SIZE(venc_mux_p),   CLK_SET_RATE_PARENT, 0x10c, 11, 1, CLK_MUX_HIWORD_MASK, },
0112     { HI3620_VDEC_MUX,   "vdec_mux",   vdec_mux_p,   ARRAY_SIZE(vdec_mux_p),   CLK_SET_RATE_PARENT, 0x110, 5,  1, CLK_MUX_HIWORD_MASK, },
0113     { HI3620_VPP_MUX,    "vpp_mux",    vpp_mux_p,    ARRAY_SIZE(vpp_mux_p),    CLK_SET_RATE_PARENT, 0x110, 11, 1, CLK_MUX_HIWORD_MASK, },
0114     { HI3620_EDC0_MUX,   "edc0_mux",   edc0_mux_p,   ARRAY_SIZE(edc0_mux_p),   CLK_SET_RATE_PARENT, 0x114, 6,  1, CLK_MUX_HIWORD_MASK, },
0115     { HI3620_LDI0_MUX,   "ldi0_mux",   ldi0_mux_p,   ARRAY_SIZE(ldi0_mux_p),   CLK_SET_RATE_PARENT, 0x114, 13, 2, CLK_MUX_HIWORD_MASK, },
0116     { HI3620_EDC1_MUX,   "edc1_mux",   edc1_mux_p,   ARRAY_SIZE(edc1_mux_p),   CLK_SET_RATE_PARENT, 0x118, 6,  1, CLK_MUX_HIWORD_MASK, },
0117     { HI3620_LDI1_MUX,   "ldi1_mux",   ldi1_mux_p,   ARRAY_SIZE(ldi1_mux_p),   CLK_SET_RATE_PARENT, 0x118, 14, 2, CLK_MUX_HIWORD_MASK, },
0118     { HI3620_RCLK_HSIC,  "rclk_hsic",  rclk_hsic_p,  ARRAY_SIZE(rclk_hsic_p),  CLK_SET_RATE_PARENT, 0x130, 2,  1, CLK_MUX_HIWORD_MASK, },
0119     { HI3620_MMC2_MUX,   "mmc2_mux",   mmc2_mux_p,   ARRAY_SIZE(mmc2_mux_p),   CLK_SET_RATE_PARENT, 0x140, 4,  1, CLK_MUX_HIWORD_MASK, },
0120     { HI3620_MMC3_MUX,   "mmc3_mux",   mmc3_mux_p,   ARRAY_SIZE(mmc3_mux_p),   CLK_SET_RATE_PARENT, 0x140, 9,  1, CLK_MUX_HIWORD_MASK, },
0121 };
0122 
0123 static struct hisi_divider_clock hi3620_div_clks[] __initdata = {
0124     { HI3620_SHAREAXI_DIV, "saxi_div",   "saxi_mux",  0, 0x100, 0, 5, CLK_DIVIDER_HIWORD_MASK, NULL, },
0125     { HI3620_CFGAXI_DIV,   "cfgaxi_div", "saxi_div",  0, 0x100, 5, 2, CLK_DIVIDER_HIWORD_MASK, NULL, },
0126     { HI3620_SD_DIV,       "sd_div",     "sd_mux",    0, 0x108, 0, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
0127     { HI3620_MMC1_DIV,     "mmc1_div",   "mmc1_mux",  0, 0x108, 5, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
0128     { HI3620_HSIC_DIV,     "hsic_div",   "rclk_hsic", 0, 0x130, 0, 2, CLK_DIVIDER_HIWORD_MASK, NULL, },
0129     { HI3620_MMC2_DIV,     "mmc2_div",   "mmc2_mux",  0, 0x140, 0, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
0130     { HI3620_MMC3_DIV,     "mmc3_div",   "mmc3_mux",  0, 0x140, 5, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
0131 };
0132 
0133 static struct hisi_gate_clock hi3620_separated_gate_clks[] __initdata = {
0134     { HI3620_TIMERCLK01,   "timerclk01",   "timer_rclk01", CLK_SET_RATE_PARENT, 0x20, 0, 0, },
0135     { HI3620_TIMER_RCLK01, "timer_rclk01", "rclk_tcxo",    CLK_SET_RATE_PARENT, 0x20, 1, 0, },
0136     { HI3620_TIMERCLK23,   "timerclk23",   "timer_rclk23", CLK_SET_RATE_PARENT, 0x20, 2, 0, },
0137     { HI3620_TIMER_RCLK23, "timer_rclk23", "rclk_tcxo",    CLK_SET_RATE_PARENT, 0x20, 3, 0, },
0138     { HI3620_RTCCLK,       "rtcclk",       "pclk",         CLK_SET_RATE_PARENT, 0x20, 5, 0, },
0139     { HI3620_KPC_CLK,      "kpc_clk",      "pclk",         CLK_SET_RATE_PARENT, 0x20, 6, 0, },
0140     { HI3620_GPIOCLK0,     "gpioclk0",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 8, 0, },
0141     { HI3620_GPIOCLK1,     "gpioclk1",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 9, 0, },
0142     { HI3620_GPIOCLK2,     "gpioclk2",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 10, 0, },
0143     { HI3620_GPIOCLK3,     "gpioclk3",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 11, 0, },
0144     { HI3620_GPIOCLK4,     "gpioclk4",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 12, 0, },
0145     { HI3620_GPIOCLK5,     "gpioclk5",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 13, 0, },
0146     { HI3620_GPIOCLK6,     "gpioclk6",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 14, 0, },
0147     { HI3620_GPIOCLK7,     "gpioclk7",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 15, 0, },
0148     { HI3620_GPIOCLK8,     "gpioclk8",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 16, 0, },
0149     { HI3620_GPIOCLK9,     "gpioclk9",     "pclk",         CLK_SET_RATE_PARENT, 0x20, 17, 0, },
0150     { HI3620_GPIOCLK10,    "gpioclk10",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 18, 0, },
0151     { HI3620_GPIOCLK11,    "gpioclk11",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 19, 0, },
0152     { HI3620_GPIOCLK12,    "gpioclk12",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 20, 0, },
0153     { HI3620_GPIOCLK13,    "gpioclk13",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 21, 0, },
0154     { HI3620_GPIOCLK14,    "gpioclk14",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 22, 0, },
0155     { HI3620_GPIOCLK15,    "gpioclk15",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 23, 0, },
0156     { HI3620_GPIOCLK16,    "gpioclk16",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 24, 0, },
0157     { HI3620_GPIOCLK17,    "gpioclk17",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 25, 0, },
0158     { HI3620_GPIOCLK18,    "gpioclk18",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 26, 0, },
0159     { HI3620_GPIOCLK19,    "gpioclk19",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 27, 0, },
0160     { HI3620_GPIOCLK20,    "gpioclk20",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 28, 0, },
0161     { HI3620_GPIOCLK21,    "gpioclk21",    "pclk",         CLK_SET_RATE_PARENT, 0x20, 29, 0, },
0162     { HI3620_DPHY0_CLK,    "dphy0_clk",    "osc26m",       CLK_SET_RATE_PARENT, 0x30, 15, 0, },
0163     { HI3620_DPHY1_CLK,    "dphy1_clk",    "osc26m",       CLK_SET_RATE_PARENT, 0x30, 16, 0, },
0164     { HI3620_DPHY2_CLK,    "dphy2_clk",    "osc26m",       CLK_SET_RATE_PARENT, 0x30, 17, 0, },
0165     { HI3620_USBPHY_CLK,   "usbphy_clk",   "rclk_pico",    CLK_SET_RATE_PARENT, 0x30, 24, 0, },
0166     { HI3620_ACP_CLK,      "acp_clk",      "rclk_cfgaxi",  CLK_SET_RATE_PARENT, 0x30, 28, 0, },
0167     { HI3620_TIMERCLK45,   "timerclk45",   "rclk_tcxo",    CLK_SET_RATE_PARENT, 0x40, 3, 0, },
0168     { HI3620_TIMERCLK67,   "timerclk67",   "rclk_tcxo",    CLK_SET_RATE_PARENT, 0x40, 4, 0, },
0169     { HI3620_TIMERCLK89,   "timerclk89",   "rclk_tcxo",    CLK_SET_RATE_PARENT, 0x40, 5, 0, },
0170     { HI3620_PWMCLK0,      "pwmclk0",      "pwm0_mux",     CLK_SET_RATE_PARENT, 0x40, 7, 0, },
0171     { HI3620_PWMCLK1,      "pwmclk1",      "pwm1_mux",     CLK_SET_RATE_PARENT, 0x40, 8, 0, },
0172     { HI3620_UARTCLK0,     "uartclk0",     "uart0_mux",    CLK_SET_RATE_PARENT, 0x40, 16, 0, },
0173     { HI3620_UARTCLK1,     "uartclk1",     "uart1_mux",    CLK_SET_RATE_PARENT, 0x40, 17, 0, },
0174     { HI3620_UARTCLK2,     "uartclk2",     "uart2_mux",    CLK_SET_RATE_PARENT, 0x40, 18, 0, },
0175     { HI3620_UARTCLK3,     "uartclk3",     "uart3_mux",    CLK_SET_RATE_PARENT, 0x40, 19, 0, },
0176     { HI3620_UARTCLK4,     "uartclk4",     "uart4_mux",    CLK_SET_RATE_PARENT, 0x40, 20, 0, },
0177     { HI3620_SPICLK0,      "spiclk0",      "spi0_mux",     CLK_SET_RATE_PARENT, 0x40, 21, 0, },
0178     { HI3620_SPICLK1,      "spiclk1",      "spi1_mux",     CLK_SET_RATE_PARENT, 0x40, 22, 0, },
0179     { HI3620_SPICLK2,      "spiclk2",      "spi2_mux",     CLK_SET_RATE_PARENT, 0x40, 23, 0, },
0180     { HI3620_I2CCLK0,      "i2cclk0",      "pclk",         CLK_SET_RATE_PARENT, 0x40, 24, 0, },
0181     { HI3620_I2CCLK1,      "i2cclk1",      "pclk",         CLK_SET_RATE_PARENT, 0x40, 25, 0, },
0182     { HI3620_SCI_CLK,      "sci_clk",      "osc26m",       CLK_SET_RATE_PARENT, 0x40, 26, 0, },
0183     { HI3620_I2CCLK2,      "i2cclk2",      "pclk",         CLK_SET_RATE_PARENT, 0x40, 28, 0, },
0184     { HI3620_I2CCLK3,      "i2cclk3",      "pclk",         CLK_SET_RATE_PARENT, 0x40, 29, 0, },
0185     { HI3620_DDRC_PER_CLK, "ddrc_per_clk", "rclk_cfgaxi",  CLK_SET_RATE_PARENT, 0x50, 9, 0, },
0186     { HI3620_DMAC_CLK,     "dmac_clk",     "rclk_cfgaxi",  CLK_SET_RATE_PARENT, 0x50, 10, 0, },
0187     { HI3620_USB2DVC_CLK,  "usb2dvc_clk",  "rclk_cfgaxi",  CLK_SET_RATE_PARENT, 0x50, 17, 0, },
0188     { HI3620_SD_CLK,       "sd_clk",       "sd_div",       CLK_SET_RATE_PARENT, 0x50, 20, 0, },
0189     { HI3620_MMC_CLK1,     "mmc_clk1",     "mmc1_mux2",    CLK_SET_RATE_PARENT, 0x50, 21, 0, },
0190     { HI3620_MMC_CLK2,     "mmc_clk2",     "mmc2_div",     CLK_SET_RATE_PARENT, 0x50, 22, 0, },
0191     { HI3620_MMC_CLK3,     "mmc_clk3",     "mmc3_div",     CLK_SET_RATE_PARENT, 0x50, 23, 0, },
0192     { HI3620_MCU_CLK,      "mcu_clk",      "acp_clk",      CLK_SET_RATE_PARENT, 0x50, 24, 0, },
0193 };
0194 
0195 static void __init hi3620_clk_init(struct device_node *np)
0196 {
0197     struct hisi_clock_data *clk_data;
0198 
0199     clk_data = hisi_clk_init(np, HI3620_NR_CLKS);
0200     if (!clk_data)
0201         return;
0202 
0203     hisi_clk_register_fixed_rate(hi3620_fixed_rate_clks,
0204                      ARRAY_SIZE(hi3620_fixed_rate_clks),
0205                      clk_data);
0206     hisi_clk_register_fixed_factor(hi3620_fixed_factor_clks,
0207                        ARRAY_SIZE(hi3620_fixed_factor_clks),
0208                        clk_data);
0209     hisi_clk_register_mux(hi3620_mux_clks, ARRAY_SIZE(hi3620_mux_clks),
0210                   clk_data);
0211     hisi_clk_register_divider(hi3620_div_clks, ARRAY_SIZE(hi3620_div_clks),
0212                   clk_data);
0213     hisi_clk_register_gate_sep(hi3620_separated_gate_clks,
0214                    ARRAY_SIZE(hi3620_separated_gate_clks),
0215                    clk_data);
0216 }
0217 CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
0218 
0219 struct hisi_mmc_clock {
0220     unsigned int        id;
0221     const char      *name;
0222     const char      *parent_name;
0223     unsigned long       flags;
0224     u32         clken_reg;
0225     u32         clken_bit;
0226     u32         div_reg;
0227     u32         div_off;
0228     u32         div_bits;
0229     u32         drv_reg;
0230     u32         drv_off;
0231     u32         drv_bits;
0232     u32         sam_reg;
0233     u32         sam_off;
0234     u32         sam_bits;
0235 };
0236 
0237 struct clk_mmc {
0238     struct clk_hw   hw;
0239     u32     id;
0240     void __iomem    *clken_reg;
0241     u32     clken_bit;
0242     void __iomem    *div_reg;
0243     u32     div_off;
0244     u32     div_bits;
0245     void __iomem    *drv_reg;
0246     u32     drv_off;
0247     u32     drv_bits;
0248     void __iomem    *sam_reg;
0249     u32     sam_off;
0250     u32     sam_bits;
0251 };
0252 
0253 #define to_mmc(_hw) container_of(_hw, struct clk_mmc, hw)
0254 
0255 static struct hisi_mmc_clock hi3620_mmc_clks[] __initdata = {
0256     { HI3620_SD_CIUCLK, "sd_bclk1", "sd_clk", CLK_SET_RATE_PARENT, 0x1f8, 0, 0x1f8, 1, 3, 0x1f8, 4, 4, 0x1f8, 8, 4},
0257     { HI3620_MMC_CIUCLK1,   "mmc_bclk1", "mmc_clk1", CLK_SET_RATE_PARENT, 0x1f8, 12, 0x1f8, 13, 3, 0x1f8, 16, 4, 0x1f8, 20, 4},
0258     { HI3620_MMC_CIUCLK2,   "mmc_bclk2", "mmc_clk2", CLK_SET_RATE_PARENT, 0x1f8, 24, 0x1f8, 25, 3, 0x1f8, 28, 4, 0x1fc, 0, 4},
0259     { HI3620_MMC_CIUCLK3,   "mmc_bclk3", "mmc_clk3", CLK_SET_RATE_PARENT, 0x1fc, 4, 0x1fc, 5, 3, 0x1fc, 8, 4, 0x1fc, 12, 4},
0260 };
0261 
0262 static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
0263                unsigned long parent_rate)
0264 {
0265     switch (parent_rate) {
0266     case 26000000:
0267         return 13000000;
0268     case 180000000:
0269         return 25000000;
0270     case 360000000:
0271         return 50000000;
0272     case 720000000:
0273         return 100000000;
0274     case 1440000000:
0275         return 180000000;
0276     default:
0277         return parent_rate;
0278     }
0279 }
0280 
0281 static int mmc_clk_determine_rate(struct clk_hw *hw,
0282                   struct clk_rate_request *req)
0283 {
0284     struct clk_mmc *mclk = to_mmc(hw);
0285 
0286     if ((req->rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
0287         req->rate = 13000000;
0288         req->best_parent_rate = 26000000;
0289     } else if (req->rate <= 26000000) {
0290         req->rate = 25000000;
0291         req->best_parent_rate = 180000000;
0292     } else if (req->rate <= 52000000) {
0293         req->rate = 50000000;
0294         req->best_parent_rate = 360000000;
0295     } else if (req->rate <= 100000000) {
0296         req->rate = 100000000;
0297         req->best_parent_rate = 720000000;
0298     } else {
0299         /* max is 180M */
0300         req->rate = 180000000;
0301         req->best_parent_rate = 1440000000;
0302     }
0303     return -EINVAL;
0304 }
0305 
0306 static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
0307 {
0308     u32 i;
0309 
0310     for (i = 0; i < len; i++) {
0311         if (para % 2)
0312             val |= 1 << (off + i);
0313         else
0314             val &= ~(1 << (off + i));
0315         para = para >> 1;
0316     }
0317 
0318     return val;
0319 }
0320 
0321 static int mmc_clk_set_timing(struct clk_hw *hw, unsigned long rate)
0322 {
0323     struct clk_mmc *mclk = to_mmc(hw);
0324     unsigned long flags;
0325     u32 sam, drv, div, val;
0326     static DEFINE_SPINLOCK(mmc_clk_lock);
0327 
0328     switch (rate) {
0329     case 13000000:
0330         sam = 3;
0331         drv = 1;
0332         div = 1;
0333         break;
0334     case 25000000:
0335         sam = 13;
0336         drv = 6;
0337         div = 6;
0338         break;
0339     case 50000000:
0340         sam = 3;
0341         drv = 6;
0342         div = 6;
0343         break;
0344     case 100000000:
0345         sam = 6;
0346         drv = 4;
0347         div = 6;
0348         break;
0349     case 180000000:
0350         sam = 6;
0351         drv = 4;
0352         div = 7;
0353         break;
0354     default:
0355         return -EINVAL;
0356     }
0357 
0358     spin_lock_irqsave(&mmc_clk_lock, flags);
0359 
0360     val = readl_relaxed(mclk->clken_reg);
0361     val &= ~(1 << mclk->clken_bit);
0362     writel_relaxed(val, mclk->clken_reg);
0363 
0364     val = readl_relaxed(mclk->sam_reg);
0365     val = mmc_clk_delay(val, sam, mclk->sam_off, mclk->sam_bits);
0366     writel_relaxed(val, mclk->sam_reg);
0367 
0368     val = readl_relaxed(mclk->drv_reg);
0369     val = mmc_clk_delay(val, drv, mclk->drv_off, mclk->drv_bits);
0370     writel_relaxed(val, mclk->drv_reg);
0371 
0372     val = readl_relaxed(mclk->div_reg);
0373     val = mmc_clk_delay(val, div, mclk->div_off, mclk->div_bits);
0374     writel_relaxed(val, mclk->div_reg);
0375 
0376     val = readl_relaxed(mclk->clken_reg);
0377     val |= 1 << mclk->clken_bit;
0378     writel_relaxed(val, mclk->clken_reg);
0379 
0380     spin_unlock_irqrestore(&mmc_clk_lock, flags);
0381 
0382     return 0;
0383 }
0384 
0385 static int mmc_clk_prepare(struct clk_hw *hw)
0386 {
0387     struct clk_mmc *mclk = to_mmc(hw);
0388     unsigned long rate;
0389 
0390     if (mclk->id == HI3620_MMC_CIUCLK1)
0391         rate = 13000000;
0392     else
0393         rate = 25000000;
0394 
0395     return mmc_clk_set_timing(hw, rate);
0396 }
0397 
0398 static int mmc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
0399                  unsigned long parent_rate)
0400 {
0401     return mmc_clk_set_timing(hw, rate);
0402 }
0403 
0404 static const struct clk_ops clk_mmc_ops = {
0405     .prepare = mmc_clk_prepare,
0406     .determine_rate = mmc_clk_determine_rate,
0407     .set_rate = mmc_clk_set_rate,
0408     .recalc_rate = mmc_clk_recalc_rate,
0409 };
0410 
0411 static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
0412             void __iomem *base, struct device_node *np)
0413 {
0414     struct clk_mmc *mclk;
0415     struct clk *clk;
0416     struct clk_init_data init;
0417 
0418     mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
0419     if (!mclk)
0420         return ERR_PTR(-ENOMEM);
0421 
0422     init.name = mmc_clk->name;
0423     init.ops = &clk_mmc_ops;
0424     init.flags = mmc_clk->flags;
0425     init.parent_names = (mmc_clk->parent_name ? &mmc_clk->parent_name : NULL);
0426     init.num_parents = (mmc_clk->parent_name ? 1 : 0);
0427     mclk->hw.init = &init;
0428 
0429     mclk->id = mmc_clk->id;
0430     mclk->clken_reg = base + mmc_clk->clken_reg;
0431     mclk->clken_bit = mmc_clk->clken_bit;
0432     mclk->div_reg = base + mmc_clk->div_reg;
0433     mclk->div_off = mmc_clk->div_off;
0434     mclk->div_bits = mmc_clk->div_bits;
0435     mclk->drv_reg = base + mmc_clk->drv_reg;
0436     mclk->drv_off = mmc_clk->drv_off;
0437     mclk->drv_bits = mmc_clk->drv_bits;
0438     mclk->sam_reg = base + mmc_clk->sam_reg;
0439     mclk->sam_off = mmc_clk->sam_off;
0440     mclk->sam_bits = mmc_clk->sam_bits;
0441 
0442     clk = clk_register(NULL, &mclk->hw);
0443     if (WARN_ON(IS_ERR(clk)))
0444         kfree(mclk);
0445     return clk;
0446 }
0447 
0448 static void __init hi3620_mmc_clk_init(struct device_node *node)
0449 {
0450     void __iomem *base;
0451     int i, num = ARRAY_SIZE(hi3620_mmc_clks);
0452     struct clk_onecell_data *clk_data;
0453 
0454     if (!node) {
0455         pr_err("failed to find pctrl node in DTS\n");
0456         return;
0457     }
0458 
0459     base = of_iomap(node, 0);
0460     if (!base) {
0461         pr_err("failed to map pctrl\n");
0462         return;
0463     }
0464 
0465     clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
0466     if (WARN_ON(!clk_data))
0467         return;
0468 
0469     clk_data->clks = kcalloc(num, sizeof(*clk_data->clks), GFP_KERNEL);
0470     if (!clk_data->clks)
0471         return;
0472 
0473     for (i = 0; i < num; i++) {
0474         struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
0475         clk_data->clks[mmc_clk->id] =
0476             hisi_register_clk_mmc(mmc_clk, base, node);
0477     }
0478 
0479     clk_data->clk_num = num;
0480     of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
0481 }
0482 
0483 CLK_OF_DECLARE(hi3620_mmc_clk, "hisilicon,hi3620-mmc-clock", hi3620_mmc_clk_init);