summaryrefslogtreecommitdiff
path: root/drivers/usb/isp1760/isp1760-udc.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2021-07-05 14:16:22 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2021-07-05 14:16:22 -0700
commit79160a603bdb51916226caf4a6616cc4e1c58a58 (patch)
tree6aa2dd8ce76799921ba56eace1c0262ab947f115 /drivers/usb/isp1760/isp1760-udc.c
parentc932ed0adb09a7fa6d6649ee04dd78c83ab07ada (diff)
parent7756f1d6369e61d1cc47d6e51619d1e1d1681a2e (diff)
Merge tag 'usb-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB / Thunderbolt updates from Greg KH: "Here is the big set of USB and Thunderbolt patches for 5.14-rc1. Nothing major here just lots of little changes for new hardware and features. Highlights are: - more USB 4 support added to the thunderbolt core - build warning fixes all over the place - usb-serial driver updates and new device support - mtu3 driver updates - gadget driver updates - dwc3 driver updates - dwc2 driver updates - isp1760 host driver updates - musb driver updates - lots of other tiny things. Full details are in the shortlog. All of these have been in linux-next for a while now with no reported issues" * tag 'usb-5.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (223 commits) phy: qcom-qusb2: Add configuration for SM4250 and SM6115 dt-bindings: phy: qcom,qusb2: document sm4250/6115 compatible dt-bindings: usb: qcom,dwc3: Add bindings for sm6115/4250 USB: cdc-acm: blacklist Heimann USB Appset device usb: xhci-mtk: allow multiple Start-Split in a microframe usb: ftdi-elan: remove redundant continue statement in a while-loop usb: class: cdc-wdm: return the correct errno code xhci: remove redundant continue statement usb: dwc3: Fix debugfs creation flow usb: gadget: hid: fix error return code in hid_bind() usb: gadget: eem: fix echo command packet response issue usb: gadget: f_hid: fix endianness issue with descriptors Revert "USB: misc: Add onboard_usb_hub driver" Revert "of/platform: Add stubs for of_platform_device_create/destroy()" Revert "usb: host: xhci-plat: Create platform device for onboard hubs in probe()" Revert "arm64: dts: qcom: sc7180-trogdor: Add nodes for onboard USB hub" xhci: solve a double free problem while doing s4 xhci: handle failed buffer copy to URB sg list and fix a W=1 copiler warning xhci: Add adaptive interrupt rate for isoch TRBs with XHCI_AVOID_BEI quirk xhci: Remove unused defines for ERST_SIZE and ERST_ENTRIES ...
Diffstat (limited to 'drivers/usb/isp1760/isp1760-udc.c')
-rw-r--r--drivers/usb/isp1760/isp1760-udc.c251
1 files changed, 173 insertions, 78 deletions
diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c
index 1714b2258b54..a78da59d6417 100644
--- a/drivers/usb/isp1760/isp1760-udc.c
+++ b/drivers/usb/isp1760/isp1760-udc.c
@@ -2,10 +2,12 @@
/*
* Driver for the NXP ISP1761 device controller
*
+ * Copyright 2021 Linaro, Rui Miguel Silva
* Copyright 2014 Ideas on Board Oy
*
* Contacts:
* Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ * Rui Miguel Silva <rui.silva@linaro.org>
*/
#include <linux/interrupt.h>
@@ -45,16 +47,62 @@ static inline struct isp1760_request *req_to_udc_req(struct usb_request *req)
return container_of(req, struct isp1760_request, req);
}
-static inline u32 isp1760_udc_read(struct isp1760_udc *udc, u16 reg)
+static u32 isp1760_udc_read(struct isp1760_udc *udc, u16 field)
{
- return isp1760_read32(udc->regs, reg);
+ return isp1760_field_read(udc->fields, field);
}
-static inline void isp1760_udc_write(struct isp1760_udc *udc, u16 reg, u32 val)
+static void isp1760_udc_write(struct isp1760_udc *udc, u16 field, u32 val)
{
- isp1760_write32(udc->regs, reg, val);
+ isp1760_field_write(udc->fields, field, val);
}
+static u32 isp1760_udc_read_raw(struct isp1760_udc *udc, u16 reg)
+{
+ __le32 val;
+
+ regmap_raw_read(udc->regs, reg, &val, 4);
+
+ return le32_to_cpu(val);
+}
+
+static u16 isp1760_udc_read_raw16(struct isp1760_udc *udc, u16 reg)
+{
+ __le16 val;
+
+ regmap_raw_read(udc->regs, reg, &val, 2);
+
+ return le16_to_cpu(val);
+}
+
+static void isp1760_udc_write_raw(struct isp1760_udc *udc, u16 reg, u32 val)
+{
+ __le32 val_le = cpu_to_le32(val);
+
+ regmap_raw_write(udc->regs, reg, &val_le, 4);
+}
+
+static void isp1760_udc_write_raw16(struct isp1760_udc *udc, u16 reg, u16 val)
+{
+ __le16 val_le = cpu_to_le16(val);
+
+ regmap_raw_write(udc->regs, reg, &val_le, 2);
+}
+
+static void isp1760_udc_set(struct isp1760_udc *udc, u32 field)
+{
+ isp1760_udc_write(udc, field, 0xFFFFFFFF);
+}
+
+static void isp1760_udc_clear(struct isp1760_udc *udc, u32 field)
+{
+ isp1760_udc_write(udc, field, 0);
+}
+
+static bool isp1760_udc_is_set(struct isp1760_udc *udc, u32 field)
+{
+ return !!isp1760_udc_read(udc, field);
+}
/* -----------------------------------------------------------------------------
* Endpoint Management
*/
@@ -75,16 +123,21 @@ static struct isp1760_ep *isp1760_udc_find_ep(struct isp1760_udc *udc,
return NULL;
}
-static void __isp1760_udc_select_ep(struct isp1760_ep *ep, int dir)
+static void __isp1760_udc_select_ep(struct isp1760_udc *udc,
+ struct isp1760_ep *ep, int dir)
{
- isp1760_udc_write(ep->udc, DC_EPINDEX,
- DC_ENDPIDX(ep->addr & USB_ENDPOINT_NUMBER_MASK) |
- (dir == USB_DIR_IN ? DC_EPDIR : 0));
+ isp1760_udc_write(udc, DC_ENDPIDX, ep->addr & USB_ENDPOINT_NUMBER_MASK);
+
+ if (dir == USB_DIR_IN)
+ isp1760_udc_set(udc, DC_EPDIR);
+ else
+ isp1760_udc_clear(udc, DC_EPDIR);
}
/**
* isp1760_udc_select_ep - Select an endpoint for register access
* @ep: The endpoint
+ * @udc: Reference to the device controller
*
* The ISP1761 endpoint registers are banked. This function selects the target
* endpoint for banked register access. The selection remains valid until the
@@ -93,9 +146,10 @@ static void __isp1760_udc_select_ep(struct isp1760_ep *ep, int dir)
*
* Called with the UDC spinlock held.
*/
-static void isp1760_udc_select_ep(struct isp1760_ep *ep)
+static void isp1760_udc_select_ep(struct isp1760_udc *udc,
+ struct isp1760_ep *ep)
{
- __isp1760_udc_select_ep(ep, ep->addr & USB_ENDPOINT_DIR_MASK);
+ __isp1760_udc_select_ep(udc, ep, ep->addr & USB_ENDPOINT_DIR_MASK);
}
/* Called with the UDC spinlock held. */
@@ -108,9 +162,13 @@ static void isp1760_udc_ctrl_send_status(struct isp1760_ep *ep, int dir)
* the direction opposite to the data stage data packets, we thus need
* to select the OUT/IN endpoint for IN/OUT transfers.
*/
- isp1760_udc_write(udc, DC_EPINDEX, DC_ENDPIDX(0) |
- (dir == USB_DIR_IN ? 0 : DC_EPDIR));
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_STATUS);
+ if (dir == USB_DIR_IN)
+ isp1760_udc_clear(udc, DC_EPDIR);
+ else
+ isp1760_udc_set(udc, DC_EPDIR);
+
+ isp1760_udc_write(udc, DC_ENDPIDX, 1);
+ isp1760_udc_set(udc, DC_STATUS);
/*
* The hardware will terminate the request automatically and go back to
@@ -157,10 +215,10 @@ static void isp1760_udc_ctrl_send_stall(struct isp1760_ep *ep)
spin_lock_irqsave(&udc->lock, flags);
/* Stall both the IN and OUT endpoints. */
- __isp1760_udc_select_ep(ep, USB_DIR_OUT);
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_STALL);
- __isp1760_udc_select_ep(ep, USB_DIR_IN);
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_STALL);
+ __isp1760_udc_select_ep(udc, ep, USB_DIR_OUT);
+ isp1760_udc_set(udc, DC_STALL);
+ __isp1760_udc_select_ep(udc, ep, USB_DIR_IN);
+ isp1760_udc_set(udc, DC_STALL);
/* A protocol stall completes the control transaction. */
udc->ep0_state = ISP1760_CTRL_SETUP;
@@ -181,8 +239,8 @@ static bool isp1760_udc_receive(struct isp1760_ep *ep,
u32 *buf;
int i;
- isp1760_udc_select_ep(ep);
- len = isp1760_udc_read(udc, DC_BUFLEN) & DC_DATACOUNT_MASK;
+ isp1760_udc_select_ep(udc, ep);
+ len = isp1760_udc_read(udc, DC_BUFLEN);
dev_dbg(udc->isp->dev, "%s: received %u bytes (%u/%u done)\n",
__func__, len, req->req.actual, req->req.length);
@@ -198,7 +256,7 @@ static bool isp1760_udc_receive(struct isp1760_ep *ep,
* datasheet doesn't clearly document how this should be
* handled.
*/
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF);
+ isp1760_udc_set(udc, DC_CLBUF);
return false;
}
@@ -209,9 +267,9 @@ static bool isp1760_udc_receive(struct isp1760_ep *ep,
* the next packet might be removed from the FIFO.
*/
for (i = len; i > 2; i -= 4, ++buf)
- *buf = le32_to_cpu(isp1760_udc_read(udc, DC_DATAPORT));
+ *buf = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT);
if (i > 0)
- *(u16 *)buf = le16_to_cpu(readw(udc->regs + DC_DATAPORT));
+ *(u16 *)buf = isp1760_udc_read_raw16(udc, ISP176x_DC_DATAPORT);
req->req.actual += len;
@@ -253,7 +311,7 @@ static void isp1760_udc_transmit(struct isp1760_ep *ep,
__func__, req->packet_size, req->req.actual,
req->req.length);
- __isp1760_udc_select_ep(ep, USB_DIR_IN);
+ __isp1760_udc_select_ep(udc, ep, USB_DIR_IN);
if (req->packet_size)
isp1760_udc_write(udc, DC_BUFLEN, req->packet_size);
@@ -265,14 +323,14 @@ static void isp1760_udc_transmit(struct isp1760_ep *ep,
* the FIFO for this kind of conditions, but doesn't seem to work.
*/
for (i = req->packet_size; i > 2; i -= 4, ++buf)
- isp1760_udc_write(udc, DC_DATAPORT, cpu_to_le32(*buf));
+ isp1760_udc_write_raw(udc, ISP176x_DC_DATAPORT, *buf);
if (i > 0)
- writew(cpu_to_le16(*(u16 *)buf), udc->regs + DC_DATAPORT);
+ isp1760_udc_write_raw16(udc, ISP176x_DC_DATAPORT, *(u16 *)buf);
if (ep->addr == 0)
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN);
+ isp1760_udc_set(udc, DC_DSEN);
if (!req->packet_size)
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_VENDP);
+ isp1760_udc_set(udc, DC_VENDP);
}
static void isp1760_ep_rx_ready(struct isp1760_ep *ep)
@@ -408,19 +466,24 @@ static int __isp1760_udc_set_halt(struct isp1760_ep *ep, bool halt)
return -EINVAL;
}
- isp1760_udc_select_ep(ep);
- isp1760_udc_write(udc, DC_CTRLFUNC, halt ? DC_STALL : 0);
+ isp1760_udc_select_ep(udc, ep);
+
+ if (halt)
+ isp1760_udc_set(udc, DC_STALL);
+ else
+ isp1760_udc_clear(udc, DC_STALL);
if (ep->addr == 0) {
/* When halting the control endpoint, stall both IN and OUT. */
- __isp1760_udc_select_ep(ep, USB_DIR_IN);
- isp1760_udc_write(udc, DC_CTRLFUNC, halt ? DC_STALL : 0);
+ __isp1760_udc_select_ep(udc, ep, USB_DIR_IN);
+ if (halt)
+ isp1760_udc_set(udc, DC_STALL);
+ else
+ isp1760_udc_clear(udc, DC_STALL);
} else if (!halt) {
/* Reset the data PID by cycling the endpoint enable bit. */
- u16 eptype = isp1760_udc_read(udc, DC_EPTYPE);
-
- isp1760_udc_write(udc, DC_EPTYPE, eptype & ~DC_EPENABLE);
- isp1760_udc_write(udc, DC_EPTYPE, eptype);
+ isp1760_udc_clear(udc, DC_EPENABLE);
+ isp1760_udc_set(udc, DC_EPENABLE);
/*
* Disabling the endpoint emptied the transmit FIFO, fill it
@@ -479,12 +542,14 @@ static int isp1760_udc_get_status(struct isp1760_udc *udc,
return -EINVAL;
}
- isp1760_udc_write(udc, DC_EPINDEX, DC_ENDPIDX(0) | DC_EPDIR);
+ isp1760_udc_set(udc, DC_EPDIR);
+ isp1760_udc_write(udc, DC_ENDPIDX, 1);
+
isp1760_udc_write(udc, DC_BUFLEN, 2);
- writew(cpu_to_le16(status), udc->regs + DC_DATAPORT);
+ isp1760_udc_write_raw16(udc, ISP176x_DC_DATAPORT, status);
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN);
+ isp1760_udc_set(udc, DC_DSEN);
dev_dbg(udc->isp->dev, "%s: status 0x%04x\n", __func__, status);
@@ -508,7 +573,8 @@ static int isp1760_udc_set_address(struct isp1760_udc *udc, u16 addr)
usb_gadget_set_state(&udc->gadget, addr ? USB_STATE_ADDRESS :
USB_STATE_DEFAULT);
- isp1760_udc_write(udc, DC_ADDRESS, DC_DEVEN | addr);
+ isp1760_udc_write(udc, DC_DEVADDR, addr);
+ isp1760_udc_set(udc, DC_DEVEN);
spin_lock(&udc->lock);
isp1760_udc_ctrl_send_status(&udc->ep[0], USB_DIR_OUT);
@@ -650,9 +716,9 @@ static void isp1760_ep0_setup(struct isp1760_udc *udc)
spin_lock(&udc->lock);
- isp1760_udc_write(udc, DC_EPINDEX, DC_EP0SETUP);
+ isp1760_udc_set(udc, DC_EP0SETUP);
- count = isp1760_udc_read(udc, DC_BUFLEN) & DC_DATACOUNT_MASK;
+ count = isp1760_udc_read(udc, DC_BUFLEN);
if (count != sizeof(req)) {
spin_unlock(&udc->lock);
@@ -663,8 +729,8 @@ static void isp1760_ep0_setup(struct isp1760_udc *udc)
return;
}
- req.data[0] = isp1760_udc_read(udc, DC_DATAPORT);
- req.data[1] = isp1760_udc_read(udc, DC_DATAPORT);
+ req.data[0] = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT);
+ req.data[1] = isp1760_udc_read_raw(udc, ISP176x_DC_DATAPORT);
if (udc->ep0_state != ISP1760_CTRL_SETUP) {
spin_unlock(&udc->lock);
@@ -732,13 +798,13 @@ static int isp1760_ep_enable(struct usb_ep *ep,
switch (usb_endpoint_type(desc)) {
case USB_ENDPOINT_XFER_ISOC:
- type = DC_ENDPTYP_ISOC;
+ type = ISP176x_DC_ENDPTYP_ISOC;
break;
case USB_ENDPOINT_XFER_BULK:
- type = DC_ENDPTYP_BULK;
+ type = ISP176x_DC_ENDPTYP_BULK;
break;
case USB_ENDPOINT_XFER_INT:
- type = DC_ENDPTYP_INTERRUPT;
+ type = ISP176x_DC_ENDPTYP_INTERRUPT;
break;
case USB_ENDPOINT_XFER_CONTROL:
default:
@@ -755,10 +821,13 @@ static int isp1760_ep_enable(struct usb_ep *ep,
uep->halted = false;
uep->wedged = false;
- isp1760_udc_select_ep(uep);
- isp1760_udc_write(udc, DC_EPMAXPKTSZ, uep->maxpacket);
+ isp1760_udc_select_ep(udc, uep);
+
+ isp1760_udc_write(udc, DC_FFOSZ, uep->maxpacket);
isp1760_udc_write(udc, DC_BUFLEN, uep->maxpacket);
- isp1760_udc_write(udc, DC_EPTYPE, DC_EPENABLE | type);
+
+ isp1760_udc_write(udc, DC_ENDPTYP, type);
+ isp1760_udc_set(udc, DC_EPENABLE);
spin_unlock_irqrestore(&udc->lock, flags);
@@ -786,8 +855,9 @@ static int isp1760_ep_disable(struct usb_ep *ep)
uep->desc = NULL;
uep->maxpacket = 0;
- isp1760_udc_select_ep(uep);
- isp1760_udc_write(udc, DC_EPTYPE, 0);
+ isp1760_udc_select_ep(udc, uep);
+ isp1760_udc_clear(udc, DC_EPENABLE);
+ isp1760_udc_clear(udc, DC_ENDPTYP);
/* TODO Synchronize with the IRQ handler */
@@ -864,8 +934,8 @@ static int isp1760_ep_queue(struct usb_ep *ep, struct usb_request *_req,
case ISP1760_CTRL_DATA_OUT:
list_add_tail(&req->queue, &uep->queue);
- __isp1760_udc_select_ep(uep, USB_DIR_OUT);
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_DSEN);
+ __isp1760_udc_select_ep(udc, uep, USB_DIR_OUT);
+ isp1760_udc_set(udc, DC_DSEN);
break;
case ISP1760_CTRL_STATUS:
@@ -1025,14 +1095,14 @@ static void isp1760_ep_fifo_flush(struct usb_ep *ep)
spin_lock_irqsave(&udc->lock, flags);
- isp1760_udc_select_ep(uep);
+ isp1760_udc_select_ep(udc, uep);
/*
* Set the CLBUF bit twice to flush both buffers in case double
* buffering is enabled.
*/
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF);
- isp1760_udc_write(udc, DC_CTRLFUNC, DC_CLBUF);
+ isp1760_udc_set(udc, DC_CLBUF);
+ isp1760_udc_set(udc, DC_CLBUF);
spin_unlock_irqrestore(&udc->lock, flags);
}
@@ -1082,6 +1152,10 @@ static void isp1760_udc_disconnect(struct isp1760_udc *udc)
static void isp1760_udc_init_hw(struct isp1760_udc *udc)
{
+ u32 intconf = udc->is_isp1763 ? ISP1763_DC_INTCONF : ISP176x_DC_INTCONF;
+ u32 intena = udc->is_isp1763 ? ISP1763_DC_INTENABLE :
+ ISP176x_DC_INTENABLE;
+
/*
* The device controller currently shares its interrupt with the host
* controller, the DC_IRQ polarity and signaling mode are ignored. Set
@@ -1091,19 +1165,22 @@ static void isp1760_udc_init_hw(struct isp1760_udc *udc)
* ACK tokens only (and NYET for the out pipe). The default
* configuration also generates an interrupt on the first NACK token.
*/
- isp1760_udc_write(udc, DC_INTCONF, DC_CDBGMOD_ACK | DC_DDBGMODIN_ACK |
- DC_DDBGMODOUT_ACK_NYET);
-
- isp1760_udc_write(udc, 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_IERESM | DC_IESUSP |
- DC_IEHS_STA | DC_IEBRST);
+ isp1760_reg_write(udc->regs, intconf,
+ ISP176x_DC_CDBGMOD_ACK | ISP176x_DC_DDBGMODIN_ACK |
+ ISP176x_DC_DDBGMODOUT_ACK);
+
+ isp1760_reg_write(udc->regs, intena, DC_IEPRXTX(7) |
+ DC_IEPRXTX(6) | DC_IEPRXTX(5) | DC_IEPRXTX(4) |
+ DC_IEPRXTX(3) | DC_IEPRXTX(2) | DC_IEPRXTX(1) |
+ DC_IEPRXTX(0) | ISP176x_DC_IEP0SETUP |
+ ISP176x_DC_IEVBUS | ISP176x_DC_IERESM |
+ ISP176x_DC_IESUSP | ISP176x_DC_IEHS_STA |
+ ISP176x_DC_IEBRST);
if (udc->connected)
isp1760_set_pullup(udc->isp, true);
- isp1760_udc_write(udc, DC_ADDRESS, DC_DEVEN);
+ isp1760_udc_set(udc, DC_DEVEN);
}
static void isp1760_udc_reset(struct isp1760_udc *udc)
@@ -1152,7 +1229,7 @@ static int isp1760_udc_get_frame(struct usb_gadget *gadget)
{
struct isp1760_udc *udc = gadget_to_udc(gadget);
- return isp1760_udc_read(udc, DC_FRAMENUM) & ((1 << 11) - 1);
+ return isp1760_udc_read(udc, DC_FRAMENUM);
}
static int isp1760_udc_wakeup(struct usb_gadget *gadget)
@@ -1219,7 +1296,7 @@ static int isp1760_udc_start(struct usb_gadget *gadget,
usb_gadget_set_state(&udc->gadget, USB_STATE_ATTACHED);
/* DMA isn't supported yet, don't enable the DMA clock. */
- isp1760_udc_write(udc, DC_MODE, DC_GLINTENA);
+ isp1760_udc_set(udc, DC_GLINTENA);
isp1760_udc_init_hw(udc);
@@ -1232,13 +1309,14 @@ static int isp1760_udc_start(struct usb_gadget *gadget,
static int isp1760_udc_stop(struct usb_gadget *gadget)
{
struct isp1760_udc *udc = gadget_to_udc(gadget);
+ u32 mode_reg = udc->is_isp1763 ? ISP1763_DC_MODE : ISP176x_DC_MODE;
unsigned long flags;
dev_dbg(udc->isp->dev, "%s\n", __func__);
del_timer_sync(&udc->vbus_timer);
- isp1760_udc_write(udc, DC_MODE, 0);
+ isp1760_reg_write(udc->regs, mode_reg, 0);
spin_lock_irqsave(&udc->lock, flags);
udc->driver = NULL;
@@ -1260,15 +1338,30 @@ static const struct usb_gadget_ops isp1760_udc_ops = {
* Interrupt Handling
*/
+static u32 isp1760_udc_irq_get_status(struct isp1760_udc *udc)
+{
+ u32 status;
+
+ if (udc->is_isp1763) {
+ status = isp1760_reg_read(udc->regs, ISP1763_DC_INTERRUPT)
+ & isp1760_reg_read(udc->regs, ISP1763_DC_INTENABLE);
+ isp1760_reg_write(udc->regs, ISP1763_DC_INTERRUPT, status);
+ } else {
+ status = isp1760_reg_read(udc->regs, ISP176x_DC_INTERRUPT)
+ & isp1760_reg_read(udc->regs, ISP176x_DC_INTENABLE);
+ isp1760_reg_write(udc->regs, ISP176x_DC_INTERRUPT, status);
+ }
+
+ return status;
+}
+
static irqreturn_t isp1760_udc_irq(int irq, void *dev)
{
struct isp1760_udc *udc = dev;
unsigned int i;
u32 status;
- status = isp1760_udc_read(udc, DC_INTERRUPT)
- & isp1760_udc_read(udc, DC_INTENABLE);
- isp1760_udc_write(udc, DC_INTERRUPT, status);
+ status = isp1760_udc_irq_get_status(udc);
if (status & DC_IEVBUS) {
dev_dbg(udc->isp->dev, "%s(VBUS)\n", __func__);
@@ -1313,7 +1406,7 @@ static irqreturn_t isp1760_udc_irq(int irq, void *dev)
dev_dbg(udc->isp->dev, "%s(SUSP)\n", __func__);
spin_lock(&udc->lock);
- if (!(isp1760_udc_read(udc, DC_MODE) & DC_VBUSSTAT))
+ if (!isp1760_udc_is_set(udc, DC_VBUSSTAT))
isp1760_udc_disconnect(udc);
else
isp1760_udc_suspend(udc);
@@ -1335,7 +1428,7 @@ static void isp1760_udc_vbus_poll(struct timer_list *t)
spin_lock_irqsave(&udc->lock, flags);
- if (!(isp1760_udc_read(udc, DC_MODE) & DC_VBUSSTAT))
+ if (!(isp1760_udc_is_set(udc, DC_VBUSSTAT)))
isp1760_udc_disconnect(udc);
else if (udc->gadget.state >= USB_STATE_POWERED)
mod_timer(&udc->vbus_timer,
@@ -1403,6 +1496,7 @@ static void isp1760_udc_init_eps(struct isp1760_udc *udc)
static int isp1760_udc_init(struct isp1760_udc *udc)
{
+ u32 mode_reg = udc->is_isp1763 ? ISP1763_DC_MODE : ISP176x_DC_MODE;
u16 scratch;
u32 chipid;
@@ -1413,7 +1507,8 @@ static int isp1760_udc_init(struct isp1760_udc *udc)
* and scratch register contents must match the expected values.
*/
isp1760_udc_write(udc, DC_SCRATCH, 0xbabe);
- chipid = isp1760_udc_read(udc, DC_CHIPID);
+ chipid = isp1760_udc_read(udc, DC_CHIP_ID_HIGH) << 16;
+ chipid |= isp1760_udc_read(udc, DC_CHIP_ID_LOW);
scratch = isp1760_udc_read(udc, DC_SCRATCH);
if (scratch != 0xbabe) {
@@ -1423,15 +1518,16 @@ static int isp1760_udc_init(struct isp1760_udc *udc)
return -ENODEV;
}
- if (chipid != 0x00011582 && chipid != 0x00158210) {
+ if (chipid != 0x00011582 && chipid != 0x00158210 &&
+ chipid != 0x00176320) {
dev_err(udc->isp->dev, "udc: invalid chip ID 0x%08x\n", chipid);
return -ENODEV;
}
/* Reset the device controller. */
- isp1760_udc_write(udc, DC_MODE, DC_SFRESET);
+ isp1760_udc_set(udc, DC_SFRESET);
usleep_range(10000, 11000);
- isp1760_udc_write(udc, DC_MODE, 0);
+ isp1760_reg_write(udc->regs, mode_reg, 0);
usleep_range(10000, 11000);
return 0;
@@ -1445,7 +1541,6 @@ int isp1760_udc_register(struct isp1760_device *isp, int irq,
udc->irq = -1;
udc->isp = isp;
- udc->regs = isp->regs;
spin_lock_init(&udc->lock);
timer_setup(&udc->vbus_timer, isp1760_udc_vbus_poll, 0);