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 Boris BREZILLON <b.brezillon@overkiz.com>
^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/clk-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) #include <linux/clkdev.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) #include <linux/clk/at91_pmc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/mfd/syscon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include "pmc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #define SYSTEM_MAX_ID		31
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #define SYSTEM_MAX_NAME_SZ	32
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #define to_clk_system(hw) container_of(hw, struct clk_system, hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) struct clk_system {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	struct clk_hw hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 	struct regmap *regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	u8 id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) static inline int is_pck(int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	return (id >= 8) && (id <= 15);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) static inline bool clk_system_ready(struct regmap *regmap, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	regmap_read(regmap, AT91_PMC_SR, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	return !!(status & (1 << id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) static int clk_system_prepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	struct clk_system *sys = to_clk_system(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 	regmap_write(sys->regmap, AT91_PMC_SCER, 1 << sys->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) 	if (!is_pck(sys->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	while (!clk_system_ready(sys->regmap, sys->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 		cpu_relax();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static void clk_system_unprepare(struct clk_hw *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	struct clk_system *sys = to_clk_system(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	regmap_write(sys->regmap, AT91_PMC_SCDR, 1 << sys->id);
^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 clk_system_is_prepared(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 clk_system *sys = to_clk_system(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 	unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	regmap_read(sys->regmap, AT91_PMC_SCSR, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	if (!(status & (1 << sys->id)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	if (!is_pck(sys->id))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	regmap_read(sys->regmap, AT91_PMC_SR, &status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	return !!(status & (1 << sys->id));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) static const struct clk_ops system_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	.prepare = clk_system_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	.unprepare = clk_system_unprepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	.is_prepared = clk_system_is_prepared,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) struct clk_hw * __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) at91_clk_register_system(struct regmap *regmap, const char *name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 			 const char *parent_name, u8 id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	struct clk_system *sys;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	struct clk_hw *hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	struct clk_init_data init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	if (!parent_name || id > SYSTEM_MAX_ID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 		return ERR_PTR(-EINVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	sys = kzalloc(sizeof(*sys), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	if (!sys)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		return ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	init.name = name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	init.ops = &system_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	init.parent_names = &parent_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	init.num_parents = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	init.flags = CLK_SET_RATE_PARENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	sys->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	sys->hw.init = &init;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	sys->regmap = regmap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	hw = &sys->hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	ret = clk_hw_register(NULL, &sys->hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		kfree(sys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		hw = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	return hw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }