Author: andrew
Date: Sun Jan 24 19:10:30 2016
New Revision: 294675
URL: https://svnweb.freebsd.org/changeset/base/294675

Log:
  Add support for controlling the clocks for the audio codec and DMA engines.
  
  Submitted by: Jared McNeill <jmcne...@invisible.ca>
  Differential Revision:        https://reviews.freebsd.org/D5052

Modified:
  head/sys/arm/allwinner/a10_clk.c
  head/sys/arm/allwinner/a10_clk.h

Modified: head/sys/arm/allwinner/a10_clk.c
==============================================================================
--- head/sys/arm/allwinner/a10_clk.c    Sun Jan 24 18:54:55 2016        
(r294674)
+++ head/sys/arm/allwinner/a10_clk.c    Sun Jan 24 19:10:30 2016        
(r294675)
@@ -255,6 +255,58 @@ a10_clk_pll6_get_rate(void)
        return ((CCM_CLK_REF_FREQ * n * k) / 2);
 }
 
+static int
+a10_clk_pll2_set_rate(unsigned int freq)
+{
+       struct a10_ccm_softc *sc;
+       uint32_t reg_value;
+       unsigned int prediv, postdiv, n;
+
+       sc = a10_ccm_sc;
+       if (sc == NULL)
+               return (ENXIO);
+
+
+       reg_value = ccm_read_4(sc, CCM_PLL2_CFG);
+       reg_value &= ~(CCM_PLL2_CFG_PREDIV | CCM_PLL2_CFG_POSTDIV |
+           CCM_PLL_CFG_FACTOR_N);
+
+       /*
+        * Audio Codec needs PLL2 to be either 24576000 Hz or 22579200 Hz
+        *
+        * PLL2 output frequency is 24MHz * n / prediv / postdiv.
+        * To get as close as possible to the desired rate, we use a
+        * pre-divider of 21 and a post-divider of 4. With these values,
+        * a multiplier of 86 or 79 gets us close to the target rates.
+        */
+       prediv = 21;
+       postdiv = 4;
+
+       switch (freq) {
+       case 24576000:
+               n = 86;
+               reg_value |= CCM_PLL_CFG_ENABLE;
+               break;
+       case 22579200:
+               n = 79;
+               reg_value |= CCM_PLL_CFG_ENABLE;
+               break;
+       case 0:
+               n = 1;
+               reg_value &= ~CCM_PLL_CFG_ENABLE;
+               break;
+       default:
+               return (EINVAL);
+       }
+
+       reg_value |= (prediv << CCM_PLL2_CFG_PREDIV_SHIFT);
+       reg_value |= (postdiv << CCM_PLL2_CFG_POSTDIV_SHIFT);
+       reg_value |= (n << CCM_PLL_CFG_FACTOR_N_SHIFT);
+       ccm_write_4(sc, CCM_PLL2_CFG, reg_value);
+
+       return (0);
+}
+
 int
 a10_clk_ahci_activate(void)
 {
@@ -347,3 +399,46 @@ a10_clk_mmc_cfg(int devid, int freq)
 
        return (0);
 }
+
+int
+a10_clk_dmac_activate(void)
+{
+       struct a10_ccm_softc *sc;
+       uint32_t reg_value;
+
+       sc = a10_ccm_sc;
+       if (sc == NULL)
+               return (ENXIO);
+
+       /* Gating AHB clock for DMA controller */
+       reg_value = ccm_read_4(sc, CCM_AHB_GATING0);
+       reg_value |= CCM_AHB_GATING_DMA;
+       ccm_write_4(sc, CCM_AHB_GATING0, reg_value);
+
+       return (0);
+}
+
+int
+a10_clk_codec_activate(unsigned int freq)
+{
+       struct a10_ccm_softc *sc;
+       uint32_t reg_value;
+
+       sc = a10_ccm_sc;
+       if (sc == NULL)
+               return (ENXIO);
+
+       a10_clk_pll2_set_rate(freq);
+
+       /* Gating APB clock for ADDA */
+       reg_value = ccm_read_4(sc, CCM_APB0_GATING);
+       reg_value |= CCM_APB0_GATING_ADDA;
+       ccm_write_4(sc, CCM_APB0_GATING, reg_value);
+
+       /* Enable audio codec clock */
+       reg_value = ccm_read_4(sc, CCM_AUDIO_CODEC_CLK);
+       reg_value |= CCM_AUDIO_CODEC_ENABLE;
+       ccm_write_4(sc, CCM_AUDIO_CODEC_CLK, reg_value);
+
+       return (0);
+}

Modified: head/sys/arm/allwinner/a10_clk.h
==============================================================================
--- head/sys/arm/allwinner/a10_clk.h    Sun Jan 24 18:54:55 2016        
(r294674)
+++ head/sys/arm/allwinner/a10_clk.h    Sun Jan 24 19:10:30 2016        
(r294675)
@@ -106,10 +106,14 @@
 #define        CCM_GMAC_CLK_EXT_RGMII  0x1
 #define        CCM_GMAC_CLK_RGMII      0x2
 
+/* APB0_GATING */
+#define        CCM_APB0_GATING_ADDA    (1 << 0)
+
 /* AHB_GATING_REG0 */
 #define        CCM_AHB_GATING_USB0     (1 << 0)
 #define        CCM_AHB_GATING_EHCI0    (1 << 1)
 #define        CCM_AHB_GATING_EHCI1    (1 << 3)
+#define        CCM_AHB_GATING_DMA      (1 << 6)
 #define        CCM_AHB_GATING_SDMMC0   (1 << 8)
 #define        CCM_AHB_GATING_EMAC     (1 << 17)
 #define        CCM_AHB_GATING_SATA     (1 << 25)
@@ -132,6 +136,11 @@
 #define        CCM_PLL_CFG_FACTOR_K_SHIFT      4
 #define        CCM_PLL_CFG_FACTOR_M            0x3
 
+#define        CCM_PLL2_CFG_POSTDIV            0x3c000000
+#define        CCM_PLL2_CFG_POSTDIV_SHIFT      26
+#define        CCM_PLL2_CFG_PREDIV             0x1f
+#define        CCM_PLL2_CFG_PREDIV_SHIFT       0
+
 #define        CCM_PLL6_CFG_SATA_CLKEN (1U << 14)
 
 #define        CCM_SD_CLK_SRC_SEL              0x3000000
@@ -146,6 +155,8 @@
 #define        CCM_SD_CLK_OPHASE_CTR_SHIFT     8
 #define        CCM_SD_CLK_DIV_RATIO_M          0xf
 
+#define        CCM_AUDIO_CODEC_ENABLE  (1U << 31)
+
 #define        CCM_CLK_REF_FREQ        24000000U
 
 int a10_clk_usb_activate(void);
@@ -155,5 +166,7 @@ int a10_clk_gmac_activate(phandle_t);
 int a10_clk_ahci_activate(void);
 int a10_clk_mmc_activate(int);
 int a10_clk_mmc_cfg(int, int);
+int a10_clk_dmac_activate(void);
+int a10_clk_codec_activate(unsigned int);
 
 #endif /* _A10_CLK_H_ */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to