^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * drivers/clk/at91/clk-slow.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/clk/at91_pmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "pmc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) struct clk_sam9260_slow {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define to_clk_sam9260_slow(hw) container_of(hw, struct clk_sam9260_slow, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) static u8 clk_sam9260_slow_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct clk_sam9260_slow *slowck = to_clk_sam9260_slow(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) regmap_read(slowck->regmap, AT91_PMC_SR, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return status & AT91_PMC_OSCSEL ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static const struct clk_ops sam9260_slow_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) .get_parent = clk_sam9260_slow_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) struct clk_hw * __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) at91_clk_register_sam9260_slow(struct regmap *regmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) const char **parent_names,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int num_parents)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct clk_sam9260_slow *slowck;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (!name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (!parent_names || !num_parents)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!slowck)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) init.ops = &sam9260_slow_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) init.parent_names = parent_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) init.num_parents = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) slowck->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) slowck->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) hw = &slowck->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) ret = clk_hw_register(NULL, &slowck->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) kfree(slowck);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) hw = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }