Linux Audio

Check our new training course

Loading...
v5.4
  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_node *node = pdev->dev.of_node;
 
 44	struct regmap *regmap;
 45	struct resource *res;
 46
 47	if (of_find_property(node, "sprd,syscon", NULL)) {
 48		regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
 49		if (IS_ERR_OR_NULL(regmap)) {
 50			pr_err("%s: failed to get syscon regmap\n", __func__);
 51			return PTR_ERR(regmap);
 52		}
 
 
 
 
 
 
 
 
 53	} else {
 54		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 55		base = devm_ioremap_resource(&pdev->dev, res);
 56		if (IS_ERR(base))
 57			return PTR_ERR(base);
 58
 59		regmap = devm_regmap_init_mmio(&pdev->dev, base,
 60					       &sprdclk_regmap_config);
 61		if (IS_ERR(regmap)) {
 62			pr_err("failed to init regmap\n");
 63			return PTR_ERR(regmap);
 64		}
 65	}
 66
 67	sprd_clk_set_regmap(desc, regmap);
 68
 69	return 0;
 70}
 71EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
 72
 73int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
 74{
 75	int i, ret;
 76	struct clk_hw *hw;
 77
 78	for (i = 0; i < clkhw->num; i++) {
 79		const char *name;
 80
 81		hw = clkhw->hws[i];
 82		if (!hw)
 83			continue;
 84
 85		name = hw->init->name;
 86		ret = devm_clk_hw_register(dev, hw);
 87		if (ret) {
 88			dev_err(dev, "Couldn't register clock %d - %s\n",
 89				i, name);
 90			return ret;
 91		}
 92	}
 93
 94	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);
 95	if (ret)
 96		dev_err(dev, "Failed to add clock provider\n");
 97
 98	return ret;
 99}
100EXPORT_SYMBOL_GPL(sprd_clk_probe);
101
102MODULE_LICENSE("GPL v2");
v6.2
  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, *np;
 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(np =	of_get_parent(node), "syscon") ||
 54		   (of_node_put(np), 0)) {
 55		regmap = device_node_to_regmap(np);
 56		of_node_put(np);
 57		if (IS_ERR(regmap)) {
 58			dev_err(dev, "failed to get regmap from its parent.\n");
 59			return PTR_ERR(regmap);
 60		}
 61	} else {
 62		base = devm_platform_ioremap_resource(pdev, 0);
 
 63		if (IS_ERR(base))
 64			return PTR_ERR(base);
 65
 66		regmap = devm_regmap_init_mmio(&pdev->dev, base,
 67					       &sprdclk_regmap_config);
 68		if (IS_ERR(regmap)) {
 69			pr_err("failed to init regmap\n");
 70			return PTR_ERR(regmap);
 71		}
 72	}
 73
 74	sprd_clk_set_regmap(desc, regmap);
 75
 76	return 0;
 77}
 78EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
 79
 80int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
 81{
 82	int i, ret;
 83	struct clk_hw *hw;
 84
 85	for (i = 0; i < clkhw->num; i++) {
 86		const char *name;
 87
 88		hw = clkhw->hws[i];
 89		if (!hw)
 90			continue;
 91
 92		name = hw->init->name;
 93		ret = devm_clk_hw_register(dev, hw);
 94		if (ret) {
 95			dev_err(dev, "Couldn't register clock %d - %s\n",
 96				i, name);
 97			return ret;
 98		}
 99	}
100
101	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);
102	if (ret)
103		dev_err(dev, "Failed to add clock provider\n");
104
105	return ret;
106}
107EXPORT_SYMBOL_GPL(sprd_clk_probe);
108
109MODULE_LICENSE("GPL v2");