/** * c67x00_hcd_irq * * This function is called from the interrupt handler in c67x00-drv.c */ static void c67x00_hcd_irq(struct c67x00_sie *sie, u16 int_status, u16 msg) { struct c67x00_hcd *c67x00 = sie->private_data; struct usb_hcd *hcd = c67x00_hcd_to_hcd(c67x00); /* Handle sie message flags */ if (msg) { if (msg & HUSB_TDListDone) c67x00_sched_kick(c67x00); else dev_warn(c67x00_hcd_dev(c67x00), "Unknown SIE msg flag(s): 0x%04x\n", msg); } if (unlikely(hcd->state == HC_STATE_HALT)) return; if (!HCD_HW_ACCESSIBLE(hcd)) return; /* Handle Start of frame events */ if (int_status & SOFEOP_FLG(sie->sie_num)) { c67x00_ll_usb_clear_status(sie, SOF_EOP_IRQ_FLG); c67x00_sched_kick(c67x00); } }
void c67x00_ll_husb_init_host_port(struct c67x00_sie *sie) { /* Set port into host mode */ hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), HOST_MODE); c67x00_ll_husb_sie_init(sie); /* Clear interrupts */ c67x00_ll_usb_clear_status(sie, HOST_STAT_MASK); /* Check */ if (!(hpi_read_word(sie->dev, USB_CTL_REG(sie->sie_num)) & HOST_MODE)) dev_warn(sie_dev(sie), "SIE %d not set to host mode\n", sie->sie_num); }
void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port) { /* Clear connect change */ c67x00_ll_usb_clear_status(sie, PORT_CONNECT_CHANGE(port)); /* Enable interrupts */ hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG, SOFEOP_TO_CPU_EN(sie->sie_num)); hpi_set_bits(sie->dev, HOST_IRQ_EN_REG(sie->sie_num), SOF_EOP_IRQ_EN | DONE_IRQ_EN); /* Enable pull down transistors */ hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), PORT_RES_EN(port)); }
void c67x00_ll_husb_reset_port(struct c67x00_sie *sie, int port) { c67x00_ll_usb_clear_status(sie, PORT_CONNECT_CHANGE(port)); hpi_set_bits(sie->dev, HPI_IRQ_ROUTING_REG, SOFEOP_TO_CPU_EN(sie->sie_num)); hpi_set_bits(sie->dev, HOST_IRQ_EN_REG(sie->sie_num), SOF_EOP_IRQ_EN | DONE_IRQ_EN); hpi_set_bits(sie->dev, USB_CTL_REG(sie->sie_num), PORT_RES_EN(port)); }
static int c67x00_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd); struct c67x00_sie *sie = c67x00->sie; u16 status, usb_status; int len = 0; unsigned int port = wIndex-1; u16 wPortChange, wPortStatus; switch (typeReq) { case GetHubStatus: *(__le32 *) buf = cpu_to_le32(0); len = 4; /* hub power */ break; case GetPortStatus: if (wIndex > C67X00_PORTS) return -EPIPE; status = c67x00_ll_usb_get_status(sie); usb_status = c67x00_ll_get_usb_ctl(sie); wPortChange = 0; if (status & PORT_CONNECT_CHANGE(port)) wPortChange |= USB_PORT_STAT_C_CONNECTION; wPortStatus = USB_PORT_STAT_POWER; if (!(status & PORT_SE0_STATUS(port))) wPortStatus |= USB_PORT_STAT_CONNECTION; if (usb_status & LOW_SPEED_PORT(port)) { wPortStatus |= USB_PORT_STAT_LOW_SPEED; c67x00->low_speed_ports |= (1 << port); } else c67x00->low_speed_ports &= ~(1 << port); if (usb_status & SOF_EOP_EN(port)) wPortStatus |= USB_PORT_STAT_ENABLE; *(__le16 *) buf = cpu_to_le16(wPortStatus); *(__le16 *) (buf + 2) = cpu_to_le16(wPortChange); len = 4; break; case SetHubFeature: /* We don't implement these */ case ClearHubFeature: switch (wValue) { case C_HUB_OVER_CURRENT: case C_HUB_LOCAL_POWER: len = 0; break; default: return -EPIPE; } break; case SetPortFeature: if (wIndex > C67X00_PORTS) return -EPIPE; switch (wValue) { case USB_PORT_FEAT_SUSPEND: dev_dbg(c67x00_hcd_dev(c67x00), "SetPortFeature %d (SUSPEND)\n", port); len = 0; break; case USB_PORT_FEAT_RESET: c67x00_hub_reset_host_port(sie, port); len = 0; break; case USB_PORT_FEAT_POWER: /* Power always enabled */ len = 0; break; default: dev_dbg(c67x00_hcd_dev(c67x00), "%s: SetPortFeature %d (0x%04x) Error!\n", __func__, port, wValue); return -EPIPE; } break; case ClearPortFeature: if (wIndex > C67X00_PORTS) return -EPIPE; switch (wValue) { case USB_PORT_FEAT_ENABLE: /* Reset the port so that the c67x00 also notices the * disconnect */ c67x00_hub_reset_host_port(sie, port); len = 0; break; case USB_PORT_FEAT_C_ENABLE: dev_dbg(c67x00_hcd_dev(c67x00), "ClearPortFeature (%d): C_ENABLE\n", port); len = 0; break; case USB_PORT_FEAT_SUSPEND: dev_dbg(c67x00_hcd_dev(c67x00), "ClearPortFeature (%d): SUSPEND\n", port); len = 0; break; case USB_PORT_FEAT_C_SUSPEND: dev_dbg(c67x00_hcd_dev(c67x00), "ClearPortFeature (%d): C_SUSPEND\n", port); len = 0; break; case USB_PORT_FEAT_POWER: dev_dbg(c67x00_hcd_dev(c67x00), "ClearPortFeature (%d): POWER\n", port); return -EPIPE; case USB_PORT_FEAT_C_CONNECTION: c67x00_ll_usb_clear_status(sie, PORT_CONNECT_CHANGE(port)); len = 0; break; case USB_PORT_FEAT_C_OVER_CURRENT: dev_dbg(c67x00_hcd_dev(c67x00), "ClearPortFeature (%d): OVER_CURRENT\n", port); len = 0; break; case USB_PORT_FEAT_C_RESET: dev_dbg(c67x00_hcd_dev(c67x00), "ClearPortFeature (%d): C_RESET\n", port); len = 0; break; default: dev_dbg(c67x00_hcd_dev(c67x00), "%s: ClearPortFeature %d (0x%04x) Error!\n", __func__, port, wValue); return -EPIPE; } break; case GetHubDescriptor: len = min_t(unsigned int, sizeof(c67x00_hub_des), wLength); memcpy(buf, c67x00_hub_des, len); break; default: dev_dbg(c67x00_hcd_dev(c67x00), "%s: unknown\n", __func__); return -EPIPE; } return 0; }