static void modem_stop(const struct subsys_desc *desc)
{
	struct q6v4_modem *drv = desc_to_modem(desc);
	if (drv->loadable) {
		pil_shutdown(&drv->q6_sw.desc);
		pil_shutdown(&drv->q6_fw.desc);
	}
}
static void mss_stop(const struct subsys_desc *desc)
{
	struct modem_data *drv = subsys_to_drv(desc);

	if (desc->is_not_loadable)
		return;

	pil_shutdown(&drv->mba->desc);
	pil_shutdown(&drv->q6->desc);
}
Beispiel #3
0
static int modem_shutdown(const struct subsys_desc *subsys)
{
	struct modem_data *drv;

	drv = container_of(subsys, struct modem_data, subsys_desc);
	/*
	 * If the modem didn't already crash, setting SMSM_RESET here will help
	 * flush caches etc. The ignore_smsm_ack flag is set to ignore the
	 * SMSM_RESET notification that is generated due to the modem settings
	 * its own SMSM_RESET bit in response to the apps setting the apps
	 * SMSM_RESET bit.
	 */
	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
		drv->ignore_smsm_ack = 1;
		smsm_reset_modem(SMSM_RESET);
	}

	/* Disable the modem watchdog to allow clean modem bootup */
	writel_relaxed(0x0, drv->wdog + 0x8);
	/*
	 * The write above needs to go through before the modem is powered up
	 * again.
	 */
	mb();
	/* Wait here to allow the modem to clean up caches, etc. */
	msleep(20);

	pil_shutdown(&drv->pil_desc);
	disable_irq_nosync(drv->irq);

	return 0;
}
static void lpass_q6_stop(const struct subsys_desc *subsys)
{
	struct q6v3_data *drv;

	drv = container_of(subsys, struct q6v3_data, subsys_desc);
	pil_shutdown(&drv->pil_desc);
}
static int wcnss_shutdown(const struct subsys_desc *subsys)
{
	struct pronto_data *drv = subsys_to_drv(subsys);

	pil_shutdown(&drv->desc);
	return 0;
}
static void riva_stop(const struct subsys_desc *desc)
{
	struct riva_data *drv;

	drv = container_of(desc, struct riva_data, subsys_desc);
	pil_shutdown(&drv->pil_desc);
}
/**
 * pil_put() - Inform PIL the peripheral no longer needs to be active
 * @peripheral_handle: pointer from a previous call to pil_get()
 *
 * This doesn't imply that a peripheral is shutdown or in reset since another
 * driver could be using the peripheral.
 */
void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: Reference count mismatch\n", __func__))
		goto err_out;
	if (!--pil->count)
		pil_shutdown(pil);
	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
Beispiel #8
0
static int modem_shutdown(const struct subsys_desc *subsys, bool force_stop)
{
	struct modem_data *drv = subsys_to_drv(subsys);
	unsigned long ret;

	if (subsys->is_not_loadable)
		return 0;

	if (!subsys_get_crash_status(drv->subsys) && force_stop &&
	    subsys->force_stop_gpio) {
		gpio_set_value(subsys->force_stop_gpio, 1);
		ret = wait_for_completion_timeout(&drv->stop_ack,
				msecs_to_jiffies(STOP_ACK_TIMEOUT_MS));
		if (!ret)
			pr_warn("Timed out on stop ack from modem.\n");
		gpio_set_value(subsys->force_stop_gpio, 0);
	}

	if (drv->subsys_desc.ramdump_disable_gpio) {
		drv->subsys_desc.ramdump_disable = gpio_get_value(
					drv->subsys_desc.ramdump_disable_gpio);
		 pr_warn("Ramdump disable gpio value is %d\n",
			drv->subsys_desc.ramdump_disable);
	}

	pil_shutdown(&drv->q6->desc);

	return 0;
}
Beispiel #9
0
static void modem_stop(const struct subsys_desc *subsys)
{
	struct modem_data *drv;

	drv = container_of(subsys, struct modem_data, subsys_desc);
	pil_shutdown(&drv->pil_desc);
}
static int modem_powerup(const struct subsys_desc *subsys)
{
	struct modem_data *drv = subsys_to_drv(subsys);
	int ret;

#ifdef CONFIG_MACH_LGE
	pr_info("%s : modem is powering up\n", __func__);
	dump_stack();
#endif
	if (subsys->is_not_loadable)
		return 0;
	/*
	 * At this time, the modem is shutdown. Therefore this function cannot
	 * run concurrently with either the watchdog bite error handler or the
	 * SMSM callback, making it safe to unset the flag below.
	 */
	INIT_COMPLETION(drv->stop_ack);
	drv->ignore_errors = false;

	/* START : subsys_modem_restart : testmode */
	ignore_errors_by_subsys_modem_restart = false;
	/* END : subsys_modem_restart : testmode */

	ret = pil_boot(&drv->q6->desc);
	if (ret)
		return ret;
	ret = pil_boot(&drv->mba->desc);
	if (ret)
		pil_shutdown(&drv->q6->desc);
	return ret;
}
void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	printk("%s: %s(%d) for %s\n", __func__, current->comm, current->pid, pil->desc->name);
	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
			pil->desc->name, __func__))
		goto err_out;
#ifdef CONFIG_MACH_VILLEC2
	if (pil->count == 1)
		goto unlock;
#endif
	if (!--pil->count)
		pil_shutdown(pil);
#ifdef CONFIG_MACH_VILLEC2
unlock:
#endif
	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
static int bcss_shutdown(const struct subsys_desc *subsys, bool force_stop)
{
	struct bcss_data *drv = subsys_to_drv(subsys);

	pil_shutdown(&drv->desc);

	return 0;
}
static int adsp_shutdown(const struct subsys_desc *subsys, bool force_stop)
{
	struct lpass_data *drv = subsys_to_lpass(subsys);

	pil_shutdown(&drv->q6->desc);

	pr_debug("ADSP is Down\n");
	adsp_set_state("OFFLINE");
	return 0;
}
static int modem_shutdown(const struct subsys_desc *subsys)
{
	struct q6v4_modem *drv = desc_to_modem(subsys);

	/* The watchdogs keep running even after the modem is shutdown */
	writel_relaxed(0x0, drv->q6_fw.wdog_base + 0x24);
	writel_relaxed(0x0, drv->q6_sw.wdog_base + 0x24);
	mb();

	if (drv->loadable) {
		pil_shutdown(&drv->q6_sw.desc);
		pil_shutdown(&drv->q6_fw.desc);
	}

	disable_irq_nosync(drv->q6_fw.wdog_irq);
	disable_irq_nosync(drv->q6_sw.wdog_irq);

	return 0;
}
static int wcnss_shutdown(const struct subsys_desc *subsys)
{
	struct pronto_data *drv = subsys_to_drv(subsys);

	pil_shutdown(&drv->desc);
	flush_delayed_work(&drv->cancel_vote_work);
	wcnss_flush_delayed_boot_votes();

	return 0;
}
/**
 * pil_put() - Inform PIL the peripheral no longer needs to be active
 * @peripheral_handle: pointer from a previous call to pil_get()
 *
 * This doesn't imply that a peripheral is shutdown or in reset since another
 * driver could be using the peripheral.
 */
void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
			pil->desc->name, __func__))
		goto err_out;

/* LGE_CHANGE */
#if CONFIG_MACH_LGE
	//LGE_CHANES : Workaround code for pereventing watchdog reset.(QCT Patch)
	if (!--pil->count){
		if (!!strncmp("modem", pil->desc->name, 5)) //ALRAN : LG FX3 - allow pil_put only for not modem*
			pil_shutdown(pil);
		else{
			pr_err("ALRAN: pil %s shutdown, but block it\n", pil->desc->name);
			pil->count++;
		}
	}
