svn commit: r324022 - head/sys/arm/allwinner

Emmanuel Vadot manu at FreeBSD.org
Tue Sep 26 19:21:45 UTC 2017


Author: manu
Date: Tue Sep 26 19:21:43 2017
New Revision: 324022
URL: https://svnweb.freebsd.org/changeset/base/324022

Log:
  a10_ehci: Enable all clocks and reset
  
  a10_ehci can have multiple clocks and reset, enable them all instead of
  only the first one.

Modified:
  head/sys/arm/allwinner/a10_ehci.c

Modified: head/sys/arm/allwinner/a10_ehci.c
==============================================================================
--- head/sys/arm/allwinner/a10_ehci.c	Tue Sep 26 19:20:50 2017	(r324021)
+++ head/sys/arm/allwinner/a10_ehci.c	Tue Sep 26 19:21:43 2017	(r324022)
@@ -88,11 +88,21 @@ __FBSDID("$FreeBSD$");
 static device_attach_t a10_ehci_attach;
 static device_detach_t a10_ehci_detach;
 
+struct clk_list {
+	TAILQ_ENTRY(clk_list)	next;
+	clk_t			clk;
+};
+
+struct hwrst_list {
+	TAILQ_ENTRY(hwrst_list)	next;
+	hwreset_t		rst;
+};
+
 struct aw_ehci_softc {
 	ehci_softc_t	sc;
-	clk_t		clk;
-	hwreset_t	rst;
-	phy_t		phy;
+	TAILQ_HEAD(, clk_list)		clk_list;
+	TAILQ_HEAD(, hwrst_list)	rst_list;
+	phy_t				phy;
 };
 
 struct aw_ehci_conf {
@@ -114,6 +124,7 @@ static struct ofw_compat_data compat_data[] = {
 	{ "allwinner,sun7i-a20-ehci",	(uintptr_t)&a10_ehci_conf },
 	{ "allwinner,sun8i-a83t-ehci",	(uintptr_t)&a31_ehci_conf },
 	{ "allwinner,sun8i-h3-ehci",	(uintptr_t)&a31_ehci_conf },
+	/* { "allwinner,sun50i-a64-ehci",	(uintptr_t)&a31_ehci_conf }, */
 	{ NULL,				(uintptr_t)NULL }
 };
 
@@ -139,8 +150,11 @@ a10_ehci_attach(device_t self)
 	ehci_softc_t *sc = &aw_sc->sc;
 	const struct aw_ehci_conf *conf;
 	bus_space_handle_t bsh;
-	int err;
-	int rid;
+	int err, rid, off;
+	struct clk_list *clkp;
+	clk_t clk;
+	struct hwrst_list *rstp;
+	hwreset_t rst;
 	uint32_t reg_value = 0;
 
 	conf = USB_CONF(self);
@@ -204,27 +218,33 @@ a10_ehci_attach(device_t self)
 
 	sc->sc_flags |= EHCI_SCFLG_DONTRESET;
 
+	/* Enable clock for USB */
+	TAILQ_INIT(&aw_sc->clk_list);
+	for (off = 0; clk_get_by_ofw_index(self, 0, off, &clk) == 0; off++) {
+		err = clk_enable(clk);
+		if (err != 0) {
+			device_printf(self, "Could not enable clock %s\n",
+			    clk_get_name(clk));
+			goto error;
+		}
+		clkp = malloc(sizeof(*clkp), M_DEVBUF, M_WAITOK | M_ZERO);
+		clkp->clk = clk;
+		TAILQ_INSERT_TAIL(&aw_sc->clk_list, clkp, next);
+	}
+
 	/* De-assert reset */
-	if (hwreset_get_by_ofw_idx(self, 0, 0, &aw_sc->rst) == 0) {
-		err = hwreset_deassert(aw_sc->rst);
+	TAILQ_INIT(&aw_sc->rst_list);
+	for (off = 0; hwreset_get_by_ofw_idx(self, 0, off, &rst) == 0; off++) {
+		err = hwreset_deassert(rst);
 		if (err != 0) {
 			device_printf(self, "Could not de-assert reset\n");
 			goto error;
 		}
+		rstp = malloc(sizeof(*rstp), M_DEVBUF, M_WAITOK | M_ZERO);
+		rstp->rst = rst;
+		TAILQ_INSERT_TAIL(&aw_sc->rst_list, rstp, next);
 	}
 
-	/* Enable clock for USB */
-	err = clk_get_by_ofw_index(self, 0, 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;
-	}
-
 	/* Enable USB PHY */
 	if (phy_get_by_ofw_name(self, 0, "usb", &aw_sc->phy) == 0) {
 		err = phy_enable(self, aw_sc->phy);
@@ -272,6 +292,8 @@ a10_ehci_detach(device_t self)
 	const struct aw_ehci_conf *conf;
 	int err;
 	uint32_t reg_value = 0;
+	struct clk_list *clk, *clk_tmp;
+	struct hwrst_list *rst, *rst_tmp;
 
 	conf = USB_CONF(self);
 
@@ -319,16 +341,26 @@ a10_ehci_detach(device_t self)
 	reg_value &= ~SW_ULPI_BYPASS; /* ULPI bypass disable */
 	A10_WRITE_4(sc, SW_USB_PMU_IRQ_ENABLE, reg_value);
 
-	/* Disable clock for USB */
-	if (aw_sc->clk != NULL) {
-		clk_disable(aw_sc->clk);
-		clk_release(aw_sc->clk);
+	/* Disable clock */
+	TAILQ_FOREACH_SAFE(clk, &aw_sc->clk_list, next, clk_tmp) {
+		err = clk_disable(clk->clk);
+		if (err != 0)
+			device_printf(self, "Could not disable clock %s\n",
+			    clk_get_name(clk->clk));
+		err = clk_release(clk->clk);
+		if (err != 0)
+			device_printf(self, "Could not release clock %s\n",
+			    clk_get_name(clk->clk));
+		TAILQ_REMOVE(&aw_sc->clk_list, clk, next);
+		free(clk, M_DEVBUF);
 	}
 
 	/* Assert reset */
-	if (aw_sc->rst != NULL) {
-		hwreset_assert(aw_sc->rst);
-		hwreset_release(aw_sc->rst);
+	TAILQ_FOREACH_SAFE(rst, &aw_sc->rst_list, next, rst_tmp) {
+		hwreset_assert(rst->rst);
+		hwreset_release(rst->rst);
+		TAILQ_REMOVE(&aw_sc->rst_list, rst, next);
+		free(rst, M_DEVBUF);
 	}
 
 	return (0);


More information about the svn-src-all mailing list