Author: jmcneill
Date: Wed Apr  6 23:11:03 2016
New Revision: 297627
URL: https://svnweb.freebsd.org/changeset/base/297627

Log:
  Convert Allwinner port to extres clk/hwreset/regulator APIs.
  
  Reviewed by:          andrew, gonzo, Emmanuel Vadot <m...@bidouilliste.com>
  Approved by:          gonzo (mentor)
  Differential Revision:        https://reviews.freebsd.org/D5752

Added:
  head/sys/arm/allwinner/aw_ccu.c   (contents, props changed)
  head/sys/arm/allwinner/aw_reset.c   (contents, props changed)
  head/sys/arm/allwinner/clk/
  head/sys/arm/allwinner/clk/aw_ahbclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_apbclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_axiclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_codecclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_cpuclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_debeclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_gate.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_gmacclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_hdmiclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_lcdclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_mmcclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_modclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_oscclk.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_pll.c   (contents, props changed)
  head/sys/arm/allwinner/clk/aw_usbclk.c   (contents, props changed)
Deleted:
  head/sys/arm/allwinner/a10_clk.c
  head/sys/arm/allwinner/a10_clk.h
  head/sys/arm/allwinner/a31/a31_clk.c
  head/sys/arm/allwinner/a31/a31_clk.h
  head/sys/boot/fdt/dts/arm/sun4i-a10.dtsi
  head/sys/boot/fdt/dts/arm/sun7i-a20.dtsi
Modified:
  head/sys/arm/allwinner/a10_ahci.c
  head/sys/arm/allwinner/a10_codec.c
  head/sys/arm/allwinner/a10_dmac.c
  head/sys/arm/allwinner/a10_ehci.c
  head/sys/arm/allwinner/a10_fb.c
  head/sys/arm/allwinner/a10_hdmi.c
  head/sys/arm/allwinner/a10_mmc.c
  head/sys/arm/allwinner/a20/a20_if_dwc.c
  head/sys/arm/allwinner/aw_usbphy.c
  head/sys/arm/allwinner/files.allwinner
  head/sys/arm/allwinner/if_emac.c
  head/sys/arm/conf/A10
  head/sys/arm/conf/A20
  head/sys/boot/fdt/dts/arm/bananapi.dts
  head/sys/boot/fdt/dts/arm/cubieboard.dts
  head/sys/boot/fdt/dts/arm/cubieboard2.dts
  head/sys/boot/fdt/dts/arm/olimex-a20-som-evb.dts
  head/sys/boot/fdt/dts/arm/olinuxino-lime.dts
  head/sys/boot/fdt/dts/arm/sun7i-a20-hdmi.dtsi
  head/sys/dev/dwc/if_dwc.c
  head/sys/dev/iicbus/twsi/a10_twsi.c

Modified: head/sys/arm/allwinner/a10_ahci.c
==============================================================================
--- head/sys/arm/allwinner/a10_ahci.c   Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a10_ahci.c   Wed Apr  6 23:11:03 2016        
(r297627)
@@ -47,7 +47,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus_subr.h>
 
 #include <dev/ahci/ahci.h>
-#include <arm/allwinner/a10_clk.h>
+#include <dev/extres/clk/clk.h>
 
 /*
  * Allwinner a1x/a2x/a8x SATA attachment.  This is just the AHCI register
@@ -117,6 +117,8 @@ __FBSDID("$FreeBSD$");
 #define        AHCI_P0PHYCR    0x0078
 #define        AHCI_P0PHYSR    0x007C
 
+#define        PLL_FREQ        100000000
+
 static void inline
 ahci_set(struct resource *m, bus_size_t off, uint32_t set)
 {
@@ -295,8 +297,11 @@ ahci_a10_attach(device_t dev)
 {
        int error;
        struct ahci_controller *ctlr;
+       clk_t clk_pll, clk_gate;
 
        ctlr = device_get_softc(dev);
+       clk_pll = clk_gate = NULL;
+
        ctlr->quirks = AHCI_Q_NOPMP;
        ctlr->vendorid = 0;
        ctlr->deviceid = 0;
@@ -307,15 +312,36 @@ ahci_a10_attach(device_t dev)
            &ctlr->r_rid, RF_ACTIVE)))
                return (ENXIO);
 
-       /* Turn on the PLL for SATA */
-       a10_clk_ahci_activate();
-
+       /* Enable clocks */
+       error = clk_get_by_ofw_index(dev, 0, &clk_pll);
+       if (error != 0) {
+               device_printf(dev, "Cannot get PLL clock\n");
+               goto fail;
+       }
+       error = clk_get_by_ofw_index(dev, 1, &clk_gate);
+       if (error != 0) {
+               device_printf(dev, "Cannot get gate clock\n");
+               goto fail;
+       }
+       error = clk_set_freq(clk_pll, PLL_FREQ, CLK_SET_ROUND_DOWN);
+       if (error != 0) {
+               device_printf(dev, "Cannot set PLL frequency\n");
+               goto fail;
+       }
+       error = clk_enable(clk_pll);
+       if (error != 0) {
+               device_printf(dev, "Cannot enable PLL\n");
+               goto fail;
+       }
+       error = clk_enable(clk_gate);
+       if (error != 0) {
+               device_printf(dev, "Cannot enable clk gate\n");
+               goto fail;
+       }
+       
        /* Reset controller */
