Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Apr 2016 23:11:04 +0000 (UTC)
From:      Jared McNeill <jmcneill@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r297627 - in head/sys: arm/allwinner arm/allwinner/a20 arm/allwinner/a31 arm/allwinner/clk arm/conf boot/fdt/dts/arm dev/dwc dev/iicbus/twsi
Message-ID:  <201604062311.u36NB43A024272@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <manu@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 <jmcneill@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 ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604062311.u36NB43A024272>