[U-Boot] [PATCH v3 3/4] drivers: musb-new: Add USB DRC driver for Microchip PIC32 OTG controller.

Marek Vasut marex at denx.de
Tue Mar 15 19:19:37 CET 2016


On 03/15/2016 01:44 PM, Purna Chandra Mandal wrote:
> This driver adds support of PIC32 MUSB OTG controller as dual role device.
> It implements platform specific glue to reuse musb core.
> 
> Signed-off-by: Cristian Birsan <cristian.birsan at microchip.com>
> Signed-off-by: Purna Chandra Mandal <purna.mandal at microchip.com>

[...]

> diff --git a/drivers/usb/musb-new/pic32.c b/drivers/usb/musb-new/pic32.c
> new file mode 100644
> index 0000000..980a971
> --- /dev/null
> +++ b/drivers/usb/musb-new/pic32.c
> @@ -0,0 +1,294 @@
> +/*
> + * Microchip PIC32 MUSB "glue layer"
> + *
> + * Copyright (C) 2015, Microchip Technology Inc.
> + *  Cristian Birsan <cristian.birsan at microchip.com>
> + *  Purna Chandra Mandal <purna.mandal at microchip.com>
> + *
> + * SPDX-License-Identifier:     GPL-2.0+
> + *
> + * Based on the dsps "glue layer" code.
> + */
> +
> +#include <common.h>
> +#include <linux/usb/musb.h>
> +#include "linux-compat.h"
> +#include "musb_core.h"
> +#include "musb_uboot.h"
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +#define PIC32_TX_EP_MASK	0x0f		/* EP0 + 7 Tx EPs */
> +#define PIC32_RX_EP_MASK	0x0e		/* 7 Rx EPs */
> +
> +#define MUSB_SOFTRST		0x7f
> +#define  MUSB_SOFTRST_NRST	BIT(0)
> +#define  MUSB_SOFTRST_NRSTX	BIT(1)
> +
> +#define USBCRCON		0
> +#define  USBCRCON_USBWKUPEN	BIT(0)  /* Enable Wakeup Interrupt */
> +#define  USBCRCON_USBRIE	BIT(1)  /* Enable Remote resume Interrupt */
> +#define  USBCRCON_USBIE		BIT(2)  /* Enable USB General interrupt */
> +#define  USBCRCON_SENDMONEN	BIT(3)  /* Enable Session End VBUS monitoring */
> +#define  USBCRCON_BSVALMONEN	BIT(4)  /* Enable B-Device VBUS monitoring */
> +#define  USBCRCON_ASVALMONEN	BIT(5)  /* Enable A-Device VBUS monitoring */
> +#define  USBCRCON_VBUSMONEN	BIT(6)  /* Enable VBUS monitoring */
> +#define  USBCRCON_PHYIDEN	BIT(7)  /* PHY ID monitoring enable */
> +#define  USBCRCON_USBIDVAL	BIT(8)  /* USB ID value */
> +#define  USBCRCON_USBIDOVEN	BIT(9)  /* USB ID override enable */
> +#define  USBCRCON_USBWK		BIT(24) /* USB Wakeup Status */
> +#define  USBCRCON_USBRF		BIT(25) /* USB Resume Status */
> +#define  USBCRCON_USBIF		BIT(26) /* USB General Interrupt Status */
> +
> +static void __iomem *musb_glue;

What would happen once you make a chip with two MUSB controllers ?

> +/* pic32_musb_disable - disable HDRC */
> +static void pic32_musb_disable(struct musb *musb)
> +{

Is there no way to shut down the MUSB on the PIC32 ?

> +}
> +
> +/* pic32_musb_enable - enable HDRC */
> +static int pic32_musb_enable(struct musb *musb)
> +{
> +	/* soft reset by NRSTx */
> +	musb_writeb(musb->mregs, MUSB_SOFTRST, MUSB_SOFTRST_NRSTX);
> +	/* set mode */
> +	musb_platform_set_mode(musb, musb->board_mode);
> +
> +	return 0;
> +}
> +
> +static irqreturn_t pic32_interrupt(int irq, void *hci)
> +{
> +	struct musb  *musb = hci;
> +	irqreturn_t ret = IRQ_NONE;
> +	u32 epintr, usbintr;
> +
> +	/* Get usb core interrupts */

You mean "get" or "ack" here ?

> +	musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
> +	if (musb->int_usb)
> +		musb_writeb(musb->mregs, MUSB_INTRUSB, musb->int_usb);
> +
> +	/* Get endpoint interrupts */

DTTO

> +	musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX) & PIC32_RX_EP_MASK;
> +	if (musb->int_rx)
> +		musb_writew(musb->mregs, MUSB_INTRRX, musb->int_rx);

