162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// Copyright (c) 2018, The Linux Foundation. All rights reserved. 362306a36Sopenharmony_ci#include <linux/clk-provider.h> 462306a36Sopenharmony_ci#include <linux/module.h> 562306a36Sopenharmony_ci#include <linux/of.h> 662306a36Sopenharmony_ci#include <linux/platform_device.h> 762306a36Sopenharmony_ci#include <linux/regmap.h> 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include "clk-alpha-pll.h" 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * Even though APSS PLL type is of existing one (like Huayra), its offsets 1362306a36Sopenharmony_ci * are different from the one mentioned in the clk-alpha-pll.c, since the 1462306a36Sopenharmony_ci * PLL is specific to APSS, so lets the define the same. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_cistatic const u8 ipq_pll_offsets[][PLL_OFF_MAX_REGS] = { 1762306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_HUAYRA] = { 1862306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x08, 1962306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x10, 2062306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x18, 2162306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x20, 2262306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x24, 2362306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x28, 2462306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x30, 2562306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x34, 2662306a36Sopenharmony_ci }, 2762306a36Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_STROMER_PLUS] = { 2862306a36Sopenharmony_ci [PLL_OFF_L_VAL] = 0x08, 2962306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL] = 0x10, 3062306a36Sopenharmony_ci [PLL_OFF_ALPHA_VAL_U] = 0x14, 3162306a36Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x18, 3262306a36Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x1c, 3362306a36Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x20, 3462306a36Sopenharmony_ci [PLL_OFF_STATUS] = 0x28, 3562306a36Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x30, 3662306a36Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x34, 3762306a36Sopenharmony_ci }, 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic struct clk_alpha_pll ipq_pll_huayra = { 4162306a36Sopenharmony_ci .offset = 0x0, 4262306a36Sopenharmony_ci .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_HUAYRA], 4362306a36Sopenharmony_ci .flags = SUPPORTS_DYNAMIC_UPDATE, 4462306a36Sopenharmony_ci .clkr = { 4562306a36Sopenharmony_ci .enable_reg = 0x0, 4662306a36Sopenharmony_ci .enable_mask = BIT(0), 4762306a36Sopenharmony_ci .hw.init = &(struct clk_init_data){ 4862306a36Sopenharmony_ci .name = "a53pll", 4962306a36Sopenharmony_ci .parent_data = &(const struct clk_parent_data) { 5062306a36Sopenharmony_ci .fw_name = "xo", 5162306a36Sopenharmony_ci }, 5262306a36Sopenharmony_ci .num_parents = 1, 5362306a36Sopenharmony_ci .ops = &clk_alpha_pll_huayra_ops, 5462306a36Sopenharmony_ci }, 5562306a36Sopenharmony_ci }, 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic struct clk_alpha_pll ipq_pll_stromer_plus = { 5962306a36Sopenharmony_ci .offset = 0x0, 6062306a36Sopenharmony_ci .regs = ipq_pll_offsets[CLK_ALPHA_PLL_TYPE_STROMER_PLUS], 6162306a36Sopenharmony_ci .flags = SUPPORTS_DYNAMIC_UPDATE, 6262306a36Sopenharmony_ci .clkr = { 6362306a36Sopenharmony_ci .enable_reg = 0x0, 6462306a36Sopenharmony_ci .enable_mask = BIT(0), 6562306a36Sopenharmony_ci .hw.init = &(struct clk_init_data){ 6662306a36Sopenharmony_ci .name = "a53pll", 6762306a36Sopenharmony_ci .parent_data = &(const struct clk_parent_data) { 6862306a36Sopenharmony_ci .fw_name = "xo", 6962306a36Sopenharmony_ci }, 7062306a36Sopenharmony_ci .num_parents = 1, 7162306a36Sopenharmony_ci .ops = &clk_alpha_pll_stromer_plus_ops, 7262306a36Sopenharmony_ci }, 7362306a36Sopenharmony_ci }, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic const struct alpha_pll_config ipq5332_pll_config = { 7762306a36Sopenharmony_ci .l = 0x2d, 7862306a36Sopenharmony_ci .config_ctl_val = 0x4001075b, 7962306a36Sopenharmony_ci .config_ctl_hi_val = 0x304, 8062306a36Sopenharmony_ci .main_output_mask = BIT(0), 8162306a36Sopenharmony_ci .aux_output_mask = BIT(1), 8262306a36Sopenharmony_ci .early_output_mask = BIT(3), 8362306a36Sopenharmony_ci .alpha_en_mask = BIT(24), 8462306a36Sopenharmony_ci .status_val = 0x3, 8562306a36Sopenharmony_ci .status_mask = GENMASK(10, 8), 8662306a36Sopenharmony_ci .lock_det = BIT(2), 8762306a36Sopenharmony_ci .test_ctl_hi_val = 0x00400003, 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic const struct alpha_pll_config ipq6018_pll_config = { 9162306a36Sopenharmony_ci .l = 0x37, 9262306a36Sopenharmony_ci .config_ctl_val = 0x240d4828, 9362306a36Sopenharmony_ci .config_ctl_hi_val = 0x6, 9462306a36Sopenharmony_ci .early_output_mask = BIT(3), 9562306a36Sopenharmony_ci .aux2_output_mask = BIT(2), 9662306a36Sopenharmony_ci .aux_output_mask = BIT(1), 9762306a36Sopenharmony_ci .main_output_mask = BIT(0), 9862306a36Sopenharmony_ci .test_ctl_val = 0x1c0000C0, 9962306a36Sopenharmony_ci .test_ctl_hi_val = 0x4000, 10062306a36Sopenharmony_ci}; 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic const struct alpha_pll_config ipq8074_pll_config = { 10362306a36Sopenharmony_ci .l = 0x48, 10462306a36Sopenharmony_ci .config_ctl_val = 0x200d4828, 10562306a36Sopenharmony_ci .config_ctl_hi_val = 0x6, 10662306a36Sopenharmony_ci .early_output_mask = BIT(3), 10762306a36Sopenharmony_ci .aux2_output_mask = BIT(2), 10862306a36Sopenharmony_ci .aux_output_mask = BIT(1), 10962306a36Sopenharmony_ci .main_output_mask = BIT(0), 11062306a36Sopenharmony_ci .test_ctl_val = 0x1c000000, 11162306a36Sopenharmony_ci .test_ctl_hi_val = 0x4000, 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic const struct alpha_pll_config ipq9574_pll_config = { 11562306a36Sopenharmony_ci .l = 0x3b, 11662306a36Sopenharmony_ci .config_ctl_val = 0x200d4828, 11762306a36Sopenharmony_ci .config_ctl_hi_val = 0x6, 11862306a36Sopenharmony_ci .early_output_mask = BIT(3), 11962306a36Sopenharmony_ci .aux2_output_mask = BIT(2), 12062306a36Sopenharmony_ci .aux_output_mask = BIT(1), 12162306a36Sopenharmony_ci .main_output_mask = BIT(0), 12262306a36Sopenharmony_ci .test_ctl_val = 0x0, 12362306a36Sopenharmony_ci .test_ctl_hi_val = 0x4000, 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistruct apss_pll_data { 12762306a36Sopenharmony_ci int pll_type; 12862306a36Sopenharmony_ci struct clk_alpha_pll *pll; 12962306a36Sopenharmony_ci const struct alpha_pll_config *pll_config; 13062306a36Sopenharmony_ci}; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic struct apss_pll_data ipq5332_pll_data = { 13362306a36Sopenharmony_ci .pll_type = CLK_ALPHA_PLL_TYPE_STROMER_PLUS, 13462306a36Sopenharmony_ci .pll = &ipq_pll_stromer_plus, 13562306a36Sopenharmony_ci .pll_config = &ipq5332_pll_config, 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_cistatic struct apss_pll_data ipq8074_pll_data = { 13962306a36Sopenharmony_ci .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA, 14062306a36Sopenharmony_ci .pll = &ipq_pll_huayra, 14162306a36Sopenharmony_ci .pll_config = &ipq8074_pll_config, 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_cistatic struct apss_pll_data ipq6018_pll_data = { 14562306a36Sopenharmony_ci .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA, 14662306a36Sopenharmony_ci .pll = &ipq_pll_huayra, 14762306a36Sopenharmony_ci .pll_config = &ipq6018_pll_config, 14862306a36Sopenharmony_ci}; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic struct apss_pll_data ipq9574_pll_data = { 15162306a36Sopenharmony_ci .pll_type = CLK_ALPHA_PLL_TYPE_HUAYRA, 15262306a36Sopenharmony_ci .pll = &ipq_pll_huayra, 15362306a36Sopenharmony_ci .pll_config = &ipq9574_pll_config, 15462306a36Sopenharmony_ci}; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic const struct regmap_config ipq_pll_regmap_config = { 15762306a36Sopenharmony_ci .reg_bits = 32, 15862306a36Sopenharmony_ci .reg_stride = 4, 15962306a36Sopenharmony_ci .val_bits = 32, 16062306a36Sopenharmony_ci .max_register = 0x40, 16162306a36Sopenharmony_ci .fast_io = true, 16262306a36Sopenharmony_ci}; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic int apss_ipq_pll_probe(struct platform_device *pdev) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci const struct apss_pll_data *data; 16762306a36Sopenharmony_ci struct device *dev = &pdev->dev; 16862306a36Sopenharmony_ci struct regmap *regmap; 16962306a36Sopenharmony_ci void __iomem *base; 17062306a36Sopenharmony_ci int ret; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci base = devm_platform_ioremap_resource(pdev, 0); 17362306a36Sopenharmony_ci if (IS_ERR(base)) 17462306a36Sopenharmony_ci return PTR_ERR(base); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci regmap = devm_regmap_init_mmio(dev, base, &ipq_pll_regmap_config); 17762306a36Sopenharmony_ci if (IS_ERR(regmap)) 17862306a36Sopenharmony_ci return PTR_ERR(regmap); 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci data = of_device_get_match_data(&pdev->dev); 18162306a36Sopenharmony_ci if (!data) 18262306a36Sopenharmony_ci return -ENODEV; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci if (data->pll_type == CLK_ALPHA_PLL_TYPE_HUAYRA) 18562306a36Sopenharmony_ci clk_alpha_pll_configure(data->pll, regmap, data->pll_config); 18662306a36Sopenharmony_ci else if (data->pll_type == CLK_ALPHA_PLL_TYPE_STROMER_PLUS) 18762306a36Sopenharmony_ci clk_stromer_pll_configure(data->pll, regmap, data->pll_config); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci ret = devm_clk_register_regmap(dev, &data->pll->clkr); 19062306a36Sopenharmony_ci if (ret) 19162306a36Sopenharmony_ci return ret; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, 19462306a36Sopenharmony_ci &data->pll->clkr.hw); 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic const struct of_device_id apss_ipq_pll_match_table[] = { 19862306a36Sopenharmony_ci { .compatible = "qcom,ipq5332-a53pll", .data = &ipq5332_pll_data }, 19962306a36Sopenharmony_ci { .compatible = "qcom,ipq6018-a53pll", .data = &ipq6018_pll_data }, 20062306a36Sopenharmony_ci { .compatible = "qcom,ipq8074-a53pll", .data = &ipq8074_pll_data }, 20162306a36Sopenharmony_ci { .compatible = "qcom,ipq9574-a73pll", .data = &ipq9574_pll_data }, 20262306a36Sopenharmony_ci { } 20362306a36Sopenharmony_ci}; 20462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, apss_ipq_pll_match_table); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic struct platform_driver apss_ipq_pll_driver = { 20762306a36Sopenharmony_ci .probe = apss_ipq_pll_probe, 20862306a36Sopenharmony_ci .driver = { 20962306a36Sopenharmony_ci .name = "qcom-ipq-apss-pll", 21062306a36Sopenharmony_ci .of_match_table = apss_ipq_pll_match_table, 21162306a36Sopenharmony_ci }, 21262306a36Sopenharmony_ci}; 21362306a36Sopenharmony_cimodule_platform_driver(apss_ipq_pll_driver); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ciMODULE_DESCRIPTION("Qualcomm technology Inc APSS ALPHA PLL Driver"); 21662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 217