Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Hi3516CV300 Clock and Reset Generator Driver
0004  *
0005  * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
0006  */
0007 
0008 #include <dt-bindings/clock/hi3516cv300-clock.h>
0009 #include <linux/clk-provider.h>
0010 #include <linux/module.h>
0011 #include <linux/of_device.h>
0012 #include <linux/platform_device.h>
0013 #include "clk.h"
0014 #include "crg.h"
0015 #include "reset.h"
0016 
0017 /* hi3516CV300 core CRG */
0018 #define HI3516CV300_INNER_CLK_OFFSET    64
0019 #define HI3516CV300_FIXED_3M        65
0020 #define HI3516CV300_FIXED_6M        66
0021 #define HI3516CV300_FIXED_24M       67
0022 #define HI3516CV300_FIXED_49P5      68
0023 #define HI3516CV300_FIXED_50M       69
0024 #define HI3516CV300_FIXED_83P3M     70
0025 #define HI3516CV300_FIXED_99M       71
0026 #define HI3516CV300_FIXED_100M      72
0027 #define HI3516CV300_FIXED_148P5M    73
0028 #define HI3516CV300_FIXED_198M      74
0029 #define HI3516CV300_FIXED_297M      75
0030 #define HI3516CV300_UART_MUX        76
0031 #define HI3516CV300_FMC_MUX     77
0032 #define HI3516CV300_MMC0_MUX        78
0033 #define HI3516CV300_MMC1_MUX        79
0034 #define HI3516CV300_MMC2_MUX        80
0035 #define HI3516CV300_MMC3_MUX        81
0036 #define HI3516CV300_PWM_MUX     82
0037 #define HI3516CV300_CRG_NR_CLKS     128
0038 
0039 static const struct hisi_fixed_rate_clock hi3516cv300_fixed_rate_clks[] = {
0040     { HI3516CV300_FIXED_3M, "3m", NULL, 0, 3000000, },
0041     { HI3516CV300_FIXED_6M, "6m", NULL, 0, 6000000, },
0042     { HI3516CV300_FIXED_24M, "24m", NULL, 0, 24000000, },
0043     { HI3516CV300_FIXED_49P5, "49.5m", NULL, 0, 49500000, },
0044     { HI3516CV300_FIXED_50M, "50m", NULL, 0, 50000000, },
0045     { HI3516CV300_FIXED_83P3M, "83.3m", NULL, 0, 83300000, },
0046     { HI3516CV300_FIXED_99M, "99m", NULL, 0, 99000000, },
0047     { HI3516CV300_FIXED_100M, "100m", NULL, 0, 100000000, },
0048     { HI3516CV300_FIXED_148P5M, "148.5m", NULL, 0, 148500000, },
0049     { HI3516CV300_FIXED_198M, "198m", NULL, 0, 198000000, },
0050     { HI3516CV300_FIXED_297M, "297m", NULL, 0, 297000000, },
0051     { HI3516CV300_APB_CLK, "apb", NULL, 0, 50000000, },
0052 };
0053 
0054 static const char *const uart_mux_p[] = {"24m", "6m"};
0055 static const char *const fmc_mux_p[] = {
0056     "24m", "83.3m", "148.5m", "198m", "297m"
0057 };
0058 static const char *const mmc_mux_p[] = {"49.5m"};
0059 static const char *const mmc2_mux_p[] = {"99m", "49.5m"};
0060 static const char *const pwm_mux_p[] = {"3m", "50m", "24m", "24m"};
0061 
0062 static u32 uart_mux_table[] = {0, 1};
0063 static u32 fmc_mux_table[] = {0, 1, 2, 3, 4};
0064 static u32 mmc_mux_table[] = {0};
0065 static u32 mmc2_mux_table[] = {0, 2};
0066 static u32 pwm_mux_table[] = {0, 1, 2, 3};
0067 
0068 static const struct hisi_mux_clock hi3516cv300_mux_clks[] = {
0069     { HI3516CV300_UART_MUX, "uart_mux", uart_mux_p, ARRAY_SIZE(uart_mux_p),
0070         CLK_SET_RATE_PARENT, 0xe4, 19, 1, 0, uart_mux_table, },
0071     { HI3516CV300_FMC_MUX, "fmc_mux", fmc_mux_p, ARRAY_SIZE(fmc_mux_p),
0072         CLK_SET_RATE_PARENT, 0xc0, 2, 3, 0, fmc_mux_table, },
0073     { HI3516CV300_MMC0_MUX, "mmc0_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
0074         CLK_SET_RATE_PARENT, 0xc4, 4, 2, 0, mmc_mux_table, },
0075     { HI3516CV300_MMC1_MUX, "mmc1_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
0076         CLK_SET_RATE_PARENT, 0xc4, 12, 2, 0, mmc_mux_table, },
0077     { HI3516CV300_MMC2_MUX, "mmc2_mux", mmc2_mux_p, ARRAY_SIZE(mmc2_mux_p),
0078         CLK_SET_RATE_PARENT, 0xc4, 20, 2, 0, mmc2_mux_table, },
0079     { HI3516CV300_MMC3_MUX, "mmc3_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),
0080         CLK_SET_RATE_PARENT, 0xc8, 4, 2, 0, mmc_mux_table, },
0081     { HI3516CV300_PWM_MUX, "pwm_mux", pwm_mux_p, ARRAY_SIZE(pwm_mux_p),
0082         CLK_SET_RATE_PARENT, 0x38, 2, 2, 0, pwm_mux_table, },
0083 };
0084 
0085 static const struct hisi_gate_clock hi3516cv300_gate_clks[] = {
0086 
0087     { HI3516CV300_UART0_CLK, "clk_uart0", "uart_mux", CLK_SET_RATE_PARENT,
0088         0xe4, 15, 0, },
0089     { HI3516CV300_UART1_CLK, "clk_uart1", "uart_mux", CLK_SET_RATE_PARENT,
0090         0xe4, 16, 0, },
0091     { HI3516CV300_UART2_CLK, "clk_uart2", "uart_mux", CLK_SET_RATE_PARENT,
0092         0xe4, 17, 0, },
0093 
0094     { HI3516CV300_SPI0_CLK, "clk_spi0", "100m", CLK_SET_RATE_PARENT,
0095         0xe4, 13, 0, },
0096     { HI3516CV300_SPI1_CLK, "clk_spi1", "100m", CLK_SET_RATE_PARENT,
0097         0xe4, 14, 0, },
0098 
0099     { HI3516CV300_FMC_CLK, "clk_fmc", "fmc_mux", CLK_SET_RATE_PARENT,
0100         0xc0, 1, 0, },
0101     { HI3516CV300_MMC0_CLK, "clk_mmc0", "mmc0_mux", CLK_SET_RATE_PARENT,
0102         0xc4, 1, 0, },
0103     { HI3516CV300_MMC1_CLK, "clk_mmc1", "mmc1_mux", CLK_SET_RATE_PARENT,
0104         0xc4, 9, 0, },
0105     { HI3516CV300_MMC2_CLK, "clk_mmc2", "mmc2_mux", CLK_SET_RATE_PARENT,
0106         0xc4, 17, 0, },
0107     { HI3516CV300_MMC3_CLK, "clk_mmc3", "mmc3_mux", CLK_SET_RATE_PARENT,
0108         0xc8, 1, 0, },
0109 
0110     { HI3516CV300_ETH_CLK, "clk_eth", NULL, 0, 0xec, 1, 0, },
0111 
0112     { HI3516CV300_DMAC_CLK, "clk_dmac", NULL, 0, 0xd8, 5, 0, },
0113     { HI3516CV300_PWM_CLK, "clk_pwm", "pwm_mux", CLK_SET_RATE_PARENT,
0114         0x38, 1, 0, },
0115 
0116     { HI3516CV300_USB2_BUS_CLK, "clk_usb2_bus", NULL, 0, 0xb8, 0, 0, },
0117     { HI3516CV300_USB2_OHCI48M_CLK, "clk_usb2_ohci48m", NULL, 0,
0118         0xb8, 1, 0, },
0119     { HI3516CV300_USB2_OHCI12M_CLK, "clk_usb2_ohci12m", NULL, 0,
0120         0xb8, 2, 0, },
0121     { HI3516CV300_USB2_OTG_UTMI_CLK, "clk_usb2_otg_utmi", NULL, 0,
0122         0xb8, 3, 0, },
0123     { HI3516CV300_USB2_HST_PHY_CLK, "clk_usb2_hst_phy", NULL, 0,
0124         0xb8, 4, 0, },
0125     { HI3516CV300_USB2_UTMI0_CLK, "clk_usb2_utmi0", NULL, 0, 0xb8, 5, 0, },
0126     { HI3516CV300_USB2_PHY_CLK, "clk_usb2_phy", NULL, 0, 0xb8, 7, 0, },
0127 };
0128 
0129 static struct hisi_clock_data *hi3516cv300_clk_register(
0130         struct platform_device *pdev)
0131 {
0132     struct hisi_clock_data *clk_data;
0133     int ret;
0134 
0135     clk_data = hisi_clk_alloc(pdev, HI3516CV300_CRG_NR_CLKS);
0136     if (!clk_data)
0137         return ERR_PTR(-ENOMEM);
0138 
0139     ret = hisi_clk_register_fixed_rate(hi3516cv300_fixed_rate_clks,
0140             ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
0141     if (ret)
0142         return ERR_PTR(ret);
0143 
0144     ret = hisi_clk_register_mux(hi3516cv300_mux_clks,
0145             ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
0146     if (ret)
0147         goto unregister_fixed_rate;
0148 
0149     ret = hisi_clk_register_gate(hi3516cv300_gate_clks,
0150             ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
0151     if (ret)
0152         goto unregister_mux;
0153 
0154     ret = of_clk_add_provider(pdev->dev.of_node,
0155             of_clk_src_onecell_get, &clk_data->clk_data);
0156     if (ret)
0157         goto unregister_gate;
0158 
0159     return clk_data;
0160 
0161 unregister_gate:
0162     hisi_clk_unregister_gate(hi3516cv300_gate_clks,
0163                 ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
0164 unregister_mux:
0165     hisi_clk_unregister_mux(hi3516cv300_mux_clks,
0166             ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
0167 unregister_fixed_rate:
0168     hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
0169             ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
0170     return ERR_PTR(ret);
0171 }
0172 
0173 static void hi3516cv300_clk_unregister(struct platform_device *pdev)
0174 {
0175     struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
0176 
0177     of_clk_del_provider(pdev->dev.of_node);
0178 
0179     hisi_clk_unregister_gate(hi3516cv300_gate_clks,
0180             ARRAY_SIZE(hi3516cv300_gate_clks), crg->clk_data);
0181     hisi_clk_unregister_mux(hi3516cv300_mux_clks,
0182             ARRAY_SIZE(hi3516cv300_mux_clks), crg->clk_data);
0183     hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
0184             ARRAY_SIZE(hi3516cv300_fixed_rate_clks), crg->clk_data);
0185 }
0186 
0187 static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
0188     .register_clks = hi3516cv300_clk_register,
0189     .unregister_clks = hi3516cv300_clk_unregister,
0190 };
0191 
0192 /* hi3516CV300 sysctrl CRG */
0193 #define HI3516CV300_SYSCTRL_NR_CLKS 16
0194 
0195 static const char *const wdt_mux_p[] __initconst = { "3m", "apb" };
0196 static u32 wdt_mux_table[] = {0, 1};
0197 
0198 static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
0199     { HI3516CV300_WDT_CLK, "wdt", wdt_mux_p, ARRAY_SIZE(wdt_mux_p),
0200         CLK_SET_RATE_PARENT, 0x0, 23, 1, 0, wdt_mux_table, },
0201 };
0202 
0203 static struct hisi_clock_data *hi3516cv300_sysctrl_clk_register(
0204         struct platform_device *pdev)
0205 {
0206     struct hisi_clock_data *clk_data;
0207     int ret;
0208 
0209     clk_data = hisi_clk_alloc(pdev, HI3516CV300_SYSCTRL_NR_CLKS);
0210     if (!clk_data)
0211         return ERR_PTR(-ENOMEM);
0212 
0213     ret = hisi_clk_register_mux(hi3516cv300_sysctrl_mux_clks,
0214             ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
0215     if (ret)
0216         return ERR_PTR(ret);
0217 
0218 
0219     ret = of_clk_add_provider(pdev->dev.of_node,
0220             of_clk_src_onecell_get, &clk_data->clk_data);
0221     if (ret)
0222         goto unregister_mux;
0223 
0224     return clk_data;
0225 
0226 unregister_mux:
0227     hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
0228             ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
0229     return ERR_PTR(ret);
0230 }
0231 
0232 static void hi3516cv300_sysctrl_clk_unregister(struct platform_device *pdev)
0233 {
0234     struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
0235 
0236     of_clk_del_provider(pdev->dev.of_node);
0237 
0238     hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
0239             ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
0240             crg->clk_data);
0241 }
0242 
0243 static const struct hisi_crg_funcs hi3516cv300_sysctrl_funcs = {
0244     .register_clks = hi3516cv300_sysctrl_clk_register,
0245     .unregister_clks = hi3516cv300_sysctrl_clk_unregister,
0246 };
0247 
0248 static const struct of_device_id hi3516cv300_crg_match_table[] = {
0249     {
0250         .compatible = "hisilicon,hi3516cv300-crg",
0251         .data = &hi3516cv300_crg_funcs
0252     },
0253     {
0254         .compatible = "hisilicon,hi3516cv300-sysctrl",
0255         .data = &hi3516cv300_sysctrl_funcs
0256     },
0257     { }
0258 };
0259 MODULE_DEVICE_TABLE(of, hi3516cv300_crg_match_table);
0260 
0261 static int hi3516cv300_crg_probe(struct platform_device *pdev)
0262 {
0263     struct hisi_crg_dev *crg;
0264 
0265     crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
0266     if (!crg)
0267         return -ENOMEM;
0268 
0269     crg->funcs = of_device_get_match_data(&pdev->dev);
0270     if (!crg->funcs)
0271         return -ENOENT;
0272 
0273     crg->rstc = hisi_reset_init(pdev);
0274     if (!crg->rstc)
0275         return -ENOMEM;
0276 
0277     crg->clk_data = crg->funcs->register_clks(pdev);
0278     if (IS_ERR(crg->clk_data)) {
0279         hisi_reset_exit(crg->rstc);
0280         return PTR_ERR(crg->clk_data);
0281     }
0282 
0283     platform_set_drvdata(pdev, crg);
0284     return 0;
0285 }
0286 
0287 static int hi3516cv300_crg_remove(struct platform_device *pdev)
0288 {
0289     struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
0290 
0291     hisi_reset_exit(crg->rstc);
0292     crg->funcs->unregister_clks(pdev);
0293     return 0;
0294 }
0295 
0296 static struct platform_driver hi3516cv300_crg_driver = {
0297     .probe          = hi3516cv300_crg_probe,
0298     .remove     = hi3516cv300_crg_remove,
0299     .driver         = {
0300         .name   = "hi3516cv300-crg",
0301         .of_match_table = hi3516cv300_crg_match_table,
0302     },
0303 };
0304 
0305 static int __init hi3516cv300_crg_init(void)
0306 {
0307     return platform_driver_register(&hi3516cv300_crg_driver);
0308 }
0309 core_initcall(hi3516cv300_crg_init);
0310 
0311 static void __exit hi3516cv300_crg_exit(void)
0312 {
0313     platform_driver_unregister(&hi3516cv300_crg_driver);
0314 }
0315 module_exit(hi3516cv300_crg_exit);
0316 
0317 MODULE_LICENSE("GPL v2");
0318 MODULE_DESCRIPTION("HiSilicon Hi3516CV300 CRG Driver");