xref: /linux/drivers/clk/zynqmp/clk-gate-zynqmp.c (revision 4917394e)
13fde0e16SJolly Shah // SPDX-License-Identifier: GPL-2.0
23fde0e16SJolly Shah /*
33fde0e16SJolly Shah  * Zynq UltraScale+ MPSoC clock controller
43fde0e16SJolly Shah  *
53fde0e16SJolly Shah  *  Copyright (C) 2016-2018 Xilinx
63fde0e16SJolly Shah  *
73fde0e16SJolly Shah  * Gated clock implementation
83fde0e16SJolly Shah  */
93fde0e16SJolly Shah 
103fde0e16SJolly Shah #include <linux/clk-provider.h>
113fde0e16SJolly Shah #include <linux/slab.h>
123fde0e16SJolly Shah #include "clk-zynqmp.h"
133fde0e16SJolly Shah 
143fde0e16SJolly Shah /**
156e1cc688SMichal Simek  * struct zynqmp_clk_gate - gating clock
163fde0e16SJolly Shah  * @hw:		handle between common and hardware-specific interfaces
173fde0e16SJolly Shah  * @flags:	hardware-specific flags
183fde0e16SJolly Shah  * @clk_id:	Id of clock
193fde0e16SJolly Shah  */
203fde0e16SJolly Shah struct zynqmp_clk_gate {
213fde0e16SJolly Shah 	struct clk_hw hw;
223fde0e16SJolly Shah 	u8 flags;
233fde0e16SJolly Shah 	u32 clk_id;
243fde0e16SJolly Shah };
253fde0e16SJolly Shah 
263fde0e16SJolly Shah #define to_zynqmp_clk_gate(_hw) container_of(_hw, struct zynqmp_clk_gate, hw)
273fde0e16SJolly Shah 
283fde0e16SJolly Shah /**
293fde0e16SJolly Shah  * zynqmp_clk_gate_enable() - Enable clock
303fde0e16SJolly Shah  * @hw:		handle between common and hardware-specific interfaces
313fde0e16SJolly Shah  *
323fde0e16SJolly Shah  * Return: 0 on success else error code
333fde0e16SJolly Shah  */
zynqmp_clk_gate_enable(struct clk_hw * hw)343fde0e16SJolly Shah static int zynqmp_clk_gate_enable(struct clk_hw *hw)
353fde0e16SJolly Shah {
363fde0e16SJolly Shah 	struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw);
373fde0e16SJolly Shah 	const char *clk_name = clk_hw_get_name(hw);
383fde0e16SJolly Shah 	u32 clk_id = gate->clk_id;
393fde0e16SJolly Shah 	int ret;
403fde0e16SJolly Shah 
413637e84cSRajan Vaja 	ret = zynqmp_pm_clock_enable(clk_id);
423fde0e16SJolly Shah 
433fde0e16SJolly Shah 	if (ret)
444917394eSMichael Tretter 		pr_debug("%s() clock enable failed for %s (id %d), ret = %d\n",
454917394eSMichael Tretter 			 __func__, clk_name, clk_id, ret);
463fde0e16SJolly Shah 
473fde0e16SJolly Shah 	return ret;
483fde0e16SJolly Shah }
493fde0e16SJolly Shah 
503fde0e16SJolly Shah /*
513fde0e16SJolly Shah  * zynqmp_clk_gate_disable() - Disable clock
523fde0e16SJolly Shah  * @hw:		handle between common and hardware-specific interfaces
533fde0e16SJolly Shah  */
zynqmp_clk_gate_disable(struct clk_hw * hw)543fde0e16SJolly Shah static void zynqmp_clk_gate_disable(struct clk_hw *hw)
553fde0e16SJolly Shah {
563fde0e16SJolly Shah 	struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw);
573fde0e16SJolly Shah 	const char *clk_name = clk_hw_get_name(hw);
583fde0e16SJolly Shah 	u32 clk_id = gate->clk_id;
593fde0e16SJolly Shah 	int ret;
603fde0e16SJolly Shah 
61f5ccd54bSRajan Vaja 	ret = zynqmp_pm_clock_disable(clk_id);
623fde0e16SJolly Shah 
633fde0e16SJolly Shah 	if (ret)
644917394eSMichael Tretter 		pr_debug("%s() clock disable failed for %s (id %d), ret = %d\n",
654917394eSMichael Tretter 			 __func__, clk_name, clk_id, ret);
663fde0e16SJolly Shah }
673fde0e16SJolly Shah 
683fde0e16SJolly Shah /**
696e1cc688SMichal Simek  * zynqmp_clk_gate_is_enabled() - Check clock state
703fde0e16SJolly Shah  * @hw:		handle between common and hardware-specific interfaces
713fde0e16SJolly Shah  *
723fde0e16SJolly Shah  * Return: 1 if enabled, 0 if disabled else error code
733fde0e16SJolly Shah  */
zynqmp_clk_gate_is_enabled(struct clk_hw * hw)743fde0e16SJolly Shah static int zynqmp_clk_gate_is_enabled(struct clk_hw *hw)
753fde0e16SJolly Shah {
763fde0e16SJolly Shah 	struct zynqmp_clk_gate *gate = to_zynqmp_clk_gate(hw);
773fde0e16SJolly Shah 	const char *clk_name = clk_hw_get_name(hw);
783fde0e16SJolly Shah 	u32 clk_id = gate->clk_id;
793fde0e16SJolly Shah 	int state, ret;
803fde0e16SJolly Shah 
815e76731dSRajan Vaja 	ret = zynqmp_pm_clock_getstate(clk_id, &state);
823fde0e16SJolly Shah 	if (ret) {
834917394eSMichael Tretter 		pr_debug("%s() clock get state failed for %s, ret = %d\n",
843fde0e16SJolly Shah 			 __func__, clk_name, ret);
853fde0e16SJolly Shah 		return -EIO;
863fde0e16SJolly Shah 	}
873fde0e16SJolly Shah 
883fde0e16SJolly Shah 	return state ? 1 : 0;
893fde0e16SJolly Shah }
903fde0e16SJolly Shah 
913fde0e16SJolly Shah static const struct clk_ops zynqmp_clk_gate_ops = {
923fde0e16SJolly Shah 	.enable = zynqmp_clk_gate_enable,
933fde0e16SJolly Shah 	.disable = zynqmp_clk_gate_disable,
943fde0e16SJolly Shah 	.is_enabled = zynqmp_clk_gate_is_enabled,
953fde0e16SJolly Shah };
963fde0e16SJolly Shah 
973fde0e16SJolly Shah /**
983fde0e16SJolly Shah  * zynqmp_clk_register_gate() - Register a gate clock with the clock framework
993fde0e16SJolly Shah  * @name:		Name of this clock
1003fde0e16SJolly Shah  * @clk_id:		Id of this clock
1013fde0e16SJolly Shah  * @parents:		Name of this clock's parents
1023fde0e16SJolly Shah  * @num_parents:	Number of parents
1033fde0e16SJolly Shah  * @nodes:		Clock topology node
1043fde0e16SJolly Shah  *
1053fde0e16SJolly Shah  * Return: clock hardware of the registered clock gate
1063fde0e16SJolly Shah  */
zynqmp_clk_register_gate(const char * name,u32 clk_id,const char * const * parents,u8 num_parents,const struct clock_topology * nodes)1073fde0e16SJolly Shah struct clk_hw *zynqmp_clk_register_gate(const char *name, u32 clk_id,
1083fde0e16SJolly Shah 					const char * const *parents,
1093fde0e16SJolly Shah 					u8 num_parents,
1103fde0e16SJolly Shah 					const struct clock_topology *nodes)
1113fde0e16SJolly Shah {
1123fde0e16SJolly Shah 	struct zynqmp_clk_gate *gate;
1133fde0e16SJolly Shah 	struct clk_hw *hw;
1143fde0e16SJolly Shah 	int ret;
1153fde0e16SJolly Shah 	struct clk_init_data init;
1163fde0e16SJolly Shah 
1173fde0e16SJolly Shah 	/* allocate the gate */
1183fde0e16SJolly Shah 	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
1193fde0e16SJolly Shah 	if (!gate)
1203fde0e16SJolly Shah 		return ERR_PTR(-ENOMEM);
1213fde0e16SJolly Shah 
1223fde0e16SJolly Shah 	init.name = name;
1233fde0e16SJolly Shah 	init.ops = &zynqmp_clk_gate_ops;
124610a5d83SRajan Vaja 
125610a5d83SRajan Vaja 	init.flags = zynqmp_clk_map_common_ccf_flags(nodes->flag);
126610a5d83SRajan Vaja 
1273fde0e16SJolly Shah 	init.parent_names = parents;
1283fde0e16SJolly Shah 	init.num_parents = 1;
1293fde0e16SJolly Shah 
1303fde0e16SJolly Shah 	/* struct clk_gate assignments */
1313fde0e16SJolly Shah 	gate->flags = nodes->type_flag;
1323fde0e16SJolly Shah 	gate->hw.init = &init;
1333fde0e16SJolly Shah 	gate->clk_id = clk_id;
1343fde0e16SJolly Shah 
1353fde0e16SJolly Shah 	hw = &gate->hw;
1363fde0e16SJolly Shah 	ret = clk_hw_register(NULL, hw);
1373fde0e16SJolly Shah 	if (ret) {
1383fde0e16SJolly Shah 		kfree(gate);
1393fde0e16SJolly Shah 		hw = ERR_PTR(ret);
1403fde0e16SJolly Shah 	}
1413fde0e16SJolly Shah 
1423fde0e16SJolly Shah 	return hw;
1433fde0e16SJolly Shah }
144