-       if ((error = ahci_a10_ctlr_reset(dev)) != 0) {
-               bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid,
-                   ctlr->r_mem);
-               return (error);
-       };
+       if ((error = ahci_a10_ctlr_reset(dev)) != 0)
+               goto fail;
 
        /*
         * No MSI registers on this platform.
@@ -330,6 +356,14 @@ ahci_a10_attach(device_t dev)
         * Note: ahci_attach will release ctlr->r_mem on errors automatically
         */
        return (ahci_attach(dev));
+
+fail:
+       if (clk_gate != NULL)
+               clk_release(clk_gate);
+       if (clk_pll != NULL)
+               clk_release(clk_pll);
+       bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
+       return (error);
 }
 
 static int

Modified: head/sys/arm/allwinner/a10_codec.c
==============================================================================
--- head/sys/arm/allwinner/a10_codec.c  Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a10_codec.c  Wed Apr  6 23:11:03 2016        
(r297627)
@@ -50,7 +50,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
 
-#include <arm/allwinner/a10_clk.h>
+#include <dev/extres/clk/clk.h>
 
 #include "sunxi_dma_if.h"
 #include "mixer_if.h"
@@ -738,6 +738,7 @@ a10codec_attach(device_t dev)
 {
        struct a10codec_info *sc;
        char status[SND_STATUSLEN];
+       clk_t clk_apb, clk_codec;
        uint32_t val;
        int error;
 
@@ -778,6 +779,24 @@ a10codec_attach(device_t dev)
                goto fail;
        }
 
+       /* Get clocks */
+       error = clk_get_by_ofw_name(dev, "apb", &clk_apb);
+       if (error != 0) {
+               device_printf(dev, "cannot find apb clock\n");
+               goto fail;
+       }
+       error = clk_get_by_ofw_name(dev, "codec", &clk_codec);
+       if (error != 0) {
+               device_printf(dev, "cannot find codec clock\n");
+               goto fail;
+       }
+
+       /* Gating APB clock for codec */
+       error = clk_enable(clk_apb);
+       if (error != 0) {
+               device_printf(dev, "cannot enable apb clock\n");
+               goto fail;
+       }
        /* Activate audio codec clock. According to the A10 and A20 user
         * manuals, Audio_pll can be either 24.576MHz or 22.5792MHz. Most
         * audio sampling rates require an 24.576MHz input clock with the
@@ -787,7 +806,17 @@ a10codec_attach(device_t dev)
         * 24.576MHz clock source and don't advertise native support for
         * the three sampling rates that require a 22.5792MHz input.
         */
-       a10_clk_codec_activate(24576000);
+       error = clk_set_freq(clk_codec, 24576000, CLK_SET_ROUND_DOWN);
+       if (error != 0) {
+               device_printf(dev, "cannot set codec clock frequency\n");
+               goto fail;
+       }
+       /* Enable audio codec clock */
+       error = clk_enable(clk_codec);
+       if (error != 0) {
+               device_printf(dev, "cannot enable codec clock\n");
+               goto fail;
+       }
 
        /* Enable DAC */
        val = CODEC_READ(sc, AC_DAC_DPC);

Modified: head/sys/arm/allwinner/a10_dmac.c
==============================================================================
--- head/sys/arm/allwinner/a10_dmac.c   Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a10_dmac.c   Wed Apr  6 23:11:03 2016        
(r297627)
@@ -46,7 +46,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus_subr.h>
 
 #include <arm/allwinner/a10_dmac.h>
-#include <arm/allwinner/a10_clk.h>
+#include <dev/extres/clk/clk.h>
 
 #include "sunxi_dma_if.h"
 
