linux/drivers/clk/clk-bd718x7.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2// Copyright (C) 2018 ROHM Semiconductors
   3
   4#include <linux/kernel.h>
   5#include <linux/module.h>
   6#include <linux/init.h>
   7#include <linux/err.h>
   8#include <linux/platform_device.h>
   9#include <linux/slab.h>
  10#include <linux/mfd/rohm-bd718x7.h>
  11#include <linux/mfd/rohm-bd70528.h>
  12#include <linux/clk-provider.h>
  13#include <linux/clkdev.h>
  14#include <linux/regmap.h>
  15
  16struct bd718xx_clk {
  17        struct clk_hw hw;
  18        u8 reg;
  19        u8 mask;
  20        struct platform_device *pdev;
  21        struct rohm_regmap_dev *mfd;
  22};
  23
  24static int bd71837_clk_set(struct clk_hw *hw, int status)
  25{
  26        struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw);
  27
  28        return regmap_update_bits(c->mfd->regmap, c->reg, c->mask, status);
  29}
  30
  31static void bd71837_clk_disable(struct clk_hw *hw)
  32{
  33        int rv;
  34        struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw);
  35
  36        rv = bd71837_clk_set(hw, 0);
  37        if (rv)
  38                dev_dbg(&c->pdev->dev, "Failed to disable 32K clk (%d)\n", rv);
  39}
  40
  41static int bd71837_clk_enable(struct clk_hw *hw)
  42{
  43        return bd71837_clk_set(hw, 1);
  44}
  45
  46static int bd71837_clk_is_enabled(struct clk_hw *hw)
  47{
  48        int enabled;
  49        int rval;
  50        struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw);
  51
  52        rval = regmap_read(c->mfd->regmap, c->reg, &enabled);
  53
  54        if (rval)
  55                return rval;
  56
  57        return enabled & c->mask;
  58}
  59
  60static const struct clk_ops bd71837_clk_ops = {
  61        .prepare = &bd71837_clk_enable,
  62        .unprepare = &bd71837_clk_disable,
  63        .is_prepared = &bd71837_clk_is_enabled,
  64};
  65
  66static int bd71837_clk_probe(struct platform_device *pdev)
  67{
  68        struct bd718xx_clk *c;
  69        int rval = -ENOMEM;
  70        const char *parent_clk;
  71        struct device *parent = pdev->dev.parent;
  72        struct rohm_regmap_dev *mfd = dev_get_drvdata(parent);
  73        struct clk_init_data init = {
  74                .name = "bd718xx-32k-out",
  75                .ops = &bd71837_clk_ops,
  76        };
  77
  78        c = devm_kzalloc(&pdev->dev, sizeof(*c), GFP_KERNEL);
  79        if (!c)
  80                return -ENOMEM;
  81
  82        init.num_parents = 1;
  83        parent_clk = of_clk_get_parent_name(parent->of_node, 0);
  84
  85        init.parent_names = &parent_clk;
  86        if (!parent_clk) {
  87                dev_err(&pdev->dev, "No parent clk found\n");
  88                return -EINVAL;
  89        }
  90        switch (mfd->chip_type) {
  91        case ROHM_CHIP_TYPE_BD71837:
  92        case ROHM_CHIP_TYPE_BD71847:
  93                c->reg = BD718XX_REG_OUT32K;
  94                c->mask = BD718XX_OUT32K_EN;
  95                break;
  96        case ROHM_CHIP_TYPE_BD70528:
  97                c->reg = BD70528_REG_CLK_OUT;
  98                c->mask = BD70528_CLK_OUT_EN_MASK;
  99                break;
 100        default:
 101                dev_err(&pdev->dev, "Unknown clk chip\n");
 102                return -EINVAL;
 103        }
 104        c->mfd = mfd;
 105        c->pdev = pdev;
 106        c->hw.init = &init;
 107
 108        of_property_read_string_index(parent->of_node,
 109                                      "clock-output-names", 0, &init.name);
 110
 111        rval = devm_clk_hw_register(&pdev->dev, &c->hw);
 112        if (rval) {
 113                dev_err(&pdev->dev, "failed to register 32K clk");
 114                return rval;
 115        }
 116        rval = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get,
 117                                           &c->hw);
 118        if (rval)
 119                dev_err(&pdev->dev, "adding clk provider failed\n");
 120
 121        return rval;
 122}
 123
 124static struct platform_driver bd71837_clk = {
 125        .driver = {
 126                .name = "bd718xx-clk",
 127        },
 128        .probe = bd71837_clk_probe,
 129};
 130
 131module_platform_driver(bd71837_clk);
 132
 133MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
 134MODULE_DESCRIPTION("BD71837/BD71847/BD70528 chip clk driver");
 135MODULE_LICENSE("GPL");
 136