#else
	if (!--pil->count)
		pil_shutdown(pil);
#endif

	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
static int dsps_shutdown(const struct subsys_desc *desc)
{
	struct dsps_data *drv = desc_to_drv(desc);
	disable_irq_nosync(drv->wdog_irq);
	if (drv->ppss_base) {
		writel_relaxed(0, drv->ppss_base + PPSS_WDOG_UNMASKED_INT_EN);
		mb(); /* Make sure wdog is disabled before shutting down */
	}
	pil_shutdown(&drv->desc);
	return 0;
}
static int pil_femto_modem_stop(struct femto_modem_data *drv)
{
	if (!drv)
		return -EINVAL;

	/* Only need to shutdown the Q6 PIL descriptor, because shutting down
	 * the others does nothing.
	 */
	pil_shutdown(&drv->q6->desc);
	return 0;
}
static int riva_shutdown(const struct subsys_desc *desc)
{
	struct riva_data *drv;

	drv = container_of(desc, struct riva_data, subsys_desc);
	pil_shutdown(&drv->pil_desc);
	flush_delayed_work(&drv->cancel_work);
	wcnss_flush_delayed_boot_votes();
	disable_irq_nosync(drv->irq);

	return 0;
}
static int lpass_q6_shutdown(const struct subsys_desc *subsys)
{
	struct q6v3_data *drv;

	drv = container_of(subsys, struct q6v3_data, subsys_desc);
	send_q6_nmi(drv);
	writel_relaxed(0x0, drv->wd_base + 0x24);
	mb();

	pil_shutdown(&drv->pil_desc);
	disable_irq_nosync(drv->irq);

	return 0;
}
static int modem_start(const struct subsys_desc *desc)
{
	struct q6v4_modem *drv = desc_to_modem(desc);
	int ret = 0;

	if (drv->loadable) {
		ret = pil_boot(&drv->q6_fw.desc);
		if (ret)
			return ret;
		ret = pil_boot(&drv->q6_sw.desc);
		if (ret)
			pil_shutdown(&drv->q6_fw.desc);
	}
	return ret;
}
void pil_force_shutdown(const char *name)
{
	struct pil_device *pil;

	pil = find_peripheral(name);
	if (!pil) {
		pr_err("%s: Couldn't find %s\n", __func__, name);
		return;
	}

	mutex_lock(&pil->lock);
	if (!WARN(!pil->count, "%s: Reference count mismatch\n", __func__))
		pil_shutdown(pil);
	mutex_unlock(&pil->lock);

	put_device(&pil->dev);
}
static int modem_ramdump(int enable, const struct subsys_desc *subsys)
{
	struct modem_data *drv = subsys_to_drv(subsys);
	int ret;

	if (!enable)
		return 0;

	ret = pil_boot(&drv->q6->desc);
	if (ret)
		return ret;

	ret = pil_do_ramdump(&drv->mba->desc, drv->ramdump_dev);
	if (ret < 0)
		pr_err("Unable to dump modem fw memory (rc = %d).\n", ret);

	pil_shutdown(&drv->q6->desc);
	return ret;
}
static int subsys_shutdown(const struct subsys_desc *subsys, bool force_stop)
{
	struct pil_tz_data *d = subsys_to_data(subsys);
	int ret;

	if (!subsys_get_crash_status(d->subsys) && force_stop &&
						subsys->force_stop_gpio) {
		gpio_set_value(subsys->force_stop_gpio, 1);
		ret = wait_for_completion_timeout(&d->stop_ack,
				msecs_to_jiffies(STOP_ACK_TIMEOUT_MS));
		if (!ret)
			pr_warn("Timed out on stop ack from %s.\n",
							subsys->name);
		gpio_set_value(subsys->force_stop_gpio, 0);
	}

	pil_shutdown(&d->desc);
	return 0;
}
static int modem_powerup(const struct subsys_desc *subsys)
{
	struct q6v4_modem *drv = desc_to_modem(subsys);
	int ret;

	if (drv->loadable) {
		ret = pil_boot(&drv->q6_fw.desc);
		if (ret)
			return ret;
		ret = pil_boot(&drv->q6_sw.desc);
		if (ret) {
			pil_shutdown(&drv->q6_fw.desc);
			return ret;
		}
	}
	enable_irq(drv->q6_fw.wdog_irq);
	enable_irq(drv->q6_sw.wdog_irq);
	return 0;
}
Beispiel #26
0
static int modem_shutdown(const struct subsys_desc *subsys)
{
	struct modem_data *drv;

	drv = container_of(subsys, struct modem_data, subsys_desc);
	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
		drv->ignore_smsm_ack = 1;
		smsm_reset_modem(SMSM_RESET);
	}

	
	writel_relaxed(0x0, drv->wdog + 0x8);
	mb();
	
	msleep(20);

	pil_shutdown(&drv->pil_desc);
	disable_irq_nosync(drv->irq);

	return 0;
}
static int modem_powerup(const struct subsys_desc *subsys)
{
	struct modem_data *drv = subsys_to_drv(subsys);
	int ret;

	if (subsys->is_not_loadable)
		return 0;
	/*
	 * At this time, the modem is shutdown. Therefore this function cannot
	 * run concurrently with either the watchdog bite error handler or the
	 * SMSM callback, making it safe to unset the flag below.
	 */
	INIT_COMPLETION(drv->stop_ack);
	drv->ignore_errors = false;
	ret = pil_boot(&drv->q6->desc);
	if (ret)
		return ret;
	ret = pil_boot(&drv->mba->desc);
	if (ret)
		pil_shutdown(&drv->q6->desc);
	return ret;
}
/**
 * pil_put() - Inform PIL the peripheral no longer needs to be active
 * @peripheral_handle: pointer from a previous call to pil_get()
 *
 * This doesn't imply that a peripheral is shutdown or in reset since another
 * driver could be using the peripheral.
 */
