static struct clk *_rcg_clk_get_parent(struct rcg_clk *rcg, int has_mnd) { u32 n_regval = 0, m_regval = 0, d_regval = 0; u32 cfg_regval; struct clk_freq_tbl *freq; u32 cmd_rcgr_regval; cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg)); if (cmd_rcgr_regval & CMD_RCGR_CONFIG_DIRTY_MASK) return NULL; if (has_mnd) { m_regval = readl_relaxed(M_REG(rcg)); n_regval = readl_relaxed(N_REG(rcg)); d_regval = readl_relaxed(D_REG(rcg)); n_regval |= (n_regval >> 8) ? BM(31, 16) : BM(31, 8); d_regval |= (d_regval >> 8) ? BM(31, 16) : BM(31, 8); } cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg)); cfg_regval &= CFG_RCGR_SRC_SEL_MASK | CFG_RCGR_DIV_MASK | MND_MODE_MASK; has_mnd = (has_mnd) && ((cfg_regval & MND_MODE_MASK) == MND_DUAL_EDGE_MODE_BVAL); cfg_regval &= ~MND_MODE_MASK; for (freq = rcg->freq_tbl; freq->freq_hz != FREQ_END; freq++) { if (freq->div_src_val != cfg_regval) continue; if (has_mnd) { if (freq->m_val != m_regval) continue; if (freq->n_val != n_regval) continue; if (freq->d_val != d_regval) continue; } break; } if (freq->freq_hz == FREQ_END) return NULL; rcg->current_freq = freq; return freq->src_clk; }
/* RCG set rate function for clocks with MND & Half Integer Dividers. */ void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf) { u32 cfg_regval; writel_relaxed(nf->m_val, M_REG(rcg)); writel_relaxed(nf->n_val, N_REG(rcg)); writel_relaxed(nf->d_val, D_REG(rcg)); cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg)); cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK); cfg_regval |= nf->div_src_val; /* Activate or disable the M/N:D divider as necessary */ cfg_regval &= ~MND_MODE_MASK; if (nf->n_val != 0) cfg_regval |= MND_DUAL_EDGE_MODE_BVAL; writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg)); rcg_update_config(rcg); }
void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf) { u32 cfg_regval; unsigned long flags; spin_lock_irqsave(&local_clock_reg_lock, flags); cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg)); writel_relaxed(nf->m_val, M_REG(rcg)); writel_relaxed(nf->n_val, N_REG(rcg)); writel_relaxed(nf->d_val, D_REG(rcg)); cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg)); cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK); cfg_regval |= nf->div_src_val; cfg_regval &= ~MND_MODE_MASK; if (nf->n_val != 0) cfg_regval |= MND_DUAL_EDGE_MODE_BVAL; writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg)); rcg_update_config(rcg); spin_unlock_irqrestore(&local_clock_reg_lock, flags); }
static struct clk *_rcg_clk_get_parent(struct rcg_clk *rcg, int has_mnd) { u32 n_regval = 0, m_regval = 0, d_regval = 0; u32 cfg_regval; struct clk_freq_tbl *freq; u32 cmd_rcgr_regval; /* Is there a pending configuration? */ cmd_rcgr_regval = readl_relaxed(CMD_RCGR_REG(rcg)); if (cmd_rcgr_regval & CMD_RCGR_CONFIG_DIRTY_MASK) return NULL; /* Get values of m, n, d, div and src_sel registers. */ if (has_mnd) { m_regval = readl_relaxed(M_REG(rcg)); n_regval = readl_relaxed(N_REG(rcg)); d_regval = readl_relaxed(D_REG(rcg)); /* * The n and d values stored in the frequency tables are sign * extended to 32 bits. The n and d values in the registers are * sign extended to 8 or 16 bits. Sign extend the values read * from the registers so that they can be compared to the * values in the frequency tables. */ n_regval |= (n_regval >> 8) ? BM(31, 16) : BM(31, 8); d_regval |= (d_regval >> 8) ? BM(31, 16) : BM(31, 8); } cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg)); cfg_regval &= CFG_RCGR_SRC_SEL_MASK | CFG_RCGR_DIV_MASK | MND_MODE_MASK; /* If mnd counter is present, check if it's in use. */ has_mnd = (has_mnd) && ((cfg_regval & MND_MODE_MASK) == MND_DUAL_EDGE_MODE_BVAL); /* * Clear out the mn counter mode bits since we now want to compare only * the source mux selection and pre-divider values in the registers. */ cfg_regval &= ~MND_MODE_MASK; /* Figure out what rate the rcg is running at */ for (freq = rcg->freq_tbl; freq->freq_hz != FREQ_END; freq++) { if (freq->div_src_val != cfg_regval) continue; if (has_mnd) { if (freq->m_val != m_regval) continue; if (freq->n_val != n_regval) continue; if (freq->d_val != d_regval) continue; } break; } /* No known frequency found */ if (freq->freq_hz == FREQ_END) return NULL; rcg->current_freq = freq; return freq->src_clk; }