Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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) }