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 (C) 2013 Freescale Semiconductor, Inc.
^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/bits.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/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/slab.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) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * struct clk_fixup_mux - imx integer fixup multiplexer clock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * @mux: the parent class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * @ops: pointer to clk_ops of parent class
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  * @fixup: a hook to fixup the write value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * The imx fixup multiplexer clock is a subclass of basic clk_mux
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * with an addtional fixup hook.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) struct clk_fixup_mux {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	struct clk_mux mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	const struct clk_ops *ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	void (*fixup)(u32 *val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) static inline struct clk_fixup_mux *to_clk_fixup_mux(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	struct clk_mux *mux = to_clk_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	return container_of(mux, struct clk_fixup_mux, mux);
^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 u8 clk_fixup_mux_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	return fixup_mux->ops->get_parent(&fixup_mux->mux.hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) static int clk_fixup_mux_set_parent(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	struct clk_fixup_mux *fixup_mux = to_clk_fixup_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	struct clk_mux *mux = to_clk_mux(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	spin_lock_irqsave(mux->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	val = readl(mux->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	val &= ~(mux->mask << mux->shift);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	val |= index << mux->shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	fixup_mux->fixup(&val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	writel(val, mux->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	spin_unlock_irqrestore(mux->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static const struct clk_ops clk_fixup_mux_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	.get_parent = clk_fixup_mux_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	.set_parent = clk_fixup_mux_set_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) struct clk_hw *imx_clk_hw_fixup_mux(const char *name, void __iomem *reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			      u8 shift, u8 width, const char * const *parents,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 			      int num_parents, void (*fixup)(u32 *val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	struct clk_fixup_mux *fixup_mux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	if (!fixup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	fixup_mux = kzalloc(sizeof(*fixup_mux), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	if (!fixup_mux)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	init.ops = &clk_fixup_mux_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	init.parent_names = parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	init.num_parents = num_parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	init.flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	fixup_mux->mux.reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	fixup_mux->mux.shift = shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	fixup_mux->mux.mask = BIT(width) - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	fixup_mux->mux.lock = &imx_ccm_lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	fixup_mux->mux.hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	fixup_mux->ops = &clk_mux_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	fixup_mux->fixup = fixup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	hw = &fixup_mux->mux.hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	ret = clk_hw_register(NULL, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		kfree(fixup_mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 		return ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	return hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }