- Main Page
- Related Pages
- Data Structures
- Files

- File List
- Globals

# drivers/usb/usbb_core.c

Go to the documentation of this file.

    00001
    00052 #include <assert.h>
    00053 #include <debug.h>
    00054 #include <irq_handler.h>
    00055 #include <physmem.h>
    00056 #include <stdbool.h>
    00057 #include <chip/clk.h>
    00058 #include <chip/memory-map.h>
    00059 #include <chip/irq-map.h>
    00060 #include <chip/portmux.h>
    00061 #include <chip/usbb.h>
    00062 #include <usb/udc.h>
    00063
    00064 #include <app/config_dmapool.h>
    00065 #include <app/config_usb.h>
    00066
    00067 #include "usbb_internal.h"
    00068 #include "usbb_regs.h"
    00069
    00070 /* Configuration sanity-checks */
    00071 #if defined(CONFIG_USBB_UDC) && !defined(CHIP_USBB_HAS_DEVICE)
    00072 # error USBB: This chip does not have a Device Controller
    00073 #endif
    00074 #if defined(CONFIG_USBB_HOST) && !defined(CHIP_USBB_HAS_HOST)
    00075 # error USBB: This chip does not have a Host Controller
    00076 #endif
    00077 #if defined(CONFIG_USBB_OTG) && !defined(CHIP_USBB_HAS_OTG)
    00078 # error USBB: This chip does not support USB On-The-Go
    00079 #endif
    00080
    00081 #ifndef usbb_desc_physmem_pool
    00082 # define usbb_desc_physmem_pool hsb_sram_pool
    00083 #endif
    00084
    00085 #define USBB_DMA_DESC_ALIGN     4
    00086
    00087 struct dma_pool         usbb_desc_pool;
    00088
    00089 static inline struct usbb_udc *usbb_get_udc(struct usbb_controller *usbb)
    00090 {
    00091 #ifdef CONFIG_USBB_UDC
    00092         return usbb->udc;
    00093 #else
    00094         return NULL;
    00095 #endif
    00096 }
    00097
    00098 static inline struct usbb_host *usbb_get_host(struct usbb_controller *usbb)
    00099 {
    00100 #ifdef CONFIG_USBB_HOST
    00101         return usbb->host;
    00102 #else
    00103         return NULL;
    00104 #endif
    00105 }
    00106
    00107 static inline bool usbb_is_otg(struct usbb_controller *usbb)
    00108 {
    00109 #ifdef CONFIG_USBB_OTG
    00110         return true;
    00111 #else
    00112         return false;
    00113 #endif
    00114 }
    00115
    00116 static void usbb_check_vbus(struct usbb_controller *usbb)
    00117 {
    00118         struct usbb_udc *udcb = usbb_get_udc(usbb);
    00119
    00120         if (usbb_read_reg(USBSTA) & USBB_USBSTA_VBUS)
    00121                 usbb_udc_vbus_on(udcb);
    00122         else
    00123                 usbb_udc_vbus_off(udcb);
    00124 }
    00125
    00132 static void usbb_enter_device_mode(struct usbb_controller *usbb)
    00133 {
    00134         struct usbb_host        *host = usbb_get_host(usbb);
    00135         struct usbb_udc         *udc = usbb_get_udc(usbb);
    00136         uint32_t                usbcon;
    00137
    00138         dbg_printf("USBB: Entering device mode...\n");
    00139
    00140         if (usbb_host_is_enabled(host))
    00141                 usbb_host_disable(host);
    00142         if (!usbb_udc_is_enabled(udc))
    00143                 usbb_udc_enable(udc);
    00144
    00145         usbb_write_reg(USBSTACLR, USBB_VBUSTI);
    00146         usbb_check_vbus(usbb);
    00147
    00148         usbcon = usbb_read_reg(USBCON);
    00149         usbcon |= USBB_VBUSTI;
    00150         usbb_write_reg(USBCON, usbcon);
    00151
    00152         dbg_printf("USBB: USBCON=%08x\n", usbb_read_reg(USBCON));
    00153 }
    00154
    00155 static void usbb_enter_host_mode(struct usbb_controller *usbb)
    00156 {
    00157         struct usbb_host        *host = usbb_get_host(usbb);
    00158         struct usbb_udc         *udc = usbb_get_udc(usbb);
    00159
    00160         if (host) {
    00161                 if (usbb_udc_is_enabled(udc))
    00162                         usbb_udc_disable(udc);
    00163                 if (!usbb_host_is_enabled(host))
    00164                         usbb_host_enable(host);
    00165         }
    00166 }
    00167
    00175 static void usbb_check_id(struct usbb_controller *usbb)
    00176 {
    00177         if (usbb_read_reg(USBSTA) & USBB_USBSTA_ID)
    00178                 usbb_enter_device_mode(usbb);
    00179         else
    00180                 usbb_enter_host_mode(usbb);
    00181 }
    00182
    00193 static void usbb_interrupt(void *data)
    00194 {
    00195         struct usbb_controller  *usbb = data;
    00196         struct usbb_udc         *udcb;
    00197         struct usbb_host        *hostb;
    00198         uint32_t                usbsta;
    00199
    00200         usbsta = usbb_read_reg(USBSTA);
    00201
    00202         if (usbb_is_otg(usbb)) {
    00203                 if (usbsta & USBB_IDTI) {
    00204                         usbb_write_reg(USBSTACLR, USBB_IDTI);
    00205                         usbb_check_id(usbb);
    00206                 }
    00207
    00208                 /* TODO: More OTG stuff */
    00209         }
    00210
    00211         udcb = usbb_get_udc(usbb);
    00212         if (usbb_udc_is_enabled(udcb)) {
    00213                 if (usbsta & USBB_VBUSTI) {
    00214                         usbb_write_reg(USBSTACLR, USBB_VBUSTI);
    00215                         usbb_check_vbus(usbb);
    00216                 }
    00217
    00218                 usbb_udc_interrupt(udcb);
    00219         }
    00220
    00221         hostb = usbb_get_host(usbb);
    00222         if (usbb_host_is_enabled(hostb)) {
    00223                 /* TODO: Host */
    00224         }
    00225 }
    00226 DEFINE_IRQ_HANDLER(usbb, usbb_interrupt, 0);
    00227
    00228 static void usbb_init_desc_pool(void)
    00229 {
    00230         phys_addr_t     addr;
    00231         phys_size_t     size;
    00232
    00233         size =  round_up(sizeof(struct usbb_sw_dma_desc), USBB_DMA_DESC_ALIGN);
    00234         size *= CONFIG_USBB_NR_DMA_DESCRIPTORS;
    00235
    00236         addr = physmem_alloc(&usbb_desc_physmem_pool, size,
    00237                         USBB_DMA_DESC_ALIGN);
    00238         assert(addr != PHYSMEM_ALLOC_ERR);
    00239
    00240         dma_pool_init_coherent(&usbb_desc_pool, addr, size,
    00241                         sizeof(struct usbb_sw_dma_desc), USBB_DMA_DESC_ALIGN);
    00242 }
    00243
    00244 static struct usbb_controller   the_usbb_controller;
    00245
    00262 static struct usbb_controller *usbb_init(void)
    00263 {
    00264         struct usbb_controller  *usbb = &the_usbb_controller;
    00265         uint32_t                usbcon;
    00266
    00267         /*
    00268          * Only do the initialization once. We might get called from
    00269          * udc_init() as well as other initialization functions.
    00270          */
    00271         if (usbb_get_host(usbb) || usbb_get_udc(usbb))
    00272                 return usbb;
    00273
    00274         usbb_init_desc_pool();
    00275
    00276         usbcon = USBB_USBCON_USBE | USBB_USBCON_OTGPADE;
    00277
    00278         if (clk_enable_usbb())
    00279                 return NULL;
    00280
    00281         setup_irq_handler(USBB_IRQ, usbb, 0, usbb);
    00282
    00283 #ifdef CONFIG_USBB_UDC
    00284         usbb->udc = usbb_udc_init();
    00285         if (!usbb->udc)
    00286                 goto err_udc;
    00287 #endif
    00288 #ifdef CONFIG_USBB_HOST
    00289         usbb->host = usbb_host_init();
    00290         if (!usbb->host)
    00291                 goto err_host;
    00292 #endif
    00293
    00294         if (usbb_is_otg(usbb)) {
    00295                 /* Full OTG */
    00296                 usbcon |= USBB_USBCON_UIDE;
    00297                 usbb_write_reg(USBCON, usbcon);
    00298                 usbb_write_reg(USBSTACLR, USBB_IDTI);
    00299                 usbb_check_id(usbb);
    00300                 usbcon |= USBB_IDTI;
    00301                 usbb_write_reg(USBCON, usbcon);
    00302
    00303                 /* TODO: initialize HNP, SRP handling, etc. */
    00304         } else if (usbb_get_udc(usbb)) {
    00305                 /* Device only */
    00306                 usbcon |= USBB_USBCON_UIMOD_DEVICE;
    00307                 usbb_write_reg(USBCON, usbcon);
    00308                 usbb_enter_device_mode(usbb);
    00309         } else if (usbb_get_host(usbb)) {
    00310                 /* Host only */
    00311                 usbcon |= USBB_USBCON_UIMOD_HOST;
    00312                 usbb_write_reg(USBCON, usbcon);
    00313                 usbb_enter_host_mode(usbb);
    00314         }
    00315
    00316         return usbb;
    00317
    00318 #ifdef CONFIG_USBB_HOST
    00319         usbb_host_shutdown(usbb_get_host(usbb));
    00320 err_host:
    00321 #endif
    00322 #ifdef CONFIG_USBB_UDC
    00323         usbb_udc_shutdown(usbb_get_udc(usbb));
    00324 err_udc:
    00325 #endif
    00326         return NULL;
    00327 }
    00328
    00342 struct udc *udc_init(void)
    00343 {
    00344         struct usbb_controller  *usbb;
    00345
    00346         usbb = usbb_init();
    00347         if (!usbb)
    00348                 return NULL;
    00349
    00350         return &usbb_get_udc(usbb)->udc;
    00351 }