Darius Augulis | 2a4f136 | 2008-11-12 13:38:31 -0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2005 Mike Lee(eemike@gmail.com) |
| 3 | * |
| 4 | * This udc driver is now under testing and code is based on pxa2xx_udc.h |
| 5 | * Please use it with your own risk! |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | */ |
| 17 | |
| 18 | #ifndef __LINUX_USB_GADGET_IMX_H |
| 19 | #define __LINUX_USB_GADGET_IMX_H |
| 20 | |
| 21 | #include <linux/types.h> |
| 22 | |
| 23 | /* Helper macros */ |
| 24 | #define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */ |
| 25 | #define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0) |
| 26 | #define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ |
| 27 | #define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0) |
| 28 | #define IMX_USB_NB_EP 6 |
| 29 | |
| 30 | /* Driver structures */ |
| 31 | struct imx_request { |
| 32 | struct usb_request req; |
| 33 | struct list_head queue; |
| 34 | unsigned int in_use; |
| 35 | }; |
| 36 | |
| 37 | enum ep0_state { |
| 38 | EP0_IDLE, |
| 39 | EP0_IN_DATA_PHASE, |
| 40 | EP0_OUT_DATA_PHASE, |
| 41 | EP0_CONFIG, |
| 42 | EP0_STALL, |
| 43 | }; |
| 44 | |
| 45 | struct imx_ep_struct { |
| 46 | struct usb_ep ep; |
| 47 | struct imx_udc_struct *imx_usb; |
| 48 | struct list_head queue; |
| 49 | unsigned char stopped; |
| 50 | unsigned char fifosize; |
| 51 | unsigned char bEndpointAddress; |
| 52 | unsigned char bmAttributes; |
| 53 | }; |
| 54 | |
| 55 | struct imx_udc_struct { |
| 56 | struct usb_gadget gadget; |
| 57 | struct usb_gadget_driver *driver; |
| 58 | struct device *dev; |
| 59 | struct imx_ep_struct imx_ep[IMX_USB_NB_EP]; |
| 60 | struct clk *clk; |
| 61 | enum ep0_state ep0state; |
| 62 | struct resource *res; |
| 63 | void __iomem *base; |
| 64 | unsigned char set_config; |
| 65 | int cfg, |
| 66 | intf, |
| 67 | alt, |
| 68 | usbd_int[7]; |
| 69 | }; |
| 70 | |
| 71 | /* USB registers */ |
| 72 | #define USB_FRAME (0x00) /* USB frame */ |
| 73 | #define USB_SPEC (0x04) /* USB Spec */ |
| 74 | #define USB_STAT (0x08) /* USB Status */ |
| 75 | #define USB_CTRL (0x0C) /* USB Control */ |
| 76 | #define USB_DADR (0x10) /* USB Desc RAM addr */ |
| 77 | #define USB_DDAT (0x14) /* USB Desc RAM/EP buffer data */ |
| 78 | #define USB_INTR (0x18) /* USB interrupt */ |
| 79 | #define USB_MASK (0x1C) /* USB Mask */ |
| 80 | #define USB_ENAB (0x24) /* USB Enable */ |
| 81 | #define USB_EP_STAT(x) (0x30 + (x*0x30)) /* USB status/control */ |
| 82 | #define USB_EP_INTR(x) (0x34 + (x*0x30)) /* USB interrupt */ |
| 83 | #define USB_EP_MASK(x) (0x38 + (x*0x30)) /* USB mask */ |
| 84 | #define USB_EP_FDAT(x) (0x3C + (x*0x30)) /* USB FIFO data */ |
| 85 | #define USB_EP_FDAT0(x) (0x3C + (x*0x30)) /* USB FIFO data */ |
| 86 | #define USB_EP_FDAT1(x) (0x3D + (x*0x30)) /* USB FIFO data */ |
| 87 | #define USB_EP_FDAT2(x) (0x3E + (x*0x30)) /* USB FIFO data */ |
| 88 | #define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */ |
| 89 | #define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */ |
| 90 | #define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */ |
| 91 | #define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */ |
| 92 | #define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */ |
| 93 | #define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */ |
| 94 | #define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */ |
| 95 | #define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */ |
| 96 | /* USB Control Register Bit Fields.*/ |
| 97 | #define CTRL_CMDOVER (1<<6) /* UDC status */ |
| 98 | #define CTRL_CMDERROR (1<<5) /* UDC status */ |
| 99 | #define CTRL_FE_ENA (1<<3) /* Enable Font End logic */ |
| 100 | #define CTRL_UDC_RST (1<<2) /* UDC reset */ |
| 101 | #define CTRL_AFE_ENA (1<<1) /* Analog Font end enable */ |
| 102 | #define CTRL_RESUME (1<<0) /* UDC resume */ |
| 103 | /* USB Status Register Bit Fields.*/ |
| 104 | #define STAT_RST (1<<8) |
| 105 | #define STAT_SUSP (1<<7) |
| 106 | #define STAT_CFG (3<<5) |
| 107 | #define STAT_INTF (3<<3) |
| 108 | #define STAT_ALTSET (7<<0) |
| 109 | /* USB Interrupt Status/Mask Registers Bit fields */ |
| 110 | #define INTR_WAKEUP (1<<31) /* Wake up Interrupt */ |
| 111 | #define INTR_MSOF (1<<7) /* Missed Start of Frame */ |
| 112 | #define INTR_SOF (1<<6) /* Start of Frame */ |
| 113 | #define INTR_RESET_STOP (1<<5) /* Reset Signaling stop */ |
| 114 | #define INTR_RESET_START (1<<4) /* Reset Signaling start */ |
| 115 | #define INTR_RESUME (1<<3) /* Suspend to resume */ |
| 116 | #define INTR_SUSPEND (1<<2) /* Active to suspend */ |
| 117 | #define INTR_FRAME_MATCH (1<<1) /* Frame matched */ |
| 118 | #define INTR_CFG_CHG (1<<0) /* Configuration change occurred */ |
| 119 | /* USB Enable Register Bit Fields.*/ |
| 120 | #define ENAB_RST (1<<31) /* Reset USB modules */ |
| 121 | #define ENAB_ENAB (1<<30) /* Enable USB modules*/ |
| 122 | #define ENAB_SUSPEND (1<<29) /* Suspend USB modules */ |
| 123 | #define ENAB_ENDIAN (1<<28) /* Endian of USB modules */ |
| 124 | #define ENAB_PWRMD (1<<0) /* Power mode of USB modules */ |
| 125 | /* USB Descriptor Ram Address Register bit fields */ |
| 126 | #define DADR_CFG (1<<31) /* Configuration */ |
| 127 | #define DADR_BSY (1<<30) /* Busy status */ |
| 128 | #define DADR_DADR (0x1FF) /* Descriptor Ram Address */ |
| 129 | /* USB Descriptor RAM/Endpoint Buffer Data Register bit fields */ |
| 130 | #define DDAT_DDAT (0xFF) /* Descriptor Endpoint Buffer */ |
| 131 | /* USB Endpoint Status Register bit fields */ |
| 132 | #define EPSTAT_BCOUNT (0x7F<<16) /* Endpoint FIFO byte count */ |
| 133 | #define EPSTAT_SIP (1<<8) /* Endpoint setup in progress */ |
| 134 | #define EPSTAT_DIR (1<<7) /* Endpoint transfer direction */ |
| 135 | #define EPSTAT_MAX (3<<5) /* Endpoint Max packet size */ |
| 136 | #define EPSTAT_TYP (3<<3) /* Endpoint type */ |
| 137 | #define EPSTAT_ZLPS (1<<2) /* Send zero length packet */ |
| 138 | #define EPSTAT_FLUSH (1<<1) /* Endpoint FIFO Flush */ |
| 139 | #define EPSTAT_STALL (1<<0) /* Force stall */ |
| 140 | /* USB Endpoint FIFO Status Register bit fields */ |
| 141 | #define FSTAT_FRAME_STAT (0xF<<24) /* Frame status bit [0-3] */ |
| 142 | #define FSTAT_ERR (1<<22) /* FIFO error */ |
| 143 | #define FSTAT_UF (1<<21) /* FIFO underflow */ |
| 144 | #define FSTAT_OF (1<<20) /* FIFO overflow */ |
| 145 | #define FSTAT_FR (1<<19) /* FIFO frame ready */ |
| 146 | #define FSTAT_FULL (1<<18) /* FIFO full */ |
| 147 | #define FSTAT_ALRM (1<<17) /* FIFO alarm */ |
| 148 | #define FSTAT_EMPTY (1<<16) /* FIFO empty */ |
| 149 | /* USB Endpoint FIFO Control Register bit fields */ |
| 150 | #define FCTRL_WFR (1<<29) /* Write frame end */ |
| 151 | /* USB Endpoint Interrupt Status Regsiter bit fields */ |
| 152 | #define EPINTR_FIFO_FULL (1<<8) /* fifo full */ |
| 153 | #define EPINTR_FIFO_EMPTY (1<<7) /* fifo empty */ |
| 154 | #define EPINTR_FIFO_ERROR (1<<6) /* fifo error */ |
| 155 | #define EPINTR_FIFO_HIGH (1<<5) /* fifo high */ |
| 156 | #define EPINTR_FIFO_LOW (1<<4) /* fifo low */ |
| 157 | #define EPINTR_MDEVREQ (1<<3) /* multi Device request */ |
| 158 | #define EPINTR_EOT (1<<2) /* fifo end of transfer */ |
| 159 | #define EPINTR_DEVREQ (1<<1) /* Device request */ |
| 160 | #define EPINTR_EOF (1<<0) /* fifo end of frame */ |
| 161 | |
| 162 | /* Debug macros */ |
| 163 | #ifdef DEBUG |
| 164 | |
| 165 | /* #define DEBUG_REQ */ |
| 166 | /* #define DEBUG_TRX */ |
| 167 | /* #define DEBUG_INIT */ |
| 168 | /* #define DEBUG_EP0 */ |
| 169 | /* #define DEBUG_EPX */ |
| 170 | /* #define DEBUG_IRQ */ |
| 171 | /* #define DEBUG_EPIRQ */ |
| 172 | /* #define DEBUG_DUMP */ |
| 173 | #define DEBUG_ERR |
| 174 | |
| 175 | #ifdef DEBUG_REQ |
| 176 | #define D_REQ(dev, args...) dev_dbg(dev, ## args) |
| 177 | #else |
| 178 | #define D_REQ(dev, args...) do {} while (0) |
| 179 | #endif /* DEBUG_REQ */ |
| 180 | |
| 181 | #ifdef DEBUG_TRX |
| 182 | #define D_TRX(dev, args...) dev_dbg(dev, ## args) |
| 183 | #else |
| 184 | #define D_TRX(dev, args...) do {} while (0) |
| 185 | #endif /* DEBUG_TRX */ |
| 186 | |
| 187 | #ifdef DEBUG_INIT |
| 188 | #define D_INI(dev, args...) dev_dbg(dev, ## args) |
| 189 | #else |
| 190 | #define D_INI(dev, args...) do {} while (0) |
| 191 | #endif /* DEBUG_INIT */ |
| 192 | |
| 193 | #ifdef DEBUG_EP0 |
| 194 | static const char *state_name[] = { |
| 195 | "EP0_IDLE", |
| 196 | "EP0_IN_DATA_PHASE", |
| 197 | "EP0_OUT_DATA_PHASE", |
| 198 | "EP0_CONFIG", |
| 199 | "EP0_STALL" |
| 200 | }; |
| 201 | #define D_EP0(dev, args...) dev_dbg(dev, ## args) |
| 202 | #else |
| 203 | #define D_EP0(dev, args...) do {} while (0) |
| 204 | #endif /* DEBUG_EP0 */ |
| 205 | |
| 206 | #ifdef DEBUG_EPX |
| 207 | #define D_EPX(dev, args...) dev_dbg(dev, ## args) |
| 208 | #else |
| 209 | #define D_EPX(dev, args...) do {} while (0) |
| 210 | #endif /* DEBUG_EP0 */ |
| 211 | |
| 212 | #ifdef DEBUG_IRQ |
| 213 | static void dump_intr(const char *label, int irqreg, struct device *dev) |
| 214 | { |
| 215 | dev_dbg(dev, "<%s> USB_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, |
| 216 | (irqreg & INTR_WAKEUP) ? " wake" : "", |
| 217 | (irqreg & INTR_MSOF) ? " msof" : "", |
| 218 | (irqreg & INTR_SOF) ? " sof" : "", |
| 219 | (irqreg & INTR_RESUME) ? " resume" : "", |
| 220 | (irqreg & INTR_SUSPEND) ? " suspend" : "", |
| 221 | (irqreg & INTR_RESET_STOP) ? " noreset" : "", |
| 222 | (irqreg & INTR_RESET_START) ? " reset" : "", |
| 223 | (irqreg & INTR_FRAME_MATCH) ? " fmatch" : "", |
| 224 | (irqreg & INTR_CFG_CHG) ? " config" : ""); |
| 225 | } |
| 226 | #else |
| 227 | #define dump_intr(x, y, z) do {} while (0) |
| 228 | #endif /* DEBUG_IRQ */ |
| 229 | |
| 230 | #ifdef DEBUG_EPIRQ |
| 231 | static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev) |
| 232 | { |
| 233 | dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr, |
| 234 | (irqreg & EPINTR_FIFO_FULL) ? " full" : "", |
| 235 | (irqreg & EPINTR_FIFO_EMPTY) ? " fempty" : "", |
| 236 | (irqreg & EPINTR_FIFO_ERROR) ? " ferr" : "", |
| 237 | (irqreg & EPINTR_FIFO_HIGH) ? " fhigh" : "", |
| 238 | (irqreg & EPINTR_FIFO_LOW) ? " flow" : "", |
| 239 | (irqreg & EPINTR_MDEVREQ) ? " mreq" : "", |
| 240 | (irqreg & EPINTR_EOF) ? " eof" : "", |
| 241 | (irqreg & EPINTR_DEVREQ) ? " devreq" : "", |
| 242 | (irqreg & EPINTR_EOT) ? " eot" : ""); |
| 243 | } |
| 244 | #else |
| 245 | #define dump_ep_intr(x, y, z, i) do {} while (0) |
| 246 | #endif /* DEBUG_IRQ */ |
| 247 | |
| 248 | #ifdef DEBUG_DUMP |
| 249 | static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb) |
| 250 | { |
| 251 | int temp = __raw_readl(imx_usb->base + USB_STAT); |
| 252 | |
| 253 | dev_dbg(imx_usb->dev, |
| 254 | "<%s> USB_STAT=[%s%s CFG=%d, INTF=%d, ALTR=%d]\n", label, |
| 255 | (temp & STAT_RST) ? " reset" : "", |
| 256 | (temp & STAT_SUSP) ? " suspend" : "", |
| 257 | (temp & STAT_CFG) >> 5, |
| 258 | (temp & STAT_INTF) >> 3, |
| 259 | (temp & STAT_ALTSET)); |
| 260 | } |
| 261 | |
| 262 | static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep) |
| 263 | { |
| 264 | int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); |
| 265 | |
| 266 | dev_dbg(imx_ep->imx_usb->dev, |
| 267 | "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), |
| 268 | (temp & EPINTR_FIFO_FULL) ? " full" : "", |
| 269 | (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "", |
| 270 | (temp & EPINTR_FIFO_ERROR) ? " ferr" : "", |
| 271 | (temp & EPINTR_FIFO_HIGH) ? " fhigh" : "", |
| 272 | (temp & EPINTR_FIFO_LOW) ? " flow" : "", |
| 273 | (temp & EPINTR_MDEVREQ) ? " mreq" : "", |
| 274 | (temp & EPINTR_EOF) ? " eof" : "", |
| 275 | (temp & EPINTR_DEVREQ) ? " devreq" : "", |
| 276 | (temp & EPINTR_EOT) ? " eot" : ""); |
| 277 | |
| 278 | temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); |
| 279 | |
| 280 | dev_dbg(imx_ep->imx_usb->dev, |
| 281 | "<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep), |
| 282 | (temp & EPSTAT_SIP) ? " sip" : "", |
| 283 | (temp & EPSTAT_STALL) ? " stall" : "", |
| 284 | (temp & EPSTAT_BCOUNT) >> 16); |
| 285 | |
| 286 | temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))); |
| 287 | |
| 288 | dev_dbg(imx_ep->imx_usb->dev, |
| 289 | "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), |
| 290 | (temp & FSTAT_ERR) ? " ferr" : "", |
| 291 | (temp & FSTAT_UF) ? " funder" : "", |
| 292 | (temp & FSTAT_OF) ? " fover" : "", |
| 293 | (temp & FSTAT_FR) ? " fready" : "", |
| 294 | (temp & FSTAT_FULL) ? " ffull" : "", |
| 295 | (temp & FSTAT_ALRM) ? " falarm" : "", |
| 296 | (temp & FSTAT_EMPTY) ? " fempty" : ""); |
| 297 | } |
| 298 | |
| 299 | static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req) |
| 300 | { |
| 301 | int i; |
| 302 | |
| 303 | if (!req || !req->buf) { |
| 304 | dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label); |
| 305 | return; |
| 306 | } |
| 307 | |
| 308 | if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) |
| 309 | || (EP_NO(imx_ep) && EP_DIR(imx_ep))) { |
| 310 | |
| 311 | dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label); |
| 312 | for (i = 0; i < req->length; i++) |
| 313 | printk("%02x-", *((u8 *)req->buf + i)); |
| 314 | printk(">\n"); |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | #else |
| 319 | #define dump_ep_stat(x, y) do {} while (0) |
| 320 | #define dump_usb_stat(x, y) do {} while (0) |
| 321 | #define dump_req(x, y, z) do {} while (0) |
| 322 | #endif /* DEBUG_DUMP */ |
| 323 | |
| 324 | #ifdef DEBUG_ERR |
| 325 | #define D_ERR(dev, args...) dev_dbg(dev, ## args) |
| 326 | #else |
| 327 | #define D_ERR(dev, args...) do {} while (0) |
| 328 | #endif |
| 329 | |
| 330 | #else |
| 331 | #define D_REQ(dev, args...) do {} while (0) |
| 332 | #define D_TRX(dev, args...) do {} while (0) |
| 333 | #define D_INI(dev, args...) do {} while (0) |
| 334 | #define D_EP0(dev, args...) do {} while (0) |
| 335 | #define D_EPX(dev, args...) do {} while (0) |
| 336 | #define dump_ep_intr(x, y, z, i) do {} while (0) |
| 337 | #define dump_intr(x, y, z) do {} while (0) |
| 338 | #define dump_ep_stat(x, y) do {} while (0) |
| 339 | #define dump_usb_stat(x, y) do {} while (0) |
| 340 | #define dump_req(x, y, z) do {} while (0) |
| 341 | #define D_ERR(dev, args...) do {} while (0) |
| 342 | #endif /* DEBUG */ |
| 343 | |
| 344 | #endif /* __LINUX_USB_GADGET_IMX_H */ |