^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);