18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci// Copyright (c) 2018, The Linux Foundation. All rights reserved.
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#include <linux/kernel.h>
58c2ecf20Sopenharmony_ci#include <linux/init.h>
68c2ecf20Sopenharmony_ci#include <linux/module.h>
78c2ecf20Sopenharmony_ci#include <linux/platform_device.h>
88c2ecf20Sopenharmony_ci#include <linux/err.h>
98c2ecf20Sopenharmony_ci#include <linux/io.h>
108c2ecf20Sopenharmony_ci#include <linux/of.h>
118c2ecf20Sopenharmony_ci#include <linux/of_device.h>
128c2ecf20Sopenharmony_ci#include <linux/clk.h>
138c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic const char *aux_parents[] = {
168c2ecf20Sopenharmony_ci	"pll8_vote",
178c2ecf20Sopenharmony_ci	"pxo",
188c2ecf20Sopenharmony_ci};
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic unsigned int aux_parent_map[] = {
218c2ecf20Sopenharmony_ci	3,
228c2ecf20Sopenharmony_ci	0,
238c2ecf20Sopenharmony_ci};
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistatic const struct of_device_id kpss_xcc_match_table[] = {
268c2ecf20Sopenharmony_ci	{ .compatible = "qcom,kpss-acc-v1", .data = (void *)1UL },
278c2ecf20Sopenharmony_ci	{ .compatible = "qcom,kpss-gcc" },
288c2ecf20Sopenharmony_ci	{}
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic int kpss_xcc_driver_probe(struct platform_device *pdev)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	const struct of_device_id *id;
358c2ecf20Sopenharmony_ci	struct clk *clk;
368c2ecf20Sopenharmony_ci	struct resource *res;
378c2ecf20Sopenharmony_ci	void __iomem *base;
388c2ecf20Sopenharmony_ci	const char *name;
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci	id = of_match_device(kpss_xcc_match_table, &pdev->dev);
418c2ecf20Sopenharmony_ci	if (!id)
428c2ecf20Sopenharmony_ci		return -ENODEV;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
458c2ecf20Sopenharmony_ci	base = devm_ioremap_resource(&pdev->dev, res);
468c2ecf20Sopenharmony_ci	if (IS_ERR(base))
478c2ecf20Sopenharmony_ci		return PTR_ERR(base);
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	if (id->data) {
508c2ecf20Sopenharmony_ci		if (of_property_read_string_index(pdev->dev.of_node,
518c2ecf20Sopenharmony_ci						  "clock-output-names",
528c2ecf20Sopenharmony_ci						  0, &name))
538c2ecf20Sopenharmony_ci			return -ENODEV;
548c2ecf20Sopenharmony_ci		base += 0x14;
558c2ecf20Sopenharmony_ci	} else {
568c2ecf20Sopenharmony_ci		name = "acpu_l2_aux";
578c2ecf20Sopenharmony_ci		base += 0x28;
588c2ecf20Sopenharmony_ci	}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	clk = clk_register_mux_table(&pdev->dev, name, aux_parents,
618c2ecf20Sopenharmony_ci				     ARRAY_SIZE(aux_parents), 0, base, 0, 0x3,
628c2ecf20Sopenharmony_ci				     0, aux_parent_map, NULL);
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, clk);
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci	return PTR_ERR_OR_ZERO(clk);
678c2ecf20Sopenharmony_ci}
688c2ecf20Sopenharmony_ci
698c2ecf20Sopenharmony_cistatic int kpss_xcc_driver_remove(struct platform_device *pdev)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	clk_unregister_mux(platform_get_drvdata(pdev));
728c2ecf20Sopenharmony_ci	return 0;
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic struct platform_driver kpss_xcc_driver = {
768c2ecf20Sopenharmony_ci	.probe = kpss_xcc_driver_probe,
778c2ecf20Sopenharmony_ci	.remove = kpss_xcc_driver_remove,
788c2ecf20Sopenharmony_ci	.driver = {
798c2ecf20Sopenharmony_ci		.name = "kpss-xcc",
808c2ecf20Sopenharmony_ci		.of_match_table = kpss_xcc_match_table,
818c2ecf20Sopenharmony_ci	},
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_cimodule_platform_driver(kpss_xcc_driver);
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Krait Processor Sub System (KPSS) Clock Driver");
868c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
878c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:kpss-xcc");
88