14116076eSJosh Cartwright /* 24116076eSJosh Cartwright * Copyright (c) 2014, The Linux Foundation. All rights reserved. 34116076eSJosh Cartwright * 44116076eSJosh Cartwright * This software is licensed under the terms of the GNU General Public 54116076eSJosh Cartwright * License version 2, as published by the Free Software Foundation, and 64116076eSJosh Cartwright * may be copied, distributed, and modified under those terms. 74116076eSJosh Cartwright * 84116076eSJosh Cartwright * This program is distributed in the hope that it will be useful, 94116076eSJosh Cartwright * but WITHOUT ANY WARRANTY; without even the implied warranty of 104116076eSJosh Cartwright * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 114116076eSJosh Cartwright * GNU General Public License for more details. 124116076eSJosh Cartwright */ 134116076eSJosh Cartwright 144116076eSJosh Cartwright #include <linux/kernel.h> 154116076eSJosh Cartwright #include <linux/bitops.h> 164116076eSJosh Cartwright #include <linux/regmap.h> 174116076eSJosh Cartwright #include <linux/export.h> 184116076eSJosh Cartwright 194116076eSJosh Cartwright #include "clk-regmap-divider.h" 204116076eSJosh Cartwright 214116076eSJosh Cartwright static inline struct clk_regmap_div *to_clk_regmap_div(struct clk_hw *hw) 224116076eSJosh Cartwright { 234116076eSJosh Cartwright return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr); 244116076eSJosh Cartwright } 254116076eSJosh Cartwright 264116076eSJosh Cartwright static long div_round_rate(struct clk_hw *hw, unsigned long rate, 274116076eSJosh Cartwright unsigned long *prate) 284116076eSJosh Cartwright { 294116076eSJosh Cartwright struct clk_regmap_div *divider = to_clk_regmap_div(hw); 304116076eSJosh Cartwright 314116076eSJosh Cartwright return divider_round_rate(hw, rate, prate, NULL, divider->width, 324116076eSJosh Cartwright CLK_DIVIDER_ROUND_CLOSEST); 334116076eSJosh Cartwright } 344116076eSJosh Cartwright 354116076eSJosh Cartwright static int div_set_rate(struct clk_hw *hw, unsigned long rate, 364116076eSJosh Cartwright unsigned long parent_rate) 374116076eSJosh Cartwright { 384116076eSJosh Cartwright struct clk_regmap_div *divider = to_clk_regmap_div(hw); 394116076eSJosh Cartwright struct clk_regmap *clkr = ÷r->clkr; 404116076eSJosh Cartwright u32 div; 414116076eSJosh Cartwright 424116076eSJosh Cartwright div = divider_get_val(rate, parent_rate, NULL, divider->width, 434116076eSJosh Cartwright CLK_DIVIDER_ROUND_CLOSEST); 444116076eSJosh Cartwright 454116076eSJosh Cartwright return regmap_update_bits(clkr->regmap, divider->reg, 464116076eSJosh Cartwright (BIT(divider->width) - 1) << divider->shift, 474116076eSJosh Cartwright div << divider->shift); 484116076eSJosh Cartwright } 494116076eSJosh Cartwright 504116076eSJosh Cartwright static unsigned long div_recalc_rate(struct clk_hw *hw, 514116076eSJosh Cartwright unsigned long parent_rate) 524116076eSJosh Cartwright { 534116076eSJosh Cartwright struct clk_regmap_div *divider = to_clk_regmap_div(hw); 544116076eSJosh Cartwright struct clk_regmap *clkr = ÷r->clkr; 554116076eSJosh Cartwright u32 div; 564116076eSJosh Cartwright 574116076eSJosh Cartwright regmap_read(clkr->regmap, divider->reg, &div); 584116076eSJosh Cartwright div >>= divider->shift; 594116076eSJosh Cartwright div &= BIT(divider->width) - 1; 604116076eSJosh Cartwright 614116076eSJosh Cartwright return divider_recalc_rate(hw, parent_rate, div, NULL, 62*12a26c29SJerome Brunet CLK_DIVIDER_ROUND_CLOSEST, divider->width); 634116076eSJosh Cartwright } 644116076eSJosh Cartwright 654116076eSJosh Cartwright const struct clk_ops clk_regmap_div_ops = { 664116076eSJosh Cartwright .round_rate = div_round_rate, 674116076eSJosh Cartwright .set_rate = div_set_rate, 684116076eSJosh Cartwright .recalc_rate = div_recalc_rate, 694116076eSJosh Cartwright }; 704116076eSJosh Cartwright EXPORT_SYMBOL_GPL(clk_regmap_div_ops); 71