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:
parent
8d817d7934
commit
fe3bbd6b38
|
@ -275,6 +275,38 @@ static void musb_default_writew(void __iomem *addr, unsigned offset, u16 data)
|
|||
__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
|
||||
*/
|
||||
|
@ -2381,6 +2413,16 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
|
|||
else
|
||||
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) {
|
||||
musb->xceiv->io_dev = musb->controller;
|
||||
musb->xceiv->io_priv = musb->mregs;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
struct musb;
|
||||
struct musb_hw_ep;
|
||||
struct musb_ep;
|
||||
struct musb_qh;
|
||||
|
||||
/* Helper defines for struct musb->hwvers */
|
||||
#define MUSB_HWVERS_MAJOR(x) ((x >> 10) & 0x1f)
|
||||
|
@ -123,6 +124,8 @@ struct musb_io;
|
|||
* @writew: write 16 bits
|
||||
* @read_fifo: reads the 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_exit: platform specific dma exit function
|
||||
* @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 (*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);
|
||||
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 *
|
||||
(*dma_init) (struct musb *musb, void __iomem *base);
|
||||
void (*dma_exit)(struct dma_controller *c);
|
||||
|
|
|
@ -286,26 +286,6 @@ __acquires(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
|
||||
* 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;
|
||||
int ready = qh->is_ready;
|
||||
int status;
|
||||
u16 toggle;
|
||||
|
||||
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) {
|
||||
case USB_ENDPOINT_XFER_BULK:
|
||||
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;
|
||||
case USB_ENDPOINT_XFER_ISOC:
|
||||
if (status == 0 && urb->error_count)
|
||||
|
@ -772,13 +754,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
|
|||
);
|
||||
csr |= MUSB_TXCSR_MODE;
|
||||
|
||||
if (!hw_ep->tx_double_buffered) {
|
||||
if (usb_gettoggle(urb->dev, qh->epnum, 1))
|
||||
csr |= MUSB_TXCSR_H_WR_DATATOGGLE
|
||||
| MUSB_TXCSR_H_DATATOGGLE;
|
||||
else
|
||||
csr |= MUSB_TXCSR_CLRDATATOG;
|
||||
}
|
||||
if (!hw_ep->tx_double_buffered)
|
||||
csr |= musb->io.set_toggle(qh, is_out, urb);
|
||||
|
||||
musb_writew(epio, MUSB_TXCSR, csr);
|
||||
/* REVISIT may need to clear FLUSHFIFO ... */
|
||||
|
@ -860,17 +837,12 @@ finish:
|
|||
|
||||
/* IN/receive */
|
||||
} else {
|
||||
u16 csr;
|
||||
u16 csr = 0;
|
||||
|
||||
if (hw_ep->rx_reinit) {
|
||||
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)
|
||||
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;
|
||||
struct musb_qh *cur_qh, *next_qh;
|
||||
u16 rx_csr, tx_csr;
|
||||
u16 toggle;
|
||||
|
||||
musb_ep_select(mbase, ep->epnum);
|
||||
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;
|
||||
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) {
|
||||
/* move cur_qh to end of queue */
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
* @read_fifo: platform specific function to read fifo
|
||||
* @write_fifo: platform specific function to write fifo
|
||||
* @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 {
|
||||
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 (*write_fifo)(struct musb_hw_ep *hw_ep, u16 len, const u8 *buf);
|
||||
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 */
|
||||
|
|
Loading…
Reference in New Issue