Changeset View
Changeset View
Standalone View
Standalone View
sys/arm/allwinner/aw_usbphy.c
Show All 33 Lines | |||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#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 <machine/bus.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 <dev/extres/clk/clk.h> | #include <dev/extres/clk/clk.h> | ||||
#include <dev/extres/hwreset/hwreset.h> | #include <dev/extres/hwreset/hwreset.h> | ||||
#include <dev/extres/regulator/regulator.h> | #include <dev/extres/regulator/regulator.h> | ||||
#define PHY_CSR 0x00 | |||||
#define ID_PULLUP_EN (1 << 17) | |||||
#define DPDM_PULLUP_EN (1 << 16) | |||||
#define FORCE_ID (0x3 << 14) | |||||
#define FORCE_ID_SHIFT 14 | |||||
#define FORCE_ID_LOW 2 | |||||
#define FORCE_VBUS_VALID (0x3 << 12) | |||||
#define FORCE_VBUS_VALID_SHIFT 12 | |||||
#define FORCE_VBUS_VALID_HIGH 3 | |||||
#define VBUS_CHANGE_DET (1 << 6) | |||||
#define ID_CHANGE_DET (1 << 5) | |||||
#define DPDM_CHANGE_DET (1 << 4) | |||||
#define USBPHY_NUMOFF 3 | #define USBPHY_NUMOFF 3 | ||||
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 struct resource_spec awusbphy_spec[] = { | |||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE }, | |||||
{ -1, 0 } | |||||
}; | |||||
static int | static int | ||||
awusbphy_init(device_t dev) | awusbphy_init(device_t dev, struct resource *res) | ||||
{ | { | ||||
char pname[20]; | char pname[20]; | ||||
int error, off; | int error, off; | ||||
regulator_t reg; | regulator_t reg; | ||||
hwreset_t rst; | hwreset_t rst; | ||||
clk_t clk; | clk_t clk; | ||||
uint32_t val; | |||||
/* Enable clocks */ | /* Enable clocks */ | ||||
for (off = 0; clk_get_by_ofw_index(dev, off, &clk) == 0; off++) { | for (off = 0; clk_get_by_ofw_index(dev, off, &clk) == 0; off++) { | ||||
error = clk_enable(clk); | error = clk_enable(clk); | ||||
if (error != 0) { | if (error != 0) { | ||||
device_printf(dev, "couldn't enable clock %s\n", | device_printf(dev, "couldn't enable clock %s\n", | ||||
clk_get_name(clk)); | clk_get_name(clk)); | ||||
return (error); | return (error); | ||||
Show All 18 Lines | for (off = 0; off < USBPHY_NUMOFF; off++) { | ||||
error = regulator_enable(reg); | error = regulator_enable(reg); | ||||
if (error != 0) { | if (error != 0) { | ||||
device_printf(dev, "couldn't enable regulator %s\n", | device_printf(dev, "couldn't enable regulator %s\n", | ||||
pname); | pname); | ||||
return (error); | return (error); | ||||
} | } | ||||
} | } | ||||
/* Enable OTG PHY for host mode */ | |||||
val = bus_read_4(res, PHY_CSR); | |||||
val &= ~(VBUS_CHANGE_DET | ID_CHANGE_DET | DPDM_CHANGE_DET); | |||||
val |= (ID_PULLUP_EN | DPDM_PULLUP_EN); | |||||
val &= ~FORCE_ID; | |||||
val |= (FORCE_ID_LOW << FORCE_ID_SHIFT); | |||||
val &= ~FORCE_VBUS_VALID; | |||||
val |= (FORCE_VBUS_VALID_HIGH << FORCE_VBUS_VALID_SHIFT); | |||||
bus_write_4(res, PHY_CSR, val); | |||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
awusbphy_probe(device_t dev) | awusbphy_probe(device_t dev) | ||||
{ | { | ||||
if (!ofw_bus_status_okay(dev)) | if (!ofw_bus_status_okay(dev)) | ||||
return (ENXIO); | return (ENXIO); | ||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) | if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) | ||||
return (ENXIO); | return (ENXIO); | ||||
device_set_desc(dev, "Allwinner USB PHY"); | device_set_desc(dev, "Allwinner USB PHY"); | ||||
return (BUS_PROBE_DEFAULT); | return (BUS_PROBE_DEFAULT); | ||||
} | } | ||||
static int | static int | ||||
awusbphy_attach(device_t dev) | awusbphy_attach(device_t dev) | ||||
{ | { | ||||
struct resource *res; | |||||
int error; | int error; | ||||
error = awusbphy_init(dev); | error = bus_alloc_resources(dev, awusbphy_spec, &res); | ||||
if (error != 0) { | |||||
device_printf(dev, "failed to allocate bus resources\n"); | |||||
return (error); | |||||
} | |||||
error = awusbphy_init(dev, res); | |||||
if (error) | if (error) | ||||
device_printf(dev, "failed to initialize USB PHY, error %d\n", | device_printf(dev, "failed to initialize USB PHY, error %d\n", | ||||
error); | error); | ||||
bus_release_resources(dev, awusbphy_spec, &res); | |||||
return (error); | return (error); | ||||
} | } | ||||
static device_method_t awusbphy_methods[] = { | static device_method_t awusbphy_methods[] = { | ||||
/* Device interface */ | /* Device interface */ | ||||
DEVMETHOD(device_probe, awusbphy_probe), | DEVMETHOD(device_probe, awusbphy_probe), | ||||
DEVMETHOD(device_attach, awusbphy_attach), | DEVMETHOD(device_attach, awusbphy_attach), | ||||
hselasky: Should the device_resume and device_suspend methods do anything? | |||||
Not Done Inline ActionsSuspend/resume not yet supported on the Allwinner port. jmcneill: Suspend/resume not yet supported on the Allwinner port. | |||||
DEVMETHOD_END | DEVMETHOD_END | ||||
}; | }; | ||||
static driver_t awusbphy_driver = { | static driver_t awusbphy_driver = { | ||||
"awusbphy", | "awusbphy", | ||||
Not Done Inline ActionsI like better when you initialize by record: driver = { Current code is OK. Same with other drivers in this patch. hselasky: I like better when you initialize by record:
driver = {
.name = "",
.xxxx
.size = ....
}… | |||||
Not Done Inline ActionsAgree, but following style used in the rest of sys/arm/allwinner. Would it be alright if I changed musb_otg_allwinner.c to use C99 initializers and left awusbphy.c as-is? jmcneill: Agree, but following style used in the rest of sys/arm/allwinner. Would it be alright if I… | |||||
awusbphy_methods, | awusbphy_methods, | ||||
0, | 0, | ||||
}; | }; | ||||
static devclass_t awusbphy_devclass; | static devclass_t awusbphy_devclass; | ||||
DRIVER_MODULE(awusbphy, simplebus, awusbphy_driver, awusbphy_devclass, 0, 0); | EARLY_DRIVER_MODULE(awusbphy, simplebus, awusbphy_driver, awusbphy_devclass, | ||||
0, 0, BUS_PASS_TIMER + BUS_PASS_ORDER_MIDDLE); | |||||
MODULE_VERSION(awusbphy, 1); | MODULE_VERSION(awusbphy, 1); |
Should the device_resume and device_suspend methods do anything?