#include <linux/clk-provider.h>
#define PCG_PREDIV_SHIFT 16
#define PCG_PREDIV_WIDTH 3
static unsigned long imx8m_clk_composite_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
struct clk_divider *divider = to_clk_divider(hw);
unsigned long prediv_rate;
unsigned int prediv_value;
prediv_value = readl(divider->reg) >> divider->shift;
prediv_value &= clk_div_mask(divider->width);
prediv_rate = divider_recalc_rate(hw, parent_rate, prediv_value,
div_value = readl(divider->reg) >> PCG_DIV_SHIFT;
div_value &= clk_div_mask(PCG_DIV_WIDTH);
return divider_recalc_rate(hw, prediv_rate, div_value, NULL,
divider->flags, PCG_DIV_WIDTH);
static int imx8m_clk_composite_compute_dividers(unsigned long rate,
unsigned long parent_rate,
int *prediv, int *postdiv)
for (div1 = 1; div1 <= PCG_PREDIV_MAX; div1++) {
for (div2 = 1; div2 <= PCG_DIV_MAX; div2++) {
int new_error = ((parent_rate / div1) / div2) - rate;
if (abs(new_error) < abs(error)) {