Same here

> +	musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX) & PIC32_TX_EP_MASK;
> +	if (musb->int_tx)
> +		musb_writew(musb->mregs, MUSB_INTRTX, musb->int_tx);
> +
> +	/* Drop spurious RX and TX if device is disconnected */
> +	if (musb->int_usb & MUSB_INTR_DISCONNECT) {
> +		musb->int_tx = 0;
> +		musb->int_rx = 0;
> +	}
> +
> +	if (musb->int_tx || musb->int_rx || musb->int_usb)
> +		ret |= musb_interrupt(musb);
> +
> +	return ret;
> +}
> +
> +static int pic32_musb_set_mode(struct musb *musb, u8 mode)
> +{
> +	struct device *dev = musb->controller;
> +
> +	switch (mode) {
> +	case MUSB_HOST:
> +		clrsetbits_le32(musb_glue + USBCRCON,
> +				USBCRCON_USBIDVAL, USBCRCON_USBIDOVEN);
> +		break;
> +	case MUSB_PERIPHERAL:
> +		setbits_le32(musb_glue + USBCRCON,
> +			     USBCRCON_USBIDVAL | USBCRCON_USBIDOVEN);
> +		break;
> +	case MUSB_OTG:
> +		dev_err(dev, "MUSB OTG mode enabled\n");

So having the core in OTG mode is an error ? Why ?

> +		break;
> +	default:
> +		dev_err(dev, "unsupported mode %d\n", mode);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +static int pic32_musb_init(struct musb *musb)
> +{
> +	u32 ctrl, hwvers;
> +	u8 power;
> +
> +	/* Returns zero if not clocked */
> +	hwvers = musb_read_hwvers(musb->mregs);
> +	if (!hwvers)
> +		return -ENODEV;
> +
> +	/* Reset the musb */
> +	power = musb_readb(musb->mregs, MUSB_POWER);
> +	power = power | MUSB_POWER_RESET;
> +	musb_writeb(musb->mregs, MUSB_POWER, power);
> +	mdelay(100);
> +
> +	/* Start the on-chip PHY and its PLL. */
> +	power = power & ~MUSB_POWER_RESET;
> +	musb_writeb(musb->mregs, MUSB_POWER, power);
> +
> +	musb->isr = pic32_interrupt;
> +
> +	ctrl =  USBCRCON_USBIF | USBCRCON_USBRF |
> +		USBCRCON_USBWK | USBCRCON_USBIDOVEN |
> +		USBCRCON_PHYIDEN | USBCRCON_USBIE |
> +		USBCRCON_USBRIE | USBCRCON_USBWKUPEN |
> +		USBCRCON_VBUSMONEN;
> +	writel(ctrl, musb_glue + USBCRCON);
> +
> +	return 0;
> +}
> +
> +/* PIC32 supports only 32bit read operation */
> +void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst)
> +{
> +	void __iomem *fifo = hw_ep->fifo;
> +	u32 val;
> +	int i;

This could become:
 bulk_len = len / 4;
 bulk_rem = len % 4;
 readsl(fifo, dst, bulk_len);
 if (rem) {
  dst += len & ~0x3;
  tmp = readl(fifo);
  copy the remaining bytes according to endianness
 }

This is 10 LoC , not 50 ;-)

> +	/* Read for 32bit-aligned destination address */
> +	if (likely((0x03 & (unsigned long)dst) == 0) && len >= 4) {
> +		readsl(fifo, dst, len / 4);
> +		dst += len & ~0x03;
> +		len &= 0x03;
> +	}
> +
> +	/*
> +	 * Now read the remaining 1 to 3 byte or complete length if
> +	 * unaligned address.
> +	 */
> +	if (len > 4) {
> +		for (i = 0; i < (len / 4); i++) {
> +			*(u32 *)dst = musb_readl(fifo, 0);
> +			dst += 4;
> +		}
> +		len &= 0x03;
> +	}
> +
> +	if (len > 0) {
> +		val = musb_readl(fifo, 0);
> +		memcpy(dst, &val, len);
> +	}
> +}

[...]

-- 
Best regards,
Marek Vasut


More information about the U-Boot mailing list