aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/host/r8a66597-hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/r8a66597-hcd.c')
-rw-r--r--drivers/usb/host/r8a66597-hcd.c330
1 files changed, 183 insertions, 147 deletions
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 3c263e51c1..a37696d83f 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -7,9 +7,11 @@
#include <common.h>
#include <console.h>
+#include <dm.h>
#include <usb.h>
#include <asm/io.h>
#include <linux/iopoll.h>
+#include <power/regulator.h>
#include "r8a66597.h"
@@ -19,33 +21,53 @@
#define R8A66597_DPRINT(...)
#endif
-static struct r8a66597 gr8a66597;
+static inline struct usb_device *usb_dev_get_parent(struct usb_device *udev)
+{
+ struct udevice *parent = udev->dev->parent;
+
+ /*
+ * When called from usb-uclass.c: usb_scan_device() udev->dev points
+ * to the parent udevice, not the actual udevice belonging to the
+ * udev as the device is not instantiated yet.
+ *
+ * If dev is an usb-bus, then we are called from usb_scan_device() for
+ * an usb-device plugged directly into the root port, return NULL.
+ */
+ if (device_get_uclass_id(udev->dev) == UCLASS_USB)
+ return NULL;
+
+ /*
+ * If these 2 are not the same we are being called from
+ * usb_scan_device() and udev itself is the parent.
+ */
+ if (dev_get_parent_priv(udev->dev) != udev)
+ return udev;
+
+ /* We are being called normally, use the parent pointer */
+ if (device_get_uclass_id(parent) == UCLASS_USB_HUB)
+ return dev_get_parent_priv(parent);
+
+ return NULL;
+}
static void get_hub_data(struct usb_device *dev, u16 *hub_devnum, u16 *hubport)
{
- int i;
+ struct usb_device *parent = usb_dev_get_parent(dev);
*hub_devnum = 0;
*hubport = 0;
/* check a device connected to root_hub */
- if ((dev->parent && dev->parent->devnum == 1) ||
- (dev->devnum == 1))
+ if ((parent && parent->devnum == 1) ||
+ dev->devnum == 1)
return;
- for (i = 0; i < USB_MAXCHILDREN; i++) {
- if (dev->parent->children[i] == dev) {
- *hub_devnum = (u8)dev->parent->devnum;
- *hubport = i;
- return;
- }
- }
-
- printf("get_hub_data error.\n");
+ *hub_devnum = (u8)parent->devnum;
+ *hubport = parent->portnr - 1;
}
static void set_devadd(struct r8a66597 *r8a66597, u8 r8a66597_address,
- struct usb_device *dev, int port)
+ struct usb_device *dev, int port)
{
u16 val, usbspd, upphub, hubport;
unsigned long devadd_reg = get_devadd_addr(r8a66597_address);
@@ -61,17 +83,6 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
u16 tmp;
int i = 0;
-#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
- do {
- r8a66597_write(r8a66597, SCKE, SYSCFG0);
- tmp = r8a66597_read(r8a66597, SYSCFG0);
- if (i++ > 1000) {
- printf("register access fail.\n");
- return -1;
- }
- } while ((tmp & SCKE) != SCKE);
- r8a66597_write(r8a66597, 0x04, 0x02);
-#else
do {
r8a66597_write(r8a66597, USBE, SYSCFG0);
tmp = r8a66597_read(r8a66597, SYSCFG0);
@@ -81,57 +92,30 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
}
} while ((tmp & USBE) != USBE);
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-#if !defined(CONFIG_RZA_USB)
- r8a66597_mdfy(r8a66597, CONFIG_R8A66597_XTAL, XTAL, SYSCFG0);
-
- i = 0;
- r8a66597_bset(r8a66597, XCKE, SYSCFG0);
- do {
- udelay(1000);
- tmp = r8a66597_read(r8a66597, SYSCFG0);
- if (i++ > 500) {
- printf("register access fail.\n");
- return -1;
- }
- } while ((tmp & SCKE) != SCKE);
-#else
/*
* RZ/A Only:
* Bits XTAL(UCKSEL) and UPLLE in SYSCFG0 for USB0 controls both USB0
* and USB1, so we must always set the USB0 register
*/
#if (CONFIG_R8A66597_XTAL == 1)
- setbits(le16, R8A66597_BASE0, XTAL);
+ r8a66597_bset(r8a66597, XTAL, SYSCFG0);
#endif
mdelay(1);
- setbits(le16, R8A66597_BASE0, UPLLE);
+ r8a66597_bset(r8a66597, UPLLE, SYSCFG0);
mdelay(1);
r8a66597_bset(r8a66597, SUSPM, SUSPMODE0);
-#endif /* CONFIG_RZA_USB */
-#endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
return 0;
}
static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
{
-#if !defined(CONFIG_RZA_USB)
- r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
- udelay(1);
-#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
- r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
- r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
- r8a66597_bclr(r8a66597, USBE, SYSCFG0);
-#endif
-#else
r8a66597_bclr(r8a66597, SUSPM, SUSPMODE0);
- clrbits(le16, R8A66597_BASE0, UPLLE);
+ r8a66597_bclr(r8a66597, UPLLE, SYSCFG0);
mdelay(1);
r8a66597_bclr(r8a66597, USBE, SYSCFG0);
mdelay(1);
-
-#endif
}
static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
@@ -141,10 +125,6 @@ static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
val = port ? DRPD : DCFM | DRPD;
r8a66597_bset(r8a66597, val, get_syscfg_reg(port));
r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
-
-#if !defined(CONFIG_RZA_USB)
- r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port));
-#endif
}
static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port)
@@ -174,9 +154,6 @@ static int enable_controller(struct r8a66597 *r8a66597)
if (ret < 0)
return ret;
-#if !defined(CONFIG_RZA_USB)
- r8a66597_bset(r8a66597, CONFIG_R8A66597_LDRV & LDRV, PINCFG);
-#endif
r8a66597_bset(r8a66597, USBE, SYSCFG0);
r8a66597_bset(r8a66597, INTL, SOFCFG);
@@ -184,9 +161,9 @@ static int enable_controller(struct r8a66597 *r8a66597)
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
r8a66597_write(r8a66597, 0, get_intenb_reg(port));
- r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, CFIFOSEL);
- r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D0FIFOSEL);
- r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D1FIFOSEL);
+ r8a66597_bclr(r8a66597, BIGEND, CFIFOSEL);
+ r8a66597_bclr(r8a66597, BIGEND, D0FIFOSEL);
+ r8a66597_bclr(r8a66597, BIGEND, D1FIFOSEL);
r8a66597_bset(r8a66597, TRNENSEL, SOFCFG);
for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
@@ -294,16 +271,13 @@ static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
unsigned long setup_addr = USBREQ;
u16 intsts1;
int timeout = 3000;
-#if defined(CONFIG_RZA_USB)
u16 dcpctr;
-#endif
u16 devsel = setup->request == USB_REQ_SET_ADDRESS ? 0 : dev->devnum;
r8a66597_write(r8a66597, make_devsel(devsel) |
(8 << dev->maxpacketsize), DCPMAXP);
r8a66597_write(r8a66597, ~(SIGN | SACK), INTSTS1);
-#if defined(CONFIG_RZA_USB)
dcpctr = r8a66597_read(r8a66597, DCPCTR);
if ((dcpctr & PID) == PID_BUF) {
if (readw_poll_timeout(r8a66597->reg + DCPCTR, dcpctr,
@@ -312,7 +286,6 @@ static int send_setup_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
return -ETIMEDOUT;
}
}
-#endif
for (i = 0; i < 4; i++) {
r8a66597_write(r8a66597, le16_to_cpu(p[i]), setup_addr);
@@ -349,7 +322,7 @@ static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
R8A66597_DPRINT("%s\n", __func__);
r8a66597_mdfy(r8a66597, MBW | BULK_OUT_PIPENUM,
- MBW | CURPIPE, CFIFOSEL);
+ MBW | CURPIPE, CFIFOSEL);
r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, BULK_OUT_PIPENUM);
tmp = r8a66597_read(r8a66597, CFIFOCTR);
if ((tmp & FRDY) == 0) {
@@ -373,7 +346,7 @@ static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
dev->act_len += size;
r8a66597_mdfy(r8a66597, PID_BUF, PID,
- get_pipectr_addr(BULK_OUT_PIPENUM));
+ get_pipectr_addr(BULK_OUT_PIPENUM));
while (!(r8a66597_read(r8a66597, BEMPSTS) & (1 << BULK_OUT_PIPENUM)))
if (ctrlc())
@@ -382,7 +355,7 @@ static int send_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev,
if (dev->act_len >= transfer_len)
r8a66597_mdfy(r8a66597, PID_NAK, PID,
- get_pipectr_addr(BULK_OUT_PIPENUM));
+ get_pipectr_addr(BULK_OUT_PIPENUM));
return 0;
}
@@ -403,17 +376,17 @@ static int receive_bulk_packet(struct r8a66597 *r8a66597,
/* prepare */
if (dev->act_len == 0) {
r8a66597_mdfy(r8a66597, PID_NAK, PID,
- get_pipectr_addr(pipenum));
+ get_pipectr_addr(pipenum));
r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS);
r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum));
r8a66597_write(r8a66597,
- (transfer_len + maxpacket - 1) / maxpacket,
+ (transfer_len + maxpacket - 1) / maxpacket,
get_pipetrn_addr(pipenum));
r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum));
r8a66597_mdfy(r8a66597, PID_BUF, PID,
- get_pipectr_addr(pipenum));
+ get_pipectr_addr(pipenum));
}
r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
@@ -490,7 +463,7 @@ static int receive_control_packet(struct r8a66597 *r8a66597,
}
static int send_status_packet(struct r8a66597 *r8a66597,
- unsigned long pipe)
+ unsigned long pipe)
{
r8a66597_bset(r8a66597, SQSET, DCPCTR);
r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR);
@@ -581,16 +554,15 @@ static int check_usb_device_connecting(struct r8a66597 *r8a66597)
return -1; /* fail */
}
-/*-------------------------------------------------------------------------*
- * Virtual Root Hub
- *-------------------------------------------------------------------------*/
+/* Virtual Root Hub */
#include <usbroothubdes.h>
-static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
- void *buffer, int transfer_len, struct devrequest *cmd)
+static int r8a66597_submit_rh_msg(struct udevice *udev, struct usb_device *dev,
+ unsigned long pipe, void *buffer,
+ int transfer_len, struct devrequest *cmd)
{
- struct r8a66597 *r8a66597 = &gr8a66597;
+ struct r8a66597 *r8a66597 = dev_get_priv(udev);
int leni = transfer_len;
int len = 0;
int stat = 0;
@@ -658,40 +630,40 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
}
break;
case RH_SET_ADDRESS:
- gr8a66597.rh_devnum = wValue;
+ r8a66597->rh_devnum = wValue;
break;
case RH_GET_DESCRIPTOR:
switch ((wValue & 0xff00) >> 8) {
case (0x01): /* device descriptor */
len = min_t(unsigned int,
- leni,
+ leni,
min_t(unsigned int,
- sizeof(root_hub_dev_des),
+ sizeof(root_hub_dev_des),
wLength));
memcpy(buffer, root_hub_dev_des, len);
break;
case (0x02): /* configuration descriptor */
len = min_t(unsigned int,
- leni,
+ leni,
min_t(unsigned int,
- sizeof(root_hub_config_des),
+ sizeof(root_hub_config_des),
wLength));
memcpy(buffer, root_hub_config_des, len);
break;
case (0x03): /* string descriptors */
if (wValue == 0x0300) {
len = min_t(unsigned int,
- leni,
+ leni,
min_t(unsigned int,
- sizeof(root_hub_str_index0),
+ sizeof(root_hub_str_index0),
wLength));
memcpy(buffer, root_hub_str_index0, len);
}
if (wValue == 0x0301) {
len = min_t(unsigned int,
- leni,
+ leni,
min_t(unsigned int,
- sizeof(root_hub_str_index1),
+ sizeof(root_hub_str_index1),
wLength));
memcpy(buffer, root_hub_str_index1, len);
}
@@ -724,7 +696,8 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
} else {
data[0] += 2;
data[8] = (temp & RH_B_DR) >> 8;
- data[10] = data[9] = 0xff;
+ data[9] = 0xff;
+ data[10] = 0xff;
}
len = min_t(unsigned int, leni,
@@ -734,7 +707,7 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
}
case RH_GET_CONFIGURATION:
- *(__u8 *) buffer = 0x01;
+ *(__u8 *)buffer = 0x01;
len = 1;
break;
case RH_SET_CONFIGURATION:
@@ -754,50 +727,22 @@ static int r8a66597_submit_rh_msg(struct usb_device *dev, unsigned long pipe,
return stat;
}
-int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
- int transfer_len)
+static int r8a66597_submit_control_msg(struct udevice *udev,
+ struct usb_device *dev,
+ unsigned long pipe, void *buffer,
+ int length, struct devrequest *setup)
{
- struct r8a66597 *r8a66597 = &gr8a66597;
- int ret = 0;
-
- R8A66597_DPRINT("%s\n", __func__);
- R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n",
- pipe, buffer, transfer_len, dev->devnum);
-
- set_devadd(r8a66597, dev->devnum, dev, 0);
-
- pipe_buffer_setting(r8a66597, dev, pipe);
-
- dev->act_len = 0;
- while (dev->act_len < transfer_len && ret == 0) {
- if (ctrlc())
- return -1;
-
- if (usb_pipein(pipe))
- ret = receive_bulk_packet(r8a66597, dev, pipe, buffer,
- transfer_len);
- else
- ret = send_bulk_packet(r8a66597, dev, pipe, buffer,
- transfer_len);
- }
-
- if (ret == 0)
- dev->status = 0;
-
- return ret;
-}
-
-int submit_control_msg(struct usb_device *dev, unsigned long pipe,
- void *buffer, int transfer_len, struct devrequest *setup)
-{
- struct r8a66597 *r8a66597 = &gr8a66597;
+ struct r8a66597 *r8a66597 = dev_get_priv(udev);
u16 r8a66597_address = setup->request == USB_REQ_SET_ADDRESS ?
0 : dev->devnum;
+ debug("%s: dev='%s', udev=%p, udev->dev='%s', portnr=%d\n", __func__,
+ udev->name, dev, dev->dev->name, dev->portnr);
+
R8A66597_DPRINT("%s\n", __func__);
if (usb_pipedevice(pipe) == r8a66597->rh_devnum)
- return r8a66597_submit_rh_msg(dev, pipe, buffer, transfer_len,
- setup);
+ return r8a66597_submit_rh_msg(udev, dev, pipe, buffer,
+ length, setup);
R8A66597_DPRINT("%s: setup\n", __func__);
set_devadd(r8a66597, r8a66597_address, dev, 0);
@@ -810,7 +755,7 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe,
dev->act_len = 0;
if (usb_pipein(pipe))
if (receive_control_packet(r8a66597, dev, buffer,
- transfer_len) < 0)
+ length) < 0)
return -1;
if (send_status_packet(r8a66597, pipe) < 0)
@@ -821,40 +766,131 @@ int submit_control_msg(struct usb_device *dev, unsigned long pipe,
return 0;
}
-int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer,
- int transfer_len, int interval)
+static int r8a66597_submit_bulk_msg(struct udevice *udev,
+ struct usb_device *dev, unsigned long pipe,
+ void *buffer, int length)
{
- /* no implement */
+ struct r8a66597 *r8a66597 = dev_get_priv(udev);
+ int ret = 0;
+
+ debug("%s: dev='%s', udev=%p\n", __func__, udev->name, dev);
+
R8A66597_DPRINT("%s\n", __func__);
- return 0;
+ R8A66597_DPRINT("pipe = %08x, buffer = %p, len = %d, devnum = %d\n",
+ pipe, buffer, length, dev->devnum);
+
+ set_devadd(r8a66597, dev->devnum, dev, 0);
+
+ pipe_buffer_setting(r8a66597, dev, pipe);
+
+ dev->act_len = 0;
+ while (dev->act_len < length && ret == 0) {
+ if (ctrlc())
+ return -1;
+
+ if (usb_pipein(pipe))
+ ret = receive_bulk_packet(r8a66597, dev, pipe, buffer,
+ length);
+ else
+ ret = send_bulk_packet(r8a66597, dev, pipe, buffer,
+ length);
+ }
+
+ if (ret == 0)
+ dev->status = 0;
+
+ return ret;
}
-int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
+static int r8a66597_usb_ofdata_to_platdata(struct udevice *dev)
{
- struct r8a66597 *r8a66597 = &gr8a66597;
+ struct r8a66597 *priv = dev_get_priv(dev);
+ fdt_addr_t addr;
- R8A66597_DPRINT("%s\n", __func__);
+ addr = dev_read_addr(dev);
+ if (addr == FDT_ADDR_T_NONE)
+ return -EINVAL;
+ priv->reg = addr;
- memset(r8a66597, 0, sizeof(*r8a66597));
- r8a66597->reg = CONFIG_R8A66597_BASE_ADDR;
+ return 0;
+}
+
+static int r8a66597_usb_probe(struct udevice *dev)
+{
+ struct r8a66597 *priv = dev_get_priv(dev);
+ struct usb_bus_priv *bus_priv = dev_get_uclass_priv(dev);
+ int ret;
+
+ bus_priv->desc_before_addr = true;
+
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
+ ret = device_get_supply_regulator(dev, "vbus-supply",
+ &priv->vbus_supply);
+ if (ret) {
+ dev_err(dev,
+ "can't get VBUS supply\n");
+ return ret;
+ }
+
+ ret = regulator_set_enable(priv->vbus_supply, true);
+ if (ret) {
+ dev_err(dev,
+ "can't enable VBUS supply\n");
+ return ret;
+ }
+ }
- disable_controller(r8a66597);
+ disable_controller(priv);
mdelay(100);
- enable_controller(r8a66597);
- r8a66597_port_power(r8a66597, 0 , 1);
+ enable_controller(priv);
+ r8a66597_port_power(priv, 0, 1);
/* check usb device */
- check_usb_device_connecting(r8a66597);
+ check_usb_device_connecting(priv);
mdelay(50);
return 0;
}
-int usb_lowlevel_stop(int index)
+static int r8a66597_usb_remove(struct udevice *dev)
{
- disable_controller(&gr8a66597);
+ struct r8a66597 *priv = dev_get_priv(dev);
+ int ret;
+
+ disable_controller(priv);
+
+ if (CONFIG_IS_ENABLED(DM_REGULATOR)) {
+ ret = regulator_set_enable(priv->vbus_supply, false);
+ if (ret) {
+ dev_err(dev,
+ "can't disable VBUS supply\n");
+ return ret;
+ }
+ }
return 0;
}
+
+struct dm_usb_ops r8a66597_usb_ops = {
+ .control = r8a66597_submit_control_msg,
+ .bulk = r8a66597_submit_bulk_msg,
+};
+
+static const struct udevice_id r8a66597_usb_ids[] = {
+ { .compatible = "renesas,rza1-usbhs" },
+ { }
+};
+
+U_BOOT_DRIVER(usb_r8a66597) = {
+ .name = "r8a66597_usb",
+ .id = UCLASS_USB,
+ .of_match = r8a66597_usb_ids,
+ .ofdata_to_platdata = r8a66597_usb_ofdata_to_platdata,
+ .probe = r8a66597_usb_probe,
+ .remove = r8a66597_usb_remove,
+ .ops = &r8a66597_usb_ops,
+ .priv_auto_alloc_size = sizeof(struct r8a66597),
+ .flags = DM_FLAG_ALLOC_PRIV_DMA,
+};