^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // OWL common clock driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (c) 2014 Actions Semi Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) // Author: David Liu <liuwei@actions-semi.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // Copyright (c) 2018 Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) // Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "owl-common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static const struct regmap_config owl_regmap_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) .max_register = 0x00cc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) .fast_io = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static void owl_clk_set_regmap(const struct owl_clk_desc *desc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct regmap *regmap)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) struct owl_clk_common *clks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) for (i = 0; i < desc->num_clks; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) clks = desc->clks[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!clks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) clks->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int owl_clk_regmap_init(struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) struct owl_clk_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) base = devm_ioremap_resource(&pdev->dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (IS_ERR(base))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return PTR_ERR(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) regmap = devm_regmap_init_mmio(&pdev->dev, base, &owl_regmap_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if (IS_ERR(regmap)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) pr_err("failed to init regmap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return PTR_ERR(regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) owl_clk_set_regmap(desc, regmap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) desc->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) for (i = 0; i < hw_clks->num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) const char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) hw = hw_clks->hws[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (IS_ERR_OR_NULL(hw))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) name = hw->init->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) ret = devm_clk_hw_register(dev, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) dev_err(dev, "Couldn't register clock %d - %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) i, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_clks);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dev_err(dev, "Failed to add clock provider\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }