Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'meson-clk-for-4.14' of git://github.com/baylibre/clk-meson into clk-next

Pull Amlogic clock driver updates from Neil Armstrong:

* meson8b: add the reset controller to the clkc
* meson: expose all clk ids
* gxbb-aoclk: Add CEC 32k clock
* gxbb: add mmc input 0 clocks
* meson: fix protection against undefined clks
* gxbb: fix audio divider flags

* tag 'meson-clk-for-4.14' of git://github.com/baylibre/clk-meson:
clk: meson: gxbb-aoclk: Add CEC 32k clock
clk: meson: gxbb-aoclk: Switch to regmap for register access
dt-bindings: clock: amlogic, gxbb-aoclkc: Update bindings
clk: meson: gxbb: Add sd_emmc clk0 clocks
clk: meson: gxbb: fix clk_mclk_i958 divider flags
clk: meson: gxbb: fix meson cts_amclk divider flags
clk: meson: meson8b: register the built-in reset controller
dt-bindings: clock: gxbb-aoclk: Add CEC 32k clock
clk: meson: gxbb: Add sd_emmc clk0 clkids
clk: meson-gxbb: expose almost every clock in the bindings
clk: meson8b: expose every clock in the bindings
clk: meson: gxbb: fix protection against undefined clks
clk: meson: meson8b: fix protection against undefined clks
dt-bindings: clock: meson8b: describe the embedded reset controller

+870 -258
+16 -6
Documentation/devicetree/bindings/clock/amlogic,gxbb-aoclkc.txt
··· 5 5 6 6 Required Properties: 7 7 8 - - compatible: should be "amlogic,gxbb-aoclkc" 9 - - reg: physical base address of the clock controller and length of memory 10 - mapped region. 8 + - compatible: value should be different for each SoC family as : 9 + - GXBB (S905) : "amlogic,meson-gxbb-aoclkc" 10 + - GXL (S905X, S905D) : "amlogic,meson-gxl-aoclkc" 11 + - GXM (S912) : "amlogic,meson-gxm-aoclkc" 12 + followed by the common "amlogic,meson-gx-aoclkc" 11 13 12 14 - #clock-cells: should be 1. 13 15 ··· 25 23 preprocessor macros in the dt-bindings/reset/gxbb-aoclkc.h header and can be 26 24 used in device tree sources. 27 25 26 + Parent node should have the following properties : 27 + - compatible: "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd" 28 + - reg: base address and size of the AO system control register space. 29 + 28 30 Example: AO Clock controller node: 29 31 30 - clkc_AO: clock-controller@040 { 31 - compatible = "amlogic,gxbb-aoclkc"; 32 - reg = <0x0 0x040 0x0 0x4>; 32 + ao_sysctrl: sys-ctrl@0 { 33 + compatible = "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd"; 34 + reg = <0x0 0x0 0x0 0x100>; 35 + 36 + clkc_AO: clock-controller { 37 + compatible = "amlogic,meson-gxbb-aoclkc", "amlogic,meson-gx-aoclkc"; 33 38 #clock-cells = <1>; 34 39 #reset-cells = <1>; 35 40 }; 41 + }; 36 42 37 43 Example: UART controller node that consumes the clock and reset generated 38 44 by the clock controller:
+8 -1
Documentation/devicetree/bindings/clock/amlogic,meson8b-clkc.txt
··· 16 16 mapped region. 17 17 18 18 - #clock-cells: should be 1. 19 + - #reset-cells: should be 1. 19 20 20 21 Each clock is assigned an identifier and client nodes can use this identifier 21 22 to specify the clock which they consume. All available clocks are defined as 22 23 preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be 23 24 used in device tree sources. 24 25 26 + Similarly a preprocessor macro for each reset line is defined in 27 + dt-bindings/reset/amlogic,meson8b-clkc-reset.h (which can be used from the 28 + device tree sources). 29 + 30 + 25 31 Example: Clock controller node: 26 32 27 33 clkc: clock-controller@c1104000 { 28 - #clock-cells = <1>; 29 34 compatible = "amlogic,meson8b-clkc"; 30 35 reg = <0xc1108000 0x4>, <0xc1104000 0x460>; 36 + #clock-cells = <1>; 37 + #reset-cells = <1>; 31 38 }; 32 39 33 40
+1
drivers/clk/meson/Kconfig
··· 6 6 config COMMON_CLK_MESON8B 7 7 bool 8 8 depends on COMMON_CLK_AMLOGIC 9 + select RESET_CONTROLLER 9 10 help 10 11 Support for the clock controller on AmLogic S802 (Meson8), 11 12 S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you
+1 -1
drivers/clk/meson/Makefile
··· 4 4 5 5 obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o 6 6 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o 7 - obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o 7 + obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o
+194
drivers/clk/meson/gxbb-aoclk-32k.c
··· 1 + /* 2 + * Copyright (c) 2017 BayLibre, SAS. 3 + * Author: Neil Armstrong <narmstrong@baylibre.com> 4 + * 5 + * SPDX-License-Identifier: GPL-2.0+ 6 + */ 7 + 8 + #include <linux/clk-provider.h> 9 + #include <linux/bitfield.h> 10 + #include <linux/regmap.h> 11 + #include "gxbb-aoclk.h" 12 + 13 + /* 14 + * The AO Domain embeds a dual/divider to generate a more precise 15 + * 32,768KHz clock for low-power suspend mode and CEC. 16 + * ______ ______ 17 + * | | | | 18 + * ______ | Div1 |-| Cnt1 | ______ 19 + * | | /|______| |______|\ | | 20 + * Xtal-->| Gate |---| ______ ______ X-X--| Gate |--> 21 + * |______| | \| | | |/ | |______| 22 + * | | Div2 |-| Cnt2 | | 23 + * | |______| |______| | 24 + * |_______________________| 25 + * 26 + * The dividing can be switched to single or dual, with a counter 27 + * for each divider to set when the switching is done. 28 + * The entire dividing mechanism can be also bypassed. 29 + */ 30 + 31 + #define CLK_CNTL0_N1_MASK GENMASK(11, 0) 32 + #define CLK_CNTL0_N2_MASK GENMASK(23, 12) 33 + #define CLK_CNTL0_DUALDIV_EN BIT(28) 34 + #define CLK_CNTL0_OUT_GATE_EN BIT(30) 35 + #define CLK_CNTL0_IN_GATE_EN BIT(31) 36 + 37 + #define CLK_CNTL1_M1_MASK GENMASK(11, 0) 38 + #define CLK_CNTL1_M2_MASK GENMASK(23, 12) 39 + #define CLK_CNTL1_BYPASS_EN BIT(24) 40 + #define CLK_CNTL1_SELECT_OSC BIT(27) 41 + 42 + #define PWR_CNTL_ALT_32K_SEL GENMASK(13, 10) 43 + 44 + struct cec_32k_freq_table { 45 + unsigned long parent_rate; 46 + unsigned long target_rate; 47 + bool dualdiv; 48 + unsigned int n1; 49 + unsigned int n2; 50 + unsigned int m1; 51 + unsigned int m2; 52 + }; 53 + 54 + static const struct cec_32k_freq_table aoclk_cec_32k_table[] = { 55 + [0] = { 56 + .parent_rate = 24000000, 57 + .target_rate = 32768, 58 + .dualdiv = true, 59 + .n1 = 733, 60 + .n2 = 732, 61 + .m1 = 8, 62 + .m2 = 11, 63 + }, 64 + }; 65 + 66 + /* 67 + * If CLK_CNTL0_DUALDIV_EN == 0 68 + * - will use N1 divider only 69 + * If CLK_CNTL0_DUALDIV_EN == 1 70 + * - hold M1 cycles of N1 divider then changes to N2 71 + * - hold M2 cycles of N2 divider then changes to N1 72 + * Then we can get more accurate division. 73 + */ 74 + static unsigned long aoclk_cec_32k_recalc_rate(struct clk_hw *hw, 75 + unsigned long parent_rate) 76 + { 77 + struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw); 78 + unsigned long n1; 79 + u32 reg0, reg1; 80 + 81 + regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, &reg0); 82 + regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, &reg1); 83 + 84 + if (reg1 & CLK_CNTL1_BYPASS_EN) 85 + return parent_rate; 86 + 87 + if (reg0 & CLK_CNTL0_DUALDIV_EN) { 88 + unsigned long n2, m1, m2, f1, f2, p1, p2; 89 + 90 + n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1; 91 + n2 = FIELD_GET(CLK_CNTL0_N2_MASK, reg0) + 1; 92 + 93 + m1 = FIELD_GET(CLK_CNTL1_M1_MASK, reg1) + 1; 94 + m2 = FIELD_GET(CLK_CNTL1_M2_MASK, reg1) + 1; 95 + 96 + f1 = DIV_ROUND_CLOSEST(parent_rate, n1); 97 + f2 = DIV_ROUND_CLOSEST(parent_rate, n2); 98 + 99 + p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2)); 100 + p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2)); 101 + 102 + return DIV_ROUND_UP(100000000, p1 + p2); 103 + } 104 + 105 + n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1; 106 + 107 + return DIV_ROUND_CLOSEST(parent_rate, n1); 108 + } 109 + 110 + static const struct cec_32k_freq_table *find_cec_32k_freq(unsigned long rate, 111 + unsigned long prate) 112 + { 113 + int i; 114 + 115 + for (i = 0 ; i < ARRAY_SIZE(aoclk_cec_32k_table) ; ++i) 116 + if (aoclk_cec_32k_table[i].parent_rate == prate && 117 + aoclk_cec_32k_table[i].target_rate == rate) 118 + return &aoclk_cec_32k_table[i]; 119 + 120 + return NULL; 121 + } 122 + 123 + static long aoclk_cec_32k_round_rate(struct clk_hw *hw, unsigned long rate, 124 + unsigned long *prate) 125 + { 126 + const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate, 127 + *prate); 128 + 129 + /* If invalid return first one */ 130 + if (!freq) 131 + return aoclk_cec_32k_table[0].target_rate; 132 + 133 + return freq->target_rate; 134 + } 135 + 136 + /* 137 + * From the Amlogic init procedure, the IN and OUT gates needs to be handled 138 + * in the init procedure to avoid any glitches. 139 + */ 140 + 141 + static int aoclk_cec_32k_set_rate(struct clk_hw *hw, unsigned long rate, 142 + unsigned long parent_rate) 143 + { 144 + const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate, 145 + parent_rate); 146 + struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw); 147 + u32 reg = 0; 148 + 149 + if (!freq) 150 + return -EINVAL; 151 + 152 + /* Disable clock */ 153 + regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, 154 + CLK_CNTL0_IN_GATE_EN | CLK_CNTL0_OUT_GATE_EN, 0); 155 + 156 + reg = FIELD_PREP(CLK_CNTL0_N1_MASK, freq->n1 - 1); 157 + if (freq->dualdiv) 158 + reg |= CLK_CNTL0_DUALDIV_EN | 159 + FIELD_PREP(CLK_CNTL0_N2_MASK, freq->n2 - 1); 160 + 161 + regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, reg); 162 + 163 + reg = FIELD_PREP(CLK_CNTL1_M1_MASK, freq->m1 - 1); 164 + if (freq->dualdiv) 165 + reg |= FIELD_PREP(CLK_CNTL1_M2_MASK, freq->m2 - 1); 166 + 167 + regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, reg); 168 + 169 + /* Enable clock */ 170 + regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, 171 + CLK_CNTL0_IN_GATE_EN, CLK_CNTL0_IN_GATE_EN); 172 + 173 + udelay(200); 174 + 175 + regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, 176 + CLK_CNTL0_OUT_GATE_EN, CLK_CNTL0_OUT_GATE_EN); 177 + 178 + regmap_update_bits(cec_32k->regmap, AO_CRT_CLK_CNTL1, 179 + CLK_CNTL1_SELECT_OSC, CLK_CNTL1_SELECT_OSC); 180 + 181 + /* Select 32k from XTAL */ 182 + regmap_update_bits(cec_32k->regmap, 183 + AO_RTI_PWR_CNTL_REG0, 184 + PWR_CNTL_ALT_32K_SEL, 185 + FIELD_PREP(PWR_CNTL_ALT_32K_SEL, 4)); 186 + 187 + return 0; 188 + } 189 + 190 + const struct clk_ops meson_aoclk_cec_32k_ops = { 191 + .recalc_rate = aoclk_cec_32k_recalc_rate, 192 + .round_rate = aoclk_cec_32k_round_rate, 193 + .set_rate = aoclk_cec_32k_set_rate, 194 + };
+46
drivers/clk/meson/gxbb-aoclk-regmap.c
··· 1 + /* 2 + * Copyright (c) 2017 BayLibre, SAS. 3 + * Author: Neil Armstrong <narmstrong@baylibre.com> 4 + * 5 + * SPDX-License-Identifier: GPL-2.0+ 6 + */ 7 + 8 + #include <linux/clk-provider.h> 9 + #include <linux/bitfield.h> 10 + #include <linux/regmap.h> 11 + #include "gxbb-aoclk.h" 12 + 13 + static int aoclk_gate_regmap_enable(struct clk_hw *hw) 14 + { 15 + struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); 16 + 17 + return regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, 18 + BIT(gate->bit_idx), BIT(gate->bit_idx)); 19 + } 20 + 21 + static void aoclk_gate_regmap_disable(struct clk_hw *hw) 22 + { 23 + struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); 24 + 25 + regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, 26 + BIT(gate->bit_idx), 0); 27 + } 28 + 29 + static int aoclk_gate_regmap_is_enabled(struct clk_hw *hw) 30 + { 31 + struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); 32 + unsigned int val; 33 + int ret; 34 + 35 + ret = regmap_read(gate->regmap, AO_RTI_GEN_CNTL_REG0, &val); 36 + if (ret) 37 + return ret; 38 + 39 + return (val & BIT(gate->bit_idx)) != 0; 40 + } 41 + 42 + const struct clk_ops meson_aoclk_gate_regmap_ops = { 43 + .enable = aoclk_gate_regmap_enable, 44 + .disable = aoclk_gate_regmap_disable, 45 + .is_enabled = aoclk_gate_regmap_is_enabled, 46 + };
+42 -23
drivers/clk/meson/gxbb-aoclk.c
··· 56 56 #include <linux/of_address.h> 57 57 #include <linux/platform_device.h> 58 58 #include <linux/reset-controller.h> 59 + #include <linux/mfd/syscon.h> 60 + #include <linux/regmap.h> 59 61 #include <linux/init.h> 62 + #include <linux/delay.h> 60 63 #include <dt-bindings/clock/gxbb-aoclkc.h> 61 64 #include <dt-bindings/reset/gxbb-aoclkc.h> 65 + #include "gxbb-aoclk.h" 62 66 63 67 static DEFINE_SPINLOCK(gxbb_aoclk_lock); 64 68 65 69 struct gxbb_aoclk_reset_controller { 66 70 struct reset_controller_dev reset; 67 71 unsigned int *data; 68 - void __iomem *base; 72 + struct regmap *regmap; 69 73 }; 70 74 71 75 static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev, ··· 78 74 struct gxbb_aoclk_reset_controller *reset = 79 75 container_of(rcdev, struct gxbb_aoclk_reset_controller, reset); 80 76 81 - writel(BIT(reset->data[id]), reset->base); 82 - 83 - return 0; 77 + return regmap_write(reset->regmap, AO_RTI_GEN_CNTL_REG0, 78 + BIT(reset->data[id])); 84 79 } 85 80 86 81 static const struct reset_control_ops gxbb_aoclk_reset_ops = { ··· 87 84 }; 88 85 89 86 #define GXBB_AO_GATE(_name, _bit) \ 90 - static struct clk_gate _name##_ao = { \ 91 - .reg = (void __iomem *)0, \ 87 + static struct aoclk_gate_regmap _name##_ao = { \ 92 88 .bit_idx = (_bit), \ 93 89 .lock = &gxbb_aoclk_lock, \ 94 90 .hw.init = &(struct clk_init_data) { \ 95 91 .name = #_name "_ao", \ 96 - .ops = &clk_gate_ops, \ 92 + .ops = &meson_aoclk_gate_regmap_ops, \ 97 93 .parent_names = (const char *[]){ "clk81" }, \ 98 94 .num_parents = 1, \ 99 95 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ ··· 106 104 GXBB_AO_GATE(uart2, 5); 107 105 GXBB_AO_GATE(ir_blaster, 6); 108 106 107 + static struct aoclk_cec_32k cec_32k_ao = { 108 + .lock = &gxbb_aoclk_lock, 109 + .hw.init = &(struct clk_init_data) { 110 + .name = "cec_32k_ao", 111 + .ops = &meson_aoclk_cec_32k_ops, 112 + .parent_names = (const char *[]){ "xtal" }, 113 + .num_parents = 1, 114 + .flags = CLK_IGNORE_UNUSED, 115 + }, 116 + }; 117 + 109 118 static unsigned int gxbb_aoclk_reset[] = { 110 119 [RESET_AO_REMOTE] = 16, 111 120 [RESET_AO_I2C_MASTER] = 18, ··· 126 113 [RESET_AO_IR_BLASTER] = 23, 127 114 }; 128 115 129 - static struct clk_gate *gxbb_aoclk_gate[] = { 116 + static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = { 130 117 [CLKID_AO_REMOTE] = &remote_ao, 131 118 [CLKID_AO_I2C_MASTER] = &i2c_master_ao, 132 119 [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao, ··· 143 130 [CLKID_AO_UART1] = &uart1_ao.hw, 144 131 [CLKID_AO_UART2] = &uart2_ao.hw, 145 132 [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw, 133 + [CLKID_AO_CEC_32K] = &cec_32k_ao.hw, 146 134 }, 147 - .num = ARRAY_SIZE(gxbb_aoclk_gate), 135 + .num = 7, 148 136 }; 149 137 150 138 static int gxbb_aoclkc_probe(struct platform_device *pdev) 151 139 { 152 - struct resource *res; 153 - void __iomem *base; 154 - int ret, clkid; 155 - struct device *dev = &pdev->dev; 156 140 struct gxbb_aoclk_reset_controller *rstc; 141 + struct device *dev = &pdev->dev; 142 + struct regmap *regmap; 143 + int ret, clkid; 157 144 158 145 rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL); 159 146 if (!rstc) 160 147 return -ENOMEM; 161 148 162 - /* Generic clocks */ 163 - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 164 - base = devm_ioremap_resource(dev, res); 165 - if (IS_ERR(base)) 166 - return PTR_ERR(base); 149 + regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); 150 + if (IS_ERR(regmap)) { 151 + dev_err(dev, "failed to get regmap\n"); 152 + return -ENODEV; 153 + } 167 154 168 155 /* Reset Controller */ 169 - rstc->base = base; 156 + rstc->regmap = regmap; 170 157 rstc->data = gxbb_aoclk_reset; 171 158 rstc->reset.ops = &gxbb_aoclk_reset_ops; 172 159 rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset); ··· 174 161 ret = devm_reset_controller_register(dev, &rstc->reset); 175 162 176 163 /* 177 - * Populate base address and register all clks 164 + * Populate regmap and register all clks 178 165 */ 179 - for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) { 180 - gxbb_aoclk_gate[clkid]->reg = base; 166 + for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) { 167 + gxbb_aoclk_gate[clkid]->regmap = regmap; 181 168 182 169 ret = devm_clk_hw_register(dev, 183 170 gxbb_aoclk_onecell_data.hws[clkid]); ··· 185 172 return ret; 186 173 } 187 174 175 + /* Specific clocks */ 176 + cec_32k_ao.regmap = regmap; 177 + ret = devm_clk_hw_register(dev, &cec_32k_ao.hw); 178 + if (ret) 179 + return ret; 180 + 188 181 return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, 189 182 &gxbb_aoclk_onecell_data); 190 183 } 191 184 192 185 static const struct of_device_id gxbb_aoclkc_match_table[] = { 193 - { .compatible = "amlogic,gxbb-aoclkc" }, 186 + { .compatible = "amlogic,meson-gx-aoclkc" }, 194 187 { } 195 188 }; 196 189
+42
drivers/clk/meson/gxbb-aoclk.h
··· 1 + /* 2 + * Copyright (c) 2017 BayLibre, SAS 3 + * Author: Neil Armstrong <narmstrong@baylibre.com> 4 + * 5 + * SPDX-License-Identifier: GPL-2.0+ 6 + */ 7 + 8 + #ifndef __GXBB_AOCLKC_H 9 + #define __GXBB_AOCLKC_H 10 + 11 + /* AO Configuration Clock registers offsets */ 12 + #define AO_RTI_PWR_CNTL_REG1 0x0c 13 + #define AO_RTI_PWR_CNTL_REG0 0x10 14 + #define AO_RTI_GEN_CNTL_REG0 0x40 15 + #define AO_OSCIN_CNTL 0x58 16 + #define AO_CRT_CLK_CNTL1 0x68 17 + #define AO_RTC_ALT_CLK_CNTL0 0x94 18 + #define AO_RTC_ALT_CLK_CNTL1 0x98 19 + 20 + struct aoclk_gate_regmap { 21 + struct clk_hw hw; 22 + unsigned bit_idx; 23 + struct regmap *regmap; 24 + spinlock_t *lock; 25 + }; 26 + 27 + #define to_aoclk_gate_regmap(_hw) \ 28 + container_of(_hw, struct aoclk_gate_regmap, hw) 29 + 30 + extern const struct clk_ops meson_aoclk_gate_regmap_ops; 31 + 32 + struct aoclk_cec_32k { 33 + struct clk_hw hw; 34 + struct regmap *regmap; 35 + spinlock_t *lock; 36 + }; 37 + 38 + #define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw) 39 + 40 + extern const struct clk_ops meson_aoclk_cec_32k_ops; 41 + 42 + #endif /* __GXBB_AOCLKC_H */
+185 -4
drivers/clk/meson/gxbb.c
··· 850 850 .shift = 0, 851 851 .width = 8, 852 852 }, 853 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 853 854 .lock = &clk_lock, 854 855 .hw.init = &(struct clk_init_data){ 855 856 .name = "cts_amclk_div", 856 857 .ops = &meson_clk_audio_divider_ops, 857 858 .parent_names = (const char *[]){ "cts_amclk_sel" }, 858 859 .num_parents = 1, 859 - .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, 860 + .flags = CLK_SET_RATE_PARENT, 860 861 }, 861 862 }; 862 863 ··· 881 880 /* Default parent unknown (register reset value: 0) */ 882 881 .table = (u32[]){ 1, 2, 3 }, 883 882 .lock = &clk_lock, 884 - .hw.init = &(struct clk_init_data){ 883 + .hw.init = &(struct clk_init_data) { 885 884 .name = "cts_mclk_i958_sel", 886 885 .ops = &clk_mux_ops, 887 886 .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, ··· 895 894 .shift = 16, 896 895 .width = 8, 897 896 .lock = &clk_lock, 898 - .hw.init = &(struct clk_init_data){ 897 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 898 + .hw.init = &(struct clk_init_data) { 899 899 .name = "cts_mclk_i958_div", 900 900 .ops = &clk_divider_ops, 901 901 .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, 902 902 .num_parents = 1, 903 - .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, 903 + .flags = CLK_SET_RATE_PARENT, 904 904 }, 905 905 }; 906 906 ··· 978 976 .parent_names = gxbb_32k_clk_parent_names, 979 977 .num_parents = 4, 980 978 .flags = CLK_SET_RATE_PARENT, 979 + }, 980 + }; 981 + 982 + static const char * const gxbb_sd_emmc_clk0_parent_names[] = { 983 + "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", 984 + 985 + /* 986 + * Following these parent clocks, we should also have had mpll2, mpll3 987 + * and gp0_pll but these clocks are too precious to be used here. All 988 + * the necessary rates for MMC and NAND operation can be acheived using 989 + * xtal or fclk_div clocks 990 + */ 991 + }; 992 + 993 + /* SDIO clock */ 994 + static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { 995 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 996 + .mask = 0x7, 997 + .shift = 9, 998 + .lock = &clk_lock, 999 + .hw.init = &(struct clk_init_data) { 1000 + .name = "sd_emmc_a_clk0_sel", 1001 + .ops = &clk_mux_ops, 1002 + .parent_names = gxbb_sd_emmc_clk0_parent_names, 1003 + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1004 + .flags = CLK_SET_RATE_PARENT, 1005 + }, 1006 + }; 1007 + 1008 + static struct clk_divider gxbb_sd_emmc_a_clk0_div = { 1009 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1010 + .shift = 0, 1011 + .width = 7, 1012 + .lock = &clk_lock, 1013 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 1014 + .hw.init = &(struct clk_init_data) { 1015 + .name = "sd_emmc_a_clk0_div", 1016 + .ops = &clk_divider_ops, 1017 + .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, 1018 + .num_parents = 1, 1019 + .flags = CLK_SET_RATE_PARENT, 1020 + }, 1021 + }; 1022 + 1023 + static struct clk_gate gxbb_sd_emmc_a_clk0 = { 1024 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1025 + .bit_idx = 7, 1026 + .lock = &clk_lock, 1027 + .hw.init = &(struct clk_init_data){ 1028 + .name = "sd_emmc_a_clk0", 1029 + .ops = &clk_gate_ops, 1030 + .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, 1031 + .num_parents = 1, 1032 + 1033 + /* 1034 + * FIXME: 1035 + * We need CLK_IGNORE_UNUSED because mmc DT node point to xtal 1036 + * instead of this clock. CCF would gate this on boot, killing 1037 + * the mmc controller. Please remove this flag once DT properly 1038 + * point to this clock instead of xtal 1039 + * 1040 + * Same goes for emmc B and C clocks 1041 + */ 1042 + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1043 + }, 1044 + }; 1045 + 1046 + /* SDcard clock */ 1047 + static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { 1048 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1049 + .mask = 0x7, 1050 + .shift = 25, 1051 + .lock = &clk_lock, 1052 + .hw.init = &(struct clk_init_data) { 1053 + .name = "sd_emmc_b_clk0_sel", 1054 + .ops = &clk_mux_ops, 1055 + .parent_names = gxbb_sd_emmc_clk0_parent_names, 1056 + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1057 + .flags = CLK_SET_RATE_PARENT, 1058 + }, 1059 + }; 1060 + 1061 + static struct clk_divider gxbb_sd_emmc_b_clk0_div = { 1062 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1063 + .shift = 16, 1064 + .width = 7, 1065 + .lock = &clk_lock, 1066 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 1067 + .hw.init = &(struct clk_init_data) { 1068 + .name = "sd_emmc_b_clk0_div", 1069 + .ops = &clk_divider_ops, 1070 + .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, 1071 + .num_parents = 1, 1072 + .flags = CLK_SET_RATE_PARENT, 1073 + }, 1074 + }; 1075 + 1076 + static struct clk_gate gxbb_sd_emmc_b_clk0 = { 1077 + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, 1078 + .bit_idx = 23, 1079 + .lock = &clk_lock, 1080 + .hw.init = &(struct clk_init_data){ 1081 + .name = "sd_emmc_b_clk0", 1082 + .ops = &clk_gate_ops, 1083 + .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, 1084 + .num_parents = 1, 1085 + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 1086 + }, 1087 + }; 1088 + 1089 + /* EMMC/NAND clock */ 1090 + static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { 1091 + .reg = (void *)HHI_NAND_CLK_CNTL, 1092 + .mask = 0x7, 1093 + .shift = 9, 1094 + .lock = &clk_lock, 1095 + .hw.init = &(struct clk_init_data) { 1096 + .name = "sd_emmc_c_clk0_sel", 1097 + .ops = &clk_mux_ops, 1098 + .parent_names = gxbb_sd_emmc_clk0_parent_names, 1099 + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), 1100 + .flags = CLK_SET_RATE_PARENT, 1101 + }, 1102 + }; 1103 + 1104 + static struct clk_divider gxbb_sd_emmc_c_clk0_div = { 1105 + .reg = (void *)HHI_NAND_CLK_CNTL, 1106 + .shift = 0, 1107 + .width = 7, 1108 + .lock = &clk_lock, 1109 + .flags = CLK_DIVIDER_ROUND_CLOSEST, 1110 + .hw.init = &(struct clk_init_data) { 1111 + .name = "sd_emmc_c_clk0_div", 1112 + .ops = &clk_divider_ops, 1113 + .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, 1114 + .num_parents = 1, 1115 + .flags = CLK_SET_RATE_PARENT, 1116 + }, 1117 + }; 1118 + 1119 + static struct clk_gate gxbb_sd_emmc_c_clk0 = { 1120 + .reg = (void *)HHI_NAND_CLK_CNTL, 1121 + .bit_idx = 7, 1122 + .lock = &clk_lock, 1123 + .hw.init = &(struct clk_init_data){ 1124 + .name = "sd_emmc_c_clk0", 1125 + .ops = &clk_gate_ops, 1126 + .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, 1127 + .num_parents = 1, 1128 + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, 981 1129 }, 982 1130 }; 983 1131 ··· 1340 1188 [CLKID_32K_CLK] = &gxbb_32k_clk.hw, 1341 1189 [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, 1342 1190 [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, 1191 + [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, 1192 + [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, 1193 + [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, 1194 + [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, 1195 + [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, 1196 + [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, 1197 + [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, 1198 + [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, 1199 + [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, 1200 + [NR_CLKS] = NULL, 1343 1201 }, 1344 1202 .num = NR_CLKS, 1345 1203 }; ··· 1472 1310 [CLKID_32K_CLK] = &gxbb_32k_clk.hw, 1473 1311 [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, 1474 1312 [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, 1313 + [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, 1314 + [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, 1315 + [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, 1316 + [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, 1317 + [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, 1318 + [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, 1319 + [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, 1320 + [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, 1321 + [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, 1322 + [NR_CLKS] = NULL, 1475 1323 }, 1476 1324 .num = NR_CLKS, 1477 1325 }; ··· 1597 1425 &gxbb_cts_amclk, 1598 1426 &gxbb_cts_mclk_i958, 1599 1427 &gxbb_32k_clk, 1428 + &gxbb_sd_emmc_a_clk0, 1429 + &gxbb_sd_emmc_b_clk0, 1430 + &gxbb_sd_emmc_c_clk0, 1600 1431 }; 1601 1432 1602 1433 static struct clk_mux *const gxbb_clk_muxes[] = { ··· 1612 1437 &gxbb_cts_mclk_i958_sel, 1613 1438 &gxbb_cts_i958, 1614 1439 &gxbb_32k_clk_sel, 1440 + &gxbb_sd_emmc_a_clk0_sel, 1441 + &gxbb_sd_emmc_b_clk0_sel, 1442 + &gxbb_sd_emmc_c_clk0_sel, 1615 1443 }; 1616 1444 1617 1445 static struct clk_divider *const gxbb_clk_dividers[] = { ··· 1624 1446 &gxbb_mali_1_div, 1625 1447 &gxbb_cts_mclk_i958_div, 1626 1448 &gxbb_32k_clk_div, 1449 + &gxbb_sd_emmc_a_clk0_div, 1450 + &gxbb_sd_emmc_b_clk0_div, 1451 + &gxbb_sd_emmc_c_clk0_div, 1627 1452 }; 1628 1453 1629 1454 static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
+14 -111
drivers/clk/meson/gxbb.h
··· 167 167 * CLKID index values 168 168 * 169 169 * These indices are entirely contrived and do not map onto the hardware. 170 - * Migrate them out of this header and into the DT header file when they need 171 - * to be exposed to client nodes in DT: include/dt-bindings/clock/gxbb-clkc.h 170 + * It has now been decided to expose everything by default in the DT header: 171 + * include/dt-bindings/clock/gxbb-clkc.h. Only the clocks ids we don't want 172 + * to expose, such as the internal muxes and dividers of composite clocks, 173 + * will remain defined here. 172 174 */ 173 - #define CLKID_SYS_PLL 0 174 175 /* ID 1 is unused (it was used by the non-existing CLKID_CPUCLK before) */ 175 - /* CLKID_HDMI_PLL */ 176 - #define CLKID_FIXED_PLL 3 177 - /* CLKID_FCLK_DIV2 */ 178 - /* CLKID_FCLK_DIV3 */ 179 - /* CLKID_FCLK_DIV4 */ 180 - #define CLKID_FCLK_DIV5 7 181 - #define CLKID_FCLK_DIV7 8 182 - /* CLKID_GP0_PLL */ 183 176 #define CLKID_MPEG_SEL 10 184 177 #define CLKID_MPEG_DIV 11 185 - /* CLKID_CLK81 */ 186 - #define CLKID_MPLL0 13 187 - #define CLKID_MPLL1 14 188 - /* CLKID_MPLL2 */ 189 - #define CLKID_DDR 16 190 - #define CLKID_DOS 17 191 - #define CLKID_ISA 18 192 - #define CLKID_PL301 19 193 - #define CLKID_PERIPHS 20 194 - /* CLKID_SPICC */ 195 - /* CLKID_I2C */ 196 - /* #define CLKID_SAR_ADC */ 197 - #define CLKID_SMART_CARD 24 198 - /* CLKID_RNG0 */ 199 - /* CLKID_UART0 */ 200 - #define CLKID_SDHC 27 201 - #define CLKID_STREAM 28 202 - #define CLKID_ASYNC_FIFO 29 203 - #define CLKID_SDIO 30 204 - #define CLKID_ABUF 31 205 - #define CLKID_HIU_IFACE 32 206 - #define CLKID_ASSIST_MISC 33 207 - /* CLKID_SPI */ 208 - #define CLKID_I2S_SPDIF 35 209 - /* CLKID_ETH */ 210 - #define CLKID_DEMUX 37 211 - /* CLKID_AIU_GLUE */ 212 - /* CLKID_IEC958 */ 213 - /* CLKID_I2S_OUT */ 214 - #define CLKID_AMCLK 41 215 - #define CLKID_AIFIFO2 42 216 - #define CLKID_MIXER 43 217 - /* CLKID_MIXER_IFACE */ 218 - #define CLKID_ADC 45 219 - #define CLKID_BLKMV 46 220 - /* CLKID_AIU */ 221 - /* CLKID_UART1 */ 222 - #define CLKID_G2D 49 223 - /* CLKID_USB0 */ 224 - /* CLKID_USB1 */ 225 - #define CLKID_RESET 52 226 - #define CLKID_NAND 53 227 - #define CLKID_DOS_PARSER 54 228 - /* CLKID_USB */ 229 - #define CLKID_VDIN1 56 230 - #define CLKID_AHB_ARB0 57 231 - #define CLKID_EFUSE 58 232 - #define CLKID_BOOT_ROM 59 233 - #define CLKID_AHB_DATA_BUS 60 234 - #define CLKID_AHB_CTRL_BUS 61 235 - #define CLKID_HDMI_INTR_SYNC 62 236 - /* CLKID_HDMI_PCLK */ 237 - /* CLKID_USB1_DDR_BRIDGE */ 238 - /* CLKID_USB0_DDR_BRIDGE */ 239 - #define CLKID_MMC_PCLK 66 240 - #define CLKID_DVIN 67 241 - /* CLKID_UART2 */ 242 - /* #define CLKID_SANA */ 243 - #define CLKID_VPU_INTR 70 244 - #define CLKID_SEC_AHB_AHB3_BRIDGE 71 245 - #define CLKID_CLK81_A53 72 246 - #define CLKID_VCLK2_VENCI0 73 247 - #define CLKID_VCLK2_VENCI1 74 248 - #define CLKID_VCLK2_VENCP0 75 249 - #define CLKID_VCLK2_VENCP1 76 250 - /* CLKID_GCLK_VENCI_INT0 */ 251 - #define CLKID_GCLK_VENCI_INT 78 252 - #define CLKID_DAC_CLK 79 253 - /* CLKID_AOCLK_GATE */ 254 - /* CLKID_IEC958_GATE */ 255 - #define CLKID_ENC480P 82 256 - #define CLKID_RNG1 83 257 - #define CLKID_GCLK_VENCI_INT1 84 258 - #define CLKID_VCLK2_VENCLMCC 85 259 - #define CLKID_VCLK2_VENCL 86 260 - #define CLKID_VCLK_OTHER 87 261 - #define CLKID_EDP 88 262 - #define CLKID_AO_MEDIA_CPU 89 263 - #define CLKID_AO_AHB_SRAM 90 264 - #define CLKID_AO_AHB_BUS 91 265 - #define CLKID_AO_IFACE 92 266 - /* CLKID_AO_I2C */ 267 - /* CLKID_SD_EMMC_A */ 268 - /* CLKID_SD_EMMC_B */ 269 - /* CLKID_SD_EMMC_C */ 270 - /* CLKID_SAR_ADC_CLK */ 271 - /* CLKID_SAR_ADC_SEL */ 272 178 #define CLKID_SAR_ADC_DIV 99 273 - /* CLKID_MALI_0_SEL */ 274 - #define CLKID_MALI_0_DIV 101 275 - /* CLKID_MALI_0 */ 276 - /* CLKID_MALI_1_SEL */ 277 - #define CLKID_MALI_1_DIV 104 278 - /* CLKID_MALI_1 */ 279 - /* CLKID_MALI */ 280 - /* CLKID_CTS_AMCLK */ 179 + #define CLKID_MALI_0_DIV 101 180 + #define CLKID_MALI_1_DIV 104 281 181 #define CLKID_CTS_AMCLK_SEL 108 282 182 #define CLKID_CTS_AMCLK_DIV 109 283 - /* CLKID_CTS_MCLK_I958 */ 284 183 #define CLKID_CTS_MCLK_I958_SEL 111 285 184 #define CLKID_CTS_MCLK_I958_DIV 112 286 - /* CLKID_CTS_I958 */ 287 - #define CLKID_32K_CLK 114 288 185 #define CLKID_32K_CLK_SEL 115 289 186 #define CLKID_32K_CLK_DIV 116 187 + #define CLKID_SD_EMMC_A_CLK0_SEL 117 188 + #define CLKID_SD_EMMC_A_CLK0_DIV 118 189 + #define CLKID_SD_EMMC_B_CLK0_SEL 120 190 + #define CLKID_SD_EMMC_B_CLK0_DIV 121 191 + #define CLKID_SD_EMMC_C_CLK0_SEL 123 192 + #define CLKID_SD_EMMC_C_CLK0_DIV 124 290 193 291 - #define NR_CLKS 117 194 + #define NR_CLKS 126 292 195 293 - /* include the CLKIDs that have been made part of the stable DT binding */ 196 + /* include the CLKIDs that have been made part of the DT binding */ 294 197 #include <dt-bindings/clock/gxbb-clkc.h> 295 198 296 199 #endif /* __GXBB_H */
+148 -12
drivers/clk/meson/meson8b.c
··· 25 25 #include <linux/clk-provider.h> 26 26 #include <linux/of_address.h> 27 27 #include <linux/platform_device.h> 28 + #include <linux/reset-controller.h> 29 + #include <linux/slab.h> 28 30 #include <linux/init.h> 29 31 30 32 #include "clkc.h" 31 33 #include "meson8b.h" 32 34 33 35 static DEFINE_SPINLOCK(clk_lock); 36 + 37 + static void __iomem *clk_base; 38 + 39 + struct meson8b_clk_reset { 40 + struct reset_controller_dev reset; 41 + void __iomem *base; 42 + }; 34 43 35 44 static const struct pll_rate_table sys_pll_rate_table[] = { 36 45 PLL_RATE(312000000, 52, 1, 2), ··· 599 590 [CLKID_MPLL0] = &meson8b_mpll0.hw, 600 591 [CLKID_MPLL1] = &meson8b_mpll1.hw, 601 592 [CLKID_MPLL2] = &meson8b_mpll2.hw, 593 + [CLK_NR_CLKS] = NULL, 602 594 }, 603 595 .num = CLK_NR_CLKS, 604 596 }; ··· 705 695 &meson8b_mpeg_clk_div, 706 696 }; 707 697 698 + static const struct meson8b_clk_reset_line { 699 + u32 reg; 700 + u8 bit_idx; 701 + } meson8b_clk_reset_bits[] = { 702 + [CLKC_RESET_L2_CACHE_SOFT_RESET] = { 703 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 30 704 + }, 705 + [CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET] = { 706 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 29 707 + }, 708 + [CLKC_RESET_SCU_SOFT_RESET] = { 709 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 28 710 + }, 711 + [CLKC_RESET_CPU3_SOFT_RESET] = { 712 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 27 713 + }, 714 + [CLKC_RESET_CPU2_SOFT_RESET] = { 715 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 26 716 + }, 717 + [CLKC_RESET_CPU1_SOFT_RESET] = { 718 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 25 719 + }, 720 + [CLKC_RESET_CPU0_SOFT_RESET] = { 721 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 24 722 + }, 723 + [CLKC_RESET_A5_GLOBAL_RESET] = { 724 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 18 725 + }, 726 + [CLKC_RESET_A5_AXI_SOFT_RESET] = { 727 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 17 728 + }, 729 + [CLKC_RESET_A5_ABP_SOFT_RESET] = { 730 + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 16 731 + }, 732 + [CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET] = { 733 + .reg = HHI_SYS_CPU_CLK_CNTL1, .bit_idx = 30 734 + }, 735 + [CLKC_RESET_VID_CLK_CNTL_SOFT_RESET] = { 736 + .reg = HHI_VID_CLK_CNTL, .bit_idx = 15 737 + }, 738 + [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST] = { 739 + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 7 740 + }, 741 + [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE] = { 742 + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 3 743 + }, 744 + [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST] = { 745 + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 1 746 + }, 747 + [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE] = { 748 + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 0 749 + }, 750 + }; 751 + 752 + static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev, 753 + unsigned long id, bool assert) 754 + { 755 + struct meson8b_clk_reset *meson8b_clk_reset = 756 + container_of(rcdev, struct meson8b_clk_reset, reset); 757 + unsigned long flags; 758 + const struct meson8b_clk_reset_line *reset; 759 + u32 val; 760 + 761 + if (id >= ARRAY_SIZE(meson8b_clk_reset_bits)) 762 + return -EINVAL; 763 + 764 + reset = &meson8b_clk_reset_bits[id]; 765 + 766 + spin_lock_irqsave(&clk_lock, flags); 767 + 768 + val = readl(meson8b_clk_reset->base + reset->reg); 769 + if (assert) 770 + val |= BIT(reset->bit_idx); 771 + else 772 + val &= ~BIT(reset->bit_idx); 773 + writel(val, meson8b_clk_reset->base + reset->reg); 774 + 775 + spin_unlock_irqrestore(&clk_lock, flags); 776 + 777 + return 0; 778 + } 779 + 780 + static int meson8b_clk_reset_assert(struct reset_controller_dev *rcdev, 781 + unsigned long id) 782 + { 783 + return meson8b_clk_reset_update(rcdev, id, true); 784 + } 785 + 786 + static int meson8b_clk_reset_deassert(struct reset_controller_dev *rcdev, 787 + unsigned long id) 788 + { 789 + return meson8b_clk_reset_update(rcdev, id, false); 790 + } 791 + 792 + static const struct reset_control_ops meson8b_clk_reset_ops = { 793 + .assert = meson8b_clk_reset_assert, 794 + .deassert = meson8b_clk_reset_deassert, 795 + }; 796 + 708 797 static int meson8b_clkc_probe(struct platform_device *pdev) 709 798 { 710 - void __iomem *clk_base; 711 799 int ret, clkid, i; 712 800 struct clk_hw *parent_hw; 713 801 struct clk *parent_clk; 714 802 struct device *dev = &pdev->dev; 715 803 716 - /* Generic clocks and PLLs */ 717 - clk_base = of_iomap(dev->of_node, 1); 718 - if (!clk_base) { 719 - pr_err("%s: Unable to map clk base\n", __func__); 804 + if (!clk_base) 720 805 return -ENXIO; 721 - } 722 806 723 807 /* Populate base address for PLLs */ 724 808 for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) ··· 852 748 /* FIXME convert to devm_clk_register */ 853 749 ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]); 854 750 if (ret) 855 - goto iounmap; 751 + return ret; 856 752 } 857 753 858 754 /* ··· 875 771 if (ret) { 876 772 pr_err("%s: failed to register clock notifier for cpu_clk\n", 877 773 __func__); 878 - goto iounmap; 774 + return ret; 879 775 } 880 776 881 777 return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, 882 778 &meson8b_hw_onecell_data); 883 - 884 - iounmap: 885 - iounmap(clk_base); 886 - return ret; 887 779 } 888 780 889 781 static const struct of_device_id meson8b_clkc_match_table[] = { ··· 898 798 }; 899 799 900 800 builtin_platform_driver(meson8b_driver); 801 + 802 + static void __init meson8b_clkc_reset_init(struct device_node *np) 803 + { 804 + struct meson8b_clk_reset *rstc; 805 + int ret; 806 + 807 + /* Generic clocks, PLLs and some of the reset-bits */ 808 + clk_base = of_iomap(np, 1); 809 + if (!clk_base) { 810 + pr_err("%s: Unable to map clk base\n", __func__); 811 + return; 812 + } 813 + 814 + rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); 815 + if (!rstc) 816 + return; 817 + 818 + /* Reset Controller */ 819 + rstc->base = clk_base; 820 + rstc->reset.ops = &meson8b_clk_reset_ops; 821 + rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits); 822 + rstc->reset.of_node = np; 823 + ret = reset_controller_register(&rstc->reset); 824 + if (ret) { 825 + pr_err("%s: Failed to register clkc reset controller: %d\n", 826 + __func__, ret); 827 + return; 828 + } 829 + } 830 + 831 + CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc", 832 + meson8b_clkc_reset_init); 833 + CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc", 834 + meson8b_clkc_reset_init); 835 + CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc", 836 + meson8b_clkc_reset_init);
+12 -100
drivers/clk/meson/meson8b.h
··· 37 37 #define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */ 38 38 #define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */ 39 39 #define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */ 40 + #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */ 41 + #define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */ 42 + #define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */ 40 43 #define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ 41 44 #define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */ 42 45 #define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ ··· 63 60 * CLKID index values 64 61 * 65 62 * These indices are entirely contrived and do not map onto the hardware. 66 - * Migrate them out of this header and into the DT header file when they need 67 - * to be exposed to client nodes in DT: include/dt-bindings/clock/meson8b-clkc.h 63 + * It has now been decided to expose everything by default in the DT header: 64 + * include/dt-bindings/clock/gxbb-clkc.h. Only the clocks ids we don't want 65 + * to expose, such as the internal muxes and dividers of composite clocks, 66 + * will remain defined here. 68 67 */ 69 - 70 - /* CLKID_UNUSED */ 71 - /* CLKID_XTAL */ 72 - /* CLKID_PLL_FIXED */ 73 - /* CLKID_PLL_VID */ 74 - /* CLKID_PLL_SYS */ 75 - /* CLKID_FCLK_DIV2 */ 76 - /* CLKID_FCLK_DIV3 */ 77 - /* CLKID_FCLK_DIV4 */ 78 - /* CLKID_FCLK_DIV5 */ 79 - /* CLKID_FCLK_DIV7 */ 80 - /* CLKID_CLK81 */ 81 - /* CLKID_MALI */ 82 - /* CLKID_CPUCLK */ 83 - /* CLKID_ZERO */ 84 - /* CLKID_MPEG_SEL */ 85 - /* CLKID_MPEG_DIV */ 86 - #define CLKID_DDR 16 87 - #define CLKID_DOS 17 88 - #define CLKID_ISA 18 89 - #define CLKID_PL301 19 90 - #define CLKID_PERIPHS 20 91 - #define CLKID_SPICC 21 92 - #define CLKID_I2C 22 93 - /* #define CLKID_SAR_ADC */ 94 - #define CLKID_SMART_CARD 24 95 - /* #define CLKID_RNG0 */ 96 - #define CLKID_UART0 26 97 - #define CLKID_SDHC 27 98 - #define CLKID_STREAM 28 99 - #define CLKID_ASYNC_FIFO 29 100 - /* #define CLKID_SDIO */ 101 - #define CLKID_ABUF 31 102 - #define CLKID_HIU_IFACE 32 103 - #define CLKID_ASSIST_MISC 33 104 - #define CLKID_SPI 34 105 - #define CLKID_I2S_SPDIF 35 106 - /* #define CLKID_ETH */ 107 - #define CLKID_DEMUX 37 108 - #define CLKID_AIU_GLUE 38 109 - #define CLKID_IEC958 39 110 - #define CLKID_I2S_OUT 40 111 - #define CLKID_AMCLK 41 112 - #define CLKID_AIFIFO2 42 113 - #define CLKID_MIXER 43 114 - #define CLKID_MIXER_IFACE 44 115 - #define CLKID_ADC 45 116 - #define CLKID_BLKMV 46 117 - #define CLKID_AIU 47 118 - #define CLKID_UART1 48 119 - #define CLKID_G2D 49 120 - /* #define CLKID_USB0 */ 121 - /* #define CLKID_USB1 */ 122 - #define CLKID_RESET 52 123 - #define CLKID_NAND 53 124 - #define CLKID_DOS_PARSER 54 125 - /* #define CLKID_USB */ 126 - #define CLKID_VDIN1 56 127 - #define CLKID_AHB_ARB0 57 128 - #define CLKID_EFUSE 58 129 - #define CLKID_BOOT_ROM 59 130 - #define CLKID_AHB_DATA_BUS 60 131 - #define CLKID_AHB_CTRL_BUS 61 132 - #define CLKID_HDMI_INTR_SYNC 62 133 - #define CLKID_HDMI_PCLK 63 134 - /* CLKID_USB1_DDR_BRIDGE */ 135 - /* CLKID_USB0_DDR_BRIDGE */ 136 - #define CLKID_MMC_PCLK 66 137 - #define CLKID_DVIN 67 138 - #define CLKID_UART2 68 139 - /* #define CLKID_SANA */ 140 - #define CLKID_VPU_INTR 70 141 - #define CLKID_SEC_AHB_AHB3_BRIDGE 71 142 - #define CLKID_CLK81_A9 72 143 - #define CLKID_VCLK2_VENCI0 73 144 - #define CLKID_VCLK2_VENCI1 74 145 - #define CLKID_VCLK2_VENCP0 75 146 - #define CLKID_VCLK2_VENCP1 76 147 - #define CLKID_GCLK_VENCI_INT 77 148 - #define CLKID_GCLK_VENCP_INT 78 149 - #define CLKID_DAC_CLK 79 150 - #define CLKID_AOCLK_GATE 80 151 - #define CLKID_IEC958_GATE 81 152 - #define CLKID_ENC480P 82 153 - #define CLKID_RNG1 83 154 - #define CLKID_GCLK_VENCL_INT 84 155 - #define CLKID_VCLK2_VENCLMCC 85 156 - #define CLKID_VCLK2_VENCL 86 157 - #define CLKID_VCLK2_OTHER 87 158 - #define CLKID_EDP 88 159 - #define CLKID_AO_MEDIA_CPU 89 160 - #define CLKID_AO_AHB_SRAM 90 161 - #define CLKID_AO_AHB_BUS 91 162 - #define CLKID_AO_IFACE 92 163 - #define CLKID_MPLL0 93 164 - #define CLKID_MPLL1 94 165 - #define CLKID_MPLL2 95 166 68 167 69 #define CLK_NR_CLKS 96 168 70 169 - /* include the CLKIDs that have been made part of the stable DT binding */ 71 + /* 72 + * include the CLKID and RESETID that have 73 + * been made part of the stable DT binding 74 + */ 170 75 #include <dt-bindings/clock/meson8b-clkc.h> 76 + #include <dt-bindings/reset/amlogic,meson8b-clkc-reset.h> 171 77 172 78 #endif /* __MESON8B_H */
+1
include/dt-bindings/clock/gxbb-aoclkc.h
··· 62 62 #define CLKID_AO_UART1 3 63 63 #define CLKID_AO_UART2 4 64 64 #define CLKID_AO_IR_BLASTER 5 65 + #define CLKID_AO_CEC_32K 6 65 66 66 67 #endif
+63
include/dt-bindings/clock/gxbb-clkc.h
··· 5 5 #ifndef __GXBB_CLKC_H 6 6 #define __GXBB_CLKC_H 7 7 8 + #define CLKID_SYS_PLL 0 8 9 #define CLKID_HDMI_PLL 2 10 + #define CLKID_FIXED_PLL 3 9 11 #define CLKID_FCLK_DIV2 4 10 12 #define CLKID_FCLK_DIV3 5 11 13 #define CLKID_FCLK_DIV4 6 14 + #define CLKID_FCLK_DIV5 7 15 + #define CLKID_FCLK_DIV7 8 12 16 #define CLKID_GP0_PLL 9 13 17 #define CLKID_CLK81 12 18 + #define CLKID_MPLL0 13 19 + #define CLKID_MPLL1 14 14 20 #define CLKID_MPLL2 15 21 + #define CLKID_DDR 16 22 + #define CLKID_DOS 17 23 + #define CLKID_ISA 18 24 + #define CLKID_PL301 19 25 + #define CLKID_PERIPHS 20 15 26 #define CLKID_SPICC 21 16 27 #define CLKID_I2C 22 17 28 #define CLKID_SAR_ADC 23 29 + #define CLKID_SMART_CARD 24 18 30 #define CLKID_RNG0 25 19 31 #define CLKID_UART0 26 32 + #define CLKID_SDHC 27 33 + #define CLKID_STREAM 28 34 + #define CLKID_ASYNC_FIFO 29 35 + #define CLKID_SDIO 30 36 + #define CLKID_ABUF 31 37 + #define CLKID_HIU_IFACE 32 38 + #define CLKID_ASSIST_MISC 33 20 39 #define CLKID_SPI 34 21 40 #define CLKID_ETH 36 41 + #define CLKID_I2S_SPDIF 35 42 + #define CLKID_DEMUX 37 22 43 #define CLKID_AIU_GLUE 38 23 44 #define CLKID_IEC958 39 24 45 #define CLKID_I2S_OUT 40 46 + #define CLKID_AMCLK 41 47 + #define CLKID_AIFIFO2 42 48 + #define CLKID_MIXER 43 25 49 #define CLKID_MIXER_IFACE 44 50 + #define CLKID_ADC 45 51 + #define CLKID_BLKMV 46 26 52 #define CLKID_AIU 47 27 53 #define CLKID_UART1 48 54 + #define CLKID_G2D 49 28 55 #define CLKID_USB0 50 29 56 #define CLKID_USB1 51 57 + #define CLKID_RESET 52 58 + #define CLKID_NAND 53 59 + #define CLKID_DOS_PARSER 54 30 60 #define CLKID_USB 55 61 + #define CLKID_VDIN1 56 62 + #define CLKID_AHB_ARB0 57 63 + #define CLKID_EFUSE 58 64 + #define CLKID_BOOT_ROM 59 65 + #define CLKID_AHB_DATA_BUS 60 66 + #define CLKID_AHB_CTRL_BUS 61 67 + #define CLKID_HDMI_INTR_SYNC 62 31 68 #define CLKID_HDMI_PCLK 63 32 69 #define CLKID_USB1_DDR_BRIDGE 64 33 70 #define CLKID_USB0_DDR_BRIDGE 65 71 + #define CLKID_MMC_PCLK 66 72 + #define CLKID_DVIN 67 34 73 #define CLKID_UART2 68 35 74 #define CLKID_SANA 69 75 + #define CLKID_VPU_INTR 70 76 + #define CLKID_SEC_AHB_AHB3_BRIDGE 71 77 + #define CLKID_CLK81_A53 72 78 + #define CLKID_VCLK2_VENCI0 73 79 + #define CLKID_VCLK2_VENCI1 74 80 + #define CLKID_VCLK2_VENCP0 75 81 + #define CLKID_VCLK2_VENCP1 76 36 82 #define CLKID_GCLK_VENCI_INT0 77 83 + #define CLKID_GCLK_VENCI_INT 78 84 + #define CLKID_DAC_CLK 79 37 85 #define CLKID_AOCLK_GATE 80 38 86 #define CLKID_IEC958_GATE 81 87 + #define CLKID_ENC480P 82 88 + #define CLKID_RNG1 83 89 + #define CLKID_GCLK_VENCI_INT1 84 90 + #define CLKID_VCLK2_VENCLMCC 85 91 + #define CLKID_VCLK2_VENCL 86 92 + #define CLKID_VCLK_OTHER 87 93 + #define CLKID_EDP 88 94 + #define CLKID_AO_MEDIA_CPU 89 95 + #define CLKID_AO_AHB_SRAM 90 96 + #define CLKID_AO_AHB_BUS 91 97 + #define CLKID_AO_IFACE 92 39 98 #define CLKID_AO_I2C 93 40 99 #define CLKID_SD_EMMC_A 94 41 100 #define CLKID_SD_EMMC_B 95 ··· 109 50 #define CLKID_CTS_AMCLK 107 110 51 #define CLKID_CTS_MCLK_I958 110 111 52 #define CLKID_CTS_I958 113 53 + #define CLKID_32K_CLK 114 54 + #define CLKID_SD_EMMC_A_CLK0 119 55 + #define CLKID_SD_EMMC_B_CLK0 122 56 + #define CLKID_SD_EMMC_C_CLK0 125 112 57 113 58 #endif /* __GXBB_CLKC_H */
+70
include/dt-bindings/clock/meson8b-clkc.h
··· 21 21 #define CLKID_ZERO 13 22 22 #define CLKID_MPEG_SEL 14 23 23 #define CLKID_MPEG_DIV 15 24 + #define CLKID_DDR 16 25 + #define CLKID_DOS 17 26 + #define CLKID_ISA 18 27 + #define CLKID_PL301 19 28 + #define CLKID_PERIPHS 20 29 + #define CLKID_SPICC 21 30 + #define CLKID_I2C 22 24 31 #define CLKID_SAR_ADC 23 32 + #define CLKID_SMART_CARD 24 25 33 #define CLKID_RNG0 25 34 + #define CLKID_UART0 26 35 + #define CLKID_SDHC 27 36 + #define CLKID_STREAM 28 37 + #define CLKID_ASYNC_FIFO 29 26 38 #define CLKID_SDIO 30 39 + #define CLKID_ABUF 31 40 + #define CLKID_HIU_IFACE 32 41 + #define CLKID_ASSIST_MISC 33 42 + #define CLKID_SPI 34 43 + #define CLKID_I2S_SPDIF 35 27 44 #define CLKID_ETH 36 45 + #define CLKID_DEMUX 37 46 + #define CLKID_AIU_GLUE 38 47 + #define CLKID_IEC958 39 48 + #define CLKID_I2S_OUT 40 49 + #define CLKID_AMCLK 41 50 + #define CLKID_AIFIFO2 42 51 + #define CLKID_MIXER 43 52 + #define CLKID_MIXER_IFACE 44 53 + #define CLKID_ADC 45 54 + #define CLKID_BLKMV 46 55 + #define CLKID_AIU 47 56 + #define CLKID_UART1 48 57 + #define CLKID_G2D 49 28 58 #define CLKID_USB0 50 29 59 #define CLKID_USB1 51 60 + #define CLKID_RESET 52 61 + #define CLKID_NAND 53 62 + #define CLKID_DOS_PARSER 54 30 63 #define CLKID_USB 55 64 + #define CLKID_VDIN1 56 65 + #define CLKID_AHB_ARB0 57 66 + #define CLKID_EFUSE 58 67 + #define CLKID_BOOT_ROM 59 68 + #define CLKID_AHB_DATA_BUS 60 69 + #define CLKID_AHB_CTRL_BUS 61 70 + #define CLKID_HDMI_INTR_SYNC 62 71 + #define CLKID_HDMI_PCLK 63 31 72 #define CLKID_USB1_DDR_BRIDGE 64 32 73 #define CLKID_USB0_DDR_BRIDGE 65 74 + #define CLKID_MMC_PCLK 66 75 + #define CLKID_DVIN 67 76 + #define CLKID_UART2 68 33 77 #define CLKID_SANA 69 78 + #define CLKID_VPU_INTR 70 79 + #define CLKID_SEC_AHB_AHB3_BRIDGE 71 80 + #define CLKID_CLK81_A9 72 81 + #define CLKID_VCLK2_VENCI0 73 82 + #define CLKID_VCLK2_VENCI1 74 83 + #define CLKID_VCLK2_VENCP0 75 84 + #define CLKID_VCLK2_VENCP1 76 85 + #define CLKID_GCLK_VENCI_INT 77 86 + #define CLKID_GCLK_VENCP_INT 78 87 + #define CLKID_DAC_CLK 79 88 + #define CLKID_AOCLK_GATE 80 89 + #define CLKID_IEC958_GATE 81 90 + #define CLKID_ENC480P 82 91 + #define CLKID_RNG1 83 92 + #define CLKID_GCLK_VENCL_INT 84 93 + #define CLKID_VCLK2_VENCLMCC 85 94 + #define CLKID_VCLK2_VENCL 86 95 + #define CLKID_VCLK2_OTHER 87 96 + #define CLKID_EDP 88 97 + #define CLKID_AO_MEDIA_CPU 89 98 + #define CLKID_AO_AHB_SRAM 90 99 + #define CLKID_AO_AHB_BUS 91 100 + #define CLKID_AO_IFACE 92 101 + #define CLKID_MPLL0 93 102 + #define CLKID_MPLL1 94 103 + #define CLKID_MPLL2 95 34 104 35 105 #endif /* __MESON8B_CLKC_H */
+27
include/dt-bindings/reset/amlogic,meson8b-clkc-reset.h
··· 1 + /* 2 + * Copyright (c) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>. 3 + * 4 + * SPDX-License-Identifier: (GPL-2.0+ OR MIT) 5 + */ 6 + 7 + #ifndef _DT_BINDINGS_AMLOGIC_MESON8B_CLKC_RESET_H 8 + #define _DT_BINDINGS_AMLOGIC_MESON8B_CLKC_RESET_H 9 + 10 + #define CLKC_RESET_L2_CACHE_SOFT_RESET 0 11 + #define CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET 1 12 + #define CLKC_RESET_SCU_SOFT_RESET 2 13 + #define CLKC_RESET_CPU0_SOFT_RESET 3 14 + #define CLKC_RESET_CPU1_SOFT_RESET 4 15 + #define CLKC_RESET_CPU2_SOFT_RESET 5 16 + #define CLKC_RESET_CPU3_SOFT_RESET 6 17 + #define CLKC_RESET_A5_GLOBAL_RESET 7 18 + #define CLKC_RESET_A5_AXI_SOFT_RESET 8 19 + #define CLKC_RESET_A5_ABP_SOFT_RESET 9 20 + #define CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET 10 21 + #define CLKC_RESET_VID_CLK_CNTL_SOFT_RESET 11 22 + #define CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST 12 23 + #define CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE 13 24 + #define CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST 14 25 + #define CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE 15 26 + 27 + #endif /* _DT_BINDINGS_AMLOGIC_MESON8B_CLKC_RESET_H */