^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) * Copyright 2015 Heiko Stuebner <heiko@sntech.de>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "clk.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) struct rockchip_inv_clock {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) spinlock_t *lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define INVERTER_MASK 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) static int rockchip_inv_get_phase(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) val = readl(inv_clock->reg) >> inv_clock->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) val &= INVERTER_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return val ? 180 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (degrees % 180 == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) val = !!degrees;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) pr_err("%s: unsupported phase %d for %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) __func__, degrees, clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) inv_clock->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) spin_lock_irqsave(inv_clock->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) reg = readl(inv_clock->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) reg &= ~BIT(inv_clock->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) reg |= val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) writel(reg, inv_clock->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) spin_unlock_irqrestore(inv_clock->lock, flags);
^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) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static const struct clk_ops rockchip_inv_clk_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) .get_phase = rockchip_inv_get_phase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) .set_phase = rockchip_inv_set_phase,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) struct clk *rockchip_clk_register_inverter(const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) const char *const *parent_names, u8 num_parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) void __iomem *reg, int shift, int flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) spinlock_t *lock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct rockchip_inv_clock *inv_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) inv_clock = kmalloc(sizeof(*inv_clock), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!inv_clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) init.num_parents = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) init.flags = CLK_SET_RATE_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) init.parent_names = parent_names;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) init.ops = &rockchip_inv_clk_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) inv_clock->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) inv_clock->reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) inv_clock->shift = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) inv_clock->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) inv_clock->lock = lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) clk = clk_register(NULL, &inv_clock->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (IS_ERR(clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) kfree(inv_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }