Changeset View
Changeset View
Standalone View
Standalone View
head/sys/arm/allwinner/aw_usbphy.c
Show All 38 Lines | |||||
#include <sys/rman.h> | #include <sys/rman.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/module.h> | #include <sys/module.h> | ||||
#include <sys/gpio.h> | #include <sys/gpio.h> | ||||
#include <dev/ofw/ofw_bus.h> | #include <dev/ofw/ofw_bus.h> | ||||
#include <dev/ofw/ofw_bus_subr.h> | #include <dev/ofw/ofw_bus_subr.h> | ||||
#include "gpio_if.h" | #include <dev/extres/clk/clk.h> | ||||
#include <dev/extres/hwreset/hwreset.h> | |||||
#include <dev/extres/regulator/regulator.h> | |||||
#define USBPHY_NUMOFF 3 | #define USBPHY_NUMOFF 3 | ||||
#define GPIO_POLARITY(flags) (((flags) & 1) ? GPIO_PIN_LOW : GPIO_PIN_HIGH) | |||||
static struct ofw_compat_data compat_data[] = { | static struct ofw_compat_data compat_data[] = { | ||||
{ "allwinner,sun4i-a10-usb-phy", 1 }, | { "allwinner,sun4i-a10-usb-phy", 1 }, | ||||
{ "allwinner,sun5i-a13-usb-phy", 1 }, | { "allwinner,sun5i-a13-usb-phy", 1 }, | ||||
{ "allwinner,sun6i-a31-usb-phy", 1 }, | { "allwinner,sun6i-a31-usb-phy", 1 }, | ||||
{ "allwinner,sun7i-a20-usb-phy", 1 }, | { "allwinner,sun7i-a20-usb-phy", 1 }, | ||||
{ NULL, 0 } | { NULL, 0 } | ||||
}; | }; | ||||
static int | static int | ||||
awusbphy_gpio_set(device_t dev, phandle_t node, const char *pname) | |||||
{ | |||||
pcell_t gpio_prop[4]; | |||||
phandle_t gpio_node; | |||||
device_t gpio_dev; | |||||
uint32_t pin, flags; | |||||
ssize_t len; | |||||
int val; | |||||
len = OF_getencprop(node, pname, gpio_prop, sizeof(gpio_prop)); | |||||
if (len == -1) | |||||
return (0); | |||||
if (len != sizeof(gpio_prop)) { | |||||
device_printf(dev, "property %s length was %d, expected %d\n", | |||||
pname, len, sizeof(gpio_prop)); | |||||
return (ENXIO); | |||||
} | |||||
gpio_node = OF_node_from_xref(gpio_prop[0]); | |||||
gpio_dev = OF_device_from_xref(gpio_prop[0]); | |||||
if (gpio_dev == NULL) { | |||||
device_printf(dev, "failed to get the GPIO device for %s\n", | |||||
pname); | |||||
return (ENOENT); | |||||
} | |||||
if (GPIO_MAP_GPIOS(gpio_dev, node, gpio_node, | |||||
sizeof(gpio_prop) / sizeof(gpio_prop[0]) - 1, gpio_prop + 1, | |||||
&pin, &flags) != 0) { | |||||
device_printf(dev, "failed to map the GPIO pin for %s\n", | |||||
pname); | |||||
return (ENXIO); | |||||
} | |||||
val = GPIO_POLARITY(flags); | |||||
GPIO_PIN_SETFLAGS(gpio_dev, pin, GPIO_PIN_OUTPUT); | |||||
GPIO_PIN_SET(gpio_dev, pin, val); | |||||
return (0); | |||||
} | |||||
static int | |||||
awusbphy_supply_set(device_t dev, const char *pname) | |||||
{ | |||||
phandle_t node, reg_node; | |||||
pcell_t reg_xref; | |||||
node = ofw_bus_get_node(dev); | |||||
if (OF_getencprop(node, pname, ®_xref, sizeof(reg_xref)) == -1) | |||||
return (0); | |||||
reg_node = OF_node_from_xref(reg_xref); | |||||
return (awusbphy_gpio_set(dev, reg_node, "gpio")); | |||||
} | |||||
static int | |||||
awusbphy_init(device_t dev) | awusbphy_init(device_t dev) | ||||
{ | { | ||||
char pname[20]; | char pname[20]; | ||||
phandle_t node; | |||||
int error, off; | int error, off; | ||||
regulator_t reg; | |||||
hwreset_t rst; | |||||
clk_t clk; | |||||
node = ofw_bus_get_node(dev); | /* Enable clocks */ | ||||
for (off = 0; clk_get_by_ofw_index(dev, off, &clk) == 0; off++) { | |||||
for (off = 0; off < USBPHY_NUMOFF; off++) { | error = clk_enable(clk); | ||||
snprintf(pname, sizeof(pname), "usb%d_id_det-gpio", off); | if (error != 0) { | ||||
error = awusbphy_gpio_set(dev, node, pname); | device_printf(dev, "couldn't enable clock %s\n", | ||||
if (error) | clk_get_name(clk)); | ||||
return (error); | return (error); | ||||
} | |||||
} | |||||
snprintf(pname, sizeof(pname), "usb%d_vbus_det-gpio", off); | /* De-assert resets */ | ||||
error = awusbphy_gpio_set(dev, node, pname); | for (off = 0; hwreset_get_by_ofw_idx(dev, off, &rst) == 0; off++) { | ||||
if (error) | error = hwreset_deassert(rst); | ||||
if (error != 0) { | |||||
device_printf(dev, "couldn't de-assert reset %d\n", | |||||
off); | |||||
return (error); | return (error); | ||||
} | |||||
} | |||||
/* Enable regulator(s) */ | |||||
for (off = 0; off < USBPHY_NUMOFF; off++) { | |||||
snprintf(pname, sizeof(pname), "usb%d_vbus-supply", off); | snprintf(pname, sizeof(pname), "usb%d_vbus-supply", off); | ||||
error = awusbphy_supply_set(dev, pname); | if (regulator_get_by_ofw_property(dev, pname, ®) != 0) | ||||
if (error) | continue; | ||||
error = regulator_enable(reg); | |||||
if (error != 0) { | |||||
device_printf(dev, "couldn't enable regulator %s\n", | |||||
pname); | |||||
return (error); | return (error); | ||||
} | |||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
awusbphy_probe(device_t dev) | awusbphy_probe(device_t dev) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 41 Lines • Show Last 20 Lines |