static int isp1301_set_peripheral(struct otg_transceiver *otg, struct usb_gadget *gadget) { struct isp1301 *isp = container_of(otg, struct isp1301, otg); if (!otg || isp != the_transceiver) return -ENODEV; if (!gadget) { OTG_IRQ_EN_REG = 0; if (!isp->otg.default_a) enable_vbus_draw(isp, 0); usb_gadget_vbus_disconnect(isp->otg.gadget); isp->otg.gadget = 0; power_down(isp); return 0; } #ifdef CONFIG_USB_OTG isp->otg.gadget = gadget; dev_dbg(&isp->client.dev, "registered gadget\n"); /* gadget driver may be suspended until vbus_connect () */ if (isp->otg.host) return isp1301_otg_enable(isp); return 0; #elif !defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE) isp->otg.gadget = gadget; // FIXME update its refcount OTG_CTRL_REG = (OTG_CTRL_REG & OTG_CTRL_MASK & ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS)) | OTG_ID; power_up(isp); isp->otg.state = OTG_STATE_B_IDLE; if (machine_is_omap_h2()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, INTR_SESS_VLD); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_VBUS_VLD); dev_info(&isp->client.dev, "B-Peripheral sessions ok\n"); dump_regs(isp, __FUNCTION__); /* If this has a Mini-AB connector, this mode is highly * nonstandard ... but can be handy for testing, so long * as you don't plug a Mini-A cable into the jack. */ if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD) b_peripheral(isp); return 0; #else dev_dbg(&isp->client.dev, "peripheral sessions not allowed\n"); return -EINVAL; #endif }
/* add or disable the host device+driver */ static int isp1301_set_host(struct otg_transceiver *otg, struct usb_bus *host) { struct isp1301 *isp = container_of(otg, struct isp1301, otg); if (!otg || isp != the_transceiver) return -ENODEV; if (!host) { omap_writew(0, OTG_IRQ_EN); power_down(isp); isp->otg.host = NULL; return 0; } #ifdef CONFIG_USB_OTG isp->otg.host = host; dev_dbg(&isp->client->dev, "registered host\n"); host_suspend(isp); if (isp->otg.gadget) return isp1301_otg_enable(isp); return 0; #elif !defined(CONFIG_USB_GADGET_OMAP) // FIXME update its refcount isp->otg.host = host; power_up(isp); if (machine_is_omap_h2()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); dev_info(&isp->client->dev, "A-Host sessions ok\n"); isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, INTR_ID_GND); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_ID_GND); /* If this has a Mini-AB connector, this mode is highly * nonstandard ... but can be handy for testing, especially with * the Mini-A end of an OTG cable. (Or something nonstandard * like MiniB-to-StandardB, maybe built with a gender mender.) */ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_VBUS_DRV); dump_regs(isp, __func__); return 0; #else dev_dbg(&isp->client->dev, "host sessions not allowed\n"); return -EINVAL; #endif }
static int isp1301_otg_enable(struct isp1301 *isp) { power_up(isp); otg_init(isp); /* NOTE: since we don't change this, this provides * a few more interrupts than are strictly needed. */ isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_VBUS_VLD | INTR_SESS_VLD | INTR_ID_GND); dev_info(&isp->client->dev, "ready for dual-role USB ...\n"); return 0; }
static void power_up(struct isp1301 *isp) { // isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND); /* do this only when cpu is driving transceiver, * so host won't see a low speed device... */ isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); }
static void power_down(struct isp1301 *isp) { isp->otg.state = OTG_STATE_UNDEFINED; // isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_GLOBAL_PWR_DN); isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SUSPEND); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_ID_PULLDOWN); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); }
static int isp1301_start_hnp(struct otg_transceiver *dev) { #ifdef CONFIG_USB_OTG struct isp1301 *isp = container_of(dev, struct isp1301, otg); u32 l; if (!dev || isp != the_transceiver) return -ENODEV; if (isp->otg.default_a && (isp->otg.host == NULL || !isp->otg.host->b_hnp_enable)) return -ENOTCONN; if (!isp->otg.default_a && (isp->otg.gadget == NULL || !isp->otg.gadget->b_hnp_enable)) return -ENOTCONN; /* We want hardware to manage most HNP protocol timings. * So do this part as early as possible... */ switch (isp->otg.state) { case OTG_STATE_B_HOST: isp->otg.state = OTG_STATE_B_PERIPHERAL; /* caller will suspend next */ break; case OTG_STATE_A_HOST: #if 0 /* autoconnect mode avoids irq latency bugs */ isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_BDIS_ACON_EN); #endif /* caller must suspend then clear A_BUSREQ */ usb_gadget_vbus_connect(isp->otg.gadget); l = omap_readl(OTG_CTRL); l |= OTG_A_SETB_HNPEN; omap_writel(l, OTG_CTRL); break; case OTG_STATE_A_PERIPHERAL: /* initiated by B-Host suspend */ break; default: return -EILSEQ; } pr_debug("otg: HNP %s, %06x ...\n", state_name(isp), omap_readl(OTG_CTRL)); check_state(isp, __func__); return 0; #else /* srp-only */ return -EINVAL; #endif }
static void b_peripheral(struct isp1301 *isp) { OTG_CTRL_REG = OTG_CTRL_REG & OTG_XCEIV_OUTPUTS; usb_gadget_vbus_connect(isp->otg.gadget); #ifdef CONFIG_USB_OTG enable_vbus_draw(isp, 8); otg_update_isp(isp); #else enable_vbus_draw(isp, 100); /* UDC driver just set OTG_BSESSVLD */ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN); isp->otg.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); dump_regs(isp, "2periph"); #endif }
static void isp_update_otg(struct isp1301 *isp, u8 stat) { u8 isp_stat, isp_bstat; enum usb_otg_state state = isp->otg.state; if (stat & INTR_BDIS_ACON) pr_debug("OTG: BDIS_ACON, %s\n", state_name(isp)); /* start certain state transitions right away */ isp_stat = isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE); if (isp_stat & INTR_ID_GND) { if (isp->otg.default_a) { switch (state) { case OTG_STATE_B_IDLE: a_idle(isp, "idle"); /* FALLTHROUGH */ case OTG_STATE_A_IDLE: enable_vbus_source(isp); /* FALLTHROUGH */ case OTG_STATE_A_WAIT_VRISE: /* we skip over OTG_STATE_A_WAIT_BCON, since * the HC will transition to A_HOST (or * A_SUSPEND!) without our noticing except * when HNP is used. */ if (isp_stat & INTR_VBUS_VLD) isp->otg.state = OTG_STATE_A_HOST; break; case OTG_STATE_A_WAIT_VFALL: if (!(isp_stat & INTR_SESS_VLD)) a_idle(isp, "vfell"); break; default: if (!(isp_stat & INTR_VBUS_VLD)) isp->otg.state = OTG_STATE_A_VBUS_ERR; break; } isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); } else { switch (state) { case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_HOST: case OTG_STATE_B_WAIT_ACON: usb_gadget_vbus_disconnect(isp->otg.gadget); break; default: break; } if (state != OTG_STATE_A_IDLE) a_idle(isp, "id"); if (isp->otg.host && state == OTG_STATE_A_IDLE) isp1301_defer_work(isp, WORK_HOST_RESUME); isp_bstat = 0; } } else { u32 l; /* if user unplugged mini-A end of cable, * don't bypass A_WAIT_VFALL. */ if (isp->otg.default_a) { switch (state) { default: isp->otg.state = OTG_STATE_A_WAIT_VFALL; break; case OTG_STATE_A_WAIT_VFALL: state = OTG_STATE_A_IDLE; /* khubd may take a while to notice and * handle this disconnect, so don't go * to B_IDLE quite yet. */ break; case OTG_STATE_A_IDLE: host_suspend(isp); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_BDIS_ACON_EN); isp->otg.state = OTG_STATE_B_IDLE; l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; l &= ~OTG_CTRL_BITS; omap_writel(l, OTG_CTRL); break; case OTG_STATE_B_IDLE: break; } } isp_bstat = isp1301_get_u8(isp, ISP1301_OTG_STATUS); switch (isp->otg.state) { case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_WAIT_ACON: case OTG_STATE_B_HOST: if (likely(isp_bstat & OTG_B_SESS_VLD)) break; enable_vbus_draw(isp, 0); #ifndef CONFIG_USB_OTG /* UDC driver will clear OTG_BSESSVLD */ isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLDOWN); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DP_PULLUP); dump_regs(isp, __func__); #endif /* FALLTHROUGH */ case OTG_STATE_B_SRP_INIT: b_idle(isp, __func__); l = omap_readl(OTG_CTRL) & OTG_XCEIV_OUTPUTS; omap_writel(l, OTG_CTRL); /* FALLTHROUGH */ case OTG_STATE_B_IDLE: if (isp->otg.gadget && (isp_bstat & OTG_B_SESS_VLD)) { #ifdef CONFIG_USB_OTG update_otg1(isp, isp_stat); update_otg2(isp, isp_bstat); #endif b_peripheral(isp); } else if (!(isp_stat & (INTR_VBUS_VLD|INTR_SESS_VLD))) isp_bstat |= OTG_B_SESS_END; break; case OTG_STATE_A_WAIT_VFALL: break; default: pr_debug("otg: unsupported b-device %s\n", state_name(isp)); break; } } if (state != isp->otg.state) pr_debug(" isp, %s -> %s\n", state_string(state), state_name(isp)); #ifdef CONFIG_USB_OTG /* update the OTG controller state to match the isp1301; may * trigger OPRT_CHG irqs for changes going to the isp1301. */ update_otg1(isp, isp_stat); update_otg2(isp, isp_bstat); check_state(isp, __func__); #endif dump_regs(isp, "isp1301->otg"); }
/* inputs going to ISP1301 */ static void otg_update_isp(struct isp1301 *isp) { u32 otg_ctrl, otg_change; u8 set = OTG1_DM_PULLDOWN, clr = OTG1_DM_PULLUP; otg_ctrl = omap_readl(OTG_CTRL); otg_change = otg_ctrl ^ isp->last_otg_ctrl; isp->last_otg_ctrl = otg_ctrl; otg_ctrl = otg_ctrl & OTG_XCEIV_INPUTS; switch (isp->otg.state) { case OTG_STATE_B_IDLE: case OTG_STATE_B_PERIPHERAL: case OTG_STATE_B_SRP_INIT: if (!(otg_ctrl & OTG_PULLUP)) { // if (otg_ctrl & OTG_B_HNPEN) { if (isp->otg.gadget->b_hnp_enable) { isp->otg.state = OTG_STATE_B_WAIT_ACON; pr_debug(" --> b_wait_acon\n"); } goto pulldown; } pullup: set |= OTG1_DP_PULLUP; clr |= OTG1_DP_PULLDOWN; break; case OTG_STATE_A_SUSPEND: case OTG_STATE_A_PERIPHERAL: if (otg_ctrl & OTG_PULLUP) goto pullup; /* FALLTHROUGH */ // case OTG_STATE_B_WAIT_ACON: default: pulldown: set |= OTG1_DP_PULLDOWN; clr |= OTG1_DP_PULLUP; break; } # define toggle(OTG,ISP) do { \ if (otg_ctrl & OTG) set |= ISP; \ else clr |= ISP; \ } while (0) if (!(isp->otg.host)) otg_ctrl &= ~OTG_DRV_VBUS; switch (isp->otg.state) { case OTG_STATE_A_SUSPEND: if (otg_ctrl & OTG_DRV_VBUS) { set |= OTG1_VBUS_DRV; break; } /* HNP failed for some reason (A_AIDL_BDIS timeout) */ notresponding(isp); /* FALLTHROUGH */ case OTG_STATE_A_VBUS_ERR: isp->otg.state = OTG_STATE_A_WAIT_VFALL; pr_debug(" --> a_wait_vfall\n"); /* FALLTHROUGH */ case OTG_STATE_A_WAIT_VFALL: /* FIXME usbcore thinks port power is still on ... */ clr |= OTG1_VBUS_DRV; break; case OTG_STATE_A_IDLE: if (otg_ctrl & OTG_DRV_VBUS) { isp->otg.state = OTG_STATE_A_WAIT_VRISE; pr_debug(" --> a_wait_vrise\n"); } /* FALLTHROUGH */ default: toggle(OTG_DRV_VBUS, OTG1_VBUS_DRV); } toggle(OTG_PU_VBUS, OTG1_VBUS_CHRG); toggle(OTG_PD_VBUS, OTG1_VBUS_DISCHRG); # undef toggle isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, set); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, clr); /* HNP switch to host or peripheral; and SRP */ if (otg_change & OTG_PULLUP) { u32 l; switch (isp->otg.state) { case OTG_STATE_B_IDLE: if (clr & OTG1_DP_PULLUP) break; isp->otg.state = OTG_STATE_B_PERIPHERAL; pr_debug(" --> b_peripheral\n"); break; case OTG_STATE_A_SUSPEND: if (clr & OTG1_DP_PULLUP) break; isp->otg.state = OTG_STATE_A_PERIPHERAL; pr_debug(" --> a_peripheral\n"); break; default: break; } l = omap_readl(OTG_CTRL); l |= OTG_PULLUP; omap_writel(l, OTG_CTRL); } check_state(isp, __func__); dump_regs(isp, "otg->isp1301"); }
static int __init isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { int status; struct isp1301 *isp; if (the_transceiver) return 0; isp = kzalloc(sizeof *isp, GFP_KERNEL); if (!isp) return 0; INIT_WORK(&isp->work, isp1301_work); init_timer(&isp->timer); isp->timer.function = isp1301_timer; isp->timer.data = (unsigned long) isp; i2c_set_clientdata(i2c, isp); isp->client = i2c; /* verify the chip (shouldn't be necesary) */ status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); if (status != I2C_VENDOR_ID_PHILIPS) { dev_dbg(&i2c->dev, "not philips id: %d\n", status); goto fail; } status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID); if (status != I2C_PRODUCT_ID_PHILIPS_1301) { dev_dbg(&i2c->dev, "not isp1301, %d\n", status); goto fail; } isp->i2c_release = i2c->dev.release; i2c->dev.release = isp1301_release; /* initial development used chiprev 2.00 */ status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE); dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n", status >> 8, status & 0xff); /* make like power-on reset */ isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK); isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI); isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN)); isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0); isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0); isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0); #ifdef CONFIG_USB_OTG status = otg_bind(isp); if (status < 0) { dev_dbg(&i2c->dev, "can't bind OTG\n"); goto fail; } #endif if (machine_is_omap_h2()) { /* full speed signaling by default */ isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SPEED); isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_SPD_SUSP_CTRL); /* IRQ wired at M14 */ omap_cfg_reg(M14_1510_GPIO2); if (gpio_request(2, "isp1301") == 0) gpio_direction_input(2); isp->irq_type = IRQF_TRIGGER_FALLING; } isp->irq_type |= IRQF_SAMPLE_RANDOM; status = request_irq(i2c->irq, isp1301_irq, isp->irq_type, DRIVER_NAME, isp); if (status < 0) { dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n", i2c->irq, status); goto fail; } isp->otg.dev = &i2c->dev; isp->otg.label = DRIVER_NAME; isp->otg.set_host = isp1301_set_host, isp->otg.set_peripheral = isp1301_set_peripheral, isp->otg.set_power = isp1301_set_power, isp->otg.start_srp = isp1301_start_srp, isp->otg.start_hnp = isp1301_start_hnp, enable_vbus_draw(isp, 0); power_down(isp); the_transceiver = isp; #ifdef CONFIG_USB_OTG update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE)); update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS)); #endif dump_regs(isp, __func__); #ifdef VERBOSE mod_timer(&isp->timer, jiffies + TIMER_JIFFIES); dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); #endif status = otg_set_transceiver(&isp->otg); if (status < 0) dev_err(&i2c->dev, "can't register transceiver, %d\n", status); return 0; fail: kfree(isp); return -ENODEV; }
/* no error returns, they'd just make bus scanning stop */ static int isp1301_probe(struct i2c_adapter *bus, int address, int kind) { int status; struct isp1301 *isp; struct i2c_client *i2c; if (the_transceiver) return 0; isp = kzalloc(sizeof *isp, GFP_KERNEL); if (!isp) return 0; INIT_WORK(&isp->work, isp1301_work, isp); init_timer(&isp->timer); isp->timer.function = isp1301_timer; isp->timer.data = (unsigned long) isp; isp->irq = -1; isp->client.addr = address; i2c_set_clientdata(&isp->client, isp); isp->client.adapter = bus; isp->client.driver = &isp1301_driver; strlcpy(isp->client.name, DRIVER_NAME, I2C_NAME_SIZE); i2c = &isp->client; /* if this is a true probe, verify the chip ... */ if (kind < 0) { status = isp1301_get_u16(isp, ISP1301_VENDOR_ID); if (status != I2C_VENDOR_ID_PHILIPS) { dev_dbg(&bus->dev, "addr %d not philips id: %d\n", address, status); goto fail1; } status = isp1301_get_u16(isp, ISP1301_PRODUCT_ID); if (status != I2C_PRODUCT_ID_PHILIPS_1301) { dev_dbg(&bus->dev, "%d not isp1301, %d\n", address, status); goto fail1; } } status = i2c_attach_client(i2c); if (status < 0) { dev_dbg(&bus->dev, "can't attach %s to device %d, err %d\n", DRIVER_NAME, address, status); fail1: kfree(isp); return 0; } isp->i2c_release = i2c->dev.release; i2c->dev.release = isp1301_release; /* initial development used chiprev 2.00 */ status = i2c_smbus_read_word_data(i2c, ISP1301_BCD_DEVICE); dev_info(&i2c->dev, "chiprev %x.%02x, driver " DRIVER_VERSION "\n", status >> 8, status & 0xff); /* make like power-on reset */ isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_1, MC1_MASK); isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_BI_DI); isp1301_clear_bits(isp, ISP1301_MODE_CONTROL_2, ~MC2_BI_DI); isp1301_set_bits(isp, ISP1301_OTG_CONTROL_1, OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN); isp1301_clear_bits(isp, ISP1301_OTG_CONTROL_1, ~(OTG1_DM_PULLDOWN | OTG1_DP_PULLDOWN)); isp1301_clear_bits(isp, ISP1301_INTERRUPT_LATCH, ~0); isp1301_clear_bits(isp, ISP1301_INTERRUPT_FALLING, ~0); isp1301_clear_bits(isp, ISP1301_INTERRUPT_RISING, ~0); #ifdef CONFIG_USB_OTG status = otg_bind(isp); if (status < 0) { dev_dbg(&i2c->dev, "can't bind OTG\n"); goto fail2; } #endif if (machine_is_omap_h2()) { /* full speed signaling by default */ isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_SPEED_REG); isp1301_set_bits(isp, ISP1301_MODE_CONTROL_2, MC2_SPD_SUSP_CTRL); /* IRQ wired at M14 */ omap_cfg_reg(M14_1510_GPIO2); isp->irq = OMAP_GPIO_IRQ(2); omap_request_gpio(2); omap_set_gpio_direction(2, 1); omap_set_gpio_edge_ctrl(2, OMAP_GPIO_FALLING_EDGE); } status = request_irq(isp->irq, isp1301_irq, IRQF_SAMPLE_RANDOM, DRIVER_NAME, isp); if (status < 0) { dev_dbg(&i2c->dev, "can't get IRQ %d, err %d\n", isp->irq, status); #ifdef CONFIG_USB_OTG fail2: #endif i2c_detach_client(i2c); goto fail1; } isp->otg.dev = &isp->client.dev; isp->otg.label = DRIVER_NAME; isp->otg.set_host = isp1301_set_host, isp->otg.set_peripheral = isp1301_set_peripheral, isp->otg.set_power = isp1301_set_power, isp->otg.start_srp = isp1301_start_srp, isp->otg.start_hnp = isp1301_start_hnp, enable_vbus_draw(isp, 0); power_down(isp); the_transceiver = isp; #ifdef CONFIG_USB_OTG update_otg1(isp, isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE)); update_otg2(isp, isp1301_get_u8(isp, ISP1301_OTG_STATUS)); #endif dump_regs(isp, __FUNCTION__); #ifdef VERBOSE mod_timer(&isp->timer, jiffies + TIMER_JIFFIES); dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); #endif status = otg_set_transceiver(&isp->otg); if (status < 0) dev_err(&i2c->dev, "can't register transceiver, %d\n", status); return 0; }
static int isp1301_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { struct isp1301 *isp = container_of(otg->phy, struct isp1301, phy); if (isp != the_transceiver) return -ENODEV; if (!gadget) { omap_writew(0, OTG_IRQ_EN); if (!otg->default_a) enable_vbus_draw(isp, 0); usb_gadget_vbus_disconnect(otg->gadget); otg->gadget = NULL; power_down(isp); return 0; } #ifdef CONFIG_USB_OTG otg->gadget = gadget; dev_dbg(&isp->client->dev, "registered gadget\n"); /* gadget driver may be suspended until vbus_connect () */ if (otg->host) return isp1301_otg_enable(isp); return 0; #elif !defined(CONFIG_USB_OHCI_HCD) && !defined(CONFIG_USB_OHCI_HCD_MODULE) otg->gadget = gadget; // FIXME update its refcount { u32 l; l = omap_readl(OTG_CTRL) & OTG_CTRL_MASK; l &= ~(OTG_XCEIV_OUTPUTS|OTG_CTRL_BITS); l |= OTG_ID; omap_writel(l, OTG_CTRL); } power_up(isp); isp->phy.otg->state = OTG_STATE_B_IDLE; if (machine_is_omap_h2() || machine_is_omap_h3()) isp1301_set_bits(isp, ISP1301_MODE_CONTROL_1, MC1_DAT_SE0); isp1301_set_bits(isp, ISP1301_INTERRUPT_RISING, INTR_SESS_VLD); isp1301_set_bits(isp, ISP1301_INTERRUPT_FALLING, INTR_VBUS_VLD); dev_info(&isp->client->dev, "B-Peripheral sessions ok\n"); dump_regs(isp, __func__); /* If this has a Mini-AB connector, this mode is highly * nonstandard ... but can be handy for testing, so long * as you don't plug a Mini-A cable into the jack. */ if (isp1301_get_u8(isp, ISP1301_INTERRUPT_SOURCE) & INTR_VBUS_VLD) b_peripheral(isp); return 0; #else dev_dbg(&isp->client->dev, "peripheral sessions not allowed\n"); return -EINVAL; #endif }