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
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  3)  * Copyright (c) 2014 Marvell Technology Group Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  5)  * Alexandre Belloni <alexandre.belloni@free-electrons.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  6)  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
^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/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/div64.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "berlin2-div.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include "berlin2-pll.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct berlin2_pll {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) 	struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) 	void __iomem *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) 	struct berlin2_pll_map map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define to_berlin2_pll(hw) container_of(hw, struct berlin2_pll, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define SPLL_CTRL0	0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define SPLL_CTRL1	0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define SPLL_CTRL2	0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define SPLL_CTRL3	0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define SPLL_CTRL4	0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define FBDIV_MASK	0x1ff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define RFDIV_MASK	0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define DIVSEL_MASK	0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)  * The output frequency formula for the pll is:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)  * clkout = fbdiv / refdiv * parent / vcodiv
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static unsigned long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) berlin2_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) 	struct berlin2_pll *pll = to_berlin2_pll(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) 	struct berlin2_pll_map *map = &pll->map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 	u32 val, fbdiv, rfdiv, vcodivsel, vcodiv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) 	u64 rate = parent_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) 	val = readl_relaxed(pll->base + SPLL_CTRL0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) 	fbdiv = (val >> map->fbdiv_shift) & FBDIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) 	rfdiv = (val >> map->rfdiv_shift) & RFDIV_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) 	if (rfdiv == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) 		pr_warn("%s has zero rfdiv\n", clk_hw_get_name(hw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) 		rfdiv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) 	val = readl_relaxed(pll->base + SPLL_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) 	vcodivsel = (val >> map->divsel_shift) & DIVSEL_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) 	vcodiv = map->vcodiv[vcodivsel];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) 	if (vcodiv == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 		pr_warn("%s has zero vcodiv (index %d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) 			clk_hw_get_name(hw), vcodivsel);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) 		vcodiv = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) 	rate *= fbdiv * map->mult;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) 	do_div(rate, rfdiv * vcodiv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) 	return (unsigned long)rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static const struct clk_ops berlin2_pll_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) 	.recalc_rate	= berlin2_pll_recalc_rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) int __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) berlin2_pll_register(const struct berlin2_pll_map *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) 		     void __iomem *base, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) 		     const char *parent_name, unsigned long flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) 	struct berlin2_pll *pll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) 	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) 	if (!pll)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) 	/* copy pll_map to allow __initconst */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) 	memcpy(&pll->map, map, sizeof(*map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) 	pll->base = base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) 	pll->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) 	init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) 	init.ops = &berlin2_pll_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) 	init.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) 	init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) 	init.flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) 	return clk_hw_register(NULL, &pll->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }