Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// Spreadtrum clock infrastructure
  4//
  5// Copyright (C) 2017 Spreadtrum, Inc.
  6// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
  7
  8#include <linux/mfd/syscon.h>
  9#include <linux/module.h>
 10#include <linux/of_address.h>
 11#include <linux/of_platform.h>
 12#include <linux/regmap.h>
 13
 14#include "common.h"
 15
 16static const struct regmap_config sprdclk_regmap_config = {
 17	.reg_bits	= 32,
 18	.reg_stride	= 4,
 19	.val_bits	= 32,
 20	.max_register	= 0xffff,
 21	.fast_io	= true,
 22};
 23
 24static void sprd_clk_set_regmap(const struct sprd_clk_desc *desc,
 25			 struct regmap *regmap)
 26{
 27	int i;
 28	struct sprd_clk_common *cclk;
 29
 30	for (i = 0; i < desc->num_clk_clks; i++) {
 31		cclk = desc->clk_clks[i];
 32		if (!cclk)
 33			continue;
 34
 35		cclk->regmap = regmap;
 36	}
 37}
 38
 39int sprd_clk_regmap_init(struct platform_device *pdev,
 40			 const struct sprd_clk_desc *desc)
 41{
 42	void __iomem *base;
 43	struct device *dev = &pdev->dev;
 44	struct device_node *node = dev->of_node;
 45	struct regmap *regmap;
 46
 47	if (of_find_property(node, "sprd,syscon", NULL)) {
 48		regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
 49		if (IS_ERR(regmap)) {
 50			pr_err("%s: failed to get syscon regmap\n", __func__);
 51			return PTR_ERR(regmap);
 52		}
 53	} else if (of_device_is_compatible(of_get_parent(dev->of_node),
 54			   "syscon")) {
 55		regmap = device_node_to_regmap(of_get_parent(dev->of_node));
 56		if (IS_ERR(regmap)) {
 57			dev_err(dev, "failed to get regmap from its parent.\n");
 58			return PTR_ERR(regmap);
 59		}
 60	} else {
 61		base = devm_platform_ioremap_resource(pdev, 0);
 62		if (IS_ERR(base))
 63			return PTR_ERR(base);
 64
 65		regmap = devm_regmap_init_mmio(&pdev->dev, base,
 66					       &sprdclk_regmap_config);
 67		if (IS_ERR(regmap)) {
 68			pr_err("failed to init regmap\n");
 69			return PTR_ERR(regmap);
 70		}
 71	}
 72
 73	sprd_clk_set_regmap(desc, regmap);
 74
 75	return 0;
 76}
 77EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
 78
 79int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
 80{
 81	int i, ret;
 82	struct clk_hw *hw;
 83
 84	for (i = 0; i < clkhw->num; i++) {
 85		const char *name;
 86
 87		hw = clkhw->hws[i];
 88		if (!hw)
 89			continue;
 90
 91		name = hw->init->name;
 92		ret = devm_clk_hw_register(dev, hw);
 93		if (ret) {
 94			dev_err(dev, "Couldn't register clock %d - %s\n",
 95				i, name);
 96			return ret;
 97		}
 98	}
 99
100	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);
101	if (ret)
102		dev_err(dev, "Failed to add clock provider\n");
103
104	return ret;
105}
106EXPORT_SYMBOL_GPL(sprd_clk_probe);
107
108MODULE_LICENSE("GPL v2");