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_status_data(struct usb_hcd *hcd, char *buf) { struct c67x00_hcd *c67x00 = hcd_to_c67x00_hcd(hcd); struct c67x00_sie *sie = c67x00->sie; u16 status; int i; *buf = 0; status = c67x00_ll_usb_get_status(sie); for (i = 0; i < C67X00_PORTS; i++) if (status & PORT_CONNECT_CHANGE(i)) *buf |= (1 << i); /* bit 0 denotes hub change, b1..n port change */ *buf <<= 1; return !!*buf; }
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; }