Date: Wed, 31 Aug 2016 10:45:53 +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: r305120 - head/sys/arm/allwinner Message-ID: <201608311045.u7VAjr3M071553@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jmcneill Date: Wed Aug 31 10:45:53 2016 New Revision: 305120 URL: https://svnweb.freebsd.org/changeset/base/305120 Log: Add support for Allwinner A64 USB PHY. Reviewed by: manu Modified: head/sys/arm/allwinner/aw_usbphy.c Modified: head/sys/arm/allwinner/aw_usbphy.c ============================================================================== --- head/sys/arm/allwinner/aw_usbphy.c Wed Aug 31 10:45:33 2016 (r305119) +++ head/sys/arm/allwinner/aw_usbphy.c Wed Aug 31 10:45:53 2016 (r305120) @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/module.h> #include <sys/gpio.h> +#include <machine/bus.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> @@ -53,25 +54,89 @@ __FBSDID("$FreeBSD$"); #include "phy_if.h" #define USBPHY_NPHYS 4 +#define USBPHY_NRES USBPHY_NPHYS + +enum awusbphy_type { + AWUSBPHY_TYPE_A10 = 1, + AWUSBPHY_TYPE_A13, + AWUSBPHY_TYPE_A20, + AWUSBPHY_TYPE_A31, + AWUSBPHY_TYPE_A83T, + AWUSBPHY_TYPE_H3, + AWUSBPHY_TYPE_A64 +}; static struct ofw_compat_data compat_data[] = { - { "allwinner,sun4i-a10-usb-phy", 1 }, - { "allwinner,sun5i-a13-usb-phy", 1 }, - { "allwinner,sun6i-a31-usb-phy", 1 }, - { "allwinner,sun7i-a20-usb-phy", 1 }, - { "allwinner,sun8i-a83t-usb-phy", 1 }, - { "allwinner,sun8i-h3-usb-phy", 1 }, + { "allwinner,sun4i-a10-usb-phy", AWUSBPHY_TYPE_A10 }, + { "allwinner,sun5i-a13-usb-phy", AWUSBPHY_TYPE_A13 }, + { "allwinner,sun6i-a31-usb-phy", AWUSBPHY_TYPE_A31 }, + { "allwinner,sun7i-a20-usb-phy", AWUSBPHY_TYPE_A20 }, + { "allwinner,sun8i-a83t-usb-phy", AWUSBPHY_TYPE_A83T }, + { "allwinner,sun8i-h3-usb-phy", AWUSBPHY_TYPE_H3 }, + { "allwinner,sun50i-a64-usb-phy", AWUSBPHY_TYPE_A64 }, { NULL, 0 } }; struct awusbphy_softc { + struct resource * res[USBPHY_NRES]; regulator_t reg[USBPHY_NPHYS]; gpio_pin_t id_det_pin; int id_det_valid; gpio_pin_t vbus_det_pin; int vbus_det_valid; + enum awusbphy_type phy_type; }; +static struct resource_spec awusbphy_spec[] = { + { SYS_RES_MEMORY, 0, RF_ACTIVE }, + { SYS_RES_MEMORY, 1, RF_ACTIVE }, + { SYS_RES_MEMORY, 2, RF_ACTIVE | RF_OPTIONAL }, + { SYS_RES_MEMORY, 3, RF_ACTIVE | RF_OPTIONAL }, + { -1, 0 } +}; + +#define RD4(sc, i, o) bus_read_4((sc)->res[(i)], (o)) +#define WR4(sc, i, o, v) bus_write_4((sc)->res[(i)], (o), (v)) +#define CLR4(sc, i, o, m) WR4(sc, i, o, RD4(sc, i, o) & ~(m)) +#define SET4(sc, i, o, m) WR4(sc, i, o, RD4(sc, i, o) | (m)) + +#define OTG_PHY_CFG 0x20 +#define OTG_PHY_ROUTE_OTG (1 << 0) +#define PMU_IRQ_ENABLE 0x00 +#define PMU_AHB_INCR8 (1 << 10) +#define PMU_AHB_INCR4 (1 << 9) +#define PMU_AHB_INCRX_ALIGN (1 << 8) +#define PMU_ULPI_BYPASS (1 << 0) +#define PMU_UNK_H3 0x10 +#define PMU_UNK_H3_CLR 0x2 + +static void +awusbphy_configure(device_t dev, int phyno) +{ + struct awusbphy_softc *sc; + + sc = device_get_softc(dev); + + if (sc->res[phyno] == NULL) + return; + + if (sc->phy_type == AWUSBPHY_TYPE_A64) { + CLR4(sc, phyno, PMU_UNK_H3, PMU_UNK_H3_CLR); + + /* EHCI0 and OTG share a PHY */ + if (phyno == 0) + SET4(sc, 0, OTG_PHY_CFG, OTG_PHY_ROUTE_OTG); + else if (phyno == 1) + CLR4(sc, 0, OTG_PHY_CFG, OTG_PHY_ROUTE_OTG); + } + + if (phyno > 0) { + /* Enable passby */ + SET4(sc, phyno, PMU_IRQ_ENABLE, PMU_ULPI_BYPASS | + PMU_AHB_INCR8 | PMU_AHB_INCR4 | PMU_AHB_INCRX_ALIGN); + } +} + static int awusbphy_init(device_t dev) { @@ -86,6 +151,8 @@ awusbphy_init(device_t dev) sc = device_get_softc(dev); node = ofw_bus_get_node(dev); + sc->phy_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; + /* Enable clocks */ for (off = 0; clk_get_by_ofw_index(dev, 0, off, &clk) == 0; off++) { error = clk_enable(clk); @@ -123,6 +190,10 @@ awusbphy_init(device_t dev) if (error == 0) sc->vbus_det_valid = 1; + /* Allocate resources */ + if (bus_alloc_resources(dev, awusbphy_spec, sc->res) != 0) + device_printf(dev, "couldn't allocate resources\n"); + return (0); } @@ -159,6 +230,9 @@ awusbphy_phy_enable(device_t dev, intptr sc = device_get_softc(dev); + /* Configure PHY */ + awusbphy_configure(dev, phy); + /* Regulators are optional. If not found, return success. */ reg = sc->reg[phy]; if (reg == NULL)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608311045.u7VAjr3M071553>