Date: Wed, 17 Jun 2015 23:26:01 +0000 (UTC) From: Oleksandr Tymoshenko <gonzo@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r284532 - in head/sys/arm/ti: . am335x omap4 Message-ID: <201506172326.t5HNQ1tW000562@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: gonzo Date: Wed Jun 17 23:26:00 2015 New Revision: 284532 URL: https://svnweb.freebsd.org/changeset/base/284532 Log: - Add clk_set_source_freq field to struct ti_clock_dev so clock device consumers can configure clock frequency - Add ti_prcm_clk_set_source_freq wrapper for clk_set_source_freq - Add am335x_clk_set_arm_disp_freq function to control pixel clock frequency for LCD and HDMI output. Both of them are sensitive to frequency skews and we need to get pixel clock matching requested frequency as close to possible Modified: head/sys/arm/ti/am335x/am335x_prcm.c head/sys/arm/ti/omap4/omap4_prcm_clks.c head/sys/arm/ti/ti_prcm.c head/sys/arm/ti/ti_prcm.h Modified: head/sys/arm/ti/am335x/am335x_prcm.c ============================================================================== --- head/sys/arm/ti/am335x/am335x_prcm.c Wed Jun 17 23:24:46 2015 (r284531) +++ head/sys/arm/ti/am335x/am335x_prcm.c Wed Jun 17 23:26:00 2015 (r284532) @@ -151,6 +151,7 @@ static int am335x_clk_hsmmc_get_source_f static int am335x_clk_get_sysclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq); static int am335x_clk_get_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int *freq); +static int am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq); static void am335x_prcm_reset(void); static int am335x_clk_cpsw_activate(struct ti_clock_dev *clkdev); static int am335x_clk_musb0_activate(struct ti_clock_dev *clkdev); @@ -163,7 +164,8 @@ static int am335x_clk_pruss_activate(str .clk_deactivate = am335x_clk_noop_deactivate, \ .clk_set_source = am335x_clk_noop_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } #define AM335X_GENERIC_CLOCK_DEV(i) \ @@ -172,7 +174,8 @@ static int am335x_clk_pruss_activate(str .clk_deactivate = am335x_clk_generic_deactivate, \ .clk_set_source = am335x_clk_generic_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } #define AM335X_GPIO_CLOCK_DEV(i) \ @@ -181,7 +184,8 @@ static int am335x_clk_pruss_activate(str .clk_deactivate = am335x_clk_generic_deactivate, \ .clk_set_source = am335x_clk_generic_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } #define AM335X_MMCHS_CLOCK_DEV(i) \ @@ -190,7 +194,8 @@ static int am335x_clk_pruss_activate(str .clk_deactivate = am335x_clk_generic_deactivate, \ .clk_set_source = am335x_clk_generic_set_source, \ .clk_accessible = NULL, \ - .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq \ + .clk_get_source_freq = am335x_clk_hsmmc_get_source_freq, \ + .clk_set_source_freq = NULL \ } struct ti_clock_dev ti_am335x_clk_devmap[] = { @@ -201,6 +206,7 @@ struct ti_clock_dev ti_am335x_clk_devmap .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = am335x_clk_get_sysclk_freq, + .clk_set_source_freq = NULL, }, /* MPU (ARM) core clocks */ { .id = MPU_CLK, @@ -209,6 +215,7 @@ struct ti_clock_dev ti_am335x_clk_devmap .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = am335x_clk_get_arm_fclk_freq, + .clk_set_source_freq = NULL, }, /* CPSW Ethernet Switch core clocks */ { .id = CPSW_CLK, @@ -217,6 +224,7 @@ struct ti_clock_dev ti_am335x_clk_devmap .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = NULL, + .clk_set_source_freq = NULL, }, /* Mentor USB HS controller core clocks */ @@ -226,6 +234,7 @@ struct ti_clock_dev ti_am335x_clk_devmap .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = NULL, + .clk_set_source_freq = NULL, }, /* LCD controller clocks */ @@ -235,6 +244,7 @@ struct ti_clock_dev ti_am335x_clk_devmap .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = am335x_clk_get_arm_disp_freq, + .clk_set_source_freq = am335x_clk_set_arm_disp_freq, }, /* UART */ @@ -296,6 +306,7 @@ struct ti_clock_dev ti_am335x_clk_devmap .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = NULL, + .clk_set_source_freq = NULL, }, /* RTC */ @@ -627,6 +638,8 @@ am335x_clk_get_sysclk_freq(struct ti_clo #define DPLL_BYP_CLKSEL(reg) ((reg>>23) & 1) #define DPLL_DIV(reg) ((reg & 0x7f)+1) #define DPLL_MULT(reg) ((reg>>8) & 0x7FF) +#define DPLL_MAX_MUL 0x800 +#define DPLL_MAX_DIV 0x80 static int am335x_clk_get_arm_fclk_freq(struct ti_clock_dev *clkdev, unsigned int *freq) @@ -662,6 +675,52 @@ am335x_clk_get_arm_disp_freq(struct ti_c return(0); } +static int +am335x_clk_set_arm_disp_freq(struct ti_clock_dev *clkdev, unsigned int freq) +{ + uint32_t sysclk; + uint32_t mul, div; + uint32_t i, j; + unsigned int delta, min_delta; + + am335x_clk_get_sysclk_freq(NULL, &sysclk); + + /* Bypass mode */ + prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4); + + /* Make sure it's in bypass mode */ + while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) + & (1 << 8))) + DELAY(10); + + /* Dumb and non-optimal implementation */ + min_delta = freq; + for (i = 1; i < DPLL_MAX_MUL; i++) { + for (j = 1; j < DPLL_MAX_DIV; j++) { + delta = abs(freq - i*(sysclk/j)); + if (delta < min_delta) { + mul = i; + div = j; + min_delta = delta; + } + if (min_delta == 0) + break; + } + } + + prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (mul << 8) | (div - 1)); + + /* Locked mode */ + prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); + + int timeout = 10000; + while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) + & (1 << 0))) && timeout--) + DELAY(10); + + return(0); +} + static void am335x_prcm_reset(void) { @@ -724,27 +783,10 @@ am335x_clk_lcdc_activate(struct ti_clock if (sc == NULL) return (ENXIO); - /* Bypass mode */ - prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x4); - - /* Make sure it's in bypass mode */ - while (!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) - & (1 << 8))) - DELAY(10); - /* - * For now set frequency to 99*SYSFREQ/8 which is twice as - * HDMI 1080p pixel clock (minimum LCDC freq divisor is 2) + * For now set frequency to 2*VGA_PIXEL_CLOCK */ - prcm_write_4(CM_WKUP_CM_CLKSEL_DPLL_DISP, (99 << 8) | 8); - - /* Locked mode */ - prcm_write_4(CM_WKUP_CM_CLKMODE_DPLL_DISP, 0x7); - - int timeout = 10000; - while ((!(prcm_read_4(CM_WKUP_CM_IDLEST_DPLL_DISP) - & (1 << 0))) && timeout--) - DELAY(10); + am335x_clk_set_arm_disp_freq(clkdev, 25175000*2); /*set MODULEMODE to ENABLE(2) */ prcm_write_4(CM_PER_LCDC_CLKCTRL, 2); Modified: head/sys/arm/ti/omap4/omap4_prcm_clks.c ============================================================================== --- head/sys/arm/ti/omap4/omap4_prcm_clks.c Wed Jun 17 23:24:46 2015 (r284531) +++ head/sys/arm/ti/omap4/omap4_prcm_clks.c Wed Jun 17 23:26:00 2015 (r284532) @@ -217,7 +217,8 @@ static int omap4_clk_get_arm_fclk_freq(s .clk_deactivate = omap4_clk_generic_deactivate, \ .clk_set_source = omap4_clk_generic_set_source, \ .clk_accessible = omap4_clk_generic_accessible, \ - .clk_get_source_freq = omap4_clk_generic_get_source_freq \ + .clk_get_source_freq = omap4_clk_generic_get_source_freq, \ + .clk_set_source_freq = NULL \ } #define OMAP4_GPTIMER_CLOCK_DEV(i) \ @@ -226,7 +227,8 @@ static int omap4_clk_get_arm_fclk_freq(s .clk_deactivate = omap4_clk_generic_deactivate, \ .clk_set_source = omap4_clk_gptimer_set_source, \ .clk_accessible = omap4_clk_generic_accessible, \ - .clk_get_source_freq = omap4_clk_gptimer_get_source_freq \ + .clk_get_source_freq = omap4_clk_gptimer_get_source_freq, \ + .clk_set_source_freq = NULL \ } #define OMAP4_HSMMC_CLOCK_DEV(i) \ @@ -235,7 +237,8 @@ static int omap4_clk_get_arm_fclk_freq(s .clk_deactivate = omap4_clk_generic_deactivate, \ .clk_set_source = omap4_clk_hsmmc_set_source, \ .clk_accessible = omap4_clk_generic_accessible, \ - .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq \ + .clk_get_source_freq = omap4_clk_hsmmc_get_source_freq, \ + .clk_set_source_freq = NULL \ } #define OMAP4_HSUSBHOST_CLOCK_DEV(i) \ @@ -244,7 +247,8 @@ static int omap4_clk_get_arm_fclk_freq(s .clk_deactivate = omap4_clk_hsusbhost_deactivate, \ .clk_set_source = omap4_clk_hsusbhost_set_source, \ .clk_accessible = omap4_clk_hsusbhost_accessible, \ - .clk_get_source_freq = NULL \ + .clk_get_source_freq = NULL, \ + .clk_set_source_freq = NULL \ } @@ -257,6 +261,7 @@ struct ti_clock_dev ti_omap4_clk_devmap[ .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = omap4_clk_get_sysclk_freq, + .clk_set_source_freq = NULL, }, /* MPU (ARM) core clocks */ { .id = MPU_CLK, @@ -265,6 +270,7 @@ struct ti_clock_dev ti_omap4_clk_devmap[ .clk_set_source = NULL, .clk_accessible = NULL, .clk_get_source_freq = omap4_clk_get_arm_fclk_freq, + .clk_set_source_freq = NULL, }, Modified: head/sys/arm/ti/ti_prcm.c ============================================================================== --- head/sys/arm/ti/ti_prcm.c Wed Jun 17 23:24:46 2015 (r284531) +++ head/sys/arm/ti/ti_prcm.c Wed Jun 17 23:26:00 2015 (r284532) @@ -285,7 +285,7 @@ ti_prcm_clk_set_source(clk_ident_t clk, * @clk: identifier for the module to enable, see ti_prcm.h for a list * of possible modules. * @freq: pointer to an integer that upon return will contain the src freq - * + * * This function returns the frequency of the source clock. * * The real work done to enable the clock is really done in the callback @@ -319,6 +319,39 @@ ti_prcm_clk_get_source_freq(clk_ident_t ret = clk_dev->clk_get_source_freq(clk_dev, freq); else ret = EINVAL; - + + return (ret); +} + +/** + * ti_prcm_clk_set_source_freq - sets the source clock frequency as close to freq as possible + * @clk: identifier for the module to enable, see ti_prcm.h for a list + * of possible modules. + * @freq: requested freq + * + * LOCKING: + * Internally locks the driver context. + * + * RETURNS: + * Returns 0 on success or positive error code on failure. + */ +int +ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq) +{ + struct ti_clock_dev *clk_dev; + int ret; + + clk_dev = ti_prcm_clk_dev(clk); + + /* Sanity check we managed to find the clock */ + if (clk_dev == NULL) + return (EINVAL); + + /* Get the source frequency of the clock */ + if (clk_dev->clk_set_source_freq) + ret = clk_dev->clk_set_source_freq(clk_dev, freq); + else + ret = EINVAL; + return (ret); } Modified: head/sys/arm/ti/ti_prcm.h ============================================================================== --- head/sys/arm/ti/ti_prcm.h Wed Jun 17 23:24:46 2015 (r284531) +++ head/sys/arm/ti/ti_prcm.h Wed Jun 17 23:26:00 2015 (r284532) @@ -184,6 +184,8 @@ struct ti_clock_dev { int (*clk_set_source)(struct ti_clock_dev *clkdev, clk_src_t clksrc); int (*clk_accessible)(struct ti_clock_dev *clkdev); + int (*clk_set_source_freq)(struct ti_clock_dev *clkdev, + unsigned int freq); int (*clk_get_source_freq)(struct ti_clock_dev *clkdev, unsigned int *freq); }; @@ -194,6 +196,7 @@ int ti_prcm_clk_disable(clk_ident_t clk) int ti_prcm_clk_accessible(clk_ident_t clk); int ti_prcm_clk_disable_autoidle(clk_ident_t clk); int ti_prcm_clk_set_source(clk_ident_t clk, clk_src_t clksrc); +int ti_prcm_clk_set_source_freq(clk_ident_t clk, unsigned int freq); int ti_prcm_clk_get_source_freq(clk_ident_t clk, unsigned int *freq); void ti_prcm_reset(void);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506172326.t5HNQ1tW000562>