]> rtime.felk.cvut.cz Git - lincan.git/blob - embedded/libs4c/usb/lpcusb/lpc.c
Merge master into can-usb1 branch to include proc update for 3.12+ kernels.
[lincan.git] / embedded / libs4c / usb / lpcusb / lpc.c
1 /*****************************************************/
2 /***   Module : USB PDI                            ***/
3 /***   Author : Roman Bartosinski (C) 28.04.2002   ***/
4 /***   Modify : 08.08.2002, 16.04.2003             ***/
5 /*****************************************************/
6
7 #include <system_def.h>
8 #include <usb/usb.h>
9 #include <usb/lpcusb.h>
10
11 #ifdef MACH_LPC17XX
12 #include <lpcUSB.h>
13 #endif
14
15 /* set device address */
16 int usb_lpc_set_addr( usb_device_t *udev, unsigned char addr) {
17   lpc_usb_set_addr(addr);
18   return 0;
19 }
20
21 int usb_lpc_set_configuration( usb_device_t *udev, unsigned char iCfg) {
22   lpc_usb_config_device(iCfg);
23   if ( iCfg) {
24     int i;
25     for(i = 0; i < udev->cntep; i++) {
26       lpc_usb_configEP(udev->ep[i].epnum, udev->ep[i].max_packet_size);
27     }
28   }
29   return 0;
30 }
31
32 /* connect usb */
33 int usb_lpc_connect( usb_device_t *udev) {
34   lpc_write_cmd_data(USB_CMD_SET_DEV_STAT,USB_DAT_WR_BYTE(USBC_DEV_CON));
35   return 0;
36 }
37
38 /* disconnect usb */
39 int usb_lpc_disconnect( usb_device_t *udev) {
40   lpc_write_cmd_data(USB_CMD_SET_DEV_STAT,USB_DAT_WR_BYTE(0));
41   return 0;
42 }
43
44 /* acknowledge control transfer */
45 void usb_lpc_ack_setup( usb_device_t *udev) {
46   lpc_usb_write_endpoint(0x80|0x00, NULL, 0);
47 }
48
49 /* stall endpoint X */
50 void usb_lpc_stall( usb_ep_t *ep) {
51   if (!ep->epnum)
52     lpc_usb_setstallEP(0x80|ep->epnum);
53   lpc_usb_setstallEP(ep->epnum);
54 }
55
56 /* unstall endpoint X */
57 void usb_lpc_unstall( usb_ep_t *ep) {
58   if (!ep->epnum)
59     lpc_usb_clrstallEP(0x80|ep->epnum);
60   lpc_usb_clrstallEP(ep->epnum);
61 }
62
63 /**
64  * usb_lpc_check events
65  * function reads interrupt register and sets event flags
66  * function returns 1 if there is some new event.
67  * function returns 0 if there isn't new event but all is OK
68  * function returns -1 if there is any error
69 */
70 int usb_lpc_check_events( usb_device_t *udev) 
71 {
72   unsigned int disr,val,last_int;
73   int ret=0,n,m,i;
74
75   disr=USBDevIntSt;
76
77   /* Device Status Interrupt (Reset, Connect change, Suspend/Resume) */
78   if (disr & USBDevInt_DEV_STAT) {
79     USBDevIntClr = USBDevInt_DEV_STAT;
80     disr&=~USBDevInt_DEV_STAT;
81     lpc_write_cmd(USB_CMD_GET_DEV_STAT);
82     val=lpc_read_cmd_data(USB_DAT_GET_DEV_STAT);
83     if (val & USBC_DEV_RST) {               /* Reset */
84       lpc_usb_reset();
85       udev->flags |= USB_FLAG_BUS_RESET;
86       ret = 1;
87     }
88     if (val & USBC_DEV_SUS_CH) {            /* Suspend/Resume */
89       if (val & USBC_DEV_SUS) {             /* Suspend */
90         udev->flags |= USB_FLAG_SUSPEND;
91         ret = 1;
92       } else {                              /* Resume */
93         /* todo */
94       }
95     }
96   }
97
98   /* Endpoint's Slow Interrupt */
99   if (disr & USBDevInt_EP_SLOW) {
100     USBDevIntClr = USBDevInt_EP_SLOW;
101     disr&=~USBDevInt_EP_SLOW;
102
103     last_int = USBEpIntSt;
104
105     /* EP0_OUT */
106     if (last_int & (1 << 0)) {
107       last_int &= ~(1 << 0);
108       USBEpIntClr = 1 << 0;
109       lpc_wait4devint(USBDevInt_CDFULL);
110       val = USBCmdData;
111       /* Setup Packet */
112       if (val & USBC_EP_SEL_STP)   
113         udev->flags |= USB_FLAG_SETUP;
114       else
115         udev->flags |= USB_FLAG_EVENT_RX0;
116       ret = 1;
117     }
118
119     /* EP0_IN */
120     if (last_int & (1 << 1)) {
121       last_int &= ~(1 << 1);
122       USBEpIntClr = 1 << 1;
123       lpc_wait4devint(USBDevInt_CDFULL);
124       val = USBCmdData;
125       udev->flags |= USB_FLAG_EVENT_TX0;
126       ret = 1;
127     }    
128
129     /* user endpoints */
130     for( i=0; i<udev->cntep; i++) {
131       if ( last_int & (udev->ep+i)->event_mask) {
132         last_int &= ~((udev->ep+i)->event_mask);
133         USBEpIntClr = (udev->ep+i)->event_mask;
134         lpc_wait4devint(USBDevInt_CDFULL);
135         val = USBCmdData;
136         udev->ep_events |= 1<<i;
137         ret = 1;
138       }
139     }
140
141     while (last_int) {                    /* Endpoint Interrupt Status */
142       for (n = 0; n < USB_EP_NUM; n++) {    /* Check All Endpoints */
143         if (last_int & (1 << n)) {
144           last_int &= ~(1 << n);
145           USBEpIntClr = 1 << n;
146           m = n >> 1;
147           if (n&1) m|=0x80;
148           lpc_wait4devint(USBDevInt_CDFULL);
149           val = USBCmdData;
150           lpc_usb_setstallEP(m);
151         }
152       }
153     }
154   }
155   if (!disr)
156     USBDevIntClr = disr;
157   return ret;
158 }
159
160 int usb_lpc_read_endpoint( usb_ep_t *ep, void *ptr, int size)
161 {
162   return lpc_usb_read_endpoint(ep->epnum, ptr, size);
163 }
164
165 int usb_lpc_write_endpoint( usb_ep_t *ep, const void *ptr, int size)
166 {
167   return lpc_usb_write_endpoint(0x80|ep->epnum, ptr, size);
168 }
169
170
171 /* init usb structures and chip */
172 int usb_lpc_init( usb_device_t *udev) {
173
174   udev->connect = usb_lpc_connect;
175   udev->set_addr = usb_lpc_set_addr;
176   udev->set_configuration = usb_lpc_set_configuration;
177   udev->disconnect = usb_lpc_disconnect;
178   udev->ack_setup = usb_lpc_ack_setup; 
179   udev->ack_control_setup = NULL;
180   udev->stall = usb_lpc_stall;
181   udev->unstall = usb_lpc_unstall;
182   udev->check_events = usb_lpc_check_events;
183   udev->read_endpoint = usb_lpc_read_endpoint;
184   udev->write_endpoint = usb_lpc_write_endpoint;
185
186   udev->ep0.max_packet_size = USB_MAX_PACKET0;
187
188   lpc_usb_hw_init();  
189   return 0;
190 }