static void twl4030_phy_power(void) { u8 pwr, clk; /* Power the PHY */ pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL); pwr &= ~PHYPWD; twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr); /* Enable clocks */ clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL); clk |= CLOCKGATING_EN | CLK32K_EN; twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk); }
static void twl4030_phy_power(struct twl4030_usb *twl, int on) { u8 pwr; pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { regulator_enable(twl->usb3v1); regulator_enable(twl->usb1v8); twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); regulator_enable(twl->usb1v5); pwr &= ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); regulator_disable(twl->usb1v5); regulator_disable(twl->usb1v8); regulator_disable(twl->usb3v1); } }
static void twl4030_phy_power(struct twl4030_usb *twl, int on) { u8 pwr; pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { regulator_enable(twl->usb3v1); regulator_enable(twl->usb1v8); /* * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP * in twl4030) resets the VUSB_DEDICATED2 register. This reset * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to * SLEEP. We work around this by clearing the bit after usv3v1 * is re-activated. This ensures that VUSB3V1 is really active. */ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); regulator_enable(twl->usb1v5); pwr &= ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); regulator_disable(twl->usb1v5); regulator_disable(twl->usb1v8); regulator_disable(twl->usb3v1); } }
static void __exit twl4030_usb_exit(void) { struct twl4030_usb *twl = the_transceiver; int val; usb_irq_disable(); free_irq(twl->irq, twl); /* set transceiver mode to power on defaults */ twl4030_usb_set_mode(twl, -1); /* autogate 60MHz ULPI clock, * clear dpll clock request for i2c access, * disable 32KHz */ val = twl4030_usb_read(PHY_CLK_CTRL); if (val >= 0) { val |= PHY_CLK_CTRL_CLOCKGATING_EN; val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); twl4030_usb_write(PHY_CLK_CTRL, (u8)val); } /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_phy_power(twl, 0); kfree(twl); }
static void twl4030_phy_power(struct twl4030_usb *twl, int on) { u8 pwr; pwr = twl4030_usb_read(PHY_PWR_CTRL); if (on) { pwr &= ~PHY_PWR_PHYPWD; if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) { printk(KERN_ERR "twl4030_usb: i2c write failed," " line %d\n", __LINE__); return; } twl4030_usb_write(PHY_CLK_CTRL, twl4030_usb_read(PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); } else { pwr |= PHY_PWR_PHYPWD; if (twl4030_usb_write_verify(PHY_PWR_CTRL, pwr) < 0) { printk(KERN_ERR "twl4030_usb: i2c write failed," " line %d\n", __LINE__); } } return; }
static int twl4030_usb_remove(struct platform_device *pdev) { struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; cancel_delayed_work(&twl->id_workaround_work); device_remove_file(twl->dev, &dev_attr_vbus); /* set transceiver mode to power on defaults */ twl4030_usb_set_mode(twl, -1); /* autogate 60MHz ULPI clock, * clear dpll clock request for i2c access, * disable 32KHz */ val = twl4030_usb_read(twl, PHY_CLK_CTRL); if (val >= 0) { val |= PHY_CLK_CTRL_CLOCKGATING_EN; val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); } /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); if (!twl->asleep) twl4030_phy_power(twl, 0); return 0; }
static int __exit twl4030_usb_remove(struct platform_device *pdev) { struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; free_irq(twl->irq, twl); device_remove_file(twl->dev, &dev_attr_vbus); twl4030_usb_set_mode(twl, -1); val = twl4030_usb_read(twl, PHY_CLK_CTRL); if (val >= 0) { val |= PHY_CLK_CTRL_CLOCKGATING_EN; val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); } twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); if (!twl->asleep) twl4030_phy_power(twl, 0); regulator_put(twl->usb1v5); regulator_put(twl->usb1v8); regulator_put(twl->usb3v1); kfree(twl->phy.otg); kfree(twl); return 0; }
static void twl4030_phy_power(struct twl4030_usb *twl, int on) { if (on) { regulator_enable(twl->usb3v1); regulator_enable(twl->usb1v8); /* * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP * in twl4030) resets the VUSB_DEDICATED2 register. This reset * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to * SLEEP. We work around this by clearing the bit after usv3v1 * is re-activated. This ensures that VUSB3V1 is really active. */ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); regulator_enable(twl->usb1v5); __twl4030_phy_power(twl, 1); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); } else { __twl4030_phy_power(twl, 0); regulator_disable(twl->usb1v5); regulator_disable(twl->usb1v8); #ifndef CONFIG_TWL4030_MADC regulator_disable(twl->usb3v1); #endif } }
static void twl4030_phy_power(struct twl4030_usb *twl, int on) { u8 pwr; pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); printk(KERN_ERR "twl4030_phy_power + : PHY_PWR_CTRL=%x ====^^==== (twl4030-usb.c)\n", pwr); pwr = twl4030_usb_read(twl, PHY_CLK_CTRL); printk(KERN_ERR "twl4030_phy_power + : PHY_CLK_CTRL=%x ====^^==== (twl4030-usb.c)\n", pwr); pwr = twl4030_usb_read(twl, PHY_CLK_CTRL_STS); printk(KERN_ERR "twl4030_phy_power + : PHY_CLK_CTRL_STS=%x ====^^==== (twl4030-usb.c)\n", pwr); if (on) { #if 0 /* LGE_CHANGE [HEAVEN: [email protected]] on 2009-10-14, for <25.12 USB interrupt fix> */ regulator_enable(twl->usb3v1); regulator_enable(twl->usb1v8); #endif /* * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP * in twl4030) resets the VUSB_DEDICATED2 register. This reset * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to * SLEEP. We work around this by clearing the bit after usv3v1 * is re-activated. This ensures that VUSB3V1 is really active. */ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); #if 1 /* LGE_CHANGE [HEAVEN: [email protected]] on 2009-10-14, for <25.12 USB interrupt fix> */ regulator_enable(twl->usb1v8); #endif regulator_enable(twl->usb1v5); pwr &= ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); } else { msleep(250); // LGE_CHANGE [HUB] jjun.lee for USB unplug detect (TI Girish) pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); regulator_disable(twl->usb1v5); regulator_disable(twl->usb1v8); #if 1 /* LGE_CHANGE [HEAVEN: [email protected]] on 2009-10-14, for <25.12 USB interrupt fix> */ /* Put VUSB3V1 regulator in sleep mode */ twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x08, VUSB_DEDICATED2); #else regulator_disable(twl->usb3v1); #endif } pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); printk(KERN_ERR "twl4030_phy_power - : PHY_PWR_CTRL=%x ====^^==== (twl4030-usb.c)\n", pwr); pwr = twl4030_usb_read(twl, PHY_CLK_CTRL); printk(KERN_ERR "twl4030_phy_power - : PHY_CLK_CTRL=%x ====^^==== (twl4030-usb.c)\n", pwr); pwr = twl4030_usb_read(twl, PHY_CLK_CTRL_STS); printk(KERN_ERR "twl4030_phy_power - : PHY_CLK_CTRL_STS=%x ====^^==== (twl4030-usb.c)\n", pwr); }
static void twl4030_i2c_access(bool on) { int val; if ((val = twl4030_usb_read(PHY_CLK_CTRL)) >= 0) { if (on) { /* enable DPLL to access PHY registers over I2C */ val |= REQ_PHY_DPLL_CLK; twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val); while (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK)) { spin(10); } if (!(twl4030_usb_read(PHY_CLK_CTRL_STS) & PHY_DPLL_CLK)) printf("Timeout setting T2 HSUSB " "PHY DPLL clock\n"); } else { /* let ULPI control the DPLL clock */ val &= ~REQ_PHY_DPLL_CLK; twl4030_usb_write(PHY_CLK_CTRL, (uint8_t)val); } } return; }
static void twl4030_phy_power(struct twl4030_usb *twl, int on) { u8 pwr; pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { pwr &= ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); } }
/* * Initiaze the ULPI interface * ULPI : Universal Transceiver Macrocell Low Pin Interface * An interface between the USB link controller like musb and the * the PHY or transceiver that drives the actual bus. */ int twl4030_usb_ulpi_init(void) { long timeout = 1000 * 1000; /* 1 sec */; u8 clk, sts, pwr; /* twl4030 ldo init */ twl4030_usb_ldo_init(); /* Enable the twl4030 phy */ twl4030_phy_power(); /* Enable DPLL to access PHY registers over I2C */ clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL); clk |= REQ_PHY_DPLL_CLK; twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk); /* Check if the PHY DPLL is locked */ sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS); while (!(sts & PHY_DPLL_CLK) && 0 < timeout) { udelay(10); sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS); timeout -= 10; } /* Final check */ sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS); if (!(sts & PHY_DPLL_CLK)) { printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n"); return -1; } /* * There are two circuit blocks attached to the PHY, * Carkit and USB OTG. Disable Carkit and enable USB OTG */ twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE); pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL); pwr |= OTG_ENAB; twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr); /* Clear the opmode bits to ensure normal encode */ twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK); /* Clear the xcvrselect bits to enable the high speed transeiver */ twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK); /* Let ULPI control the DPLL clock */ clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL); clk &= ~REQ_PHY_DPLL_CLK; twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk); return 0; }
static int __exit twl4030_usb_remove(struct platform_device *pdev) { struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; free_irq(twl->irq, twl); device_remove_file(twl->dev, &dev_attr_vbus); /* set transceiver mode to power on defaults */ twl4030_usb_set_mode(twl, -1); /* autogate 60MHz ULPI clock, * clear dpll clock request for i2c access, * disable 32KHz */ val = twl4030_usb_read(twl, PHY_CLK_CTRL); if (val >= 0) { val |= PHY_CLK_CTRL_CLOCKGATING_EN; val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); } /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_phy_power(twl, 0); regulator_put(twl->usb1v5); regulator_put(twl->usb1v8); #if 0 /* LGE_CHANGE [HEAVEN: [email protected]] on 2009-10-14, for <25.12 USB interrupt fix> */ regulator_put(twl->usb3v1); #endif kfree(twl); #if 1 /* mbk_wake mbk_temp */ // LGE_CHANGE wake lock for usb connection wake_lock_destroy(&the_wlock.wake_lock); // LGE_CHANGE wake lock for usb connection #endif return 0; }
static void twl4030_phy_power(struct twl4030_usb *twl, int on) { if (on) { regulator_enable(twl->usb3v1); regulator_enable(twl->usb1v8); twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); regulator_enable(twl->usb1v5); __twl4030_phy_power(twl, 1); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); } else { __twl4030_phy_power(twl, 0); regulator_disable(twl->usb1v5); regulator_disable(twl->usb1v8); regulator_disable(twl->usb3v1); } }
static int __exit twl4030_usb_remove(struct platform_device *pdev) { struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; free_irq(twl->irq, twl); device_remove_file(twl->dev, &dev_attr_vbus); /* set transceiver mode to power on defaults */ twl4030_usb_set_mode(twl, -1); /* autogate 60MHz ULPI clock, * clear dpll clock request for i2c access, * disable 32KHz */ val = twl4030_usb_read(twl, PHY_CLK_CTRL); if (val >= 0) { val |= PHY_CLK_CTRL_CLOCKGATING_EN; val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); } /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_phy_power(twl, 0); regulator_put(twl->usb1v5); regulator_put(twl->usb1v8); regulator_put(twl->usb3v1); wake_lock_destroy(&usb_lock); kfree(twl); return 0; }
static int twl4030_usb_runtime_resume(struct device *dev) { struct twl4030_usb *twl = dev_get_drvdata(dev); int res; dev_dbg(twl->dev, "%s\n", __func__); res = regulator_enable(twl->usb3v1); if (res) dev_err(twl->dev, "Failed to enable usb3v1\n"); res = regulator_enable(twl->usb1v8); if (res) dev_err(twl->dev, "Failed to enable usb1v8\n"); /* * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP * in twl4030) resets the VUSB_DEDICATED2 register. This reset * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to * SLEEP. We work around this by clearing the bit after usv3v1 * is re-activated. This ensures that VUSB3V1 is really active. */ twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); res = regulator_enable(twl->usb1v5); if (res) dev_err(twl->dev, "Failed to enable usb1v5\n"); __twl4030_phy_power(twl, 1); twl4030_usb_write(twl, PHY_CLK_CTRL, twl4030_usb_read(twl, PHY_CLK_CTRL) | (PHY_CLK_CTRL_CLOCKGATING_EN | PHY_CLK_CTRL_CLK32K_EN)); return 0; }
static int twl4030_usb_remove(struct platform_device *pdev) { struct twl4030_usb *twl = platform_get_drvdata(pdev); int val; usb_remove_phy(&twl->phy); pm_runtime_get_sync(twl->dev); cancel_delayed_work(&twl->id_workaround_work); device_remove_file(twl->dev, &dev_attr_vbus); /* set transceiver mode to power on defaults */ twl4030_usb_set_mode(twl, -1); /* idle ulpi before powering off */ if (cable_present(twl->linkstat)) pm_runtime_put_noidle(twl->dev); pm_runtime_mark_last_busy(twl->dev); pm_runtime_put_sync_suspend(twl->dev); pm_runtime_disable(twl->dev); /* autogate 60MHz ULPI clock, * clear dpll clock request for i2c access, * disable 32KHz */ val = twl4030_usb_read(twl, PHY_CLK_CTRL); if (val >= 0) { val |= PHY_CLK_CTRL_CLOCKGATING_EN; val &= ~(PHY_CLK_CTRL_CLK32K_EN | REQ_PHY_DPLL_CLK); twl4030_usb_write(twl, PHY_CLK_CTRL, (u8)val); } /* disable complete OTG block */ twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); return 0; }
static int twl4030_usb_clear_bits(uint8_t reg, uint8_t bits) { return twl4030_usb_write(reg + 2, bits); }
static inline int twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) { return twl4030_usb_write(twl, reg + 2, bits); }
static inline int twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits) { return twl4030_usb_write(reg + 1, bits); }
static inline int twl4030_usb_clear_bits(struct twl4030_usb *twl, u8 reg, u8 bits) { return twl4030_usb_write(twl, ULPI_CLR(reg), bits); }
static inline int twl4030_usb_set_bits(struct twl4030_usb *twl, u8 reg, u8 bits) { return twl4030_usb_write(twl, ULPI_SET(reg), bits); }
int twl4030_usb_reset(void) { TRACE_ENTRY; #if 0 twl4030_usb_clear_bits(OTG_CTRL, DMPULLDOWN | DPPULLDOWN); twl4030_usb_clear_bits(USB_INT_EN_RISE, ~0); twl4030_usb_clear_bits(USB_INT_EN_FALL, ~0); twl4030_usb_clear_bits(MCPC_IO_CTRL, ~TXDTYP); twl4030_usb_set_bits(MCPC_IO_CTRL, TXDTYP); twl4030_usb_clear_bits(OTHER_FUNC_CTRL, (BDIS_ACON_EN | FIVEWIRE_MODE)); twl4030_usb_clear_bits(OTHER_IFC_CTRL, ~0); twl4030_usb_clear_bits(OTHER_INT_EN_RISE, ~0); twl4030_usb_clear_bits(OTHER_INT_EN_FALL, ~0); twl4030_usb_clear_bits(OTHER_IFC_CTRL2, ~0); twl4030_usb_clear_bits(REG_CTRL_EN, ULPI_I2C_CONFLICT_INTEN); twl4030_usb_clear_bits(OTHER_FUNC_CTRL2, VBAT_TIMER_EN); #endif /* Enable writing to power configuration registers */ i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0xC0); i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0x0C); /* put VUSB3V1 LDO in active state */ i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED2, 0); /* input to VUSB3V1 LDO is from VBAT, not VBUS */ i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB_DEDICATED1, 0x14); /* turn on 3.1V regulator */ i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_DEV_GRP, 0x20); i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB3V1_TYPE, 0); /* turn on 1.5V regulator */ i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_DEV_GRP, 0x20); i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V5_TYPE, 0); /* turn on 1.8V regulator */ i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_DEV_GRP, 0x20); i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, VUSB1V8_TYPE, 0); /* disable access to power configuration registers */ i2c_write_reg(TWL_I2C_BUS, TWL_PM_RECEIVER_ADDR, PROTECT_KEY, 0); /* turn on the phy */ uint8_t pwr = twl4030_usb_read(PHY_PWR_CTRL); pwr &= ~PHYPWD; twl4030_usb_write(PHY_PWR_CTRL, pwr); twl4030_usb_write(PHY_CLK_CTRL, twl4030_usb_read(PHY_CLK_CTRL) | (CLOCKGATING_EN | CLK32K_EN)); /* set DPLL i2c access mode */ twl4030_i2c_access(true); /* set ulpi mode */ twl4030_usb_clear_bits(IFC_CTRL, CARKITMODE); twl4030_usb_set_bits(POWER_CTRL, OTG_ENAB); twl4030_usb_write(FUNC_CTRL, XCVRSELECT_HS); // set high speed mode // twl4030_usb_write(FUNC_CTRL, XCVRSELECT_FS); // set full speed mode twl4030_i2c_access(false); return 0; }
static int twl4030_usb_set_bits(uint8_t reg, uint8_t bits) { return twl4030_usb_write(reg + 1, bits); }