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); }
void lpc31_clkinit(const struct lpc31_clkinit_s* cfg) { struct lpc31_domainconfig_s domain; /* Reset all clocks and connect them to FFAST */ lpc31_resetclks(); /* Initialize Domain0 = SYS_BASE clocks */ domain.dmnid = DOMAINID_SYS; domain.finsel = cfg->domain0.finsel; domain.clk1 = CLKID_SYSBASE_FIRST; domain.nclks = (CLKID_SYSBASE_LAST - CLKID_SYSBASE_FIRST) + 1; domain.fdiv1 = FRACDIV_BASE0_LOW; domain.nfdiv = FRACDIV_BASE0_CNT; domain.sub = cfg->domain0.sub; lpc31_domaininit(&domain); /* Initialize Domain1 = AHB0APB0_BASE clocks */ domain.dmnid = DOMAINID_AHB0APB0; domain.finsel = cfg->domain1.finsel; domain.clk1 = CLKID_AHB0APB0_FIRST; domain.nclks = (CLKID_AHB0APB0_LAST - CLKID_AHB0APB0_FIRST) + 1; domain.fdiv1 = FRACDIV_BASE1_LOW; domain.nfdiv = FRACDIV_BASE1_CNT; domain.sub = cfg->domain1.sub; lpc31_domaininit(&domain); /* Initialize Domain2 = AHB0APB1_BASE clocks */ domain.dmnid = DOMAINID_AHB0APB1; domain.finsel = cfg->domain2.finsel; domain.clk1 = CLKID_AHB0APB1_FIRST; domain.nclks = (CLKID_AHB0APB1_LAST - CLKID_AHB0APB1_FIRST) + 1; domain.fdiv1 = FRACDIV_BASE2_LOW; domain.nfdiv = FRACDIV_BASE2_CNT; domain.sub = cfg->domain2.sub; lpc31_domaininit(&domain); /* Initialize Domain3 = AHB0APB2_BASE clocks */ domain.dmnid = DOMAINID_AHB0APB2; domain.finsel = cfg->domain3.finsel; domain.clk1 = CLKID_AHB0APB2_FIRST; domain.nclks = (CLKID_AHB0APB2_LAST - CLKID_AHB0APB2_FIRST) + 1; domain.fdiv1 = FRACDIV_BASE3_LOW; domain.nfdiv = FRACDIV_BASE3_CNT; domain.sub = cfg->domain3.sub; lpc31_domaininit(&domain); /* Initialize Domain4 = AHB0APB3_BASE clocks */ domain.dmnid = DOMAINID_AHB0APB3; domain.finsel = cfg->domain4.finsel; domain.clk1 = CLKID_AHB0APB3_FIRST; domain.nclks = (CLKID_AHB0APB3_LAST - CLKID_AHB0APB3_FIRST) + 1; domain.fdiv1 = FRACDIV_BASE4_LOW; domain.nfdiv = FRACDIV_BASE4_CNT; domain.sub = cfg->domain4.sub; lpc31_domaininit(&domain); /* Initialize Domain5 = PCM_BASE clocks */ domain.dmnid = DOMAINID_PCM; domain.finsel = cfg->domain5.finsel; domain.clk1 = CLKID_PCM_FIRST; domain.nclks = 1; domain.fdiv1 = FRACDIV_BASE5_LOW; domain.nfdiv = FRACDIV_BASE5_CNT; domain.sub = cfg->domain5.sub; lpc31_domaininit(&domain); /* Initialize Domain6 = UART_BASE clocks */ domain.dmnid = DOMAINID_UART; domain.finsel = cfg->domain6.finsel; domain.clk1 = CLKID_UART_FIRST; domain.nclks = 1; domain.fdiv1 = FRACDIV_BASE6_LOW; domain.nfdiv = FRACDIV_BASE6_CNT; domain.sub = cfg->domain6.sub; lpc31_domaininit(&domain); /* Initialize Domain7 = CLK1024FS_BASE clocks */ domain.dmnid = DOMAINID_CLK1024FS; domain.finsel = cfg->domain7.finsel; domain.clk1 = CLKID_CLK1024FS_FIRST; domain.nclks = (CLKID_CLK1024FS_LAST - CLKID_CLK1024FS_FIRST) + 1; domain.fdiv1 = FRACDIV_BASE7_LOW; domain.nfdiv = FRACDIV_BASE7_CNT; domain.sub = cfg->domain7.sub; lpc31_domaininit(&domain); /* Initialize Domain8 = I2SRX_BCK0_BASE clocks */ lpc31_selectfreqin(DOMAINID_BCK0, cfg->domain8.finsel); /* Initialize Domain9 = I2SRX_BCK1_BASE clocks */ lpc31_selectfreqin(DOMAINID_BCK1, cfg->domain9.finsel); /* Initialize Domain10 = SPI_BASE clocks */ domain.dmnid = DOMAINID_SPI; domain.finsel = cfg->domain10.finsel; domain.clk1 = CLKID_SPI_FIRST; domain.nclks = (CLKID_SPI_LAST - CLKID_SPI_FIRST) + 1; domain.fdiv1 = FRACDIV_BASE10_LOW; domain.nfdiv = FRACDIV_BASE10_CNT; domain.sub = cfg->domain10.sub; lpc31_domaininit(&domain); /* Initialize Domain11 = SYSCLK_O_BASE clocks */ lpc31_selectfreqin(DOMAINID_SYSCLKO, cfg->domain11.finsel); /* Initialize Dynamic fractional dividers -- to be provided */ }