@@ -111,6 +111,7 @@ a10dmac_attach(device_t dev)
 {
        struct a10dmac_softc *sc;
        unsigned int index;
+       clk_t clk;
        int error;
 
        sc = device_get_softc(dev);
@@ -123,7 +124,16 @@ a10dmac_attach(device_t dev)
        mtx_init(&sc->sc_mtx, "a10 dmac", NULL, MTX_SPIN);
 
        /* Activate DMA controller clock */
-       a10_clk_dmac_activate();
+       error = clk_get_by_ofw_index(dev, 0, &clk);
+       if (error != 0) {
+               device_printf(dev, "cannot get clock\n");
+               return (error);
+       }
+       error = clk_enable(clk);
+       if (error != 0) {
+               device_printf(dev, "cannot enable clock\n");
+               return (error);
+       }
 
        /* Disable all interrupts and clear pending status */
        DMA_WRITE(sc, AWIN_DMA_IRQ_EN_REG, 0);

Modified: head/sys/arm/allwinner/a10_ehci.c
==============================================================================
--- head/sys/arm/allwinner/a10_ehci.c   Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a10_ehci.c   Wed Apr  6 23:11:03 2016        
(r297627)
@@ -59,8 +59,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/usb/controller/ehcireg.h>
 
 #include <arm/allwinner/allwinner_machdep.h>
-#include <arm/allwinner/a10_clk.h>
-#include <arm/allwinner/a31/a31_clk.h>
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
 
 #define EHCI_HC_DEVSTR                 "Allwinner Integrated USB 2.0 
controller"
 
@@ -90,25 +90,22 @@ static device_detach_t a10_ehci_detach;
 bs_r_1_proto(reversed);
 bs_w_1_proto(reversed);
 
+struct aw_ehci_softc {
+       ehci_softc_t    sc;
+       clk_t           clk;
+       hwreset_t       rst;
+};
+
 struct aw_ehci_conf {
-       int             (*clk_activate)(void);
-       int             (*clk_deactivate)(void);
        bool            sdram_init;
 };
 
 static const struct aw_ehci_conf a10_ehci_conf = {
-#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
-       .clk_activate = a10_clk_ehci_activate,
-       .clk_deactivate = a10_clk_ehci_deactivate,
-#endif
        .sdram_init = true,
 };
 
 static const struct aw_ehci_conf a31_ehci_conf = {
-#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
-       .clk_activate = a31_clk_ehci_activate,
-       .clk_deactivate = a31_clk_ehci_deactivate,
-#endif
+       .sdram_init = false,
 };
 
 static struct ofw_compat_data compat_data[] = {
@@ -136,7 +133,8 @@ a10_ehci_probe(device_t self)
 static int
 a10_ehci_attach(device_t self)
 {
-       ehci_softc_t *sc = device_get_softc(self);
+       struct aw_ehci_softc *aw_sc = device_get_softc(self);
+       ehci_softc_t *sc = &aw_sc->sc;
        const struct aw_ehci_conf *conf;
        bus_space_handle_t bsh;
        int err;
@@ -144,10 +142,6 @@ a10_ehci_attach(device_t self)
        uint32_t reg_value = 0;
 
        conf = USB_CONF(self);
-       if (conf->clk_activate == NULL) {
-               device_printf(self, "clock not supported\n");
-               return (ENXIO);
-       }
 
        /* initialise some bus fields */
        sc->sc_bus.parent = self;
@@ -208,9 +202,24 @@ a10_ehci_attach(device_t self)
 
        sc->sc_flags |= EHCI_SCFLG_DONTRESET;
 
+       /* De-assert reset */
+       if (hwreset_get_by_ofw_idx(self, 0, &aw_sc->rst) == 0) {
+               err = hwreset_deassert(aw_sc->rst);
+               if (err != 0) {
+                       device_printf(self, "Could not de-assert reset\n");
+                       goto error;
+               }
+       }
+
        /* Enable clock for USB */
-       if (conf->clk_activate() != 0) {
-               device_printf(self, "Could not activate clock\n");
+       err = clk_get_by_ofw_index(self, 0, &aw_sc->clk);
+       if (err != 0) {
+               device_printf(self, "Could not get clock\n");
+               goto error;
+       }
+       err = clk_enable(aw_sc->clk);
+       if (err != 0) {
+               device_printf(self, "Could not enable clock\n");
                goto error;
        }
 
@@ -240,6 +249,8 @@ a10_ehci_attach(device_t self)
        return (0);
 
 error:
+       if (aw_sc->clk)
+               clk_release(aw_sc->clk);
        a10_ehci_detach(self);
        return (ENXIO);
 }
@@ -247,7 +258,8 @@ error:
 static int
 a10_ehci_detach(device_t self)
 {
-       ehci_softc_t *sc = device_get_softc(self);
+       struct aw_ehci_softc *aw_sc = device_get_softc(self);
+       ehci_softc_t *sc = &aw_sc->sc;
        const struct aw_ehci_conf *conf;
        device_t bdev;
        int err;
@@ -305,7 +317,14 @@ a10_ehci_detach(device_t self)
        A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
 
        /* Disable clock for USB */
-       conf->clk_deactivate();
+       clk_disable(aw_sc->clk);
+       clk_release(aw_sc->clk);
+
+       /* Assert reset */
+       if (aw_sc->rst != NULL) {
+               hwreset_assert(aw_sc->rst);
+               hwreset_release(aw_sc->rst);
+       }
 
        return (0);
 }

Modified: head/sys/arm/allwinner/a10_fb.c
==============================================================================
--- head/sys/arm/allwinner/a10_fb.c     Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a10_fb.c     Wed Apr  6 23:11:03 2016        
(r297627)
@@ -54,7 +54,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/videomode/videomode.h>
 #include <dev/videomode/edidvar.h>
 
-#include <arm/allwinner/a10_clk.h>
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
 
 #include "fb_if.h"
 #include "hdmi_if.h"
@@ -66,6 +67,7 @@ __FBSDID("$FreeBSD$");
 #define        FB_ALIGN        0x1000
 
 #define        HDMI_ENABLE_DELAY       20000
+#define        DEBE_FREQ               300000000
 
 #define        DOT_CLOCK_TO_HZ(c)      ((c) * 1000)
 
@@ -193,18 +195,68 @@ a10fb_freefb(struct a10fb_softc *sc)
        kmem_free(kernel_arena, sc->vaddr, sc->fbsize);
 }
 
-static void
+static int
 a10fb_setup_debe(struct a10fb_softc *sc, const struct videomode *mode)
 {
        int width, height, interlace, reg;
+       clk_t clk_ahb, clk_dram, clk_debe;
+       hwreset_t rst;
        uint32_t val;
+       int error;
 
        interlace = !!(mode->flags & VID_INTERLACE);
        width = mode->hdisplay;
        height = mode->vdisplay << interlace;
 
-       /* Enable DEBE clocks */
-       a10_clk_debe_activate();
+       /* Leave reset */
+       error = hwreset_get_by_ofw_name(sc->dev, "de_be", &rst);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find reset 'de_be'\n");
+               return (error);
+       }
+       error = hwreset_deassert(rst);
+       if (error != 0) {
+               device_printf(sc->dev, "couldn't de-assert reset 'de_be'\n");
+               return (error);
+       }
+       /* Gating AHB clock for BE */
+       error = clk_get_by_ofw_name(sc->dev, "ahb_de_be", &clk_ahb);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find clk 'ahb_de_be'\n");
+               return (error);
+       }
+       error = clk_enable(clk_ahb);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot enable clk 'ahb_de_be'\n");
+               return (error);
+       }
+       /* Enable DRAM clock to BE */
+       error = clk_get_by_ofw_name(sc->dev, "dram_de_be", &clk_dram);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find clk 'dram_de_be'\n");
+               return (error);
+       }
+       error = clk_enable(clk_dram);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot enable clk 'dram_de_be'\n");
+               return (error);
+       }
+       /* Set BE clock to 300MHz and enable */
+       error = clk_get_by_ofw_name(sc->dev, "de_be", &clk_debe);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find clk 'de_be'\n");
+               return (error);
+       }
+       error = clk_set_freq(clk_debe, DEBE_FREQ, CLK_SET_ROUND_DOWN);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot set 'de_be' frequency\n");
+               return (error);
+       }
+       error = clk_enable(clk_debe);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot enable clk 'de_be'\n");
+               return (error);
+       }
 
        /* Initialize all registers to 0 */
        for (reg = DEBE_REG_START; reg < DEBE_REG_END; reg += DEBE_REG_WIDTH)