void pil_put(void *peripheral_handle)
{
	struct pil_device *pil_d, *pil = peripheral_handle;

	if (IS_ERR_OR_NULL(pil))
		return;

	if (pil->count <= 1) {
		printk(KERN_DEBUG "%s:%s, count:%d, pid:%d, %s\n", __func__,
				pil->desc->name, pil->count, current->pid,
				current->comm);
	}
	mutex_lock(&pil->lock);
	if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
			pil->desc->name, __func__))
		goto err_out;
	if (!strncmp(pil->desc->name, "modem", 5)) {
		if (pil->count == 1)
			goto unlock;
	}
	if (!--pil->count) {
		pil_shutdown(pil);
		WARN_ON(1);
	}
unlock:
	mutex_unlock(&pil->lock);

	pil_d = find_peripheral(pil->desc->depends_on);
	module_put(pil->owner);
	if (pil_d) {
		pil_put(pil_d);
		put_device(&pil_d->dev);
	}
	put_device(&pil->dev);
	return;
err_out:
	mutex_unlock(&pil->lock);
	return;
}
static int modem_powerup(const struct subsys_desc *subsys)
{
	struct modem_data *drv = subsys_to_drv(subsys);
	int ret;

	if (subsys->is_not_loadable)
		return 0;
	/*
                                                                       
                                                                       
                                                          
  */
	INIT_COMPLETION(drv->stop_ack);
	drv->ignore_errors = false;
	ret = pil_boot(&drv->q6->desc);
	if (ret)
		return ret;
	ret = pil_boot(&drv->mba->desc);
	if (ret)
		pil_shutdown(&drv->q6->desc);
	return ret;
}
static int __msm_pil_shutdown(struct device *dev, void *data)
{
	pil_shutdown(to_pil_device(dev));
	return 0;
}