mirror of
https://github.com/u-boot/u-boot.git
synced 2024-11-25 21:24:21 +08:00
This commit is contained in:
commit
54f683dbfb
1
Makefile
1
Makefile
@ -847,6 +847,7 @@ libs-y += drivers/usb/host/
|
||||
libs-y += drivers/usb/mtu3/
|
||||
libs-y += drivers/usb/musb/
|
||||
libs-y += drivers/usb/musb-new/
|
||||
libs-y += drivers/usb/isp1760/
|
||||
libs-y += drivers/usb/phy/
|
||||
libs-y += drivers/usb/ulpi/
|
||||
ifdef CONFIG_POST
|
||||
|
@ -810,7 +810,6 @@ config ARCH_KEYSTONE
|
||||
select CMD_POWEROFF
|
||||
select CPU_V7A
|
||||
select DDR_SPD
|
||||
select GPIO_EXTRA_HEADER
|
||||
select SUPPORT_SPL
|
||||
select SYS_ARCH_TIMER
|
||||
select SYS_THUMB_BUILD
|
||||
|
@ -19,7 +19,7 @@ static int spl_sdp_load_image(struct spl_image_info *spl_image,
|
||||
|
||||
usb_gadget_initialize(controller_index);
|
||||
|
||||
board_usb_init(0, USB_INIT_DEVICE);
|
||||
board_usb_init(controller_index, USB_INIT_DEVICE);
|
||||
|
||||
g_dnl_clear_detach();
|
||||
ret = g_dnl_register("usb_dnl_sdp");
|
||||
|
@ -47,6 +47,8 @@
|
||||
#define HUB_SHORT_RESET_TIME 20
|
||||
#define HUB_LONG_RESET_TIME 200
|
||||
|
||||
#define HUB_DEBOUNCE_TIMEOUT 1000
|
||||
|
||||
#define PORT_OVERCURRENT_MAX_SCAN_COUNT 3
|
||||
|
||||
struct usb_device_scan {
|
||||
@ -208,10 +210,10 @@ static void usb_hub_power_on(struct usb_hub_device *hub)
|
||||
* will be done based on this value in the USB port loop in
|
||||
* usb_hub_configure() later.
|
||||
*/
|
||||
hub->connect_timeout = hub->query_delay + 1000;
|
||||
hub->connect_timeout = hub->query_delay + HUB_DEBOUNCE_TIMEOUT;
|
||||
debug("devnum=%d poweron: query_delay=%d connect_timeout=%d\n",
|
||||
dev->devnum, max(100, (int)pgood_delay),
|
||||
max(100, (int)pgood_delay) + 1000);
|
||||
max(100, (int)pgood_delay) + HUB_DEBOUNCE_TIMEOUT);
|
||||
}
|
||||
|
||||
#if !CONFIG_IS_ENABLED(DM_USB)
|
||||
|
@ -581,21 +581,22 @@ static int probe_usb_keyboard(struct usb_device *dev)
|
||||
|
||||
stdinname = env_get("stdin");
|
||||
#if CONFIG_IS_ENABLED(CONSOLE_MUX)
|
||||
error = iomux_doenv(stdin, stdinname);
|
||||
if (error)
|
||||
return error;
|
||||
if (strstr(stdinname, DEVNAME) != NULL) {
|
||||
error = iomux_doenv(stdin, stdinname);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
#else
|
||||
/* Check if this is the standard input device. */
|
||||
if (strcmp(stdinname, DEVNAME))
|
||||
return 1;
|
||||
if (!strcmp(stdinname, DEVNAME)) {
|
||||
/* Reassign the console */
|
||||
if (overwrite_console())
|
||||
return 1;
|
||||
|
||||
/* Reassign the console */
|
||||
if (overwrite_console())
|
||||
return 1;
|
||||
|
||||
error = console_assign(stdin, DEVNAME);
|
||||
if (error)
|
||||
return error;
|
||||
error = console_assign(stdin, DEVNAME);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
@ -28,6 +28,8 @@ CONFIG_SYS_BOOTM_LEN=0x800000
|
||||
# CONFIG_CMD_XIMG is not set
|
||||
CONFIG_CMD_LOADM=y
|
||||
# CONFIG_CMD_LOADS is not set
|
||||
CONFIG_CMD_MMC=y
|
||||
CONFIG_CMD_USB=y
|
||||
# CONFIG_CMD_SETEXPR is not set
|
||||
# CONFIG_CMD_NFS is not set
|
||||
CONFIG_CMD_CACHE=y
|
||||
@ -50,4 +52,5 @@ CONFIG_DM_RTC=y
|
||||
CONFIG_RTC_EMULATION=y
|
||||
CONFIG_DM_SERIAL=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_ISP1760=y
|
||||
CONFIG_ERRNO_STR=y
|
||||
|
@ -68,6 +68,8 @@ config SPL_DM_USB_GADGET
|
||||
|
||||
source "drivers/usb/host/Kconfig"
|
||||
|
||||
source "drivers/usb/isp1760/Kconfig"
|
||||
|
||||
source "drivers/usb/cdns3/Kconfig"
|
||||
|
||||
source "drivers/usb/dwc3/Kconfig"
|
||||
|
@ -4,5 +4,9 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_$(SPL_)DM_USB) += common.o
|
||||
obj-$(CONFIG_USB_ISP1760) += usb_urb.o
|
||||
obj-$(CONFIG_USB_MUSB_HOST) += usb_urb.o
|
||||
obj-$(CONFIG_USB_MUSB_GADGET) += usb_urb.o
|
||||
obj-$(CONFIG_USB_R8A66597_HCD) += usb_urb.o
|
||||
obj-$(CONFIG_USB_EHCI_FSL) += fsl-dt-fixup.o fsl-errata.o
|
||||
obj-$(CONFIG_USB_XHCI_FSL) += fsl-dt-fixup.o fsl-errata.o
|
||||
|
160
drivers/usb/common/usb_urb.c
Normal file
160
drivers/usb/common/usb_urb.c
Normal file
@ -0,0 +1,160 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Common code for usb urb handling, based on the musb-new code
|
||||
*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dm/device.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <usb.h>
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_USB)
|
||||
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;
|
||||
}
|
||||
#else
|
||||
struct usb_device *usb_dev_get_parent(struct usb_device *udev)
|
||||
{
|
||||
return udev->parent;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void usb_urb_complete(struct urb *urb)
|
||||
{
|
||||
urb->dev->status &= ~USB_ST_NOT_PROC;
|
||||
urb->dev->act_len = urb->actual_length;
|
||||
|
||||
if (urb->status == -EINPROGRESS)
|
||||
urb->status = 0;
|
||||
}
|
||||
|
||||
void usb_urb_fill(struct urb *urb, struct usb_host_endpoint *hep,
|
||||
struct usb_device *dev, int endpoint_type,
|
||||
unsigned long pipe, void *buffer, int len,
|
||||
struct devrequest *setup, int interval)
|
||||
{
|
||||
int epnum = usb_pipeendpoint(pipe);
|
||||
int is_in = usb_pipein(pipe);
|
||||
u16 maxpacketsize = is_in ? dev->epmaxpacketin[epnum] :
|
||||
dev->epmaxpacketout[epnum];
|
||||
|
||||
memset(urb, 0, sizeof(struct urb));
|
||||
memset(hep, 0, sizeof(struct usb_host_endpoint));
|
||||
INIT_LIST_HEAD(&hep->urb_list);
|
||||
INIT_LIST_HEAD(&urb->urb_list);
|
||||
urb->ep = hep;
|
||||
urb->complete = usb_urb_complete;
|
||||
urb->status = -EINPROGRESS;
|
||||
urb->dev = dev;
|
||||
urb->pipe = pipe;
|
||||
urb->transfer_buffer = buffer;
|
||||
urb->transfer_dma = (unsigned long)buffer;
|
||||
urb->transfer_buffer_length = len;
|
||||
urb->setup_packet = (unsigned char *)setup;
|
||||
|
||||
urb->ep->desc.wMaxPacketSize = __cpu_to_le16(maxpacketsize);
|
||||
urb->ep->desc.bmAttributes = endpoint_type;
|
||||
urb->ep->desc.bEndpointAddress = ((is_in ? USB_DIR_IN : USB_DIR_OUT) |
|
||||
epnum);
|
||||
urb->ep->desc.bInterval = interval;
|
||||
}
|
||||
|
||||
int usb_urb_submit(struct usb_hcd *hcd, struct urb *urb)
|
||||
{
|
||||
const struct usb_urb_ops *ops = hcd->urb_ops;
|
||||
unsigned long timeout;
|
||||
int ret;
|
||||
|
||||
if (!ops)
|
||||
return -EINVAL;
|
||||
|
||||
ret = ops->urb_enqueue(hcd, urb, 0);
|
||||
if (ret < 0) {
|
||||
printf("Failed to enqueue URB to controller\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
timeout = get_timer(0) + USB_TIMEOUT_MS(urb->pipe);
|
||||
do {
|
||||
if (ctrlc())
|
||||
return -EIO;
|
||||
ops->isr(0, hcd);
|
||||
} while (urb->status == -EINPROGRESS && get_timer(0) < timeout);
|
||||
|
||||
if (urb->status == -EINPROGRESS)
|
||||
ops->urb_dequeue(hcd, urb, -ETIME);
|
||||
|
||||
return urb->status;
|
||||
}
|
||||
|
||||
int usb_urb_submit_control(struct usb_hcd *hcd, struct urb *urb,
|
||||
struct usb_host_endpoint *hep,
|
||||
struct usb_device *dev, unsigned long pipe,
|
||||
void *buffer, int len, struct devrequest *setup,
|
||||
int interval, enum usb_device_speed speed)
|
||||
{
|
||||
const struct usb_urb_ops *ops = hcd->urb_ops;
|
||||
|
||||
usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_CONTROL, pipe, buffer,
|
||||
len, setup, 0);
|
||||
|
||||
/* Fix speed for non hub-attached devices */
|
||||
if (!usb_dev_get_parent(dev)) {
|
||||
dev->speed = speed;
|
||||
if (ops->hub_control)
|
||||
return ops->hub_control(hcd, dev, pipe, buffer, len,
|
||||
setup);
|
||||
}
|
||||
|
||||
return usb_urb_submit(hcd, urb);
|
||||
}
|
||||
|
||||
int usb_urb_submit_bulk(struct usb_hcd *hcd, struct urb *urb,
|
||||
struct usb_host_endpoint *hep, struct usb_device *dev,
|
||||
unsigned long pipe, void *buffer, int len)
|
||||
{
|
||||
usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_BULK, pipe, buffer, len,
|
||||
NULL, 0);
|
||||
|
||||
return usb_urb_submit(hcd, urb);
|
||||
}
|
||||
|
||||
int usb_urb_submit_irq(struct usb_hcd *hcd, struct urb *urb,
|
||||
struct usb_host_endpoint *hep, struct usb_device *dev,
|
||||
unsigned long pipe, void *buffer, int len, int interval)
|
||||
{
|
||||
usb_urb_fill(urb, hep, dev, USB_ENDPOINT_XFER_INT, pipe, buffer, len,
|
||||
NULL, interval);
|
||||
|
||||
return usb_urb_submit(hcd, urb);
|
||||
}
|
@ -26,6 +26,7 @@
|
||||
#include <reset.h>
|
||||
#include <clk.h>
|
||||
#include <usb/xhci.h>
|
||||
#include <asm/gpio.h>
|
||||
|
||||
struct dwc3_glue_data {
|
||||
struct clk_bulk clks;
|
||||
@ -43,6 +44,7 @@ struct dwc3_generic_priv {
|
||||
void *base;
|
||||
struct dwc3 dwc3;
|
||||
struct phy_bulk phys;
|
||||
struct gpio_desc ulpi_reset;
|
||||
};
|
||||
|
||||
struct dwc3_generic_host_priv {
|
||||
@ -78,6 +80,27 @@ static int dwc3_generic_probe(struct udevice *dev,
|
||||
if (rc && rc != -ENOTSUPP)
|
||||
return rc;
|
||||
|
||||
if (CONFIG_IS_ENABLED(DM_GPIO) &&
|
||||
device_is_compatible(dev->parent, "xlnx,zynqmp-dwc3")) {
|
||||
rc = gpio_request_by_name(dev->parent, "reset-gpios", 0,
|
||||
&priv->ulpi_reset, GPIOD_ACTIVE_LOW);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
/* Toggle ulpi to reset the phy. */
|
||||
rc = dm_gpio_set_value(&priv->ulpi_reset, 1);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mdelay(5);
|
||||
|
||||
rc = dm_gpio_set_value(&priv->ulpi_reset, 0);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
if (device_is_compatible(dev->parent, "rockchip,rk3399-dwc3"))
|
||||
reset_deassert_bulk(&glue->resets);
|
||||
|
||||
@ -99,6 +122,13 @@ static int dwc3_generic_remove(struct udevice *dev,
|
||||
{
|
||||
struct dwc3 *dwc3 = &priv->dwc3;
|
||||
|
||||
if (CONFIG_IS_ENABLED(DM_GPIO) &&
|
||||
device_is_compatible(dev->parent, "xlnx,zynqmp-dwc3")) {
|
||||
struct gpio_desc *ulpi_reset = &priv->ulpi_reset;
|
||||
|
||||
dm_gpio_free(ulpi_reset->dev, ulpi_reset);
|
||||
}
|
||||
|
||||
dwc3_remove(dwc3);
|
||||
dwc3_shutdown_phy(dev, &priv->phys);
|
||||
unmap_physmem(dwc3->regs, MAP_NOCACHE);
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include <dm/device_compat.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include <power/regulator.h>
|
||||
|
||||
#include "r8a66597.h"
|
||||
@ -24,35 +25,6 @@
|
||||
#define R8A66597_DPRINT(...)
|
||||
#endif
|
||||
|
||||
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)
|
||||
{
|
||||
struct usb_device *parent = usb_dev_get_parent(dev);
|
||||
|
12
drivers/usb/isp1760/Kconfig
Normal file
12
drivers/usb/isp1760/Kconfig
Normal file
@ -0,0 +1,12 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
config USB_ISP1760
|
||||
tristate "NXP ISP 1760/1761/1763 support"
|
||||
select DM_USB
|
||||
select USB_HOST
|
||||
help
|
||||
Say Y or M here if your system as an ISP1760/1761/1763 USB host
|
||||
controller.
|
||||
|
||||
This USB controller is usually attached to a non-DMA-Master
|
||||
capable bus.
|
6
drivers/usb/isp1760/Makefile
Normal file
6
drivers/usb/isp1760/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
isp1760-y := isp1760-core.o isp1760-if.o isp1760-uboot.o isp1760-hcd.o
|
||||
|
||||
#isp1760-hcd.o
|
||||
|
||||
obj-$(CONFIG_USB_ISP1760) += isp1760.o
|
380
drivers/usb/isp1760/isp1760-core.c
Normal file
380
drivers/usb/isp1760/isp1760-core.c
Normal file
@ -0,0 +1,380 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2022 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
* This is based on linux kernel driver, original developed:
|
||||
* Copyright 2014 Laurent Pinchart
|
||||
* Copyright 2007 Sebastian Siewior
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/devres.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <regmap.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
#include "isp1760-hcd.h"
|
||||
#include "isp1760-regs.h"
|
||||
|
||||
#define msleep(a) udelay((a) * 1000)
|
||||
|
||||
static int isp1760_init_core(struct isp1760_device *isp)
|
||||
{
|
||||
struct isp1760_hcd *hcd = &isp->hcd;
|
||||
|
||||
/*
|
||||
* Reset the host controller, including the CPU interface
|
||||
* configuration.
|
||||
*/
|
||||
isp1760_field_set(hcd->fields, SW_RESET_RESET_ALL);
|
||||
msleep(100);
|
||||
|
||||
/* Setup HW Mode Control: This assumes a level active-low interrupt */
|
||||
if ((isp->devflags & ISP1760_FLAG_ANALOG_OC) && hcd->is_isp1763)
|
||||
return -EINVAL;
|
||||
|
||||
if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_16)
|
||||
isp1760_field_clear(hcd->fields, HW_DATA_BUS_WIDTH);
|
||||
if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_8)
|
||||
isp1760_field_set(hcd->fields, HW_DATA_BUS_WIDTH);
|
||||
if (isp->devflags & ISP1760_FLAG_ANALOG_OC)
|
||||
isp1760_field_set(hcd->fields, HW_ANA_DIGI_OC);
|
||||
if (isp->devflags & ISP1760_FLAG_DACK_POL_HIGH)
|
||||
isp1760_field_set(hcd->fields, HW_DACK_POL_HIGH);
|
||||
if (isp->devflags & ISP1760_FLAG_DREQ_POL_HIGH)
|
||||
isp1760_field_set(hcd->fields, HW_DREQ_POL_HIGH);
|
||||
if (isp->devflags & ISP1760_FLAG_INTR_POL_HIGH)
|
||||
isp1760_field_set(hcd->fields, HW_INTR_HIGH_ACT);
|
||||
if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG)
|
||||
isp1760_field_set(hcd->fields, HW_INTR_EDGE_TRIG);
|
||||
|
||||
/*
|
||||
* The ISP1761 has a dedicated DC IRQ line but supports sharing the HC
|
||||
* IRQ line for both the host and device controllers. Hardcode IRQ
|
||||
* sharing for now and disable the DC interrupts globally to avoid
|
||||
* spurious interrupts during HCD registration.
|
||||
*/
|
||||
if (isp->devflags & ISP1760_FLAG_ISP1761) {
|
||||
isp1760_reg_write(hcd->regs, ISP176x_DC_MODE, 0);
|
||||
isp1760_field_set(hcd->fields, HW_COMN_IRQ);
|
||||
}
|
||||
|
||||
/*
|
||||
* PORT 1 Control register of the ISP1760 is the OTG control register
|
||||
* on ISP1761.
|
||||
*
|
||||
* TODO: Really support OTG. For now we configure port 1 in device mode
|
||||
*/
|
||||
if (((isp->devflags & ISP1760_FLAG_ISP1761) ||
|
||||
(isp->devflags & ISP1760_FLAG_ISP1763)) &&
|
||||
(isp->devflags & ISP1760_FLAG_PERIPHERAL_EN)) {
|
||||
isp1760_field_set(hcd->fields, HW_DM_PULLDOWN);
|
||||
isp1760_field_set(hcd->fields, HW_DP_PULLDOWN);
|
||||
isp1760_field_set(hcd->fields, HW_OTG_DISABLE);
|
||||
} else {
|
||||
isp1760_field_set(hcd->fields, HW_SW_SEL_HC_DC);
|
||||
isp1760_field_set(hcd->fields, HW_VBUS_DRV);
|
||||
isp1760_field_set(hcd->fields, HW_SEL_CP_EXT);
|
||||
}
|
||||
|
||||
printf("%s bus width: %u, oc: %s\n",
|
||||
hcd->is_isp1763 ? "isp1763" : "isp1760",
|
||||
isp->devflags & ISP1760_FLAG_BUS_WIDTH_8 ? 8 :
|
||||
isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32,
|
||||
hcd->is_isp1763 ? "not available" :
|
||||
isp->devflags & ISP1760_FLAG_ANALOG_OC ? "analog" : "digital");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isp1760_set_pullup(struct isp1760_device *isp, bool enable)
|
||||
{
|
||||
struct isp1760_hcd *hcd = &isp->hcd;
|
||||
|
||||
if (enable)
|
||||
isp1760_field_set(hcd->fields, HW_DP_PULLUP);
|
||||
else
|
||||
isp1760_field_set(hcd->fields, HW_DP_PULLUP_CLEAR);
|
||||
}
|
||||
|
||||
/*
|
||||
* ISP1760/61:
|
||||
*
|
||||
* 60kb divided in:
|
||||
* - 32 blocks @ 256 bytes
|
||||
* - 20 blocks @ 1024 bytes
|
||||
* - 4 blocks @ 8192 bytes
|
||||
*/
|
||||
static const struct isp1760_memory_layout isp176x_memory_conf = {
|
||||
.blocks[0] = 32,
|
||||
.blocks_size[0] = 256,
|
||||
.blocks[1] = 20,
|
||||
.blocks_size[1] = 1024,
|
||||
.blocks[2] = 4,
|
||||
.blocks_size[2] = 8192,
|
||||
|
||||
.slot_num = 32,
|
||||
.payload_blocks = 32 + 20 + 4,
|
||||
.payload_area_size = 0xf000,
|
||||
};
|
||||
|
||||
/*
|
||||
* ISP1763:
|
||||
*
|
||||
* 20kb divided in:
|
||||
* - 8 blocks @ 256 bytes
|
||||
* - 2 blocks @ 1024 bytes
|
||||
* - 4 blocks @ 4096 bytes
|
||||
*/
|
||||
static const struct isp1760_memory_layout isp1763_memory_conf = {
|
||||
.blocks[0] = 8,
|
||||
.blocks_size[0] = 256,
|
||||
.blocks[1] = 2,
|
||||
.blocks_size[1] = 1024,
|
||||
.blocks[2] = 4,
|
||||
.blocks_size[2] = 4096,
|
||||
|
||||
.slot_num = 16,
|
||||
.payload_blocks = 8 + 2 + 4,
|
||||
.payload_area_size = 0x5000,
|
||||
};
|
||||
|
||||
static const struct regmap_config isp1760_hc_regmap_conf = {
|
||||
.width = REGMAP_SIZE_16,
|
||||
};
|
||||
|
||||
static const struct reg_field isp1760_hc_reg_fields[] = {
|
||||
[HCS_PPC] = REG_FIELD(ISP176x_HC_HCSPARAMS, 4, 4),
|
||||
[HCS_N_PORTS] = REG_FIELD(ISP176x_HC_HCSPARAMS, 0, 3),
|
||||
[HCC_ISOC_CACHE] = REG_FIELD(ISP176x_HC_HCCPARAMS, 7, 7),
|
||||
[HCC_ISOC_THRES] = REG_FIELD(ISP176x_HC_HCCPARAMS, 4, 6),
|
||||
[CMD_LRESET] = REG_FIELD(ISP176x_HC_USBCMD, 7, 7),
|
||||
[CMD_RESET] = REG_FIELD(ISP176x_HC_USBCMD, 1, 1),
|
||||
[CMD_RUN] = REG_FIELD(ISP176x_HC_USBCMD, 0, 0),
|
||||
[STS_PCD] = REG_FIELD(ISP176x_HC_USBSTS, 2, 2),
|
||||
[HC_FRINDEX] = REG_FIELD(ISP176x_HC_FRINDEX, 0, 13),
|
||||
[FLAG_CF] = REG_FIELD(ISP176x_HC_CONFIGFLAG, 0, 0),
|
||||
[HC_ISO_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_ISO_PTD_DONEMAP, 0, 31),
|
||||
[HC_ISO_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_ISO_PTD_SKIPMAP, 0, 31),
|
||||
[HC_ISO_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_ISO_PTD_LASTPTD, 0, 31),
|
||||
[HC_INT_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_INT_PTD_DONEMAP, 0, 31),
|
||||
[HC_INT_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_INT_PTD_SKIPMAP, 0, 31),
|
||||
[HC_INT_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_INT_PTD_LASTPTD, 0, 31),
|
||||
[HC_ATL_PTD_DONEMAP] = REG_FIELD(ISP176x_HC_ATL_PTD_DONEMAP, 0, 31),
|
||||
[HC_ATL_PTD_SKIPMAP] = REG_FIELD(ISP176x_HC_ATL_PTD_SKIPMAP, 0, 31),
|
||||
[HC_ATL_PTD_LASTPTD] = REG_FIELD(ISP176x_HC_ATL_PTD_LASTPTD, 0, 31),
|
||||
[PORT_OWNER] = REG_FIELD(ISP176x_HC_PORTSC1, 13, 13),
|
||||
[PORT_POWER] = REG_FIELD(ISP176x_HC_PORTSC1, 12, 12),
|
||||
[PORT_LSTATUS] = REG_FIELD(ISP176x_HC_PORTSC1, 10, 11),
|
||||
[PORT_RESET] = REG_FIELD(ISP176x_HC_PORTSC1, 8, 8),
|
||||
[PORT_SUSPEND] = REG_FIELD(ISP176x_HC_PORTSC1, 7, 7),
|
||||
[PORT_RESUME] = REG_FIELD(ISP176x_HC_PORTSC1, 6, 6),
|
||||
[PORT_PE] = REG_FIELD(ISP176x_HC_PORTSC1, 2, 2),
|
||||
[PORT_CSC] = REG_FIELD(ISP176x_HC_PORTSC1, 1, 1),
|
||||
[PORT_CONNECT] = REG_FIELD(ISP176x_HC_PORTSC1, 0, 0),
|
||||
[ALL_ATX_RESET] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 31, 31),
|
||||
[HW_ANA_DIGI_OC] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 15, 15),
|
||||
[HW_COMN_IRQ] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 10, 10),
|
||||
[HW_DATA_BUS_WIDTH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 8, 8),
|
||||
[HW_DACK_POL_HIGH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 6, 6),
|
||||
[HW_DREQ_POL_HIGH] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 5, 5),
|
||||
[HW_INTR_HIGH_ACT] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 2, 2),
|
||||
[HW_INTR_EDGE_TRIG] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 1, 1),
|
||||
[HW_GLOBAL_INTR_EN] = REG_FIELD(ISP176x_HC_HW_MODE_CTRL, 0, 0),
|
||||
[HC_CHIP_REV] = REG_FIELD(ISP176x_HC_CHIP_ID, 16, 31),
|
||||
[HC_CHIP_ID_HIGH] = REG_FIELD(ISP176x_HC_CHIP_ID, 8, 15),
|
||||
[HC_CHIP_ID_LOW] = REG_FIELD(ISP176x_HC_CHIP_ID, 0, 7),
|
||||
[HC_SCRATCH] = REG_FIELD(ISP176x_HC_SCRATCH, 0, 31),
|
||||
[SW_RESET_RESET_ALL] = REG_FIELD(ISP176x_HC_RESET, 0, 0),
|
||||
[ISO_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 2, 2),
|
||||
[INT_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 1, 1),
|
||||
[ATL_BUF_FILL] = REG_FIELD(ISP176x_HC_BUFFER_STATUS, 0, 0),
|
||||
[MEM_BANK_SEL] = REG_FIELD(ISP176x_HC_MEMORY, 16, 17),
|
||||
[MEM_START_ADDR] = REG_FIELD(ISP176x_HC_MEMORY, 0, 15),
|
||||
[HC_INTERRUPT] = REG_FIELD(ISP176x_HC_INTERRUPT, 0, 9),
|
||||
[HC_ATL_IRQ_ENABLE] = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 8, 8),
|
||||
[HC_INT_IRQ_ENABLE] = REG_FIELD(ISP176x_HC_INTERRUPT_ENABLE, 7, 7),
|
||||
[HC_ISO_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_OR, 0, 31),
|
||||
[HC_INT_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_OR, 0, 31),
|
||||
[HC_ATL_IRQ_MASK_OR] = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_OR, 0, 31),
|
||||
[HC_ISO_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ISO_IRQ_MASK_AND, 0, 31),
|
||||
[HC_INT_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_INT_IRQ_MASK_AND, 0, 31),
|
||||
[HC_ATL_IRQ_MASK_AND] = REG_FIELD(ISP176x_HC_ATL_IRQ_MASK_AND, 0, 31),
|
||||
[HW_OTG_DISABLE] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 10, 10),
|
||||
[HW_SW_SEL_HC_DC] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 7, 7),
|
||||
[HW_VBUS_DRV] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 4, 4),
|
||||
[HW_SEL_CP_EXT] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 3, 3),
|
||||
[HW_DM_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 2, 2),
|
||||
[HW_DP_PULLDOWN] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 1, 1),
|
||||
[HW_DP_PULLUP] = REG_FIELD(ISP176x_HC_OTG_CTRL_SET, 0, 0),
|
||||
[HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 10, 10),
|
||||
[HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 7, 7),
|
||||
[HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 4, 4),
|
||||
[HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 3, 3),
|
||||
[HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 2, 2),
|
||||
[HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 1, 1),
|
||||
[HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP176x_HC_OTG_CTRL_CLEAR, 0, 0),
|
||||
/* Make sure the array is sized properly during compilation */
|
||||
[HC_FIELD_MAX] = {},
|
||||
};
|
||||
|
||||
static const struct regmap_config isp1763_hc_regmap_conf = {
|
||||
.width = REGMAP_SIZE_16,
|
||||
};
|
||||
|
||||
static const struct reg_field isp1763_hc_reg_fields[] = {
|
||||
[CMD_LRESET] = REG_FIELD(ISP1763_HC_USBCMD, 7, 7),
|
||||
[CMD_RESET] = REG_FIELD(ISP1763_HC_USBCMD, 1, 1),
|
||||
[CMD_RUN] = REG_FIELD(ISP1763_HC_USBCMD, 0, 0),
|
||||
[STS_PCD] = REG_FIELD(ISP1763_HC_USBSTS, 2, 2),
|
||||
[HC_FRINDEX] = REG_FIELD(ISP1763_HC_FRINDEX, 0, 13),
|
||||
[FLAG_CF] = REG_FIELD(ISP1763_HC_CONFIGFLAG, 0, 0),
|
||||
[HC_ISO_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_ISO_PTD_DONEMAP, 0, 15),
|
||||
[HC_ISO_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_ISO_PTD_SKIPMAP, 0, 15),
|
||||
[HC_ISO_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_ISO_PTD_LASTPTD, 0, 15),
|
||||
[HC_INT_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_INT_PTD_DONEMAP, 0, 15),
|
||||
[HC_INT_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_INT_PTD_SKIPMAP, 0, 15),
|
||||
[HC_INT_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_INT_PTD_LASTPTD, 0, 15),
|
||||
[HC_ATL_PTD_DONEMAP] = REG_FIELD(ISP1763_HC_ATL_PTD_DONEMAP, 0, 15),
|
||||
[HC_ATL_PTD_SKIPMAP] = REG_FIELD(ISP1763_HC_ATL_PTD_SKIPMAP, 0, 15),
|
||||
[HC_ATL_PTD_LASTPTD] = REG_FIELD(ISP1763_HC_ATL_PTD_LASTPTD, 0, 15),
|
||||
[PORT_OWNER] = REG_FIELD(ISP1763_HC_PORTSC1, 13, 13),
|
||||
[PORT_POWER] = REG_FIELD(ISP1763_HC_PORTSC1, 12, 12),
|
||||
[PORT_LSTATUS] = REG_FIELD(ISP1763_HC_PORTSC1, 10, 11),
|
||||
[PORT_RESET] = REG_FIELD(ISP1763_HC_PORTSC1, 8, 8),
|
||||
[PORT_SUSPEND] = REG_FIELD(ISP1763_HC_PORTSC1, 7, 7),
|
||||
[PORT_RESUME] = REG_FIELD(ISP1763_HC_PORTSC1, 6, 6),
|
||||
[PORT_PE] = REG_FIELD(ISP1763_HC_PORTSC1, 2, 2),
|
||||
[PORT_CSC] = REG_FIELD(ISP1763_HC_PORTSC1, 1, 1),
|
||||
[PORT_CONNECT] = REG_FIELD(ISP1763_HC_PORTSC1, 0, 0),
|
||||
[HW_DATA_BUS_WIDTH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 4, 4),
|
||||
[HW_DACK_POL_HIGH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 6, 6),
|
||||
[HW_DREQ_POL_HIGH] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 5, 5),
|
||||
[HW_INTF_LOCK] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 3, 3),
|
||||
[HW_INTR_HIGH_ACT] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 2, 2),
|
||||
[HW_INTR_EDGE_TRIG] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 1, 1),
|
||||
[HW_GLOBAL_INTR_EN] = REG_FIELD(ISP1763_HC_HW_MODE_CTRL, 0, 0),
|
||||
[SW_RESET_RESET_ATX] = REG_FIELD(ISP1763_HC_RESET, 3, 3),
|
||||
[SW_RESET_RESET_ALL] = REG_FIELD(ISP1763_HC_RESET, 0, 0),
|
||||
[HC_CHIP_ID_HIGH] = REG_FIELD(ISP1763_HC_CHIP_ID, 0, 15),
|
||||
[HC_CHIP_ID_LOW] = REG_FIELD(ISP1763_HC_CHIP_REV, 8, 15),
|
||||
[HC_CHIP_REV] = REG_FIELD(ISP1763_HC_CHIP_REV, 0, 7),
|
||||
[HC_SCRATCH] = REG_FIELD(ISP1763_HC_SCRATCH, 0, 15),
|
||||
[ISO_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 2, 2),
|
||||
[INT_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 1, 1),
|
||||
[ATL_BUF_FILL] = REG_FIELD(ISP1763_HC_BUFFER_STATUS, 0, 0),
|
||||
[MEM_START_ADDR] = REG_FIELD(ISP1763_HC_MEMORY, 0, 15),
|
||||
[HC_DATA] = REG_FIELD(ISP1763_HC_DATA, 0, 15),
|
||||
[HC_INTERRUPT] = REG_FIELD(ISP1763_HC_INTERRUPT, 0, 10),
|
||||
[HC_ATL_IRQ_ENABLE] = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 8, 8),
|
||||
[HC_INT_IRQ_ENABLE] = REG_FIELD(ISP1763_HC_INTERRUPT_ENABLE, 7, 7),
|
||||
[HC_ISO_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_OR, 0, 15),
|
||||
[HC_INT_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_OR, 0, 15),
|
||||
[HC_ATL_IRQ_MASK_OR] = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_OR, 0, 15),
|
||||
[HC_ISO_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_ISO_IRQ_MASK_AND, 0, 15),
|
||||
[HC_INT_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_INT_IRQ_MASK_AND, 0, 15),
|
||||
[HC_ATL_IRQ_MASK_AND] = REG_FIELD(ISP1763_HC_ATL_IRQ_MASK_AND, 0, 15),
|
||||
[HW_HC_2_DIS] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 15, 15),
|
||||
[HW_OTG_DISABLE] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 10, 10),
|
||||
[HW_SW_SEL_HC_DC] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 7, 7),
|
||||
[HW_VBUS_DRV] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 4, 4),
|
||||
[HW_SEL_CP_EXT] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 3, 3),
|
||||
[HW_DM_PULLDOWN] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 2, 2),
|
||||
[HW_DP_PULLDOWN] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 1, 1),
|
||||
[HW_DP_PULLUP] = REG_FIELD(ISP1763_HC_OTG_CTRL_SET, 0, 0),
|
||||
[HW_HC_2_DIS_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 15, 15),
|
||||
[HW_OTG_DISABLE_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 10, 10),
|
||||
[HW_SW_SEL_HC_DC_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 7, 7),
|
||||
[HW_VBUS_DRV_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 4, 4),
|
||||
[HW_SEL_CP_EXT_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 3, 3),
|
||||
[HW_DM_PULLDOWN_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 2, 2),
|
||||
[HW_DP_PULLDOWN_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 1, 1),
|
||||
[HW_DP_PULLUP_CLEAR] = REG_FIELD(ISP1763_HC_OTG_CTRL_CLEAR, 0, 0),
|
||||
/* Make sure the array is sized properly during compilation */
|
||||
[HC_FIELD_MAX] = {},
|
||||
};
|
||||
|
||||
int isp1760_register(struct isp1760_device *isp, struct resource *mem, int irq,
|
||||
unsigned long irqflags)
|
||||
{
|
||||
const struct regmap_config *hc_regmap;
|
||||
const struct reg_field *hc_reg_fields;
|
||||
struct isp1760_hcd *hcd;
|
||||
struct regmap_field *f;
|
||||
unsigned int devflags;
|
||||
struct udevice *dev;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
hcd = &isp->hcd;
|
||||
devflags = isp->devflags;
|
||||
dev = isp->dev;
|
||||
|
||||
hcd->is_isp1763 = !!(devflags & ISP1760_FLAG_ISP1763);
|
||||
|
||||
if (!hcd->is_isp1763 && (devflags & ISP1760_FLAG_BUS_WIDTH_8)) {
|
||||
dev_err(dev, "isp1760/61 do not support data width 8\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (hcd->is_isp1763) {
|
||||
hc_regmap = &isp1763_hc_regmap_conf;
|
||||
hc_reg_fields = &isp1763_hc_reg_fields[0];
|
||||
} else {
|
||||
hc_regmap = &isp1760_hc_regmap_conf;
|
||||
hc_reg_fields = &isp1760_hc_reg_fields[0];
|
||||
}
|
||||
|
||||
hcd->base = devm_ioremap(dev, mem->start, resource_size(mem));
|
||||
if (IS_ERR(hcd->base))
|
||||
return PTR_ERR(hcd->base);
|
||||
|
||||
hcd->regs = devm_regmap_init(dev, NULL, NULL, hc_regmap);
|
||||
if (IS_ERR(hcd->regs))
|
||||
return PTR_ERR(hcd->regs);
|
||||
|
||||
for (i = 0; i < HC_FIELD_MAX; i++) {
|
||||
f = devm_regmap_field_alloc(dev, hcd->regs, hc_reg_fields[i]);
|
||||
if (IS_ERR(f))
|
||||
return PTR_ERR(f);
|
||||
|
||||
hcd->fields[i] = f;
|
||||
}
|
||||
|
||||
if (hcd->is_isp1763)
|
||||
hcd->memory_layout = &isp1763_memory_conf;
|
||||
else
|
||||
hcd->memory_layout = &isp176x_memory_conf;
|
||||
|
||||
ret = isp1760_init_core(isp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
hcd->dev = dev;
|
||||
|
||||
ret = isp1760_hcd_register(hcd, mem, irq, irqflags, dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = isp1760_hcd_lowlevel_init(hcd);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_set_drvdata(dev, isp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void isp1760_unregister(struct isp1760_device *isp)
|
||||
{
|
||||
isp1760_hcd_unregister(&isp->hcd);
|
||||
}
|
96
drivers/usb/isp1760/isp1760-core.h
Normal file
96
drivers/usb/isp1760/isp1760-core.h
Normal file
@ -0,0 +1,96 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva
|
||||
* Copyright 2014 Laurent Pinchart
|
||||
* Copyright 2007 Sebastian Siewior
|
||||
*
|
||||
* Contacts:
|
||||
* Sebastian Siewior <bigeasy@linutronix.de>
|
||||
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
* Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*/
|
||||
|
||||
#ifndef _ISP1760_CORE_H_
|
||||
#define _ISP1760_CORE_H_
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <regmap.h>
|
||||
|
||||
#include "isp1760-hcd.h"
|
||||
|
||||
struct device;
|
||||
struct gpio_desc;
|
||||
|
||||
/*
|
||||
* Device flags that can vary from board to board. All of these
|
||||
* indicate the most "atypical" case, so that a devflags of 0 is
|
||||
* a sane default configuration.
|
||||
*/
|
||||
#define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */
|
||||
#define ISP1760_FLAG_PERIPHERAL_EN 0x00000004 /* Port 1 supports Peripheral mode*/
|
||||
#define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */
|
||||
#define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */
|
||||
#define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */
|
||||
#define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */
|
||||
#define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */
|
||||
#define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */
|
||||
#define ISP1760_FLAG_ISP1763 0x00000200 /* Chip is ISP1763 */
|
||||
#define ISP1760_FLAG_BUS_WIDTH_8 0x00000400 /* 8-bit data bus width */
|
||||
|
||||
struct isp1760_device {
|
||||
struct udevice *dev;
|
||||
|
||||
unsigned int devflags;
|
||||
struct gpio_desc *rst_gpio;
|
||||
|
||||
struct isp1760_hcd hcd;
|
||||
};
|
||||
|
||||
int isp1760_register(struct isp1760_device *isp, struct resource *mem, int irq,
|
||||
unsigned long irqflags);
|
||||
void isp1760_unregister(struct isp1760_device *isp);
|
||||
|
||||
void isp1760_set_pullup(struct isp1760_device *isp, bool enable);
|
||||
|
||||
static inline u32 isp1760_field_read(struct regmap_field **fields, u32 field)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_field_read(fields[field], &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void isp1760_field_write(struct regmap_field **fields, u32 field,
|
||||
u32 val)
|
||||
{
|
||||
regmap_field_write(fields[field], val);
|
||||
}
|
||||
|
||||
static inline void isp1760_field_set(struct regmap_field **fields, u32 field)
|
||||
{
|
||||
isp1760_field_write(fields, field, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
static inline void isp1760_field_clear(struct regmap_field **fields, u32 field)
|
||||
{
|
||||
isp1760_field_write(fields, field, 0);
|
||||
}
|
||||
|
||||
static inline u32 isp1760_reg_read(struct regmap *regs, u32 reg)
|
||||
{
|
||||
unsigned int val;
|
||||
|
||||
regmap_read(regs, reg, &val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static inline void isp1760_reg_write(struct regmap *regs, u32 reg, u32 val)
|
||||
{
|
||||
regmap_write(regs, reg, val);
|
||||
}
|
||||
#endif
|
2477
drivers/usb/isp1760/isp1760-hcd.c
Normal file
2477
drivers/usb/isp1760/isp1760-hcd.c
Normal file
File diff suppressed because it is too large
Load Diff
81
drivers/usb/isp1760/isp1760-hcd.h
Normal file
81
drivers/usb/isp1760/isp1760-hcd.h
Normal file
@ -0,0 +1,81 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef _ISP1760_HCD_H_
|
||||
#define _ISP1760_HCD_H_
|
||||
|
||||
#include <regmap.h>
|
||||
|
||||
#include "isp1760-regs.h"
|
||||
|
||||
struct isp1760_qh;
|
||||
struct isp1760_qtd;
|
||||
struct resource;
|
||||
struct usb_hcd;
|
||||
|
||||
struct isp1760_slotinfo {
|
||||
struct isp1760_qh *qh;
|
||||
struct isp1760_qtd *qtd;
|
||||
unsigned long timestamp;
|
||||
};
|
||||
|
||||
/* chip memory management */
|
||||
#define ISP176x_BLOCK_MAX (32 + 20 + 4)
|
||||
#define ISP176x_BLOCK_NUM 3
|
||||
|
||||
struct isp1760_memory_layout {
|
||||
unsigned int blocks[ISP176x_BLOCK_NUM];
|
||||
unsigned int blocks_size[ISP176x_BLOCK_NUM];
|
||||
|
||||
unsigned int slot_num;
|
||||
unsigned int payload_blocks;
|
||||
unsigned int payload_area_size;
|
||||
};
|
||||
|
||||
struct isp1760_memory_chunk {
|
||||
unsigned int start;
|
||||
unsigned int size;
|
||||
unsigned int free;
|
||||
};
|
||||
|
||||
enum isp1760_queue_head_types {
|
||||
QH_CONTROL,
|
||||
QH_BULK,
|
||||
QH_INTERRUPT,
|
||||
QH_END
|
||||
};
|
||||
|
||||
struct isp1760_hcd {
|
||||
struct usb_hcd *hcd;
|
||||
struct udevice *dev;
|
||||
|
||||
void __iomem *base;
|
||||
|
||||
struct regmap *regs;
|
||||
struct regmap_field *fields[HC_FIELD_MAX];
|
||||
|
||||
bool is_isp1763;
|
||||
const struct isp1760_memory_layout *memory_layout;
|
||||
|
||||
struct isp1760_slotinfo *atl_slots;
|
||||
int atl_done_map;
|
||||
struct isp1760_slotinfo *int_slots;
|
||||
int int_done_map;
|
||||
struct isp1760_memory_chunk memory_pool[ISP176x_BLOCK_MAX];
|
||||
struct list_head qh_list[QH_END];
|
||||
|
||||
/* periodic schedule support */
|
||||
#define DEFAULT_I_TDPS 1024
|
||||
unsigned int periodic_size;
|
||||
unsigned int i_thresh;
|
||||
unsigned long reset_done;
|
||||
unsigned long next_statechange;
|
||||
};
|
||||
|
||||
int isp1760_hcd_register(struct isp1760_hcd *priv, struct resource *mem,
|
||||
int irq, unsigned long irqflags, struct udevice *dev);
|
||||
void isp1760_hcd_unregister(struct isp1760_hcd *priv);
|
||||
int isp1760_hcd_lowlevel_init(struct isp1760_hcd *priv);
|
||||
|
||||
int isp1760_init_kmem_once(void);
|
||||
void isp1760_deinit_kmem_cache(void);
|
||||
|
||||
#endif /* _ISP1760_HCD_H_ */
|
125
drivers/usb/isp1760/isp1760-if.c
Normal file
125
drivers/usb/isp1760/isp1760-if.c
Normal file
@ -0,0 +1,125 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
* based on original code from:
|
||||
* (c) 2007 Sebastian Siewior <bigeasy@linutronix.de>
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/devres.h>
|
||||
#include <dm/lists.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <log.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
#include "isp1760-regs.h"
|
||||
#include "isp1760-uboot.h"
|
||||
|
||||
static int isp1760_of_to_plat(struct udevice *dev)
|
||||
{
|
||||
struct isp1760_device *isp = dev_get_plat(dev);
|
||||
unsigned int devflags = 0;
|
||||
u32 bus_width = 0;
|
||||
ofnode dp;
|
||||
|
||||
if (!dev_has_ofnode(dev)) {
|
||||
/* select isp1763 as the default device */
|
||||
devflags = ISP1760_FLAG_ISP1763 | ISP1760_FLAG_BUS_WIDTH_16;
|
||||
pr_err("isp1760: no platform data\n");
|
||||
goto isp_setup;
|
||||
}
|
||||
|
||||
dp = dev_ofnode(dev);
|
||||
|
||||
if (ofnode_device_is_compatible(dp, "nxp,usb-isp1761"))
|
||||
devflags |= ISP1760_FLAG_ISP1761;
|
||||
|
||||
if (ofnode_device_is_compatible(dp, "nxp,usb-isp1763"))
|
||||
devflags |= ISP1760_FLAG_ISP1763;
|
||||
|
||||
/*
|
||||
* Some systems wire up only 8 of 16 data lines or
|
||||
* 16 of the 32 data lines
|
||||
*/
|
||||
bus_width = ofnode_read_u32_default(dp, "bus-width", 16);
|
||||
if (bus_width == 16)
|
||||
devflags |= ISP1760_FLAG_BUS_WIDTH_16;
|
||||
else if (bus_width == 8)
|
||||
devflags |= ISP1760_FLAG_BUS_WIDTH_8;
|
||||
|
||||
if (usb_get_dr_mode(dev_ofnode(dev)) == USB_DR_MODE_PERIPHERAL)
|
||||
devflags |= ISP1760_FLAG_PERIPHERAL_EN;
|
||||
|
||||
if (ofnode_read_bool(dp, "analog-oc"))
|
||||
devflags |= ISP1760_FLAG_ANALOG_OC;
|
||||
|
||||
if (ofnode_read_bool(dp, "dack-polarity"))
|
||||
devflags |= ISP1760_FLAG_DACK_POL_HIGH;
|
||||
|
||||
if (ofnode_read_bool(dp, "dreq-polarity"))
|
||||
devflags |= ISP1760_FLAG_DREQ_POL_HIGH;
|
||||
|
||||
isp_setup:
|
||||
isp->devflags = devflags;
|
||||
isp->dev = dev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp1760_plat_probe(struct udevice *dev)
|
||||
{
|
||||
struct isp1760_device *isp = dev_get_plat(dev);
|
||||
struct resource mem_res;
|
||||
struct resource irq_res;
|
||||
int ret;
|
||||
|
||||
dev_read_resource(dev, 0, &mem_res);
|
||||
dev_read_resource(dev, 1, &irq_res);
|
||||
|
||||
isp1760_init_kmem_once();
|
||||
|
||||
ret = isp1760_register(isp, &mem_res, irq_res.start, irq_res.flags);
|
||||
if (ret < 0) {
|
||||
isp1760_deinit_kmem_cache();
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int isp1760_plat_remove(struct udevice *dev)
|
||||
{
|
||||
struct isp1760_device *isp = dev_get_plat(dev);
|
||||
|
||||
isp1760_deinit_kmem_cache();
|
||||
isp1760_unregister(isp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id isp1760_ids[] = {
|
||||
{ .compatible = "nxp,usb-isp1760", },
|
||||
{ .compatible = "nxp,usb-isp1761", },
|
||||
{ .compatible = "nxp,usb-isp1763", },
|
||||
{ },
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(isp1760) = {
|
||||
.name = "isp1760",
|
||||
.id = UCLASS_USB,
|
||||
.of_match = isp1760_ids,
|
||||
.of_to_plat = isp1760_of_to_plat,
|
||||
.ops = &isp1760_usb_ops,
|
||||
.probe = isp1760_plat_probe,
|
||||
.remove = isp1760_plat_remove,
|
||||
.plat_auto = sizeof(struct isp1760_device),
|
||||
.priv_auto = sizeof(struct isp1760_host_data),
|
||||
};
|
292
drivers/usb/isp1760/isp1760-regs.h
Normal file
292
drivers/usb/isp1760/isp1760-regs.h
Normal file
@ -0,0 +1,292 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva
|
||||
* Copyright 2014 Laurent Pinchart
|
||||
* Copyright 2007 Sebastian Siewior
|
||||
*
|
||||
* Contacts:
|
||||
* Sebastian Siewior <bigeasy@linutronix.de>
|
||||
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
* Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*/
|
||||
|
||||
#ifndef _ISP176x_REGS_H_
|
||||
#define _ISP176x_REGS_H_
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Host Controller
|
||||
*/
|
||||
|
||||
/* ISP1760/31 */
|
||||
/* EHCI capability registers */
|
||||
#define ISP176x_HC_VERSION 0x002
|
||||
#define ISP176x_HC_HCSPARAMS 0x004
|
||||
#define ISP176x_HC_HCCPARAMS 0x008
|
||||
|
||||
/* EHCI operational registers */
|
||||
#define ISP176x_HC_USBCMD 0x020
|
||||
#define ISP176x_HC_USBSTS 0x024
|
||||
#define ISP176x_HC_FRINDEX 0x02c
|
||||
|
||||
#define ISP176x_HC_CONFIGFLAG 0x060
|
||||
#define ISP176x_HC_PORTSC1 0x064
|
||||
|
||||
#define ISP176x_HC_ISO_PTD_DONEMAP 0x130
|
||||
#define ISP176x_HC_ISO_PTD_SKIPMAP 0x134
|
||||
#define ISP176x_HC_ISO_PTD_LASTPTD 0x138
|
||||
#define ISP176x_HC_INT_PTD_DONEMAP 0x140
|
||||
#define ISP176x_HC_INT_PTD_SKIPMAP 0x144
|
||||
#define ISP176x_HC_INT_PTD_LASTPTD 0x148
|
||||
#define ISP176x_HC_ATL_PTD_DONEMAP 0x150
|
||||
#define ISP176x_HC_ATL_PTD_SKIPMAP 0x154
|
||||
#define ISP176x_HC_ATL_PTD_LASTPTD 0x158
|
||||
|
||||
/* Configuration Register */
|
||||
#define ISP176x_HC_HW_MODE_CTRL 0x300
|
||||
#define ISP176x_HC_CHIP_ID 0x304
|
||||
#define ISP176x_HC_SCRATCH 0x308
|
||||
#define ISP176x_HC_RESET 0x30c
|
||||
#define ISP176x_HC_BUFFER_STATUS 0x334
|
||||
#define ISP176x_HC_MEMORY 0x33c
|
||||
|
||||
/* Interrupt Register */
|
||||
#define ISP176x_HC_INTERRUPT 0x310
|
||||
#define ISP176x_HC_INTERRUPT_ENABLE 0x314
|
||||
#define ISP176x_HC_ISO_IRQ_MASK_OR 0x318
|
||||
#define ISP176x_HC_INT_IRQ_MASK_OR 0x31c
|
||||
#define ISP176x_HC_ATL_IRQ_MASK_OR 0x320
|
||||
#define ISP176x_HC_ISO_IRQ_MASK_AND 0x324
|
||||
#define ISP176x_HC_INT_IRQ_MASK_AND 0x328
|
||||
#define ISP176x_HC_ATL_IRQ_MASK_AND 0x32c
|
||||
|
||||
#define ISP176x_HC_OTG_CTRL_SET 0x374
|
||||
#define ISP176x_HC_OTG_CTRL_CLEAR 0x376
|
||||
|
||||
enum isp176x_host_controller_fields {
|
||||
/* HC_PORTSC1 */
|
||||
PORT_OWNER, PORT_POWER, PORT_LSTATUS, PORT_RESET, PORT_SUSPEND,
|
||||
PORT_RESUME, PORT_PE, PORT_CSC, PORT_CONNECT,
|
||||
/* HC_HCSPARAMS */
|
||||
HCS_PPC, HCS_N_PORTS,
|
||||
/* HC_HCCPARAMS */
|
||||
HCC_ISOC_CACHE, HCC_ISOC_THRES,
|
||||
/* HC_USBCMD */
|
||||
CMD_LRESET, CMD_RESET, CMD_RUN,
|
||||
/* HC_USBSTS */
|
||||
STS_PCD,
|
||||
/* HC_FRINDEX */
|
||||
HC_FRINDEX,
|
||||
/* HC_CONFIGFLAG */
|
||||
FLAG_CF,
|
||||
/* ISO/INT/ATL PTD */
|
||||
HC_ISO_PTD_DONEMAP, HC_ISO_PTD_SKIPMAP, HC_ISO_PTD_LASTPTD,
|
||||
HC_INT_PTD_DONEMAP, HC_INT_PTD_SKIPMAP, HC_INT_PTD_LASTPTD,
|
||||
HC_ATL_PTD_DONEMAP, HC_ATL_PTD_SKIPMAP, HC_ATL_PTD_LASTPTD,
|
||||
/* HC_HW_MODE_CTRL */
|
||||
ALL_ATX_RESET, HW_ANA_DIGI_OC, HW_DEV_DMA, HW_COMN_IRQ, HW_COMN_DMA,
|
||||
HW_DATA_BUS_WIDTH, HW_DACK_POL_HIGH, HW_DREQ_POL_HIGH, HW_INTR_HIGH_ACT,
|
||||
HW_INTF_LOCK, HW_INTR_EDGE_TRIG, HW_GLOBAL_INTR_EN,
|
||||
/* HC_CHIP_ID */
|
||||
HC_CHIP_ID_HIGH, HC_CHIP_ID_LOW, HC_CHIP_REV,
|
||||
/* HC_SCRATCH */
|
||||
HC_SCRATCH,
|
||||
/* HC_RESET */
|
||||
SW_RESET_RESET_ATX, SW_RESET_RESET_HC, SW_RESET_RESET_ALL,
|
||||
/* HC_BUFFER_STATUS */
|
||||
ISO_BUF_FILL, INT_BUF_FILL, ATL_BUF_FILL,
|
||||
/* HC_MEMORY */
|
||||
MEM_BANK_SEL, MEM_START_ADDR,
|
||||
/* HC_DATA */
|
||||
HC_DATA,
|
||||
/* HC_INTERRUPT */
|
||||
HC_INTERRUPT,
|
||||
/* HC_INTERRUPT_ENABLE */
|
||||
HC_INT_IRQ_ENABLE, HC_ATL_IRQ_ENABLE,
|
||||
/* INTERRUPT MASKS */
|
||||
HC_ISO_IRQ_MASK_OR, HC_INT_IRQ_MASK_OR, HC_ATL_IRQ_MASK_OR,
|
||||
HC_ISO_IRQ_MASK_AND, HC_INT_IRQ_MASK_AND, HC_ATL_IRQ_MASK_AND,
|
||||
/* HW_OTG_CTRL_SET */
|
||||
HW_OTG_DISABLE, HW_SW_SEL_HC_DC, HW_VBUS_DRV, HW_SEL_CP_EXT,
|
||||
HW_DM_PULLDOWN, HW_DP_PULLDOWN, HW_DP_PULLUP, HW_HC_2_DIS,
|
||||
/* HW_OTG_CTRL_CLR */
|
||||
HW_OTG_DISABLE_CLEAR, HW_SW_SEL_HC_DC_CLEAR, HW_VBUS_DRV_CLEAR,
|
||||
HW_SEL_CP_EXT_CLEAR, HW_DM_PULLDOWN_CLEAR, HW_DP_PULLDOWN_CLEAR,
|
||||
HW_DP_PULLUP_CLEAR, HW_HC_2_DIS_CLEAR,
|
||||
/* Last element */
|
||||
HC_FIELD_MAX,
|
||||
};
|
||||
|
||||
/* ISP1763 */
|
||||
/* EHCI operational registers */
|
||||
#define ISP1763_HC_USBCMD 0x8c
|
||||
#define ISP1763_HC_USBSTS 0x90
|
||||
#define ISP1763_HC_FRINDEX 0x98
|
||||
|
||||
#define ISP1763_HC_CONFIGFLAG 0x9c
|
||||
#define ISP1763_HC_PORTSC1 0xa0
|
||||
|
||||
#define ISP1763_HC_ISO_PTD_DONEMAP 0xa4
|
||||
#define ISP1763_HC_ISO_PTD_SKIPMAP 0xa6
|
||||
#define ISP1763_HC_ISO_PTD_LASTPTD 0xa8
|
||||
#define ISP1763_HC_INT_PTD_DONEMAP 0xaa
|
||||
#define ISP1763_HC_INT_PTD_SKIPMAP 0xac
|
||||
#define ISP1763_HC_INT_PTD_LASTPTD 0xae
|
||||
#define ISP1763_HC_ATL_PTD_DONEMAP 0xb0
|
||||
#define ISP1763_HC_ATL_PTD_SKIPMAP 0xb2
|
||||
#define ISP1763_HC_ATL_PTD_LASTPTD 0xb4
|
||||
|
||||
/* Configuration Register */
|
||||
#define ISP1763_HC_HW_MODE_CTRL 0xb6
|
||||
#define ISP1763_HC_CHIP_REV 0x70
|
||||
#define ISP1763_HC_CHIP_ID 0x72
|
||||
#define ISP1763_HC_SCRATCH 0x78
|
||||
#define ISP1763_HC_RESET 0xb8
|
||||
#define ISP1763_HC_BUFFER_STATUS 0xba
|
||||
#define ISP1763_HC_MEMORY 0xc4
|
||||
#define ISP1763_HC_DATA 0xc6
|
||||
|
||||
/* Interrupt Register */
|
||||
#define ISP1763_HC_INTERRUPT 0xd4
|
||||
#define ISP1763_HC_INTERRUPT_ENABLE 0xd6
|
||||
#define ISP1763_HC_ISO_IRQ_MASK_OR 0xd8
|
||||
#define ISP1763_HC_INT_IRQ_MASK_OR 0xda
|
||||
#define ISP1763_HC_ATL_IRQ_MASK_OR 0xdc
|
||||
#define ISP1763_HC_ISO_IRQ_MASK_AND 0xde
|
||||
#define ISP1763_HC_INT_IRQ_MASK_AND 0xe0
|
||||
#define ISP1763_HC_ATL_IRQ_MASK_AND 0xe2
|
||||
|
||||
#define ISP1763_HC_OTG_CTRL_SET 0xe4
|
||||
#define ISP1763_HC_OTG_CTRL_CLEAR 0xe6
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Peripheral Controller
|
||||
*/
|
||||
|
||||
#define DC_IEPTX(n) (1 << (11 + 2 * (n)))
|
||||
#define DC_IEPRX(n) (1 << (10 + 2 * (n)))
|
||||
#define DC_IEPRXTX(n) (3 << (10 + 2 * (n)))
|
||||
|
||||
#define ISP176x_DC_CDBGMOD_ACK BIT(6)
|
||||
#define ISP176x_DC_DDBGMODIN_ACK BIT(4)
|
||||
#define ISP176x_DC_DDBGMODOUT_ACK BIT(2)
|
||||
|
||||
#define ISP176x_DC_IEP0SETUP BIT(8)
|
||||
#define ISP176x_DC_IEVBUS BIT(7)
|
||||
#define ISP176x_DC_IEHS_STA BIT(5)
|
||||
#define ISP176x_DC_IERESM BIT(4)
|
||||
#define ISP176x_DC_IESUSP BIT(3)
|
||||
#define ISP176x_DC_IEBRST BIT(0)
|
||||
|
||||
#define ISP176x_DC_ENDPTYP_ISOC 0x01
|
||||
#define ISP176x_DC_ENDPTYP_BULK 0x02
|
||||
#define ISP176x_DC_ENDPTYP_INTERRUPT 0x03
|
||||
|
||||
/* Initialization Registers */
|
||||
#define ISP176x_DC_ADDRESS 0x0200
|
||||
#define ISP176x_DC_MODE 0x020c
|
||||
#define ISP176x_DC_INTCONF 0x0210
|
||||
#define ISP176x_DC_DEBUG 0x0212
|
||||
#define ISP176x_DC_INTENABLE 0x0214
|
||||
|
||||
/* Data Flow Registers */
|
||||
#define ISP176x_DC_EPMAXPKTSZ 0x0204
|
||||
#define ISP176x_DC_EPTYPE 0x0208
|
||||
|
||||
#define ISP176x_DC_BUFLEN 0x021c
|
||||
#define ISP176x_DC_BUFSTAT 0x021e
|
||||
#define ISP176x_DC_DATAPORT 0x0220
|
||||
|
||||
#define ISP176x_DC_CTRLFUNC 0x0228
|
||||
#define ISP176x_DC_EPINDEX 0x022c
|
||||
|
||||
/* DMA Registers */
|
||||
#define ISP176x_DC_DMACMD 0x0230
|
||||
#define ISP176x_DC_DMATXCOUNT 0x0234
|
||||
#define ISP176x_DC_DMACONF 0x0238
|
||||
#define ISP176x_DC_DMAHW 0x023c
|
||||
#define ISP176x_DC_DMAINTREASON 0x0250
|
||||
#define ISP176x_DC_DMAINTEN 0x0254
|
||||
#define ISP176x_DC_DMAEP 0x0258
|
||||
#define ISP176x_DC_DMABURSTCOUNT 0x0264
|
||||
|
||||
/* General Registers */
|
||||
#define ISP176x_DC_INTERRUPT 0x0218
|
||||
#define ISP176x_DC_CHIPID 0x0270
|
||||
#define ISP176x_DC_FRAMENUM 0x0274
|
||||
#define ISP176x_DC_SCRATCH 0x0278
|
||||
#define ISP176x_DC_UNLOCKDEV 0x027c
|
||||
#define ISP176x_DC_INTPULSEWIDTH 0x0280
|
||||
#define ISP176x_DC_TESTMODE 0x0284
|
||||
|
||||
enum isp176x_device_controller_fields {
|
||||
/* DC_ADDRESS */
|
||||
DC_DEVEN, DC_DEVADDR,
|
||||
/* DC_MODE */
|
||||
DC_VBUSSTAT, DC_SFRESET, DC_GLINTENA,
|
||||
/* DC_INTCONF */
|
||||
DC_CDBGMOD_ACK, DC_DDBGMODIN_ACK, DC_DDBGMODOUT_ACK, DC_INTPOL,
|
||||
/* DC_INTENABLE */
|
||||
DC_IEPRXTX_7, DC_IEPRXTX_6, DC_IEPRXTX_5, DC_IEPRXTX_4, DC_IEPRXTX_3,
|
||||
DC_IEPRXTX_2, DC_IEPRXTX_1, DC_IEPRXTX_0,
|
||||
DC_IEP0SETUP, DC_IEVBUS, DC_IEHS_STA, DC_IERESM, DC_IESUSP, DC_IEBRST,
|
||||
/* DC_EPINDEX */
|
||||
DC_EP0SETUP, DC_ENDPIDX, DC_EPDIR,
|
||||
/* DC_CTRLFUNC */
|
||||
DC_CLBUF, DC_VENDP, DC_DSEN, DC_STATUS, DC_STALL,
|
||||
/* DC_BUFLEN */
|
||||
DC_BUFLEN,
|
||||
/* DC_EPMAXPKTSZ */
|
||||
DC_FFOSZ,
|
||||
/* DC_EPTYPE */
|
||||
DC_EPENABLE, DC_ENDPTYP,
|
||||
/* DC_FRAMENUM */
|
||||
DC_FRAMENUM, DC_UFRAMENUM,
|
||||
/* DC_CHIP_ID */
|
||||
DC_CHIP_ID_HIGH, DC_CHIP_ID_LOW,
|
||||
/* DC_SCRATCH */
|
||||
DC_SCRATCH,
|
||||
/* Last element */
|
||||
DC_FIELD_MAX,
|
||||
};
|
||||
|
||||
/* ISP1763 */
|
||||
/* Initialization Registers */
|
||||
#define ISP1763_DC_ADDRESS 0x00
|
||||
#define ISP1763_DC_MODE 0x0c
|
||||
#define ISP1763_DC_INTCONF 0x10
|
||||
#define ISP1763_DC_INTENABLE 0x14
|
||||
|
||||
/* Data Flow Registers */
|
||||
#define ISP1763_DC_EPMAXPKTSZ 0x04
|
||||
#define ISP1763_DC_EPTYPE 0x08
|
||||
|
||||
#define ISP1763_DC_BUFLEN 0x1c
|
||||
#define ISP1763_DC_BUFSTAT 0x1e
|
||||
#define ISP1763_DC_DATAPORT 0x20
|
||||
|
||||
#define ISP1763_DC_CTRLFUNC 0x28
|
||||
#define ISP1763_DC_EPINDEX 0x2c
|
||||
|
||||
/* DMA Registers */
|
||||
#define ISP1763_DC_DMACMD 0x30
|
||||
#define ISP1763_DC_DMATXCOUNT 0x34
|
||||
#define ISP1763_DC_DMACONF 0x38
|
||||
#define ISP1763_DC_DMAHW 0x3c
|
||||
#define ISP1763_DC_DMAINTREASON 0x50
|
||||
#define ISP1763_DC_DMAINTEN 0x54
|
||||
#define ISP1763_DC_DMAEP 0x58
|
||||
#define ISP1763_DC_DMABURSTCOUNT 0x64
|
||||
|
||||
/* General Registers */
|
||||
#define ISP1763_DC_INTERRUPT 0x18
|
||||
#define ISP1763_DC_CHIPID_LOW 0x70
|
||||
#define ISP1763_DC_CHIPID_HIGH 0x72
|
||||
#define ISP1763_DC_FRAMENUM 0x74
|
||||
#define ISP1763_DC_SCRATCH 0x78
|
||||
#define ISP1763_DC_UNLOCKDEV 0x7c
|
||||
#define ISP1763_DC_INTPULSEWIDTH 0x80
|
||||
#define ISP1763_DC_TESTMODE 0x84
|
||||
|
||||
#endif
|
75
drivers/usb/isp1760/isp1760-uboot.c
Normal file
75
drivers/usb/isp1760/isp1760-uboot.c
Normal file
@ -0,0 +1,75 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/device-internal.h>
|
||||
#include <dm/device_compat.h>
|
||||
#include <dm/devres.h>
|
||||
#include <dm/lists.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include <log.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
#include "isp1760-hcd.h"
|
||||
#include "isp1760-regs.h"
|
||||
#include "isp1760-uboot.h"
|
||||
|
||||
static int isp1760_msg_submit_control(struct udevice *dev,
|
||||
struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer,
|
||||
int length, struct devrequest *setup)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
|
||||
return usb_urb_submit_control(&host->hcd, &host->urb, &host->hep, udev,
|
||||
pipe, buffer, length, setup, 0,
|
||||
host->host_speed);
|
||||
}
|
||||
|
||||
static int isp1760_msg_submit_bulk(struct udevice *dev, struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer, int length)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
|
||||
return usb_urb_submit_bulk(&host->hcd, &host->urb, &host->hep, udev,
|
||||
pipe, buffer, length);
|
||||
}
|
||||
|
||||
static int isp1760_msg_submit_irq(struct udevice *dev, struct usb_device *udev,
|
||||
unsigned long pipe, void *buffer, int length,
|
||||
int interval, bool nonblock)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
|
||||
return usb_urb_submit_irq(&host->hcd, &host->urb, &host->hep, udev,
|
||||
pipe, buffer, length, interval);
|
||||
}
|
||||
|
||||
static int isp1760_get_max_xfer_size(struct udevice *dev, size_t *size)
|
||||
{
|
||||
struct isp1760_host_data *host = dev_get_priv(dev);
|
||||
struct isp1760_hcd *priv = host->hcd.hcd_priv;
|
||||
const struct isp1760_memory_layout *mem = priv->memory_layout;
|
||||
|
||||
*size = mem->blocks_size[ISP176x_BLOCK_NUM - 1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dm_usb_ops isp1760_usb_ops = {
|
||||
.control = isp1760_msg_submit_control,
|
||||
.bulk = isp1760_msg_submit_bulk,
|
||||
.interrupt = isp1760_msg_submit_irq,
|
||||
.get_max_xfer_size = isp1760_get_max_xfer_size,
|
||||
};
|
27
drivers/usb/isp1760/isp1760-uboot.h
Normal file
27
drivers/usb/isp1760/isp1760-uboot.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for the NXP ISP1760 chip
|
||||
*
|
||||
* Copyright 2021 Linaro, Rui Miguel Silva <rui.silva@linaro.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __ISP1760_UBOOT_H__
|
||||
#define __ISP1760_UBOOT_H__
|
||||
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include <usb.h>
|
||||
|
||||
#include "isp1760-core.h"
|
||||
|
||||
struct isp1760_host_data {
|
||||
struct isp1760_hcd *priv;
|
||||
struct usb_hcd hcd;
|
||||
enum usb_device_speed host_speed;
|
||||
struct usb_host_endpoint hep;
|
||||
struct urb urb;
|
||||
};
|
||||
|
||||
extern struct dm_usb_ops isp1760_usb_ops;
|
||||
|
||||
#endif
|
@ -89,9 +89,9 @@
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/musb.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include <asm/io.h>
|
||||
#include "linux-compat.h"
|
||||
#include "usb-compat.h"
|
||||
#endif
|
||||
|
||||
#include "musb_core.h"
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include <dm/device_compat.h>
|
||||
#include <usb.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include "linux-compat.h"
|
||||
#include "usb-compat.h"
|
||||
#endif
|
||||
|
||||
#include "musb_core.h"
|
||||
|
@ -10,7 +10,7 @@
|
||||
#ifndef _MUSB_HOST_H
|
||||
#define _MUSB_HOST_H
|
||||
#ifdef __UBOOT__
|
||||
#include "usb-compat.h"
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#endif
|
||||
|
||||
static inline struct usb_hcd *musb_to_hcd(struct musb *musb)
|
||||
|
@ -8,10 +8,10 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
|
||||
#include <usb.h>
|
||||
#include "linux-compat.h"
|
||||
#include "usb-compat.h"
|
||||
#include "musb_core.h"
|
||||
#include "musb_host.h"
|
||||
#include "musb_gadget.h"
|
||||
@ -453,39 +453,3 @@ struct musb *musb_register(struct musb_hdrc_platform_data *plat, void *bdata,
|
||||
|
||||
return *musbp;
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_USB)
|
||||
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;
|
||||
}
|
||||
#else
|
||||
struct usb_device *usb_dev_get_parent(struct usb_device *udev)
|
||||
{
|
||||
return udev->parent;
|
||||
}
|
||||
#endif
|
||||
|
@ -8,8 +8,8 @@
|
||||
#define __MUSB_UBOOT_H__
|
||||
|
||||
#include <usb.h>
|
||||
#include <linux/usb/usb_urb_compat.h>
|
||||
#include "linux-compat.h"
|
||||
#include "usb-compat.h"
|
||||
#include "musb_core.h"
|
||||
|
||||
struct musb_host_data {
|
||||
|
@ -24,4 +24,10 @@
|
||||
|
||||
#define CONFIG_SYS_SDRAM_BASE PHYS_SDRAM_1
|
||||
|
||||
#define BOOT_TARGET_DEVICES(func) \
|
||||
func(USB, usb, 0)
|
||||
|
||||
#include <config_distro_bootcmd.h>
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,16 +1,32 @@
|
||||
#ifndef __USB_COMPAT_H__
|
||||
#define __USB_COMPAT_H__
|
||||
/* SPDX-License-Identifier: GPL-2.0+ */
|
||||
|
||||
#include "usb.h"
|
||||
#ifndef __USB_URB_COMPAT_H__
|
||||
#define __USB_URB_COMPAT_H__
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <usb.h>
|
||||
|
||||
struct udevice;
|
||||
struct urb;
|
||||
struct usb_hcd;
|
||||
|
||||
struct usb_urb_ops {
|
||||
int (*urb_enqueue)(struct usb_hcd *hcd, struct urb *urb,
|
||||
gfp_t mem_flags);
|
||||
int (*urb_dequeue)(struct usb_hcd *hcd, struct urb *urb, int status);
|
||||
int (*hub_control)(struct usb_hcd *hcd, struct usb_device *dev,
|
||||
unsigned long pipe, void *buffer, int len,
|
||||
struct devrequest *setup);
|
||||
irqreturn_t (*isr)(int irq, void *priv);
|
||||
};
|
||||
|
||||
struct usb_hcd {
|
||||
void *hcd_priv;
|
||||
const struct usb_urb_ops *urb_ops;
|
||||
};
|
||||
|
||||
struct usb_host_endpoint {
|
||||
struct usb_endpoint_descriptor desc;
|
||||
struct usb_endpoint_descriptor desc;
|
||||
struct list_head urb_list;
|
||||
void *hcpriv;
|
||||
};
|
||||
@ -23,8 +39,6 @@ struct usb_host_endpoint {
|
||||
#define URB_SHORT_NOT_OK 0x0001 /* report short reads as errors */
|
||||
#define URB_ZERO_PACKET 0x0040 /* Finish bulk OUT with short packet */
|
||||
|
||||
struct urb;
|
||||
|
||||
typedef void (*usb_complete_t)(struct urb *);
|
||||
|
||||
struct urb {
|
||||
@ -76,4 +90,25 @@ static inline int usb_hcd_unmap_urb_for_dma(struct usb_hcd *hcd,
|
||||
*/
|
||||
struct usb_device *usb_dev_get_parent(struct usb_device *udev);
|
||||
|
||||
int usb_urb_submit_control(struct usb_hcd *hcd, struct urb *urb,
|
||||
struct usb_host_endpoint *hep,
|
||||
struct usb_device *dev, unsigned long pipe,
|
||||
void *buffer, int len, struct devrequest *setup,
|
||||
int interval, enum usb_device_speed speed);
|
||||
|
||||
int usb_urb_submit_bulk(struct usb_hcd *hcd, struct urb *urb,
|
||||
struct usb_host_endpoint *hep, struct usb_device *dev,
|
||||
unsigned long pipe, void *buffer, int len);
|
||||
|
||||
int usb_urb_submit_irq(struct usb_hcd *hcd, struct urb *urb,
|
||||
struct usb_host_endpoint *hep, struct usb_device *dev,
|
||||
unsigned long pipe, void *buffer, int len, int interval);
|
||||
|
||||
void usb_urb_fill(struct urb *urb, struct usb_host_endpoint *hep,
|
||||
struct usb_device *dev, int endpoint_type,
|
||||
unsigned long pipe, void *buffer, int len,
|
||||
struct devrequest *setup, int interval);
|
||||
|
||||
int usb_urb_submit(struct usb_hcd *hcd, struct urb *urb);
|
||||
|
||||
#endif /* __USB_COMPAT_H__ */
|
@ -81,6 +81,32 @@
|
||||
#define EndpointOutRequest \
|
||||
((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8)
|
||||
|
||||
/* class requests from the USB 2.0 hub spec, table 11-15 */
|
||||
#define HUB_CLASS_REQ(dir, type, request) ((((dir) | (type)) << 8) | (request))
|
||||
/* GetBusState and SetHubDescriptor are optional, omitted */
|
||||
#define ClearHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, \
|
||||
USB_REQ_CLEAR_FEATURE)
|
||||
#define ClearPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
|
||||
USB_REQ_CLEAR_FEATURE)
|
||||
#define GetHubDescriptor HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, \
|
||||
USB_REQ_GET_DESCRIPTOR)
|
||||
#define GetHubStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_HUB, \
|
||||
USB_REQ_GET_STATUS)
|
||||
#define GetPortStatus HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, \
|
||||
USB_REQ_GET_STATUS)
|
||||
#define SetHubFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_HUB, \
|
||||
USB_REQ_SET_FEATURE)
|
||||
#define SetPortFeature HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
|
||||
USB_REQ_SET_FEATURE)
|
||||
#define ClearTTBuffer HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
|
||||
HUB_CLEAR_TT_BUFFER)
|
||||
#define ResetTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
|
||||
HUB_RESET_TT)
|
||||
#define GetTTState HUB_CLASS_REQ(USB_DIR_IN, USB_RT_PORT, \
|
||||
HUB_GET_TT_STATE)
|
||||
#define StopTT HUB_CLASS_REQ(USB_DIR_OUT, USB_RT_PORT, \
|
||||
HUB_STOP_TT)
|
||||
|
||||
/* Descriptor types */
|
||||
#define USB_DT_DEVICE 0x01
|
||||
#define USB_DT_CONFIG 0x02
|
||||
@ -289,10 +315,16 @@
|
||||
#define USB_SS_PORT_STAT_C_CONFIG_ERROR 0x0080
|
||||
|
||||
/* wHubCharacteristics (masks) */
|
||||
#define HUB_CHAR_COMMON_OCPM 0x0000 /* All ports Over-Current reporting */
|
||||
#define HUB_CHAR_INDV_PORT_LPSM 0x0001 /* per-port power control */
|
||||
#define HUB_CHAR_NO_LPSM 0x0002 /* no power switching */
|
||||
#define HUB_CHAR_LPSM 0x0003
|
||||
#define HUB_CHAR_COMPOUND 0x0004
|
||||
#define HUB_CHAR_INDV_PORT_OCPM 0x0008 /* per-port Over-current reporting */
|
||||
#define HUB_CHAR_NO_OCPM 0x0010 /* No Over-current Protection support */
|
||||
#define HUB_CHAR_OCPM 0x0018
|
||||
#define HUB_CHAR_TTTT 0x0060 /* TT Think Time mask */
|
||||
#define HUB_CHAR_PORTIND 0x0080 /* per-port indicators (LEDs) */
|
||||
|
||||
/*
|
||||
* Hub Status & Hub Change bit masks
|
||||
|
Loading…
Reference in New Issue
Block a user