brintos

brintos / linux-shallow public Read only

0
0
Text · 4.0 KiB · 36f637d Raw
143 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2024 Neil Armstrong <neil.armstrong@linaro.org>4 */5 6#include <linux/module.h>7#include "vclk.h"8 9/* The VCLK gate has a supplementary reset bit to pulse after ungating */10 11static inline struct meson_vclk_gate_data *12clk_get_meson_vclk_gate_data(struct clk_regmap *clk)13{14	return (struct meson_vclk_gate_data *)clk->data;15}16 17static int meson_vclk_gate_enable(struct clk_hw *hw)18{19	struct clk_regmap *clk = to_clk_regmap(hw);20	struct meson_vclk_gate_data *vclk = clk_get_meson_vclk_gate_data(clk);21 22	meson_parm_write(clk->map, &vclk->enable, 1);23 24	/* Do a reset pulse */25	meson_parm_write(clk->map, &vclk->reset, 1);26	meson_parm_write(clk->map, &vclk->reset, 0);27 28	return 0;29}30 31static void meson_vclk_gate_disable(struct clk_hw *hw)32{33	struct clk_regmap *clk = to_clk_regmap(hw);34	struct meson_vclk_gate_data *vclk = clk_get_meson_vclk_gate_data(clk);35 36	meson_parm_write(clk->map, &vclk->enable, 0);37}38 39static int meson_vclk_gate_is_enabled(struct clk_hw *hw)40{41	struct clk_regmap *clk = to_clk_regmap(hw);42	struct meson_vclk_gate_data *vclk = clk_get_meson_vclk_gate_data(clk);43 44	return meson_parm_read(clk->map, &vclk->enable);45}46 47const struct clk_ops meson_vclk_gate_ops = {48	.enable = meson_vclk_gate_enable,49	.disable = meson_vclk_gate_disable,50	.is_enabled = meson_vclk_gate_is_enabled,51};52EXPORT_SYMBOL_NS_GPL(meson_vclk_gate_ops, CLK_MESON);53 54/* The VCLK Divider has supplementary reset & enable bits */55 56static inline struct meson_vclk_div_data *57clk_get_meson_vclk_div_data(struct clk_regmap *clk)58{59	return (struct meson_vclk_div_data *)clk->data;60}61 62static unsigned long meson_vclk_div_recalc_rate(struct clk_hw *hw,63						unsigned long prate)64{65	struct clk_regmap *clk = to_clk_regmap(hw);66	struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk);67 68	return divider_recalc_rate(hw, prate, meson_parm_read(clk->map, &vclk->div),69				   vclk->table, vclk->flags, vclk->div.width);70}71 72static int meson_vclk_div_determine_rate(struct clk_hw *hw,73					 struct clk_rate_request *req)74{75	struct clk_regmap *clk = to_clk_regmap(hw);76	struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk);77 78	return divider_determine_rate(hw, req, vclk->table, vclk->div.width,79				      vclk->flags);80}81 82static int meson_vclk_div_set_rate(struct clk_hw *hw, unsigned long rate,83				   unsigned long parent_rate)84{85	struct clk_regmap *clk = to_clk_regmap(hw);86	struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk);87	int ret;88 89	ret = divider_get_val(rate, parent_rate, vclk->table, vclk->div.width,90			      vclk->flags);91	if (ret < 0)92		return ret;93 94	meson_parm_write(clk->map, &vclk->div, ret);95 96	return 0;97};98 99static int meson_vclk_div_enable(struct clk_hw *hw)100{101	struct clk_regmap *clk = to_clk_regmap(hw);102	struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk);103 104	/* Unreset the divider when ungating */105	meson_parm_write(clk->map, &vclk->reset, 0);106	meson_parm_write(clk->map, &vclk->enable, 1);107 108	return 0;109}110 111static void meson_vclk_div_disable(struct clk_hw *hw)112{113	struct clk_regmap *clk = to_clk_regmap(hw);114	struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk);115 116	/* Reset the divider when gating */117	meson_parm_write(clk->map, &vclk->enable, 0);118	meson_parm_write(clk->map, &vclk->reset, 1);119}120 121static int meson_vclk_div_is_enabled(struct clk_hw *hw)122{123	struct clk_regmap *clk = to_clk_regmap(hw);124	struct meson_vclk_div_data *vclk = clk_get_meson_vclk_div_data(clk);125 126	return meson_parm_read(clk->map, &vclk->enable);127}128 129const struct clk_ops meson_vclk_div_ops = {130	.recalc_rate = meson_vclk_div_recalc_rate,131	.determine_rate = meson_vclk_div_determine_rate,132	.set_rate = meson_vclk_div_set_rate,133	.enable = meson_vclk_div_enable,134	.disable = meson_vclk_div_disable,135	.is_enabled = meson_vclk_div_is_enabled,136};137EXPORT_SYMBOL_NS_GPL(meson_vclk_div_ops, CLK_MESON);138 139MODULE_DESCRIPTION("Amlogic vclk clock driver");140MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");141MODULE_LICENSE("GPL");142MODULE_IMPORT_NS(CLK_MESON);143