|
- //---
- // gint:clock:freq - Clock frequency management
- //---
-
- #include <gint/drivers.h>
- #include <gint/clock.h>
- #include <core/std.h>
-
- #include <gint/mpu.h>
- #include <gint/mpu/cpg.h>
-
- //---
- // Driver storage
- //---
-
- /* Local copy of the CPG settings */
- GBSS static clock_frequency_t freq;
-
- /* clock_freq() - get the frequency of the main clocks */
- const clock_frequency_t *clock_freq(void)
- {
- return &freq;
- }
-
- //---
- // SH7705 Clock signals
- //---
-
- #ifdef FX9860G
- #define CPG SH7705_CPG
-
- static void sh7705_probe(void)
- {
- /* According to Sentaro21 in the sources of Ftune 1.0.1, the clock mode
- is thought to be 5, which means that:
- - CPG input is XTAL (14.745'600 MHz)
- - PLL2 is active and *2 (29.491'200 MHz)
- - CKIO is output from PLL2 (29.491'200 MHz) */
- int xtal = 14745600;
- int pll2 = 2;
- int ckio = xtal * pll2;
-
- /* This signal is multiplied by the PLL1 circuit */
- int pll1 = CPG.FRQCR.STC + 1;
-
- /* Iphi and Pphi have dividers (Bphi is always equal to CKIO) */
- int idiv = CPG.FRQCR.IFC;
- int pdiv = CPG.FRQCR.PFC;
-
- /* Fill in the setting structure */
- freq.PLL1 = pll1;
- freq.PLL2 = pll2;
- freq.Bphi_div = 1;
- freq.Iphi_div = idiv + 1;
- freq.Pphi_div = pdiv + 1;
-
- /* Deduce the frequency of the main clocks. This value is ckio/3 */
- int ckio_3 = 9830400;
-
- /* Exchange the setting values 2 and 3 */
- idiv = idiv ^ (idiv >> 1);
- pdiv = pdiv ^ (pdiv >> 1);
-
- freq.CKIO_f = ckio;
- freq.Bphi_f = ckio;
- freq.Iphi_f = (idiv == 3) ? ckio_3 : ckio >> idiv;
- freq.Pphi_f = (pdiv == 3) ? ckio_3 : ckio >> pdiv;
- }
-
- #undef CPG
- #endif /* FX9860G */
-
- //---
- // SH7305 clock signals
- //---
-
- #define CPG SH7305_CPG
-
- static void sh7305_probe(void)
- {
- /* The meaning of the PLL setting on SH7305 differs from the
- documentation of SH7224; the value must not be doubled. */
- int pll = CPG.FRQCRA.STC + 1;
- freq.PLL = pll;
-
- /* The FLL ratio is the value of the setting, halved if SELXM=1 */
- int fll = CPG.FLLFRQ.FLF;
- if(CPG.FLLFRQ.SELXM == 1) fll >>= 1;
- freq.FLL = fll;
-
- /* On SH7724, the divider ratio is given by 1 / (setting + 1), but
- SH7305 behaves as 1 / (2^setting + 1). */
-
- int divb = CPG.FRQCRA.BFC;
- int divi = CPG.FRQCRA.IFC;
- int divp = CPG.FRQCRA.P1FC;
-
- freq.Bphi_div = 1 << (divb + 1);
- freq.Iphi_div = 1 << (divi + 1);
- freq.Pphi_div = 1 << (divp + 1);
-
- /* Deduce the input frequency of divider 1 */
- int base = 32768;
- if(CPG.PLLCR.FLLE) base *= fll;
- if(CPG.PLLCR.PLLE) base *= pll;
-
- /* And the frequency of all other input clocks */
- freq.RTCCLK_f = 32768;
- freq.Bphi_f = base >> (divb + 1);
- freq.Iphi_f = base >> (divi + 1);
- freq.Pphi_f = base >> (divp + 1);
- }
-
- #undef CPG
-
- //---
- // Other driver stuff
- //---
-
- #ifdef GINT_BOOT_LOG
-
- static const char *cpg_status(void)
- {
- static char status[18];
- sprintf(status, "I%3d B%3d P%3d C%c",
- freq.Iphi_f / 1000000,
- freq.Bphi_f / 1000000,
- freq.Pphi_f / 1000000,
- isSH3() ? 'e' : 'E'
- );
- return status;
- }
-
- #endif /* GINT_BOOT_LOG */
-
- static void init(void)
- {
- /* This avoids warnings about sh7705() not being defined on fxcg50 */
- #ifdef FX9860G
- isSH3() ? sh7705_probe() :
- #endif
-
- sh7305_probe();
- }
-
- gint_driver_t drv_cpg = {
- .name = "CPG",
- .init = init,
- .status = GINT_DRIVER_STATUS(cpg_status),
- .ctx_size = 0,
- .sys_ctx = NULL,
- .ctx_save = NULL,
- .ctx_restore = NULL,
- };
-
- GINT_DECLARE_DRIVER(1, drv_cpg);
|