brintos

brintos / linux-shallow public Read only

0
0
Text · 4.3 KiB · e6b815a Raw
186 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.4 */5 6#include <linux/clk-provider.h>7#include <linux/platform_device.h>8#include <linux/pm_clock.h>9#include <linux/pm_runtime.h>10#include <linux/module.h>11#include <linux/of_address.h>12#include <linux/regmap.h>13 14#include <dt-bindings/clock/qcom,lpass-sc7280.h>15 16#include "clk-regmap.h"17#include "clk-branch.h"18#include "common.h"19 20static struct clk_branch lpass_top_cc_lpi_q6_axim_hs_clk = {21	.halt_reg = 0x0,22	.halt_check = BRANCH_HALT,23	.clkr = {24		.enable_reg = 0x0,25		.enable_mask = BIT(0),26		.hw.init = &(struct clk_init_data){27			.name = "lpass_top_cc_lpi_q6_axim_hs_clk",28			.ops = &clk_branch2_ops,29		},30	},31};32 33static struct clk_branch lpass_qdsp6ss_core_clk = {34	.halt_reg = 0x20,35	/* CLK_OFF would not toggle until LPASS is out of reset */36	.halt_check = BRANCH_HALT_SKIP,37	.clkr = {38		.enable_reg = 0x20,39		.enable_mask = BIT(0),40		.hw.init = &(struct clk_init_data){41			.name = "lpass_qdsp6ss_core_clk",42			.ops = &clk_branch2_ops,43		},44	},45};46 47static struct clk_branch lpass_qdsp6ss_xo_clk = {48	.halt_reg = 0x38,49	/* CLK_OFF would not toggle until LPASS is out of reset */50	.halt_check = BRANCH_HALT_SKIP,51	.clkr = {52		.enable_reg = 0x38,53		.enable_mask = BIT(0),54		.hw.init = &(struct clk_init_data){55			.name = "lpass_qdsp6ss_xo_clk",56			.ops = &clk_branch2_ops,57		},58	},59};60 61static struct clk_branch lpass_qdsp6ss_sleep_clk = {62	.halt_reg = 0x3c,63	/* CLK_OFF would not toggle until LPASS is out of reset */64	.halt_check = BRANCH_HALT_SKIP,65	.clkr = {66		.enable_reg = 0x3c,67		.enable_mask = BIT(0),68		.hw.init = &(struct clk_init_data){69			.name = "lpass_qdsp6ss_sleep_clk",70			.ops = &clk_branch2_ops,71		},72	},73};74 75static struct regmap_config lpass_regmap_config = {76	.reg_bits	= 32,77	.reg_stride	= 4,78	.val_bits	= 32,79	.fast_io	= true,80};81 82static struct clk_regmap *lpass_cc_top_sc7280_clocks[] = {83	[LPASS_TOP_CC_LPI_Q6_AXIM_HS_CLK] =84				&lpass_top_cc_lpi_q6_axim_hs_clk.clkr,85};86 87static const struct qcom_cc_desc lpass_cc_top_sc7280_desc = {88	.config = &lpass_regmap_config,89	.clks = lpass_cc_top_sc7280_clocks,90	.num_clks = ARRAY_SIZE(lpass_cc_top_sc7280_clocks),91};92 93static struct clk_regmap *lpass_qdsp6ss_sc7280_clocks[] = {94	[LPASS_QDSP6SS_XO_CLK] = &lpass_qdsp6ss_xo_clk.clkr,95	[LPASS_QDSP6SS_SLEEP_CLK] = &lpass_qdsp6ss_sleep_clk.clkr,96	[LPASS_QDSP6SS_CORE_CLK] = &lpass_qdsp6ss_core_clk.clkr,97};98 99static const struct qcom_cc_desc lpass_qdsp6ss_sc7280_desc = {100	.config = &lpass_regmap_config,101	.clks = lpass_qdsp6ss_sc7280_clocks,102	.num_clks = ARRAY_SIZE(lpass_qdsp6ss_sc7280_clocks),103};104 105static int lpass_cc_sc7280_probe(struct platform_device *pdev)106{107	const struct qcom_cc_desc *desc;108	int ret;109 110	ret = devm_pm_runtime_enable(&pdev->dev);111	if (ret)112		return ret;113 114	ret = pm_clk_create(&pdev->dev);115	if (ret)116		return ret;117 118	ret = pm_clk_add(&pdev->dev, "iface");119	if (ret < 0) {120		dev_err(&pdev->dev, "failed to acquire iface clock\n");121		goto err_destroy_pm_clk;122	}123 124	ret = pm_runtime_resume_and_get(&pdev->dev);125	if (ret)126		goto err_destroy_pm_clk;127 128	if (!of_property_read_bool(pdev->dev.of_node, "qcom,adsp-pil-mode")) {129		lpass_regmap_config.name = "qdsp6ss";130		lpass_regmap_config.max_register = 0x3f;131		desc = &lpass_qdsp6ss_sc7280_desc;132 133		ret = qcom_cc_probe_by_index(pdev, 0, desc);134		if (ret)135			goto err_put_rpm;136	}137 138	lpass_regmap_config.name = "top_cc";139	lpass_regmap_config.max_register = 0x4;140	desc = &lpass_cc_top_sc7280_desc;141 142	ret = qcom_cc_probe_by_index(pdev, 1, desc);143	if (ret)144		goto err_put_rpm;145 146	pm_runtime_put(&pdev->dev);147 148	return 0;149 150err_put_rpm:151	pm_runtime_put_sync(&pdev->dev);152err_destroy_pm_clk:153	pm_clk_destroy(&pdev->dev);154 155	return ret;156}157 158static const struct of_device_id lpass_cc_sc7280_match_table[] = {159	{ .compatible = "qcom,sc7280-lpasscc" },160	{ }161};162MODULE_DEVICE_TABLE(of, lpass_cc_sc7280_match_table);163 164static struct platform_driver lpass_cc_sc7280_driver = {165	.probe		= lpass_cc_sc7280_probe,166	.driver		= {167		.name	= "sc7280-lpasscc",168		.of_match_table = lpass_cc_sc7280_match_table,169	},170};171 172static int __init lpass_cc_sc7280_init(void)173{174	return platform_driver_register(&lpass_cc_sc7280_driver);175}176subsys_initcall(lpass_cc_sc7280_init);177 178static void __exit lpass_cc_sc7280_exit(void)179{180	platform_driver_unregister(&lpass_cc_sc7280_driver);181}182module_exit(lpass_cc_sc7280_exit);183 184MODULE_DESCRIPTION("QTI LPASS_CC SC7280 Driver");185MODULE_LICENSE("GPL v2");186