From: Rui Miguel Silva <rui.silva@linaro.org>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sebastian Siewior <bigeasy@linutronix.de>,
Laurent Pinchart <laurent.pinchart@ideasonboard.com>,
Rob Herring <robh+dt@kernel.org>
Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org,
Rui Miguel Silva <rui.silva@linaro.org>
Subject: [PATCH v4 9/9] usb: isp1763: add peripheral mode
Date: Thu, 13 May 2021 09:47:17 +0100 [thread overview]
Message-ID: <20210513084717.2487366-10-rui.silva@linaro.org> (raw)
In-Reply-To: <20210513084717.2487366-1-rui.silva@linaro.org>
Besides the already host mode support add peripheral mode support for
the isp1763 IP from the isp1760 family.
Signed-off-by: Rui Miguel Silva <rui.silva@linaro.org>
---
drivers/usb/isp1760/isp1760-core.c | 25 +++++++++++------
drivers/usb/isp1760/isp1760-regs.h | 42 ++++++++++++++++++++++++++++
drivers/usb/isp1760/isp1760-udc.c | 45 ++++++++++++++++++++++--------
drivers/usb/isp1760/isp1760-udc.h | 1 +
4 files changed, 94 insertions(+), 19 deletions(-)
diff --git a/drivers/usb/isp1760/isp1760-core.c b/drivers/usb/isp1760/isp1760-core.c
index 1d847f13abab..ff07e2890692 100644
--- a/drivers/usb/isp1760/isp1760-core.c
+++ b/drivers/usb/isp1760/isp1760-core.c
@@ -83,7 +83,8 @@ static int isp1760_init_core(struct isp1760_device *isp)
*
* TODO: Really support OTG. For now we configure port 1 in device mode
*/
- if ((isp->devflags & ISP1760_FLAG_ISP1761) &&
+ 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);
@@ -470,13 +471,15 @@ static const struct regmap_config isp1763_dc_regmap_conf = {
int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
struct device *dev, unsigned int devflags)
{
- bool udc_disabled = !(devflags & ISP1760_FLAG_ISP1761);
const struct regmap_config *hc_regmap;
const struct reg_field *hc_reg_fields;
+ const struct regmap_config *dc_regmap;
+ const struct reg_field *dc_reg_fields;
struct isp1760_device *isp;
struct isp1760_hcd *hcd;
struct isp1760_udc *udc;
struct regmap_field *f;
+ bool udc_enabled;
int ret;
int i;
@@ -484,8 +487,11 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
* If neither the HCD not the UDC is enabled return an error, as no
* device would be registered.
*/
+ udc_enabled = ((devflags & ISP1760_FLAG_ISP1763) ||
+ (devflags & ISP1760_FLAG_ISP1761));
+
if ((!IS_ENABLED(CONFIG_USB_ISP1760_HCD) || usb_disabled()) &&
- (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || udc_disabled))
+ (!IS_ENABLED(CONFIG_USB_ISP1761_UDC) || !udc_enabled))
return -ENODEV;
isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL);
@@ -498,6 +504,7 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
udc = &isp->udc;
hcd->is_isp1763 = !!(devflags & ISP1760_FLAG_ISP1763);
+ udc->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");
@@ -507,9 +514,13 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
if (hcd->is_isp1763) {
hc_regmap = &isp1763_hc_regmap_conf;
hc_reg_fields = &isp1763_hc_reg_fields[0];
+ dc_regmap = &isp1763_dc_regmap_conf;
+ dc_reg_fields = &isp1763_dc_reg_fields[0];
} else {
hc_regmap = &isp1760_hc_regmap_conf;
hc_reg_fields = &isp1760_hc_reg_fields[0];
+ dc_regmap = &isp1761_dc_regmap_conf;
+ dc_reg_fields = &isp1761_dc_reg_fields[0];
}
isp->rst_gpio = devm_gpiod_get_optional(dev, NULL, GPIOD_OUT_HIGH);
@@ -532,14 +543,12 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
hcd->fields[i] = f;
}
- udc->regs = devm_regmap_init_mmio(dev, hcd->base,
- &isp1761_dc_regmap_conf);
+ udc->regs = devm_regmap_init_mmio(dev, hcd->base, dc_regmap);
if (IS_ERR(udc->regs))
return PTR_ERR(udc->regs);
for (i = 0; i < DC_FIELD_MAX; i++) {
- f = devm_regmap_field_alloc(dev, udc->regs,
- isp1761_dc_reg_fields[i]);
+ f = devm_regmap_field_alloc(dev, udc->regs, dc_reg_fields[i]);
if (IS_ERR(f))
return PTR_ERR(f);
@@ -562,7 +571,7 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags,
return ret;
}
- if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && !udc_disabled) {
+ if (IS_ENABLED(CONFIG_USB_ISP1761_UDC) && udc_enabled) {
ret = isp1760_udc_register(isp, irq, irqflags);
if (ret < 0) {
isp1760_hcd_unregister(hcd);
diff --git a/drivers/usb/isp1760/isp1760-regs.h b/drivers/usb/isp1760/isp1760-regs.h
index 4f632cbbbd1f..94ea60c20b2a 100644
--- a/drivers/usb/isp1760/isp1760-regs.h
+++ b/drivers/usb/isp1760/isp1760-regs.h
@@ -243,8 +243,50 @@ enum isp176x_device_controller_fields {
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
diff --git a/drivers/usb/isp1760/isp1760-udc.c b/drivers/usb/isp1760/isp1760-udc.c
index 30efc9d32506..3e05e3605435 100644
--- a/drivers/usb/isp1760/isp1760-udc.c
+++ b/drivers/usb/isp1760/isp1760-udc.c
@@ -1151,6 +1151,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
@@ -1160,11 +1164,11 @@ 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_reg_write(udc->regs, ISP176x_DC_INTCONF,
+ isp1760_reg_write(udc->regs, intconf,
ISP176x_DC_CDBGMOD_ACK | ISP176x_DC_DDBGMODIN_ACK |
ISP176x_DC_DDBGMODOUT_ACK);
- isp1760_reg_write(udc->regs, ISP176x_DC_INTENABLE, DC_IEPRXTX(7) |
+ 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 |
@@ -1304,13 +1308,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_reg_write(udc->regs, ISP176x_DC_MODE, 0);
+ isp1760_reg_write(udc->regs, mode_reg, 0);
spin_lock_irqsave(&udc->lock, flags);
udc->driver = NULL;
@@ -1332,15 +1337,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_reg_read(udc->regs, ISP176x_DC_INTERRUPT)
- & isp1760_reg_read(udc->regs, ISP176x_DC_INTENABLE);
- isp1760_reg_write(udc->regs, ISP176x_DC_INTERRUPT, status);
+ status = isp1760_udc_irq_get_status(udc);
if (status & DC_IEVBUS) {
dev_dbg(udc->isp->dev, "%s(VBUS)\n", __func__);
@@ -1475,6 +1495,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;
@@ -1484,9 +1505,10 @@ static int isp1760_udc_init(struct isp1760_udc *udc)
* register, and reading the scratch register value back. The chip ID
* and scratch register contents must match the expected values.
*/
- isp1760_reg_write(udc->regs, ISP176x_DC_SCRATCH, 0xbabe);
- chipid = isp1760_reg_read(udc->regs, ISP176x_DC_CHIPID);
- scratch = isp1760_reg_read(udc->regs, ISP176x_DC_SCRATCH);
+ isp1760_udc_write(udc, DC_SCRATCH, 0xbabe);
+ 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) {
dev_err(udc->isp->dev,
@@ -1495,7 +1517,8 @@ 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;
}
@@ -1503,7 +1526,7 @@ static int isp1760_udc_init(struct isp1760_udc *udc)
/* Reset the device controller. */
isp1760_udc_set(udc, DC_SFRESET);
usleep_range(10000, 11000);
- isp1760_reg_write(udc->regs, ISP176x_DC_MODE, 0);
+ isp1760_reg_write(udc->regs, mode_reg, 0);
usleep_range(10000, 11000);
return 0;
diff --git a/drivers/usb/isp1760/isp1760-udc.h b/drivers/usb/isp1760/isp1760-udc.h
index f2ab5929cc9f..22044e86bc0e 100644
--- a/drivers/usb/isp1760/isp1760-udc.h
+++ b/drivers/usb/isp1760/isp1760-udc.h
@@ -84,6 +84,7 @@ struct isp1760_udc {
u16 ep0_length;
bool connected;
+ bool is_isp1763;
unsigned int devstatus;
};
--
2.31.1
next prev parent reply other threads:[~2021-05-13 8:48 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-13 8:47 [PATCH v4 0/9] usb: isp1760: extend support for isp1763 Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 1/9] usb: isp1760: fix strict typechecking Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 2/9] usb: isp1760: move to regmap for register access Rui Miguel Silva
2021-08-20 13:30 ` Dietmar Eggemann
2021-08-20 14:36 ` Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 3/9] usb: isp1760: use relaxed primitives Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 4/9] usb: isp1760: remove platform data struct and code Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 5/9] usb: isp1760: hcd: refactor mempool config and setup Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 6/9] usb: isp1760: use dr_mode binding Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 7/9] usb: isp1760: add support for isp1763 Rui Miguel Silva
2021-05-13 8:47 ` [PATCH v4 8/9] dt-bindings: usb: nxp,isp1760: add bindings Rui Miguel Silva
2021-05-18 1:08 ` Rob Herring
2021-05-13 8:47 ` Rui Miguel Silva [this message]
2021-06-06 22:52 ` [PATCH v4 0/9] usb: isp1760: extend support for isp1763 Laurent Pinchart
2021-06-07 8:42 ` Rui Miguel Silva
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210513084717.2487366-10-rui.silva@linaro.org \
--to=rui.silva@linaro.org \
--cc=bigeasy@linutronix.de \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=laurent.pinchart@ideasonboard.com \
--cc=linux-usb@vger.kernel.org \
--cc=robh+dt@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).