void lpc31_setfdiv(enum lpc31_domainid_e dmnid, enum lpc31_clockid_e clkid, const struct lpc31_fdivconfig_s *fdiv) { uint32_t regaddr; unsigned int basefreq; int fdcndx; int bcrndx; /* Get the frequency divider associated with this clock */ fdcndx = lpc31_fdcndx(clkid, dmnid); /* Does this clock have a frequency divicer? */ if (fdcndx != FDCNDX_INVALID) { /* Yes.. Save the current reference frequency selection */ regaddr = LPC31_CGU_SSR((int)dmnid); basefreq = (getreg32(regaddr) & CGU_SSR_FS_MASK) >> CGU_SSR_FS_SHIFT; /* Switch domain to FFAST input */ lpc31_selectfreqin(dmnid, CGU_FS_FFAST); /* Get the index of the associated BCR register. Does this domain * have a BCR? */ bcrndx = lpc31_bcrndx(dmnid); if (bcrndx != BCRNDX_INVALID) { /* Yes... Disable the BCR */ regaddr = LPC31_CGU_BCR(bcrndx); putreg32(0, regaddr); } /* Change fractional divider to the provided settings */ lpc31_fdivinit(fdcndx, fdiv, true); /* Re-enable the BCR (if one is associated with this domain) */ if (bcrndx != BCRNDX_INVALID) { regaddr = LPC31_CGU_BCR(bcrndx); putreg32(CGU_BCR_FDRUN, regaddr); } /* Switch the domain back to its original base frequency */ lpc31_selectfreqin(dmnid, basefreq); }
static void lpc31_domaininit(struct lpc31_domainconfig_s* dmn) { const struct lpc31_subdomainconfig_s * sub = dmn->sub; uint32_t fdivcfg; uint32_t regaddr; uint32_t regval; int fdndx; int clkndx; int bcrndx = lpc31_bcrndx(dmn->dmnid); int esrndx; if (bcrndx != BCRNDX_INVALID) { /* Disable BCR for domain */ regaddr = LPC31_CGU_BCR(bcrndx); putreg32(0, regaddr); } /* Configure the fractional dividers in this domain */ for (fdndx = 0; fdndx < dmn->nfdiv; fdndx++, sub++) { /* Set fractional divider confiruation but don't enable it yet */ fdivcfg = lpc31_fdivinit(fdndx + dmn->fdiv1, &sub->fdiv, false); /* Enable frac divider only if it has valid settings */ if (fdivcfg != 0) { /* Select the fractional dividir for each clock in this * sub domain. */ for (clkndx = 0; clkndx <= dmn->nclks; clkndx++) { /* Does this clock have an ESR register? */ esrndx = lpc31_esrndx((enum lpc31_clockid_e)(clkndx + dmn->clk1)); if (esrndx != ESRNDX_INVALID) { /* Yes.. Check if this clock belongs to this sub-domain */ if (sub->clkset & (1 << clkndx)) { /* Yes.. configure the clock to use this fractional divider */ regaddr = LPC31_CGU_ESR(esrndx); putreg32((fdndx << CGU_ESR_ESRSEL_SHIFT) | CGU_ESR_ESREN, regaddr); } } } /* Enable the fractional divider */ regaddr = LPC31_CGU_FDC(fdndx + dmn->fdiv1); regval = getreg32(regaddr); regval |= CGU_FDC_RUN; putreg32(regval, regaddr); } } if (bcrndx != BCRNDX_INVALID) { /* Enable the BCR for domain */ regaddr = LPC31_CGU_BCR(bcrndx); putreg32(CGU_BCR_FDRUN, regaddr); } /* Select input base clock for domain*/ lpc31_selectfreqin(dmn->dmnid, dmn->finsel); }