static void smsc375x_pwrsrc_event_worker(struct work_struct *work)
{
	struct smsc375x_chip *chip =
	    container_of(work, struct smsc375x_chip, vbus_work);
	int ret;

	pm_runtime_get_sync(&chip->client->dev);

	if (chip->id_short && chip->pdata->is_vbus_online()) {
		/*
		 * only after reading the status register
		 * MUX path is being closed. And by default
		 * MUX is to connected Host mode path.
		 */
		ret = smsc375x_read_reg(chip->client, SMSC375X_REG_STAT);
		if (ret < 0)
			dev_warn(&chip->client->dev,
				"status read failed%d\n", ret);
		else
			dev_info(&chip->client->dev, "Stat:%x\n", ret);
	} else {
		smsc375x_detect_dev(chip);
	}

	pm_runtime_put_sync(&chip->client->dev);
}
static irqreturn_t smsc375x_irq_handler(int irq, void *data)
{
	struct smsc375x_chip *chip = data;

	pm_runtime_get_sync(&chip->client->dev);

	dev_info(&chip->client->dev, "SMSC USB INT!\n");

	smsc375x_detect_dev(chip);

	pm_runtime_put_sync(&chip->client->dev);
	return IRQ_HANDLED;
}
static void smsc375x_pwrsrc_event_worker(struct work_struct *work)
{
	struct smsc375x_chip *chip =
	    container_of(work, struct smsc375x_chip, vbus_work);
	int ret;

	pm_runtime_get_sync(&chip->client->dev);

	/*
	 * Sometimes SMSC INT triggering is only
	 * happening after reading the status bits.
	 * So we are reading the status register as WA
	 * to invoke teh MUX INT in case of connect events.
	 */
	if (!chip->pdata->is_vbus_online())
		ret = smsc375x_detect_dev(chip);
	else
		ret = smsc375x_read_reg(chip->client, SMSC375X_REG_STAT);
	if (ret < 0)
		dev_warn(&chip->client->dev, "pwrsrc evt error\n");

	pm_runtime_put_sync(&chip->client->dev);
}
static int smsc375x_probe(struct i2c_client *client,
			 const struct i2c_device_id *id)
{
	struct smsc375x_chip *chip;
	int ret = 0, id_val = -1;

	chip = kzalloc(sizeof(struct smsc375x_chip), GFP_KERNEL);
	if (!chip) {
		dev_err(&client->dev, "failed to allocate driver data\n");
		return -ENOMEM;
	}

	chip->client = client;
#ifdef CONFIG_ACPI
	chip->pdata =   smsc375x_platform_data();
#else
	chip->pdata = dev->platform_data;
#endif
	i2c_set_clientdata(client, chip);
	wake_lock_init(&chip->wakelock, WAKE_LOCK_SUSPEND,
						"smsc375x_wakelock");

	/* register with extcon */
	chip->edev = kzalloc(sizeof(struct extcon_dev), GFP_KERNEL);
	if (!chip->edev) {
		dev_err(&client->dev, "mem alloc failed\n");
		ret = -ENOMEM;
		goto extcon_mem_failed;
	}
	chip->edev->name = "smsc375x";
	chip->edev->supported_cable = smsc375x_extcon_cable;
	ret = extcon_dev_register(chip->edev, &client->dev);
	if (ret) {
		dev_err(&client->dev, "extcon registration failed!!\n");
		goto extcon_reg_failed;
	}

	/* register for EXTCON USB notification */
	INIT_WORK(&chip->vbus_work, smsc375x_pwrsrc_event_worker);
	chip->vbus_nb.notifier_call = smsc375x_handle_pwrsrc_notification;
	ret = extcon_register_interest(&chip->cable_obj, NULL,
			SMSC375X_EXTCON_USB, &chip->vbus_nb);

	/* OTG notification */
	chip->otg = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!chip->otg) {
		dev_warn(&client->dev, "Failed to get otg transceiver!!\n");
		goto otg_reg_failed;
	}

	INIT_WORK(&chip->otg_work, smsc375x_otg_event_worker);
	chip->id_nb.notifier_call = smsc375x_handle_otg_notification;
	ret = usb_register_notifier(chip->otg, &chip->id_nb);
	if (ret) {
		dev_err(&chip->client->dev,
			"failed to register otg notifier\n");
		goto id_reg_failed;
	}

	ret = smsc375x_irq_init(chip);
	if (ret)
		goto intr_reg_failed;

	chip_ptr = chip;

	if (chip->otg->get_id_status) {
		ret = chip->otg->get_id_status(chip->otg, &id_val);
		if (ret < 0) {
			dev_warn(&client->dev,
				"otg get ID status failed:%d\n", ret);
			ret = 0;
		}
	}

	if (!id_val && !chip->id_short)
		atomic_notifier_call_chain(&chip->otg->notifier,
						USB_EVENT_ID, &id_val);
	else
		smsc375x_detect_dev(chip);

	/* Init Runtime PM State */
	pm_runtime_put_noidle(&chip->client->dev);
	pm_schedule_suspend(&chip->client->dev, MSEC_PER_SEC);

	return 0;

intr_reg_failed:
	usb_unregister_notifier(chip->otg, &chip->id_nb);
id_reg_failed:
	usb_put_phy(chip->otg);
otg_reg_failed:
	extcon_dev_unregister(chip->edev);
extcon_reg_failed:
	kfree(chip->edev);
extcon_mem_failed:
	kfree(chip);
	return ret;
}