Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Clock driver for Hi655x
0004  *
0005  * Copyright (c) 2017, Linaro Ltd.
0006  *
0007  * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
0008  */
0009 #include <linux/clk-provider.h>
0010 #include <linux/module.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/regmap.h>
0013 #include <linux/slab.h>
0014 #include <linux/mfd/core.h>
0015 #include <linux/mfd/hi655x-pmic.h>
0016 
0017 #define HI655X_CLK_BASE HI655X_BUS_ADDR(0x1c)
0018 #define HI655X_CLK_SET  BIT(6)
0019 
0020 struct hi655x_clk {
0021     struct hi655x_pmic *hi655x;
0022     struct clk_hw       clk_hw;
0023 };
0024 
0025 static unsigned long hi655x_clk_recalc_rate(struct clk_hw *hw,
0026                         unsigned long parent_rate)
0027 {
0028     return 32768;
0029 }
0030 
0031 static int hi655x_clk_enable(struct clk_hw *hw, bool enable)
0032 {
0033     struct hi655x_clk *hi655x_clk =
0034         container_of(hw, struct hi655x_clk, clk_hw);
0035 
0036     struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
0037 
0038     return regmap_update_bits(hi655x->regmap, HI655X_CLK_BASE,
0039                   HI655X_CLK_SET, enable ? HI655X_CLK_SET : 0);
0040 }
0041 
0042 static int hi655x_clk_prepare(struct clk_hw *hw)
0043 {
0044     return hi655x_clk_enable(hw, true);
0045 }
0046 
0047 static void hi655x_clk_unprepare(struct clk_hw *hw)
0048 {
0049     hi655x_clk_enable(hw, false);
0050 }
0051 
0052 static int hi655x_clk_is_prepared(struct clk_hw *hw)
0053 {
0054     struct hi655x_clk *hi655x_clk =
0055         container_of(hw, struct hi655x_clk, clk_hw);
0056     struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
0057     int ret;
0058     uint32_t val;
0059 
0060     ret = regmap_read(hi655x->regmap, HI655X_CLK_BASE, &val);
0061     if (ret < 0)
0062         return ret;
0063 
0064     return val & HI655X_CLK_BASE;
0065 }
0066 
0067 static const struct clk_ops hi655x_clk_ops = {
0068     .prepare     = hi655x_clk_prepare,
0069     .unprepare   = hi655x_clk_unprepare,
0070     .is_prepared = hi655x_clk_is_prepared,
0071     .recalc_rate = hi655x_clk_recalc_rate,
0072 };
0073 
0074 static int hi655x_clk_probe(struct platform_device *pdev)
0075 {
0076     struct device *parent = pdev->dev.parent;
0077     struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
0078     struct hi655x_clk *hi655x_clk;
0079     const char *clk_name = "hi655x-clk";
0080     struct clk_init_data init = {
0081         .name = clk_name,
0082         .ops = &hi655x_clk_ops
0083     };
0084     int ret;
0085 
0086     hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
0087     if (!hi655x_clk)
0088         return -ENOMEM;
0089 
0090     of_property_read_string_index(parent->of_node, "clock-output-names",
0091                       0, &clk_name);
0092 
0093     hi655x_clk->clk_hw.init = &init;
0094     hi655x_clk->hi655x  = hi655x;
0095 
0096     platform_set_drvdata(pdev, hi655x_clk);
0097 
0098     ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
0099     if (ret)
0100         return ret;
0101 
0102     return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
0103                        &hi655x_clk->clk_hw);
0104 }
0105 
0106 static struct platform_driver hi655x_clk_driver = {
0107     .probe =  hi655x_clk_probe,
0108     .driver     = {
0109         .name   = "hi655x-clk",
0110     },
0111 };
0112 
0113 module_platform_driver(hi655x_clk_driver);
0114 
0115 MODULE_DESCRIPTION("Clk driver for the hi655x series PMICs");
0116 MODULE_AUTHOR("Daniel Lezcano <daniel.lezcano@linaro.org>");
0117 MODULE_LICENSE("GPL");
0118 MODULE_ALIAS("platform:hi655x-clk");