sl811-hcd.c (288ead45fa6637e959015d055304f521cbbc0575) | sl811-hcd.c (749da5f82fe33ff68dd4aa1a5e35cd9aa6246dab) |
---|---|
1/* 2 * SL811HS HCD (Host Controller Driver) for USB. 3 * 4 * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) 5 * Copyright (C) 2004-2005 David Brownell 6 * 7 * Periodic scheduling is based on Roman's OHCI code 8 * Copyright (C) 1999 Roman Weissgaerber --- 76 unchanged lines hidden (view full) --- 85/*-------------------------------------------------------------------------*/ 86 87static void port_power(struct sl811 *sl811, int is_on) 88{ 89 struct usb_hcd *hcd = sl811_to_hcd(sl811); 90 91 /* hub is inactive unless the port is powered */ 92 if (is_on) { | 1/* 2 * SL811HS HCD (Host Controller Driver) for USB. 3 * 4 * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) 5 * Copyright (C) 2004-2005 David Brownell 6 * 7 * Periodic scheduling is based on Roman's OHCI code 8 * Copyright (C) 1999 Roman Weissgaerber --- 76 unchanged lines hidden (view full) --- 85/*-------------------------------------------------------------------------*/ 86 87static void port_power(struct sl811 *sl811, int is_on) 88{ 89 struct usb_hcd *hcd = sl811_to_hcd(sl811); 90 91 /* hub is inactive unless the port is powered */ 92 if (is_on) { |
93 if (sl811->port1 & (1 << USB_PORT_FEAT_POWER)) | 93 if (sl811->port1 & USB_PORT_STAT_POWER) |
94 return; 95 | 94 return; 95 |
96 sl811->port1 = (1 << USB_PORT_FEAT_POWER); | 96 sl811->port1 = USB_PORT_STAT_POWER; |
97 sl811->irq_enable = SL11H_INTMASK_INSRMV; 98 } else { 99 sl811->port1 = 0; 100 sl811->irq_enable = 0; 101 hcd->state = HC_STATE_HALT; 102 } 103 sl811->ctrl1 = 0; 104 sl811_write(sl811, SL11H_IRQ_ENABLE, 0); --- 297 unchanged lines hidden (view full) --- 402 } 403 return ep; 404} 405 406#define MIN_JIFFIES ((msecs_to_jiffies(2) > 1) ? msecs_to_jiffies(2) : 2) 407 408static inline void start_transfer(struct sl811 *sl811) 409{ | 97 sl811->irq_enable = SL11H_INTMASK_INSRMV; 98 } else { 99 sl811->port1 = 0; 100 sl811->irq_enable = 0; 101 hcd->state = HC_STATE_HALT; 102 } 103 sl811->ctrl1 = 0; 104 sl811_write(sl811, SL11H_IRQ_ENABLE, 0); --- 297 unchanged lines hidden (view full) --- 402 } 403 return ep; 404} 405 406#define MIN_JIFFIES ((msecs_to_jiffies(2) > 1) ? msecs_to_jiffies(2) : 2) 407 408static inline void start_transfer(struct sl811 *sl811) 409{ |
410 if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) | 410 if (sl811->port1 & USB_PORT_STAT_SUSPEND) |
411 return; 412 if (sl811->active_a == NULL) { 413 sl811->active_a = start(sl811, SL811_EP_A(SL811_HOST_BUF)); 414 if (sl811->active_a != NULL) 415 sl811->jiffies_a = jiffies + MIN_JIFFIES; 416 } 417#ifdef USE_B 418 if (sl811->active_b == NULL) { --- 297 unchanged lines hidden (view full) --- 716 sl811->active_b = NULL; 717 } 718#endif 719 720 /* port status seems weird until after reset, so 721 * force the reset and make khubd clean up later. 722 */ 723 if (irqstat & SL11H_INTMASK_RD) | 411 return; 412 if (sl811->active_a == NULL) { 413 sl811->active_a = start(sl811, SL811_EP_A(SL811_HOST_BUF)); 414 if (sl811->active_a != NULL) 415 sl811->jiffies_a = jiffies + MIN_JIFFIES; 416 } 417#ifdef USE_B 418 if (sl811->active_b == NULL) { --- 297 unchanged lines hidden (view full) --- 716 sl811->active_b = NULL; 717 } 718#endif 719 720 /* port status seems weird until after reset, so 721 * force the reset and make khubd clean up later. 722 */ 723 if (irqstat & SL11H_INTMASK_RD) |
724 sl811->port1 &= ~(1 << USB_PORT_FEAT_CONNECTION); | 724 sl811->port1 &= ~USB_PORT_STAT_CONNECTION; |
725 else | 725 else |
726 sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION; | 726 sl811->port1 |= USB_PORT_STAT_CONNECTION; |
727 | 727 |
728 sl811->port1 |= 1 << USB_PORT_FEAT_C_CONNECTION; | 728 sl811->port1 |= USB_PORT_STAT_C_CONNECTION << 16; |
729 730 } else if (irqstat & SL11H_INTMASK_RD) { | 729 730 } else if (irqstat & SL11H_INTMASK_RD) { |
731 if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) { | 731 if (sl811->port1 & USB_PORT_STAT_SUSPEND) { |
732 DBG("wakeup\n"); | 732 DBG("wakeup\n"); |
733 sl811->port1 |= 1 << USB_PORT_FEAT_C_SUSPEND; | 733 sl811->port1 |= USB_PORT_STAT_C_SUSPEND << 16; |
734 sl811->stat_wake++; 735 } else 736 irqstat &= ~SL11H_INTMASK_RD; 737 } 738 739 if (irqstat) { | 734 sl811->stat_wake++; 735 } else 736 irqstat &= ~SL11H_INTMASK_RD; 737 } 738 739 if (irqstat) { |
740 if (sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)) | 740 if (sl811->port1 & USB_PORT_STAT_ENABLE) |
741 start_transfer(sl811); 742 ret = IRQ_HANDLED; 743 if (retries--) 744 goto retry; 745 } 746 747 if (sl811->periodic_count == 0 && list_empty(&sl811->async)) 748 sofirq_off(sl811); --- 65 unchanged lines hidden (view full) --- 814 815 /* avoid all allocations within spinlocks */ 816 if (!hep->hcpriv) 817 ep = kzalloc(sizeof *ep, mem_flags); 818 819 spin_lock_irqsave(&sl811->lock, flags); 820 821 /* don't submit to a dead or disabled port */ | 741 start_transfer(sl811); 742 ret = IRQ_HANDLED; 743 if (retries--) 744 goto retry; 745 } 746 747 if (sl811->periodic_count == 0 && list_empty(&sl811->async)) 748 sofirq_off(sl811); --- 65 unchanged lines hidden (view full) --- 814 815 /* avoid all allocations within spinlocks */ 816 if (!hep->hcpriv) 817 ep = kzalloc(sizeof *ep, mem_flags); 818 819 spin_lock_irqsave(&sl811->lock, flags); 820 821 /* don't submit to a dead or disabled port */ |
822 if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)) | 822 if (!(sl811->port1 & USB_PORT_STAT_ENABLE) |
823 || !HC_IS_RUNNING(hcd->state)) { 824 retval = -ENODEV; 825 kfree(ep); 826 goto fail_not_linked; 827 } 828 retval = usb_hcd_link_urb_to_ep(hcd, urb); 829 if (retval) { 830 kfree(ep); --- 283 unchanged lines hidden (view full) --- 1114 1115static void 1116sl811h_timer(unsigned long _sl811) 1117{ 1118 struct sl811 *sl811 = (void *) _sl811; 1119 unsigned long flags; 1120 u8 irqstat; 1121 u8 signaling = sl811->ctrl1 & SL11H_CTL1MASK_FORCE; | 823 || !HC_IS_RUNNING(hcd->state)) { 824 retval = -ENODEV; 825 kfree(ep); 826 goto fail_not_linked; 827 } 828 retval = usb_hcd_link_urb_to_ep(hcd, urb); 829 if (retval) { 830 kfree(ep); --- 283 unchanged lines hidden (view full) --- 1114 1115static void 1116sl811h_timer(unsigned long _sl811) 1117{ 1118 struct sl811 *sl811 = (void *) _sl811; 1119 unsigned long flags; 1120 u8 irqstat; 1121 u8 signaling = sl811->ctrl1 & SL11H_CTL1MASK_FORCE; |
1122 const u32 mask = (1 << USB_PORT_FEAT_CONNECTION) 1123 | (1 << USB_PORT_FEAT_ENABLE) | 1122 const u32 mask = USB_PORT_STAT_CONNECTION 1123 | USB_PORT_STAT_ENABLE |
1124 | USB_PORT_STAT_LOW_SPEED; 1125 1126 spin_lock_irqsave(&sl811->lock, flags); 1127 1128 /* stop special signaling */ 1129 sl811->ctrl1 &= ~SL11H_CTL1MASK_FORCE; 1130 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); 1131 udelay(3); 1132 1133 irqstat = sl811_read(sl811, SL11H_IRQ_STATUS); 1134 1135 switch (signaling) { 1136 case SL11H_CTL1MASK_SE0: 1137 DBG("end reset\n"); | 1124 | USB_PORT_STAT_LOW_SPEED; 1125 1126 spin_lock_irqsave(&sl811->lock, flags); 1127 1128 /* stop special signaling */ 1129 sl811->ctrl1 &= ~SL11H_CTL1MASK_FORCE; 1130 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); 1131 udelay(3); 1132 1133 irqstat = sl811_read(sl811, SL11H_IRQ_STATUS); 1134 1135 switch (signaling) { 1136 case SL11H_CTL1MASK_SE0: 1137 DBG("end reset\n"); |
1138 sl811->port1 = (1 << USB_PORT_FEAT_C_RESET) 1139 | (1 << USB_PORT_FEAT_POWER); | 1138 sl811->port1 = (USB_PORT_STAT_C_RESET << 16) 1139 | USB_PORT_STAT_POWER; |
1140 sl811->ctrl1 = 0; 1141 /* don't wrongly ack RD */ 1142 if (irqstat & SL11H_INTMASK_INSRMV) 1143 irqstat &= ~SL11H_INTMASK_RD; 1144 break; 1145 case SL11H_CTL1MASK_K: 1146 DBG("end resume\n"); | 1140 sl811->ctrl1 = 0; 1141 /* don't wrongly ack RD */ 1142 if (irqstat & SL11H_INTMASK_INSRMV) 1143 irqstat &= ~SL11H_INTMASK_RD; 1144 break; 1145 case SL11H_CTL1MASK_K: 1146 DBG("end resume\n"); |
1147 sl811->port1 &= ~(1 << USB_PORT_FEAT_SUSPEND); | 1147 sl811->port1 &= ~USB_PORT_STAT_SUSPEND; |
1148 break; 1149 default: 1150 DBG("odd timer signaling: %02x\n", signaling); 1151 break; 1152 } 1153 sl811_write(sl811, SL11H_IRQ_STATUS, irqstat); 1154 1155 if (irqstat & SL11H_INTMASK_RD) { 1156 /* usbcore nukes all pending transactions on disconnect */ | 1148 break; 1149 default: 1150 DBG("odd timer signaling: %02x\n", signaling); 1151 break; 1152 } 1153 sl811_write(sl811, SL11H_IRQ_STATUS, irqstat); 1154 1155 if (irqstat & SL11H_INTMASK_RD) { 1156 /* usbcore nukes all pending transactions on disconnect */ |
1157 if (sl811->port1 & (1 << USB_PORT_FEAT_CONNECTION)) 1158 sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION) 1159 | (1 << USB_PORT_FEAT_C_ENABLE); | 1157 if (sl811->port1 & USB_PORT_STAT_CONNECTION) 1158 sl811->port1 |= (USB_PORT_STAT_C_CONNECTION << 16) 1159 | (USB_PORT_STAT_C_ENABLE << 16); |
1160 sl811->port1 &= ~mask; 1161 sl811->irq_enable = SL11H_INTMASK_INSRMV; 1162 } else { 1163 sl811->port1 |= mask; 1164 if (irqstat & SL11H_INTMASK_DP) 1165 sl811->port1 &= ~USB_PORT_STAT_LOW_SPEED; 1166 sl811->irq_enable = SL11H_INTMASK_INSRMV | SL11H_INTMASK_RD; 1167 } 1168 | 1160 sl811->port1 &= ~mask; 1161 sl811->irq_enable = SL11H_INTMASK_INSRMV; 1162 } else { 1163 sl811->port1 |= mask; 1164 if (irqstat & SL11H_INTMASK_DP) 1165 sl811->port1 &= ~USB_PORT_STAT_LOW_SPEED; 1166 sl811->irq_enable = SL11H_INTMASK_INSRMV | SL11H_INTMASK_RD; 1167 } 1168 |
1169 if (sl811->port1 & (1 << USB_PORT_FEAT_CONNECTION)) { | 1169 if (sl811->port1 & USB_PORT_STAT_CONNECTION) { |
1170 u8 ctrl2 = SL811HS_CTL2_INIT; 1171 1172 sl811->irq_enable |= SL11H_INTMASK_DONE_A; 1173#ifdef USE_B 1174 sl811->irq_enable |= SL11H_INTMASK_DONE_B; 1175#endif 1176 if (sl811->port1 & USB_PORT_STAT_LOW_SPEED) { 1177 sl811->ctrl1 |= SL11H_CTL1MASK_LSPD; --- 50 unchanged lines hidden (view full) --- 1228 } 1229 break; 1230 case ClearPortFeature: 1231 if (wIndex != 1 || wLength != 0) 1232 goto error; 1233 1234 switch (wValue) { 1235 case USB_PORT_FEAT_ENABLE: | 1170 u8 ctrl2 = SL811HS_CTL2_INIT; 1171 1172 sl811->irq_enable |= SL11H_INTMASK_DONE_A; 1173#ifdef USE_B 1174 sl811->irq_enable |= SL11H_INTMASK_DONE_B; 1175#endif 1176 if (sl811->port1 & USB_PORT_STAT_LOW_SPEED) { 1177 sl811->ctrl1 |= SL11H_CTL1MASK_LSPD; --- 50 unchanged lines hidden (view full) --- 1228 } 1229 break; 1230 case ClearPortFeature: 1231 if (wIndex != 1 || wLength != 0) 1232 goto error; 1233 1234 switch (wValue) { 1235 case USB_PORT_FEAT_ENABLE: |
1236 sl811->port1 &= (1 << USB_PORT_FEAT_POWER); | 1236 sl811->port1 &= USB_PORT_STAT_POWER; |
1237 sl811->ctrl1 = 0; 1238 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); 1239 sl811->irq_enable = SL11H_INTMASK_INSRMV; 1240 sl811_write(sl811, SL11H_IRQ_ENABLE, 1241 sl811->irq_enable); 1242 break; 1243 case USB_PORT_FEAT_SUSPEND: | 1237 sl811->ctrl1 = 0; 1238 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); 1239 sl811->irq_enable = SL11H_INTMASK_INSRMV; 1240 sl811_write(sl811, SL11H_IRQ_ENABLE, 1241 sl811->irq_enable); 1242 break; 1243 case USB_PORT_FEAT_SUSPEND: |
1244 if (!(sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND))) | 1244 if (!(sl811->port1 & USB_PORT_STAT_SUSPEND)) |
1245 break; 1246 1247 /* 20 msec of resume/K signaling, other irqs blocked */ 1248 DBG("start resume...\n"); 1249 sl811->irq_enable = 0; 1250 sl811_write(sl811, SL11H_IRQ_ENABLE, 1251 sl811->irq_enable); 1252 sl811->ctrl1 |= SL11H_CTL1MASK_K; --- 32 unchanged lines hidden (view full) --- 1285#endif 1286 DBG("GetPortStatus %08x\n", sl811->port1); 1287 break; 1288 case SetPortFeature: 1289 if (wIndex != 1 || wLength != 0) 1290 goto error; 1291 switch (wValue) { 1292 case USB_PORT_FEAT_SUSPEND: | 1245 break; 1246 1247 /* 20 msec of resume/K signaling, other irqs blocked */ 1248 DBG("start resume...\n"); 1249 sl811->irq_enable = 0; 1250 sl811_write(sl811, SL11H_IRQ_ENABLE, 1251 sl811->irq_enable); 1252 sl811->ctrl1 |= SL11H_CTL1MASK_K; --- 32 unchanged lines hidden (view full) --- 1285#endif 1286 DBG("GetPortStatus %08x\n", sl811->port1); 1287 break; 1288 case SetPortFeature: 1289 if (wIndex != 1 || wLength != 0) 1290 goto error; 1291 switch (wValue) { 1292 case USB_PORT_FEAT_SUSPEND: |
1293 if (sl811->port1 & (1 << USB_PORT_FEAT_RESET)) | 1293 if (sl811->port1 & USB_PORT_STAT_RESET) |
1294 goto error; | 1294 goto error; |
1295 if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))) | 1295 if (!(sl811->port1 & USB_PORT_STAT_ENABLE)) |
1296 goto error; 1297 1298 DBG("suspend...\n"); 1299 sl811->ctrl1 &= ~SL11H_CTL1MASK_SOF_ENA; 1300 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); 1301 break; 1302 case USB_PORT_FEAT_POWER: 1303 port_power(sl811, 1); 1304 break; 1305 case USB_PORT_FEAT_RESET: | 1296 goto error; 1297 1298 DBG("suspend...\n"); 1299 sl811->ctrl1 &= ~SL11H_CTL1MASK_SOF_ENA; 1300 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); 1301 break; 1302 case USB_PORT_FEAT_POWER: 1303 port_power(sl811, 1); 1304 break; 1305 case USB_PORT_FEAT_RESET: |
1306 if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) | 1306 if (sl811->port1 & USB_PORT_STAT_SUSPEND) |
1307 goto error; | 1307 goto error; |
1308 if (!(sl811->port1 & (1 << USB_PORT_FEAT_POWER))) | 1308 if (!(sl811->port1 & USB_PORT_STAT_POWER)) |
1309 break; 1310 1311 /* 50 msec of reset/SE0 signaling, irqs blocked */ 1312 sl811->irq_enable = 0; 1313 sl811_write(sl811, SL11H_IRQ_ENABLE, 1314 sl811->irq_enable); 1315 sl811->ctrl1 = SL11H_CTL1MASK_SE0; 1316 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); | 1309 break; 1310 1311 /* 50 msec of reset/SE0 signaling, irqs blocked */ 1312 sl811->irq_enable = 0; 1313 sl811_write(sl811, SL11H_IRQ_ENABLE, 1314 sl811->irq_enable); 1315 sl811->ctrl1 = SL11H_CTL1MASK_SE0; 1316 sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); |
1317 sl811->port1 |= (1 << USB_PORT_FEAT_RESET); | 1317 sl811->port1 |= USB_PORT_STAT_RESET; |
1318 mod_timer(&sl811->timer, jiffies 1319 + msecs_to_jiffies(50)); 1320 break; 1321 default: 1322 goto error; 1323 } 1324 sl811->port1 |= 1 << wValue; 1325 break; --- 512 unchanged lines hidden --- | 1318 mod_timer(&sl811->timer, jiffies 1319 + msecs_to_jiffies(50)); 1320 break; 1321 default: 1322 goto error; 1323 } 1324 sl811->port1 |= 1 << wValue; 1325 break; --- 512 unchanged lines hidden --- |