usb: musb: Add get/set toggle hooks

Add get/set toggle hooks in struct musb_io and struct musb_platform_ops
for special platform; remove function musb_save_toggle, use the set/get
callback to handle toggle.

Signed-off-by: Min Guo <min.guo@mediatek.com>
Signed-off-by: Bin Liu <b-liu@ti.com>
Link: https://lore.kernel.org/r/20200115132547.364-21-b-liu@ti.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Min Guo 2020-01-15 07:25:42 -06:00 committed by Greg Kroah-Hartman
parent 8d817d7934
commit fe3bbd6b38
4 changed files with 61 additions and 36 deletions

View file

@ -275,6 +275,38 @@ static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data)
__raw_writew(data, addr + offset); __raw_writew(data, addr + offset);
} }
static u16 musb_default_get_toggle(struct musb_qh *qh, int is_out)
{
void __iomem *epio = qh->hw_ep->regs;
u16 csr;
if (is_out)
csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
else
csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
return csr;
}
static u16 musb_default_set_toggle(struct musb_qh *qh, int is_out,
struct urb *urb)
{
u16 csr;
u16 toggle;
toggle = usb_gettoggle(urb->dev, qh->epnum, is_out);
if (is_out)
csr = toggle ? (MUSB_TXCSR_H_WR_DATATOGGLE
| MUSB_TXCSR_H_DATATOGGLE)
: MUSB_TXCSR_CLRDATATOG;
else
csr = toggle ? (MUSB_RXCSR_H_WR_DATATOGGLE
| MUSB_RXCSR_H_DATATOGGLE) : 0;
return csr;
}
/* /*
* Load an endpoint's FIFO * Load an endpoint's FIFO
*/ */
@ -2381,6 +2413,16 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
else else
musb->io.write_fifo = musb_default_write_fifo; musb->io.write_fifo = musb_default_write_fifo;
if (musb->ops->get_toggle)
musb->io.get_toggle = musb->ops->get_toggle;
else
musb->io.get_toggle = musb_default_get_toggle;
if (musb->ops->set_toggle)
musb->io.set_toggle = musb->ops->set_toggle;
else
musb->io.set_toggle = musb_default_set_toggle;
if (!musb->xceiv->io_ops) { if (!musb->xceiv->io_ops) {
musb->xceiv->io_dev = musb->controller; musb->xceiv->io_dev = musb->controller;
musb->xceiv->io_priv = musb->mregs; musb->xceiv->io_priv = musb->mregs;

View file

@ -27,6 +27,7 @@
struct musb; struct musb;
struct musb_hw_ep; struct musb_hw_ep;
struct musb_ep; struct musb_ep;
struct musb_qh;
/* Helper defines for struct musb->hwvers */ /* Helper defines for struct musb->hwvers */
#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f) #define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f)
@ -123,6 +124,8 @@ struct musb_io;
* @writew: write 16 bits * @writew: write 16 bits
* @read_fifo: reads the fifo * @read_fifo: reads the fifo
* @write_fifo: writes to fifo * @write_fifo: writes to fifo
* @get_toggle: platform specific get toggle function
* @set_toggle: platform specific set toggle function
* @dma_init: platform specific dma init function * @dma_init: platform specific dma init function
* @dma_exit: platform specific dma exit function * @dma_exit: platform specific dma exit function
* @init: turns on clocks, sets up platform-specific registers, etc * @init: turns on clocks, sets up platform-specific registers, etc
@ -167,6 +170,8 @@ struct musb_platform_ops {
void (*writew)(void __iomem *addr, unsigned offset, u16 data); void (*writew)(void __iomem *addr, unsigned offset, u16 data);
void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
u16 (*get_toggle)(struct musb_qh *qh, int is_out);
u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
struct dma_controller * struct dma_controller *
(*dma_init) (struct musb *musb, void __iomem *base); (*dma_init) (struct musb *musb, void __iomem *base);
void (*dma_exit)(struct dma_controller *c); void (*dma_exit)(struct dma_controller *c);

View file

@ -286,26 +286,6 @@ __acquires(musb->lock)
spin_lock(&musb->lock); spin_lock(&musb->lock);
} }
/* For bulk/interrupt endpoints only */
static inline void musb_save_toggle(struct musb_qh *qh, int is_in,
struct urb *urb)
{
void __iomem *epio = qh->hw_ep->regs;
u16 csr;
/*
* FIXME: the current Mentor DMA code seems to have
* problems getting toggle correct.
*/
if (is_in)
csr = musb_readw(epio, MUSB_RXCSR) & MUSB_RXCSR_H_DATATOGGLE;
else
csr = musb_readw(epio, MUSB_TXCSR) & MUSB_TXCSR_H_DATATOGGLE;
usb_settoggle(urb->dev, qh->epnum, !is_in, csr ? 1 : 0);
}
/* /*
* Advance this hardware endpoint's queue, completing the specified URB and * Advance this hardware endpoint's queue, completing the specified URB and
* advancing to either the next URB queued to that qh, or else invalidating * advancing to either the next URB queued to that qh, or else invalidating
@ -320,6 +300,7 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
struct musb_hw_ep *ep = qh->hw_ep; struct musb_hw_ep *ep = qh->hw_ep;
int ready = qh->is_ready; int ready = qh->is_ready;
int status; int status;
u16 toggle;
status = (urb->status == -EINPROGRESS) ? 0 : urb->status; status = (urb->status == -EINPROGRESS) ? 0 : urb->status;
@ -327,7 +308,8 @@ static void musb_advance_schedule(struct musb *musb, struct urb *urb,
switch (qh->type) { switch (qh->type) {
case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_BULK:
case USB_ENDPOINT_XFER_INT: case USB_ENDPOINT_XFER_INT:
musb_save_toggle(qh, is_in, urb); toggle = musb->io.get_toggle(qh, !is_in);
usb_settoggle(urb->dev, qh->epnum, !is_in, toggle ? 1 : 0);
break; break;
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
if (status == 0 && urb->error_count) if (status == 0 && urb->error_count)
@ -772,13 +754,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
); );
csr |= MUSB_TXCSR_MODE; csr |= MUSB_TXCSR_MODE;
if (!hw_ep->tx_double_buffered) { if (!hw_ep->tx_double_buffered)
if (usb_gettoggle(urb->dev, qh->epnum, 1)) csr |= musb->io.set_toggle(qh, is_out, urb);
csr |= MUSB_TXCSR_H_WR_DATATOGGLE
| MUSB_TXCSR_H_DATATOGGLE;
else
csr |= MUSB_TXCSR_CLRDATATOG;
}
musb_writew(epio, MUSB_TXCSR, csr); musb_writew(epio, MUSB_TXCSR, csr);
/* REVISIT may need to clear FLUSHFIFO ... */ /* REVISIT may need to clear FLUSHFIFO ... */
@ -860,17 +837,12 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
/* IN/receive */ /* IN/receive */
} else { } else {
u16 csr; u16 csr = 0;
if (hw_ep->rx_reinit) { if (hw_ep->rx_reinit) {
musb_rx_reinit(musb, qh, epnum); musb_rx_reinit(musb, qh, epnum);
csr |= musb->io.set_toggle(qh, is_out, urb);
/* init new state: toggle and NYET, maybe DMA later */
if (usb_gettoggle(urb->dev, qh->epnum, 0))
csr = MUSB_RXCSR_H_WR_DATATOGGLE
| MUSB_RXCSR_H_DATATOGGLE;
else
csr = 0;
if (qh->type == USB_ENDPOINT_XFER_INT) if (qh->type == USB_ENDPOINT_XFER_INT)
csr |= MUSB_RXCSR_DISNYET; csr |= MUSB_RXCSR_DISNYET;
@ -933,6 +905,7 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
void __iomem *epio = ep->regs; void __iomem *epio = ep->regs;
struct musb_qh *cur_qh, *next_qh; struct musb_qh *cur_qh, *next_qh;
u16 rx_csr, tx_csr; u16 rx_csr, tx_csr;
u16 toggle;
musb_ep_select(mbase, ep->epnum); musb_ep_select(mbase, ep->epnum);
if (is_in) { if (is_in) {
@ -970,7 +943,8 @@ static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep,
urb->actual_length += dma->actual_len; urb->actual_length += dma->actual_len;
dma->actual_len = 0L; dma->actual_len = 0L;
} }
musb_save_toggle(cur_qh, is_in, urb); toggle = musb->io.get_toggle(cur_qh, !is_in);
usb_settoggle(urb->dev, cur_qh->epnum, !is_in, toggle ? 1 : 0);
if (is_in) { if (is_in) {
/* move cur_qh to end of queue */ /* move cur_qh to end of queue */

View file

@ -22,6 +22,8 @@
* @read_fifo: platform specific function to read fifo * @read_fifo: platform specific function to read fifo
* @write_fifo: platform specific function to write fifo * @write_fifo: platform specific function to write fifo
* @busctl_offset: platform specific function to get busctl offset * @busctl_offset: platform specific function to get busctl offset
* @get_toggle: platform specific function to get toggle
* @set_toggle: platform specific function to set toggle
*/ */
struct musb_io { struct musb_io {
u32 (*ep_offset)(u8 epnum, u16 offset); u32 (*ep_offset)(u8 epnum, u16 offset);
@ -30,6 +32,8 @@ struct musb_io {
void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf); void (*read_fifo)(struct musb_hw_ep *hw_ep, u16 len, u8 *buf);
void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf); void (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
u32 (*busctl_offset)(u8 epnum, u16 offset); u32 (*busctl_offset)(u8 epnum, u16 offset);
u16 (*get_toggle)(struct musb_qh *qh, int is_out);
u16 (*set_toggle)(struct musb_qh *qh, int is_out, struct urb *urb);
}; };
/* Do not add new entries here, add them the struct musb_io instead */ /* Do not add new entries here, add them the struct musb_io instead */