0001
0002
0003
0004
0005
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
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
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");