1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Qualcomm A53 PLL driver 4 * 5 * Copyright (c) 2017, Linaro Limited 6 * Author: Georgi Djakov <georgi.djakov@linaro.org> 7 */ 8 9 #include <linux/clk-provider.h> 10 #include <linux/kernel.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 #include <linux/module.h> 14 15 #include "clk-pll.h" 16 #include "clk-regmap.h" 17 18 static const struct pll_freq_tbl a53pll_freq[] = { 19 { 998400000, 52, 0x0, 0x1, 0 }, 20 { 1094400000, 57, 0x0, 0x1, 0 }, 21 { 1152000000, 62, 0x0, 0x1, 0 }, 22 { 1209600000, 63, 0x0, 0x1, 0 }, 23 { 1248000000, 65, 0x0, 0x1, 0 }, 24 { 1363200000, 71, 0x0, 0x1, 0 }, 25 { 1401600000, 73, 0x0, 0x1, 0 }, 26 { } 27 }; 28 29 static const struct regmap_config a53pll_regmap_config = { 30 .reg_bits = 32, 31 .reg_stride = 4, 32 .val_bits = 32, 33 .max_register = 0x40, 34 .fast_io = true, 35 }; 36 37 static int qcom_a53pll_probe(struct platform_device *pdev) 38 { 39 struct device *dev = &pdev->dev; 40 struct regmap *regmap; 41 struct resource *res; 42 struct clk_pll *pll; 43 void __iomem *base; 44 struct clk_init_data init = { }; 45 int ret; 46 47 pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); 48 if (!pll) 49 return -ENOMEM; 50 51 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 52 base = devm_ioremap_resource(dev, res); 53 if (IS_ERR(base)) 54 return PTR_ERR(base); 55 56 regmap = devm_regmap_init_mmio(dev, base, &a53pll_regmap_config); 57 if (IS_ERR(regmap)) 58 return PTR_ERR(regmap); 59 60 pll->l_reg = 0x04; 61 pll->m_reg = 0x08; 62 pll->n_reg = 0x0c; 63 pll->config_reg = 0x14; 64 pll->mode_reg = 0x00; 65 pll->status_reg = 0x1c; 66 pll->status_bit = 16; 67 pll->freq_tbl = a53pll_freq; 68 69 init.name = "a53pll"; 70 init.parent_names = (const char *[]){ "xo" }; 71 init.num_parents = 1; 72 init.ops = &clk_pll_sr2_ops; 73 init.flags = CLK_IS_CRITICAL; 74 pll->clkr.hw.init = &init; 75 76 ret = devm_clk_register_regmap(dev, &pll->clkr); 77 if (ret) { 78 dev_err(dev, "failed to register regmap clock: %d\n", ret); 79 return ret; 80 } 81 82 ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, 83 &pll->clkr.hw); 84 if (ret) { 85 dev_err(dev, "failed to add clock provider: %d\n", ret); 86 return ret; 87 } 88 89 return 0; 90 } 91 92 static const struct of_device_id qcom_a53pll_match_table[] = { 93 { .compatible = "qcom,msm8916-a53pll" }, 94 { } 95 }; 96 MODULE_DEVICE_TABLE(of, qcom_a53pll_match_table); 97 98 static struct platform_driver qcom_a53pll_driver = { 99 .probe = qcom_a53pll_probe, 100 .driver = { 101 .name = "qcom-a53pll", 102 .of_match_table = qcom_a53pll_match_table, 103 }, 104 }; 105 module_platform_driver(qcom_a53pll_driver); 106 107 MODULE_DESCRIPTION("Qualcomm A53 PLL Driver"); 108 MODULE_LICENSE("GPL v2"); 109