@@ -247,14 +299,55 @@ a10fb_setup_debe(struct a10fb_softc *sc,
        val = DEBE_READ(sc, DEBE_MODCTL);
        val |= MODCTL_START_CTL;
        DEBE_WRITE(sc, DEBE_MODCTL, val);
+
+       return (0);
 }
 
-static void
+static int
+a10fb_setup_pll(struct a10fb_softc *sc, uint64_t freq)
+{
+       clk_t clk_sclk1, clk_sclk2;
+       int error;
+
+       error = clk_get_by_ofw_name(sc->dev, "lcd_ch1_sclk1", &clk_sclk1);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find clk 'lcd_ch1_sclk1'\n");
+               return (error);
+       }
+       error = clk_get_by_ofw_name(sc->dev, "lcd_ch1_sclk2", &clk_sclk2);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find clk 'lcd_ch1_sclk2'\n");
+               return (error);
+       }
+
+       error = clk_set_freq(clk_sclk2, freq, 0);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot set lcd ch1 frequency\n");
+               return (error);
+       }
+       error = clk_enable(clk_sclk2);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot enable lcd ch1 sclk2\n");
+               return (error);
+       }
+       error = clk_enable(clk_sclk1);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot enable lcd ch1 sclk1\n");
+               return (error);
+       }
+
+       return (0);
+}
+
+static int
 a10fb_setup_tcon(struct a10fb_softc *sc, const struct videomode *mode)
 {
        u_int interlace, hspw, hbp, vspw, vbp, vbl, width, height, start_delay;
        u_int vtotal, framerate, clk;
+       clk_t clk_ahb;
+       hwreset_t rst;
        uint32_t val;
+       int error;
 
        interlace = !!(mode->flags & VID_INTERLACE);
        width = mode->hdisplay;
@@ -266,8 +359,28 @@ a10fb_setup_tcon(struct a10fb_softc *sc,
        vbl = VBLANK_LEN(mode->vtotal, mode->vdisplay, interlace);
        start_delay = START_DELAY(vbl);
 
-       /* Enable LCD clocks */
-       a10_clk_lcd_activate();
+       /* Leave reset */
+       error = hwreset_get_by_ofw_name(sc->dev, "lcd", &rst);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find reset 'lcd'\n");
+               return (error);
+       }
+       error = hwreset_deassert(rst);
+       if (error != 0) {
+               device_printf(sc->dev, "couldn't de-assert reset 'lcd'\n");
+               return (error);
+       }
+       /* Gating AHB clock for LCD */
+       error = clk_get_by_ofw_name(sc->dev, "ahb_lcd", &clk_ahb);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot find clk 'ahb_lcd'\n");
+               return (error);
+       }
+       error = clk_enable(clk_ahb);
+       if (error != 0) {
+               device_printf(sc->dev, "cannot enable clk 'ahb_lcd'\n");
+               return (error);
+       }
 
        /* Disable TCON and TCON1 */
        TCON_WRITE(sc, TCON_GCTL, 0);
@@ -322,7 +435,7 @@ a10fb_setup_tcon(struct a10fb_softc *sc,
        TCON_WRITE(sc, TCON1_CTL, val);
 
        /* Setup PLL */
-       a10_clk_tcon_activate(DOT_CLOCK_TO_HZ(mode->dot_clock));
+       return (a10fb_setup_pll(sc, DOT_CLOCK_TO_HZ(mode->dot_clock)));
 }
 
 static void
@@ -378,10 +491,14 @@ a10fb_configure(struct a10fb_softc *sc, 
        }
 
        /* Setup display backend */
-       a10fb_setup_debe(sc, mode);
+       error = a10fb_setup_debe(sc, mode);
+       if (error != 0)
+               return (error);
 
        /* Setup display timing controller */
-       a10fb_setup_tcon(sc, mode);
+       error = a10fb_setup_tcon(sc, mode);
+       if (error != 0)
+               return (error);
 
        /* Attach framebuffer device */
        sc->info.fb_name = device_get_nameunit(sc->dev);

Modified: head/sys/arm/allwinner/a10_hdmi.c
==============================================================================
--- head/sys/arm/allwinner/a10_hdmi.c   Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a10_hdmi.c   Wed Apr  6 23:11:03 2016        
(r297627)
@@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/videomode/videomode.h>
 #include <dev/videomode/edidvar.h>
 
-#include <arm/allwinner/a10_clk.h>
+#include <dev/extres/clk/clk.h>
 
 #include "hdmi_if.h"
 
@@ -204,6 +204,7 @@ __FBSDID("$FreeBSD$");
 #define        HDMI_VSDB_MINLEN        5
 #define        HDMI_OUI                "\x03\x0c\x00"
 #define        HDMI_OUI_LEN            3
+#define        HDMI_DEFAULT_FREQ       297000000
 
 struct a10hdmi_softc {
        struct resource         *res;
@@ -214,6 +215,10 @@ struct a10hdmi_softc {
 
        int                     has_hdmi;
        int                     has_audio;
+
+       clk_t                   clk_ahb;
+       clk_t                   clk_hdmi;
+       clk_t                   clk_lcd;
 };
 
 static struct resource_spec a10hdmi_spec[] = {
@@ -287,7 +292,33 @@ a10hdmi_attach(device_t dev)
                return (ENXIO);
        }
 
-       a10_clk_hdmi_activate();
+       /* Setup clocks */
+       error = clk_get_by_ofw_name(dev, "ahb", &sc->clk_ahb);
+       if (error != 0) {
+               device_printf(dev, "cannot find ahb clock\n");
+               return (error);
+       }
+       error = clk_get_by_ofw_name(dev, "hdmi", &sc->clk_hdmi);
+       if (error != 0) {
+               device_printf(dev, "cannot find hdmi clock\n");
+               return (error);
+       }
+       error = clk_get_by_ofw_name(dev, "lcd", &sc->clk_lcd);
+       if (error != 0) {
+               device_printf(dev, "cannot find lcd clock\n");
+       }
+       /* Enable HDMI clock */
+       error = clk_enable(sc->clk_hdmi);
+       if (error != 0) {
+               device_printf(dev, "cannot enable hdmi clock\n");
+               return (error);
+       }
+       /* Gating AHB clock for HDMI */
+       error = clk_enable(sc->clk_ahb);
+       if (error != 0) {
+               device_printf(dev, "cannot enable ahb gate\n");
+               return (error);
+       }
 
        a10hdmi_init(sc);
 
@@ -527,6 +558,38 @@ a10hdmi_set_audiomode(device_t dev, cons
 }
 
 static int
+a10hdmi_get_tcon_config(struct a10hdmi_softc *sc, int *div, int *dbl)
+{
+       uint64_t lcd_fin, lcd_fout;
+       clk_t clk_lcd_parent;
+       const char *pname;
+       int error;
+
+       error = clk_get_parent(sc->clk_lcd, &clk_lcd_parent);
+       if (error != 0)
+               return (error);
+
+       /* Get the LCD CH1 special clock 2 divider */
+       error = clk_get_freq(sc->clk_lcd, &lcd_fout);
+       if (error != 0)
+               return (error);
+       error = clk_get_freq(clk_lcd_parent, &lcd_fin);
+       if (error != 0)
+               return (error);
+       *div = lcd_fin / lcd_fout;
+
+       /* Detect LCD CH1 special clock using a 1X or 2X source */
+       /* XXX */
+       pname = clk_get_name(clk_lcd_parent);
+       if (strcmp(pname, "pll3-1x") == 0 || strcmp(pname, "pll7-1x") == 0)
+               *dbl = 0;
+       else
+               *dbl = 1;
+
+       return (0);
+}
+
+static int
 a10hdmi_set_videomode(device_t dev, const struct videomode *mode)
 {
        struct a10hdmi_softc *sc;
@@ -543,9 +606,11 @@ a10hdmi_set_videomode(device_t dev, cons
        vspw = mode->vsync_end - mode->vsync_start;
        vbp = mode->vtotal - mode->vsync_start;
 
-       error = a10_clk_tcon_get_config(&clk_div, &clk_dbl);
-       if (error != 0)
+       error = a10hdmi_get_tcon_config(sc, &clk_div, &clk_dbl);
+       if (error != 0) {
+               device_printf(dev, "couldn't get tcon config: %d\n", error);
                return (error);
+       }
 
        /* Clear interrupt status */
        HDMI_WRITE(sc, HDMI_INT_STATUS, HDMI_READ(sc, HDMI_INT_STATUS));

Modified: head/sys/arm/allwinner/a10_mmc.c
==============================================================================
--- head/sys/arm/allwinner/a10_mmc.c    Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a10_mmc.c    Wed Apr  6 23:11:03 2016        
(r297627)
@@ -49,9 +49,9 @@ __FBSDID("$FreeBSD$");
 #include <dev/mmc/mmcbrvar.h>
 
 #include <arm/allwinner/allwinner_machdep.h>
-#include <arm/allwinner/a10_clk.h>
 #include <arm/allwinner/a10_mmc.h>
-#include <arm/allwinner/a31/a31_clk.h>
+#include <dev/extres/clk/clk.h>
+#include <dev/extres/hwreset/hwreset.h>
 
 #define        A10_MMC_MEMRES          0
 #define        A10_MMC_IRQRES          1
@@ -60,6 +60,8 @@ __FBSDID("$FreeBSD$");
 #define        A10_MMC_DMA_MAX_SIZE    0x2000
 #define        A10_MMC_DMA_FTRGLEVEL   0x20070008
 
+#define        CARD_ID_FREQUENCY       400000
+
 static int a10_mmc_pio_mode = 0;
 
 TUNABLE_INT("hw.a10.mmc.pio_mode", &a10_mmc_pio_mode);
@@ -74,6 +76,9 @@ struct a10_mmc_softc {
        bus_space_handle_t      a10_bsh;
        bus_space_tag_t         a10_bst;
        device_t                a10_dev;
+       clk_t                   a10_clk_ahb;
+       clk_t                   a10_clk_mmc;
+       hwreset_t               a10_rst_ahb;
        int                     a10_bus_busy;
        int                     a10_id;
        int                     a10_resid;
@@ -147,7 +152,7 @@ a10_mmc_attach(device_t dev)
        struct a10_mmc_softc *sc;
        struct sysctl_ctx_list *ctx;
        struct sysctl_oid_list *tree;
-       int clk;
+       int error;
 
        sc = device_get_softc(dev);
        sc->a10_dev = dev;
@@ -170,6 +175,9 @@ a10_mmc_attach(device_t dev)
                device_printf(dev, "cannot setup interrupt handler\n");
                return (ENXIO);
        }
+       mtx_init(&sc->a10_mtx, device_get_nameunit(sc->a10_dev), "a10_mmc",
+           MTX_DEF);
+       callout_init_mtx(&sc->a10_timeoutc, &sc->a10_mtx, 0);
 
        /*
         * Later chips use a different FIFO offset. Unfortunately the FDT
@@ -186,30 +194,41 @@ a10_mmc_attach(device_t dev)
                break;
        }
 
+       /* De-assert reset */
+       if (hwreset_get_by_ofw_name(dev, "ahb", &sc->a10_rst_ahb) == 0) {
+               error = hwreset_deassert(sc->a10_rst_ahb);
+               if (error != 0) {
+                       device_printf(dev, "cannot de-assert reset\n");
+                       return (error);
+               }
+       }
+
        /* Activate the module clock. */
-       switch (allwinner_soc_type()) {
-#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
-       case ALLWINNERSOC_A10:
-       case ALLWINNERSOC_A10S:
-       case ALLWINNERSOC_A20:
-               clk = a10_clk_mmc_activate(sc->a10_id);
-               break;
-#endif
-#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
-       case ALLWINNERSOC_A31:
-       case ALLWINNERSOC_A31S:
-               clk = a31_clk_mmc_activate(sc->a10_id);
-               break;
-#endif
-       default:
-               clk = -1;
+       error = clk_get_by_ofw_name(dev, "ahb", &sc->a10_clk_ahb);
+       if (error != 0) {
+               device_printf(dev, "cannot get ahb clock\n");
+               goto fail;
        }
-       if (clk != 0) {
-               bus_teardown_intr(dev, sc->a10_res[A10_MMC_IRQRES],
-                   sc->a10_intrhand);
-               bus_release_resources(dev, a10_mmc_res_spec, sc->a10_res);
-               device_printf(dev, "cannot activate mmc clock\n");
-               return (ENXIO);
+       error = clk_enable(sc->a10_clk_ahb);
+       if (error != 0) {
+               device_printf(dev, "cannot enable ahb clock\n");
+               goto fail;
+       }
+       error = clk_get_by_ofw_name(dev, "mmc", &sc->a10_clk_mmc);
+       if (error != 0) {
+               device_printf(dev, "cannot get mmc clock\n");
+               goto fail;
+       }
+       error = clk_set_freq(sc->a10_clk_mmc, CARD_ID_FREQUENCY,
+           CLK_SET_ROUND_DOWN);
+       if (error != 0) {
+               device_printf(dev, "cannot init mmc clock\n");
+               goto fail;
+       }
+       error = clk_enable(sc->a10_clk_mmc);
+       if (error != 0) {
+               device_printf(dev, "cannot enable mmc clock\n");
+               goto fail;
        }
 
        sc->a10_timeout = 10;
@@ -217,9 +236,6 @@ a10_mmc_attach(device_t dev)
        tree = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
        SYSCTL_ADD_INT(ctx, tree, OID_AUTO, "req_timeout", CTLFLAG_RW,
            &sc->a10_timeout, 0, "Request timeout in seconds");
-       mtx_init(&sc->a10_mtx, device_get_nameunit(sc->a10_dev), "a10_mmc",
-           MTX_DEF);
-       callout_init_mtx(&sc->a10_timeoutc, &sc->a10_mtx, 0);
 
        /* Reset controller. */
        if (a10_mmc_reset(sc) != 0) {
@@ -826,25 +842,14 @@ a10_mmc_update_ios(device_t bus, device_
                        return (error);
 
                /* Set the MMC clock. */
-               switch (allwinner_soc_type()) {
-#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
-               case ALLWINNERSOC_A10:
-               case ALLWINNERSOC_A10S:
-               case ALLWINNERSOC_A20:
-                       error = a10_clk_mmc_cfg(sc->a10_id, ios->clock);
-                       break;
-#endif
-#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
-               case ALLWINNERSOC_A31:
-               case ALLWINNERSOC_A31S:
-                       error = a31_clk_mmc_cfg(sc->a10_id, ios->clock);
-                       break;
-#endif
-               default:
-                       error = ENXIO;
-               }
-               if (error != 0)
+               error = clk_set_freq(sc->a10_clk_mmc, ios->clock,
+                   CLK_SET_ROUND_DOWN);
+               if (error != 0) {
+                       device_printf(sc->a10_dev,
+                           "failed to set frequency to %u Hz: %d\n",
+                           ios->clock, error);
                        return (error);
+               }
 
                /* Enable clock. */
                clkcr |= A10_MMC_CARD_CLK_ON;

Modified: head/sys/arm/allwinner/a20/a20_if_dwc.c
==============================================================================
--- head/sys/arm/allwinner/a20/a20_if_dwc.c     Wed Apr  6 22:38:50 2016        
(r297626)
+++ head/sys/arm/allwinner/a20/a20_if_dwc.c     Wed Apr  6 23:11:03 2016        
(r297627)
@@ -41,8 +41,7 @@ __FBSDID("$FreeBSD$");
 #include <dev/ofw/ofw_bus_subr.h>
 
 #include <arm/allwinner/allwinner_machdep.h>
-#include <arm/allwinner/a10_clk.h>
-#include <arm/allwinner/a31/a31_clk.h>
+#include <dev/extres/clk/clk.h>
 
 #include "if_dwc_if.h"
 
@@ -62,29 +61,39 @@ a20_if_dwc_probe(device_t dev)
 static int
 a20_if_dwc_init(device_t dev)
 {
-       int clk;
-
-       /* Activate GMAC clock and set the pin mux to rgmii. */
-       switch (allwinner_soc_type()) {
-#if defined(SOC_ALLWINNER_A10) || defined(SOC_ALLWINNER_A20)
-       case ALLWINNERSOC_A10:
-       case ALLWINNERSOC_A10S:
-       case ALLWINNERSOC_A20:
-               clk = a10_clk_gmac_activate(ofw_bus_get_node(dev));
-               break;
-#endif
-#if defined(SOC_ALLWINNER_A31) || defined(SOC_ALLWINNER_A31S)
-       case ALLWINNERSOC_A31:
-       case ALLWINNERSOC_A31S:
-               clk = a31_clk_gmac_activate(ofw_bus_get_node(dev));
-               break;
-#endif
-       default:
-               clk = -1;
-       }
-       if (clk != 0) {
-               device_printf(dev, "could not activate gmac module\n");
-               return (ENXIO);
+       const char *tx_parent_name;
+       char *phy_type;
+       clk_t clk_tx, clk_tx_parent;
+       phandle_t node;
+       int error;
+
+       node = ofw_bus_get_node(dev);
+
+       /* Configure PHY for MII or RGMII mode */
+       if (OF_getprop_alloc(node, "phy-mode", 1, (void **)&phy_type)) {
+               error = clk_get_by_ofw_name(dev, "allwinner_gmac_tx", &clk_tx);
+               if (error != 0) {
+                       device_printf(dev, "could not get tx clk\n");
+                       return (error);
+               }
+
+               if (strcmp(phy_type, "rgmii") == 0)
+                       tx_parent_name = "gmac_int_tx";
+               else
+                       tx_parent_name = "mii_phy_tx";
+
+               error = clk_get_by_name(dev, tx_parent_name, &clk_tx_parent);
+               if (error != 0) {
+                       device_printf(dev, "could not get clock '%s'\n",
+                           tx_parent_name);
+                       return (error);
+               }
+
+               error = clk_set_parent_by_clk(clk_tx, clk_tx_parent);
+               if (error != 0) {
+                       device_printf(dev, "could not set tx clk parent\n");
+                       return (error);
+               }
        }
 
        return (0);

Added: head/sys/arm/allwinner/aw_ccu.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/arm/allwinner/aw_ccu.c     Wed Apr  6 23:11:03 2016        
(r297627)
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 2016 Jared McNeill <jmcne...@invisible.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Allwinner oscillator clock
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+
+#include <dev/extres/clk/clk.h>
+
+#include "clkdev_if.h"
+
+#define        CCU_BASE        0x01c20000
+#define        CCU_SIZE        0x400
+
+struct aw_ccu_softc {
+       struct simplebus_softc  sc;
+       bus_space_tag_t         bst;
+       bus_space_handle_t      bsh;
+       struct mtx              mtx;
+};
+
+static struct ofw_compat_data compat_data[] = {
+       { "allwinner,sun4i-a10",        1 },
+       { "allwinner,sun7i-a20",        1 },
+       { "allwinner,sun6i-a31",        1 },
+       { "allwinner,sun6i-a31s",       1 },
+       { NULL, 0 }
+};
+
+static int
+aw_ccu_check_addr(bus_addr_t addr)
+{
+       if (addr < CCU_BASE || addr >= (CCU_BASE + CCU_SIZE))
+               return (EINVAL);
+       return (0);
+}
+
+static int
+aw_ccu_write_4(device_t dev, bus_addr_t addr, uint32_t val)
+{
+       struct aw_ccu_softc *sc;
+
+       if (aw_ccu_check_addr(addr) != 0)
+               return (EINVAL);
+
+       sc = device_get_softc(dev);
+       mtx_assert(&sc->mtx, MA_OWNED);
+       bus_space_write_4(sc->bst, sc->bsh, addr - CCU_BASE, val);
+
+       return (0);
+}
+
+static int
+aw_ccu_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
+{
+       struct aw_ccu_softc *sc;
+
+       if (aw_ccu_check_addr(addr) != 0)
+               return (EINVAL);
+
+       sc = device_get_softc(dev);
+       mtx_assert(&sc->mtx, MA_OWNED);
+       *val = bus_space_read_4(sc->bst, sc->bsh, addr - CCU_BASE);
+
+       return (0);
+}
+
+static int
+aw_ccu_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
+{
+       struct aw_ccu_softc *sc;
+       uint32_t val;
+
+       if (aw_ccu_check_addr(addr) != 0)
+               return (EINVAL);
+
+       sc = device_get_softc(dev);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
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