Пример #1
0
static int arche_platform_pm_notifier(struct notifier_block *notifier,
				      unsigned long pm_event, void *unused)
{
	struct arche_platform_drvdata *arche_pdata =
		container_of(notifier, struct arche_platform_drvdata,
			     pm_notifier);
	int ret = NOTIFY_DONE;

	mutex_lock(&arche_pdata->platform_state_mutex);
	switch (pm_event) {
	case PM_SUSPEND_PREPARE:
		if (arche_pdata->state != ARCHE_PLATFORM_STATE_ACTIVE) {
			ret = NOTIFY_STOP;
			break;
		}
		device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
		arche_platform_poweroff_seq(arche_pdata);
		break;
	case PM_POST_SUSPEND:
		if (arche_pdata->state != ARCHE_PLATFORM_STATE_OFF)
			break;

		arche_platform_wd_irq_en(arche_pdata);
		arche_platform_coldboot_seq(arche_pdata);
		break;
	default:
		break;
	}
	mutex_unlock(&arche_pdata->platform_state_mutex);

	return ret;
}
Пример #2
0
static void arche_platform_shutdown(struct platform_device *pdev)
{
	struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);

	arche_platform_poweroff_seq(arche_pdata);

	usb3613_hub_mode_ctrl(false);
}
Пример #3
0
static int arche_platform_remove(struct platform_device *pdev)
{
	struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);

	unregister_pm_notifier(&arche_pdata->pm_notifier);
	device_remove_file(&pdev->dev, &dev_attr_state);
	device_for_each_child(&pdev->dev, NULL, arche_remove_child);
	arche_platform_poweroff_seq(arche_pdata);

	if (usb3613_hub_mode_ctrl(false))
		dev_warn(arche_pdata->dev, "failed to control hub device\n");
		/* TODO: Should we do anything more here ?? */
	return 0;
}
Пример #4
0
static ssize_t state_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct arche_platform_drvdata *arche_pdata = platform_get_drvdata(pdev);
	int ret = 0;

retry:
	mutex_lock(&arche_pdata->platform_state_mutex);
	if (arche_pdata->state == ARCHE_PLATFORM_STATE_TIME_SYNC) {
		mutex_unlock(&arche_pdata->platform_state_mutex);
		ret = wait_event_interruptible(
			arche_pdata->wq,
			arche_pdata->state != ARCHE_PLATFORM_STATE_TIME_SYNC);
		if (ret)
			return ret;
		goto retry;
	}

	if (sysfs_streq(buf, "off")) {
		if (arche_pdata->state == ARCHE_PLATFORM_STATE_OFF)
			goto exit;

		/*  If SVC goes down, bring down APB's as well */
		device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);

		arche_platform_poweroff_seq(arche_pdata);

	} else if (sysfs_streq(buf, "active")) {
		if (arche_pdata->state == ARCHE_PLATFORM_STATE_ACTIVE)
			goto exit;

		/* First we want to make sure we power off everything
		 * and then activate back again
		 */
		device_for_each_child(arche_pdata->dev, NULL, apb_poweroff);
		arche_platform_poweroff_seq(arche_pdata);

		arche_platform_wd_irq_en(arche_pdata);
		ret = arche_platform_coldboot_seq(arche_pdata);
		if (ret)
			goto exit;

	} else if (sysfs_streq(buf, "standby")) {
		if (arche_pdata->state == ARCHE_PLATFORM_STATE_STANDBY)
			goto exit;

		dev_warn(arche_pdata->dev, "standby state not supported\n");
	} else if (sysfs_streq(buf, "fw_flashing")) {
		if (arche_pdata->state == ARCHE_PLATFORM_STATE_FW_FLASHING)
			goto exit;

		/*
		 * Here we only control SVC.
		 *
		 * In case of FW_FLASHING mode we do not want to control
		 * APBs, as in case of V2, SPI bus is shared between both
		 * the APBs. So let user chose which APB he wants to flash.
		 */
		arche_platform_poweroff_seq(arche_pdata);

		ret = arche_platform_fw_flashing_seq(arche_pdata);
		if (ret)
			goto exit;
	} else {
		dev_err(arche_pdata->dev, "unknown state\n");
		ret = -EINVAL;
	}

exit:
	mutex_unlock(&arche_pdata->platform_state_mutex);
	return ret ? ret : count;
}