brintos

brintos / linux-shallow public Read only

0
0
Text · 2.6 KiB · 0f21816 Raw
114 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Spreadtrum clock infrastructure4//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/platform_device.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	.fast_io	= true,21};22 23static void sprd_clk_set_regmap(const struct sprd_clk_desc *desc,24			 struct regmap *regmap)25{26	int i;27	struct sprd_clk_common *cclk;28 29	for (i = 0; i < desc->num_clk_clks; i++) {30		cclk = desc->clk_clks[i];31		if (!cclk)32			continue;33 34		cclk->regmap = regmap;35	}36}37 38int sprd_clk_regmap_init(struct platform_device *pdev,39			 const struct sprd_clk_desc *desc)40{41	void __iomem *base;42	struct device *dev = &pdev->dev;43	struct device_node *node = dev->of_node, *np;44	struct regmap *regmap;45	struct resource *res;46	struct regmap_config reg_config = sprdclk_regmap_config;47 48	if (of_property_present(node, "sprd,syscon")) {49		regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");50		if (IS_ERR(regmap)) {51			pr_err("%s: failed to get syscon regmap\n", __func__);52			return PTR_ERR(regmap);53		}54	} else if (of_device_is_compatible(np =	of_get_parent(node), "syscon") ||55		   (of_node_put(np), 0)) {56		regmap = device_node_to_regmap(np);57		of_node_put(np);58		if (IS_ERR(regmap)) {59			dev_err(dev, "failed to get regmap from its parent.\n");60			return PTR_ERR(regmap);61		}62	} else {63		base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);64		if (IS_ERR(base))65			return PTR_ERR(base);66 67		reg_config.max_register = resource_size(res) - reg_config.reg_stride;68 69		regmap = devm_regmap_init_mmio(&pdev->dev, base,70					       &reg_config);71		if (IS_ERR(regmap)) {72			pr_err("failed to init regmap\n");73			return PTR_ERR(regmap);74		}75	}76 77	sprd_clk_set_regmap(desc, regmap);78 79	return 0;80}81EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);82 83int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)84{85	int i, ret;86	struct clk_hw *hw;87 88	for (i = 0; i < clkhw->num; i++) {89		const char *name;90 91		hw = clkhw->hws[i];92		if (!hw)93			continue;94 95		name = hw->init->name;96		ret = devm_clk_hw_register(dev, hw);97		if (ret) {98			dev_err(dev, "Couldn't register clock %d - %s\n",99				i, name);100			return ret;101		}102	}103 104	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);105	if (ret)106		dev_err(dev, "Failed to add clock provider\n");107 108	return ret;109}110EXPORT_SYMBOL_GPL(sprd_clk_probe);111 112MODULE_DESCRIPTION("Spreadtrum clock infrastructure");113MODULE_LICENSE("GPL v2");114