Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Clock driver for Hi655x
  4 *
  5 * Copyright (c) 2017, Linaro Ltd.
  6 *
  7 * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
  8 */
  9#include <linux/clk-provider.h>
 10#include <linux/module.h>
 11#include <linux/platform_device.h>
 12#include <linux/regmap.h>
 13#include <linux/slab.h>
 14#include <linux/mfd/core.h>
 15#include <linux/mfd/hi655x-pmic.h>
 16
 17#define HI655X_CLK_BASE	HI655X_BUS_ADDR(0x1c)
 18#define HI655X_CLK_SET	BIT(6)
 19
 20struct hi655x_clk {
 21	struct hi655x_pmic *hi655x;
 22	struct clk_hw       clk_hw;
 23};
 24
 25static unsigned long hi655x_clk_recalc_rate(struct clk_hw *hw,
 26					    unsigned long parent_rate)
 27{
 28	return 32768;
 29}
 30
 31static int hi655x_clk_enable(struct clk_hw *hw, bool enable)
 32{
 33	struct hi655x_clk *hi655x_clk =
 34		container_of(hw, struct hi655x_clk, clk_hw);
 35
 36	struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
 37
 38	return regmap_update_bits(hi655x->regmap, HI655X_CLK_BASE,
 39				  HI655X_CLK_SET, enable ? HI655X_CLK_SET : 0);
 40}
 41
 42static int hi655x_clk_prepare(struct clk_hw *hw)
 43{
 44	return hi655x_clk_enable(hw, true);
 45}
 46
 47static void hi655x_clk_unprepare(struct clk_hw *hw)
 48{
 49	hi655x_clk_enable(hw, false);
 50}
 51
 52static int hi655x_clk_is_prepared(struct clk_hw *hw)
 53{
 54	struct hi655x_clk *hi655x_clk =
 55		container_of(hw, struct hi655x_clk, clk_hw);
 56	struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
 57	int ret;
 58	uint32_t val;
 59
 60	ret = regmap_read(hi655x->regmap, HI655X_CLK_BASE, &val);
 61	if (ret < 0)
 62		return ret;
 63
 64	return val & HI655X_CLK_BASE;
 65}
 66
 67static const struct clk_ops hi655x_clk_ops = {
 68	.prepare     = hi655x_clk_prepare,
 69	.unprepare   = hi655x_clk_unprepare,
 70	.is_prepared = hi655x_clk_is_prepared,
 71	.recalc_rate = hi655x_clk_recalc_rate,
 72};
 73
 74static int hi655x_clk_probe(struct platform_device *pdev)
 75{
 76	struct device *parent = pdev->dev.parent;
 77	struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
 78	struct hi655x_clk *hi655x_clk;
 79	const char *clk_name = "hi655x-clk";
 80	struct clk_init_data init = {
 81		.name = clk_name,
 82		.ops = &hi655x_clk_ops
 83	};
 84	int ret;
 85
 86	hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
 87	if (!hi655x_clk)
 88		return -ENOMEM;
 89
 90	of_property_read_string_index(parent->of_node, "clock-output-names",
 91				      0, &clk_name);
 92
 93	hi655x_clk->clk_hw.init	= &init;
 94	hi655x_clk->hi655x	= hi655x;
 95
 96	platform_set_drvdata(pdev, hi655x_clk);
 97
 98	ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
 99	if (ret)
100		return ret;
101
102	return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
103					   &hi655x_clk->clk_hw);
104}
105
106static struct platform_driver hi655x_clk_driver = {
107	.probe =  hi655x_clk_probe,
108	.driver		= {
109		.name	= "hi655x-clk",
110	},
111};
112
113module_platform_driver(hi655x_clk_driver);
114
115MODULE_DESCRIPTION("Clk driver for the hi655x series PMICs");
116MODULE_AUTHOR("Daniel Lezcano <daniel.lezcano@linaro.org>");
117MODULE_LICENSE("GPL");
118MODULE_ALIAS("platform:hi655x-clk");