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 Maxime Ripard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * Maxime Ripard <maxime.ripard@free-electrons.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/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/of.h>
^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/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define TCON_CH1_SCLK2_PARENTS		4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define TCON_CH1_SCLK2_GATE_BIT		BIT(31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #define TCON_CH1_SCLK2_MUX_MASK		3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define TCON_CH1_SCLK2_MUX_SHIFT	24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #define TCON_CH1_SCLK2_DIV_MASK		0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #define TCON_CH1_SCLK2_DIV_SHIFT	0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #define TCON_CH1_SCLK1_GATE_BIT		BIT(15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #define TCON_CH1_SCLK1_HALF_BIT		BIT(11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) struct tcon_ch1_clk {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	struct clk_hw	hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	spinlock_t	lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	void __iomem	*reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #define hw_to_tclk(hw)	container_of(hw, struct tcon_ch1_clk, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) static void tcon_ch1_disable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	spin_lock_irqsave(&tclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	reg = readl(tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	reg &= ~(TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	writel(reg, tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	spin_unlock_irqrestore(&tclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) static int tcon_ch1_enable(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	spin_lock_irqsave(&tclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	reg = readl(tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	reg |= TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	writel(reg, tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	spin_unlock_irqrestore(&tclk->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 int tcon_ch1_is_enabled(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	reg = readl(tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	return reg & (TCON_CH1_SCLK2_GATE_BIT | TCON_CH1_SCLK1_GATE_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) static u8 tcon_ch1_get_parent(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	reg = readl(tclk->reg) >> TCON_CH1_SCLK2_MUX_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	reg &= reg >> TCON_CH1_SCLK2_MUX_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	return reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) static int tcon_ch1_set_parent(struct clk_hw *hw, u8 index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	spin_lock_irqsave(&tclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	reg = readl(tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	reg &= ~(TCON_CH1_SCLK2_MUX_MASK << TCON_CH1_SCLK2_MUX_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	reg |= index << TCON_CH1_SCLK2_MUX_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	writel(reg, tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	spin_unlock_irqrestore(&tclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) static unsigned long tcon_ch1_calc_divider(unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 					   unsigned long parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 					   u8 *div,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 					   bool *half)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	unsigned long best_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	u8 best_m = 0, m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	bool is_double;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	for (m = 1; m < 16; m++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		u8 d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		for (d = 1; d < 3; d++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			unsigned long tmp_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 			tmp_rate = parent_rate / m / d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 			if (tmp_rate > rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 				continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 			if (!best_rate ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			    (rate - tmp_rate) < (rate - best_rate)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 				best_rate = tmp_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 				best_m = m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 				is_double = d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (div && half) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		*div = best_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		*half = is_double;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	return best_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static int tcon_ch1_determine_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 				   struct clk_rate_request *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	long best_rate = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		unsigned long parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		unsigned long tmp_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		struct clk_hw *parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		parent = clk_hw_get_parent_by_index(hw, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 		if (!parent)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 			continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 		parent_rate = clk_hw_get_rate(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		tmp_rate = tcon_ch1_calc_divider(req->rate, parent_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 						 NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 		if (best_rate < 0 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 		    (req->rate - tmp_rate) < (req->rate - best_rate)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			best_rate = tmp_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			req->best_parent_rate = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			req->best_parent_hw = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	if (best_rate < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		return best_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	req->rate = best_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) static unsigned long tcon_ch1_recalc_rate(struct clk_hw *hw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 					  unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	reg = readl(tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	parent_rate /= (reg & TCON_CH1_SCLK2_DIV_MASK) + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	if (reg & TCON_CH1_SCLK1_HALF_BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 		parent_rate /= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	return parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static int tcon_ch1_set_rate(struct clk_hw *hw, unsigned long rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 			     unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	struct tcon_ch1_clk *tclk = hw_to_tclk(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	bool half;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	u8 div_m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	u32 reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	tcon_ch1_calc_divider(rate, parent_rate, &div_m, &half);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	spin_lock_irqsave(&tclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	reg = readl(tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 	reg &= ~(TCON_CH1_SCLK2_DIV_MASK | TCON_CH1_SCLK1_HALF_BIT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	reg |= (div_m - 1) & TCON_CH1_SCLK2_DIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	if (half)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		reg |= TCON_CH1_SCLK1_HALF_BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	writel(reg, tclk->reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 	spin_unlock_irqrestore(&tclk->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static const struct clk_ops tcon_ch1_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	.disable	= tcon_ch1_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	.enable		= tcon_ch1_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 	.is_enabled	= tcon_ch1_is_enabled,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 	.get_parent	= tcon_ch1_get_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	.set_parent	= tcon_ch1_set_parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 	.determine_rate	= tcon_ch1_determine_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	.recalc_rate	= tcon_ch1_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	.set_rate	= tcon_ch1_set_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) static void __init tcon_ch1_setup(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	const char *parents[TCON_CH1_SCLK2_PARENTS];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	const char *clk_name = node->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 	struct tcon_ch1_clk *tclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	struct resource res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	struct clk *clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	void __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	of_property_read_string(node, "clock-output-names", &clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	reg = of_io_request_and_map(node, 0, of_node_full_name(node));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	if (IS_ERR(reg)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		pr_err("%s: Could not map the clock registers\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	ret = of_clk_parent_fill(node, parents, TCON_CH1_SCLK2_PARENTS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	if (ret != TCON_CH1_SCLK2_PARENTS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		pr_err("%s Could not retrieve the parents\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		goto err_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	tclk = kzalloc(sizeof(*tclk), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	if (!tclk)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		goto err_unmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	init.name = clk_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	init.ops = &tcon_ch1_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 	init.parent_names = parents;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	init.num_parents = TCON_CH1_SCLK2_PARENTS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	init.flags = CLK_SET_RATE_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	tclk->reg = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	tclk->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	spin_lock_init(&tclk->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	clk = clk_register(NULL, &tclk->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	if (IS_ERR(clk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		pr_err("%s: Couldn't register the clock\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		goto err_free_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 		pr_err("%s: Couldn't register our clock provider\n", clk_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 		goto err_unregister_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) err_unregister_clk:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 	clk_unregister(clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) err_free_data:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	kfree(tclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) err_unmap:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 	iounmap(reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	of_address_to_resource(node, 0, &res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 	release_mem_region(res.start, resource_size(&res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) CLK_OF_DECLARE(tcon_ch1, "allwinner,sun4i-a10-tcon-ch1-clk",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 	       tcon_ch1_setup);