Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/xilinx/zy7_slcr.c
Show First 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | |||||
/* Override cgem_set_refclk() in gigabit ethernet driver | /* Override cgem_set_refclk() in gigabit ethernet driver | ||||
* (sys/dev/cadence/if_cgem.c). This function is called to | * (sys/dev/cadence/if_cgem.c). This function is called to | ||||
* request a change in the gem's reference clock speed. | * request a change in the gem's reference clock speed. | ||||
*/ | */ | ||||
int | int | ||||
cgem_set_ref_clk(int unit, int frequency) | cgem_set_ref_clk(int unit, int frequency) | ||||
{ | { | ||||
struct zy7_slcr_softc *sc = zy7_slcr_softc_p; | struct zy7_slcr_softc *sc = zy7_slcr_softc_p; | ||||
uint32_t clk_reg_val; | |||||
int base_frequency; | |||||
int div0, div1; | int div0, div1; | ||||
if (!sc) | if (!sc) | ||||
return (-1); | return (-1); | ||||
clk_reg_val = RD4(sc, unit ? ZY7_SLCR_GEM1_CLK_CTRL : | |||||
ZY7_SLCR_GEM0_CLK_CTRL); | |||||
switch (clk_reg_val & ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_MASK) { | |||||
case ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_EMIO_CLK: | |||||
/* Do not touch clock divisors if clock is from EMIO. */ | |||||
return (0); | |||||
case ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_ARM_PLL: | |||||
base_frequency = arm_pll_frequency; | |||||
break; | |||||
case ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_DDR_PLL: | |||||
base_frequency = ddr_pll_frequency; | |||||
break; | |||||
case ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_IO_PLL: | |||||
default: | |||||
base_frequency = io_pll_frequency; | |||||
break; | |||||
} | |||||
/* Find suitable divisor pairs. Round result to nearest khz | /* Find suitable divisor pairs. Round result to nearest khz | ||||
* to test for match. | * to test for match. | ||||
*/ | */ | ||||
for (div1 = 1; div1 <= ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MAX; div1++) { | for (div1 = 1; div1 <= ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MAX; div1++) { | ||||
div0 = (io_pll_frequency + div1 * frequency / 2) / | div0 = (base_frequency + div1 * frequency / 2) / | ||||
div1 / frequency; | div1 / frequency; | ||||
if (div0 > 0 && div0 <= ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_MAX && | if (div0 > 0 && div0 <= ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_MAX && | ||||
((io_pll_frequency / div0 / div1) + 500) / 1000 == | ((base_frequency / div0 / div1) + 500) / 1000 == | ||||
(frequency + 500) / 1000) | (frequency + 500) / 1000) | ||||
break; | break; | ||||
} | } | ||||
if (div1 > ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MAX) | if (div1 > ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MAX) | ||||
return (-1); | return (-1); | ||||
ZSLCR_LOCK(sc); | ZSLCR_LOCK(sc); | ||||
/* Unlock SLCR registers. */ | /* Unlock SLCR registers. */ | ||||
zy7_slcr_unlock(sc); | zy7_slcr_unlock(sc); | ||||
/* Modify GEM reference clock. */ | /* Modify GEM reference clock divisors. */ | ||||
clk_reg_val &= ~(ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_MASK | | |||||
ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_MASK); | |||||
WR4(sc, unit ? ZY7_SLCR_GEM1_CLK_CTRL : ZY7_SLCR_GEM0_CLK_CTRL, | WR4(sc, unit ? ZY7_SLCR_GEM1_CLK_CTRL : ZY7_SLCR_GEM0_CLK_CTRL, | ||||
(div1 << ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_SHIFT) | | clk_reg_val | (div1 << ZY7_SLCR_GEM_CLK_CTRL_DIVISOR1_SHIFT) | | ||||
(div0 << ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_SHIFT) | | (div0 << ZY7_SLCR_GEM_CLK_CTRL_DIVISOR_SHIFT)); | ||||
ZY7_SLCR_GEM_CLK_CTRL_SRCSEL_IO_PLL | | |||||
ZY7_SLCR_GEM_CLK_CTRL_CLKACT); | |||||
/* Lock SLCR registers. */ | /* Lock SLCR registers. */ | ||||
zy7_slcr_lock(sc); | zy7_slcr_lock(sc); | ||||
ZSLCR_UNLOCK(sc); | ZSLCR_UNLOCK(sc); | ||||
return (0); | return (0); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 458 Lines • Show Last 20 Lines |