#include "musb_host.h"
-
#ifdef CONFIG_USB_MUSB_OTG
#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST)
extern irqreturn_t musb_g_ep0_irq(struct musb *);
extern void musb_g_tx(struct musb *, u8);
-extern void musb_g_rx(struct musb *, u8);
+extern void musb_g_rx(struct musb *, u8, bool);
extern void musb_g_reset(struct musb *);
extern void musb_g_suspend(struct musb *);
extern void musb_g_resume(struct musb *);
*/
#if defined(CONFIG_ARCH_DAVINCI) || defined(CONFIG_ARCH_OMAP2430) \
- || defined(CONFIG_ARCH_OMAP3430)
+ || defined(CONFIG_ARCH_OMAP3430) || defined(CONFIG_BLACKFIN)
/* REVISIT indexed access seemed to
* misbehave (on DaVinci) for at least peripheral IN ...
*/
struct musb_qh *in_qh;
struct musb_qh *out_qh;
+ /* list of rx and tx qhs, control transfer needs only
+ * one list thus only in_list is used for control.
+ */
+ struct list_head in_list;
+ struct list_head out_list;
+
u8 rx_reinit;
u8 tx_reinit;
#endif
#endif
}
+#define MUSB_MAX_EPS 16
+
+struct musb_ctx {
+ /* common register */
+ u16 intrtxe;
+ u16 intrrxe;
+
+ u8 intrusbe;
+
+ u8 faddr;
+ u8 power;
+
+ u8 frame;
+ u8 index;
+ u8 testmode;
+ u8 devctl;
+ u8 misc;
+
+ /* indexed registers */
+ u16 txmaxp[MUSB_MAX_EPS];
+ u16 txcsr[MUSB_MAX_EPS];
+
+ u16 rxmaxp[MUSB_MAX_EPS];
+ u16 rxcsr[MUSB_MAX_EPS];
+
+ u16 csr0; /* select ep0 to read/write this register */
+
+ u8 txtype[MUSB_MAX_EPS];
+ u8 txinterval[MUSB_MAX_EPS];
+
+ u8 rxtype[MUSB_MAX_EPS];
+ u8 rxinterval[MUSB_MAX_EPS];
+
+ u8 fifosize[MUSB_MAX_EPS];
+
+ u8 rxfifosz[MUSB_MAX_EPS];
+ u8 txfifosz[MUSB_MAX_EPS];
+ u16 txfifoadd[MUSB_MAX_EPS];
+ u16 rxfifoadd[MUSB_MAX_EPS];
+
+ u8 count0;
+ u8 type0;
+ u8 naklimit0;
+};
+
/*
* struct musb - Driver instance data.
*/
struct musb {
/* device lock */
spinlock_t lock;
+ struct mutex mutex;
struct clk *clock;
irqreturn_t (*isr)(int, void *);
struct work_struct irq_work;
+ struct work_struct vbus_work;
/* this hub status bit is reserved by USB 2.0 and not seen by usbcore */
#define MUSB_PORT_STAT_RESUME (1 << 31)
*/
struct musb_hw_ep *bulk_ep;
- struct list_head control; /* of musb_qh */
- struct list_head in_bulk; /* of musb_qh */
- struct list_head out_bulk; /* of musb_qh */
struct musb_qh *periodic[32]; /* tree of interrupt+iso */
#endif
u16 int_rx;
u16 int_tx;
- struct otg_transceiver xceiv;
+ struct otg_transceiver *xceiv;
int nIrq;
+ unsigned irq_wake:1;
struct musb_hw_ep endpoints[MUSB_C_NUM_EPS];
#define control_ep endpoints
u16 epmask;
u8 nr_endpoints;
+ struct musb_board_data *board;
u8 board_mode; /* enum musb_mode */
int (*board_set_power)(int state);
u8 min_power; /* vbus for periph, in mA/2 */
+ unsigned power_draw; /* current power draw, gadget only */
+
bool is_host;
int a_wait_bcon; /* VBUS timeout in msecs */
struct usb_gadget_driver *gadget_driver; /* its driver */
#endif
+ /* true if this chip can enable SUSPENDM */
+ unsigned suspendm:1;
+
+ /* true if we're using dma */
+ unsigned use_dma:1;
+
struct musb_hdrc_config *config;
#ifdef MUSB_CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#endif
+ unsigned is_charger:1;
};
static inline void musb_set_vbus(struct musb *musb, int is_on)
}
#endif
+#ifdef CONFIG_BLACKFIN
+static inline int musb_read_fifosize(struct musb *musb,
+ struct musb_hw_ep *hw_ep, u8 epnum)
+{
+ musb->nr_endpoints++;
+ musb->epmask |= (1 << epnum);
+
+ if (epnum < 5) {
+ hw_ep->max_packet_sz_tx = 128;
+ hw_ep->max_packet_sz_rx = 128;
+ } else {
+ hw_ep->max_packet_sz_tx = 1024;
+ hw_ep->max_packet_sz_rx = 1024;
+ }
+ hw_ep->is_shared_fifo = false;
+
+ return 0;
+}
+
+static inline void musb_configure_ep0(struct musb *musb)
+{
+ musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].is_shared_fifo = true;
+}
+
+#else
+
+static inline int musb_read_fifosize(struct musb *musb,
+ struct musb_hw_ep *hw_ep, u8 epnum)
+{
+ u8 reg = 0;
+
+ /* read from core using indexed model */
+ reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE);
+ /* 0's returned when no more endpoints */
+ if (!reg)
+ return -ENODEV;
+
+ musb->nr_endpoints++;
+ musb->epmask |= (1 << epnum);
+
+ hw_ep->max_packet_sz_tx = 1 << (reg & 0x0f);
+
+ /* shared TX/RX FIFO? */
+ if ((reg & 0xf0) == 0xf0) {
+ hw_ep->max_packet_sz_rx = hw_ep->max_packet_sz_tx;
+ hw_ep->is_shared_fifo = true;
+ return 0;
+ } else {
+ hw_ep->max_packet_sz_rx = 1 << ((reg & 0xf0) >> 4);
+ hw_ep->is_shared_fifo = false;
+ }
+
+ return 0;
+}
+
+static inline void musb_configure_ep0(struct musb *musb)
+{
+ musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE;
+ musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE;
+}
+#endif /* CONFIG_BLACKFIN */
+
/***************************** Glue it together *****************************/
extern void musb_hnp_stop(struct musb *musb);
-extern void musb_platform_set_mode(struct musb *musb, u8 musb_mode);
+extern int musb_platform_set_mode(struct musb *musb, u8 musb_mode);
-#if defined(CONFIG_USB_TUSB6010) || \
+#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN) || \
defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX)
extern void musb_platform_try_idle(struct musb *musb, unsigned long timeout);
#else
#define musb_platform_try_idle(x, y) do {} while (0)
#endif
-#ifdef CONFIG_USB_TUSB6010
+#if defined(CONFIG_USB_TUSB6010) || defined(CONFIG_BLACKFIN)
extern int musb_platform_get_vbus_status(struct musb *musb);
#else
#define musb_platform_get_vbus_status(x) 0
#endif
+#ifdef CONFIG_PM
+extern void musb_save_ctx(struct musb *musb);
+extern void musb_restore_ctx(struct musb *musb);
+extern void musb_save_ctx_and_suspend(struct usb_gadget *, int);
+extern void musb_restore_ctx_and_resume(struct usb_gadget *);
+#else
+static inline void musb_save_ctx(struct musb *musb) {}
+static inline void musb_restore_ctx(struct musb *musb) {}
+static inline void musb_save_ctx_and_suspend(struct usb_gadget *, int) {}
+static inline void musb_restore_ctx_and_resume(struct usb_gadget *) {}
+#endif
+
extern int __init musb_platform_init(struct musb *musb);
extern int musb_platform_exit(struct musb *musb);
+/*-------------------------- ProcFS definitions ---------------------*/
+
+struct proc_dir_entry;
+
+#ifdef CONFIG_MUSB_PROC_FS
+extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data);
+extern void musb_debug_delete(char *name, struct musb *data);
+#else
+static inline struct proc_dir_entry *
+musb_debug_create(char *name, struct musb *data)
+{
+ return NULL;
+}
+static inline void musb_debug_delete(char *name, struct musb *data)
+{
+}
+#endif
+
#endif /* __MUSB_CORE_H__ */