void ddl_fw_release(struct ddl_buf_addr *dram_base)
{
	void *cookie = dram_base->pil_cookie;
	if (res_trk_is_cp_enabled() &&
		res_trk_check_for_sec_session()) {
		res_trk_close_secure_session();
		if (IS_ERR_OR_NULL(cookie)) {
			pr_err("Invalid params");
		return;
	}
	if (res_trk_enable_footswitch()) {
		pr_err("Failed to enable footswitch");
		return;
	}
	if (res_trk_enable_iommu_clocks()) {
		res_trk_disable_footswitch();
		pr_err("Failed to enable iommu clocks\n");
		return;
	}
	subsystem_put(cookie);
	if (res_trk_disable_iommu_clocks())
		pr_err("Failed to disable iommu clocks\n");
	if (res_trk_disable_footswitch())
		pr_err("Failed to disable footswitch\n");
	} else {
	if (res_trk_check_for_sec_session())
		res_trk_close_secure_session();
		res_trk_release_fw_addr();
	}
}
static int adsp_loader_remove(struct platform_device *pdev)
{
	struct adsp_loader_private *priv;

	priv = platform_get_drvdata(pdev);
	if (priv != NULL)
		subsystem_put(priv->pil_h);
	pr_info("%s: Q6/ADSP image is unloaded\n", __func__);

	return 0;
}
static void __exit wcnss_wlan_exit(void)
{
	if (penv) {
		if (penv->pil)
			subsystem_put(penv->pil);


		penv = NULL;
	}

	platform_driver_unregister(&wcnss_ctrl_driver);
	platform_driver_unregister(&wcnss_wlan_ctrl_driver);
	platform_driver_unregister(&wcnss_wlan_driver);
#ifdef CONFIG_WCNSS_MEM_PRE_ALLOC
	wcnss_prealloc_deinit();
#endif
}
Exemple #4
0
static void dsps_unload(void)
{
	pr_debug("%s.\n", __func__);

	subsystem_put(drv->pil);
}
Exemple #5
0
static void smd_tty_port_shutdown(struct tty_port *tport)
{
	struct smd_tty_info *info;
	struct tty_struct *tty = tty_port_tty_get(tport);
	unsigned long flags;
#ifdef CONFIG_MSM_SMD_TTY_DS_LEGACY
	int res = 0;
	int n = tty->index;
#endif

	info = tty->driver_data;
	if (info == 0) {
		tty_kref_put(tty);
		return;
	}

	mutex_lock(&smd_tty_lock);

	spin_lock_irqsave(&info->reset_lock, flags);
	info->is_open = 0;
	spin_unlock_irqrestore(&info->reset_lock, flags);

	tasklet_kill(&info->tty_tsklt);
	wake_lock_destroy(&info->wake_lock);
	wake_lock_destroy(&info->ra_wake_lock);

	SMD_TTY_INFO("%s with PID %u closed port %s",
			current->comm, current->pid,
			info->smd->port_name);
	tty->driver_data = NULL;
	del_timer(&info->buf_req_timer);

	smd_close(info->ch);
#ifdef CONFIG_MSM_SMD_TTY_DS_LEGACY
	/*
	 * At current smd_tty framework, if smd_tty_open()
	 * is invoked by process before smd_tty_close() is
	 * completely finished, smd_tty_open() may fail
	 * because smd_tty_close() does not wait to close smd
	 * channel from modem. To fix this situation, new SMD
	 * notify status, SMD_EVENT_REOPEN_READY is used.
	 * Until smd_tty receive this status, smd_tty_close()
	 * will be wait(in fact, process will be wait).
	 */
	pr_info("%s: waiting to close smd %s completely\n",
			__func__, smd_tty[n].smd->port_name);
	/* wait for reopen ready status in seconds */
	res = wait_event_interruptible_timeout(
		info->ch_opened_wait_queue,
		!info->is_open, (smd_tty_ds_modem_wait * HZ));
	if (res <= 0) {
		/* just in case, remain result value */
		pr_err("%s: timeout to wait for %s smd_close. "
				"next smd_open may fail\n",
				__func__, smd_tty[n].smd->port_name);
	}
#endif
	info->ch = NULL;
	subsystem_put(info->pil);

	mutex_unlock(&smd_tty_lock);
	tty_kref_put(tty);
}
Exemple #6
0
static int smd_tty_port_activate(struct tty_port *tport,
				 struct tty_struct *tty)
{
	int res = 0;
	unsigned int n = tty->index;
	struct smd_tty_info *info;
	const char *peripheral = NULL;


	if (n >= MAX_SMD_TTYS || !smd_tty[n].smd)
		return -ENODEV;

	info = smd_tty + n;

	mutex_lock(&smd_tty_lock);
	tty->driver_data = info;

	peripheral = smd_edge_to_subsystem(smd_tty[n].smd->edge);
	if (peripheral) {
		info->pil = subsystem_get(peripheral);
		if (IS_ERR(info->pil)) {
			SMD_TTY_INFO(
				"%s failed on smd_tty device :%s subsystem_get failed for %s",
				__func__, smd_tty[n].smd->port_name,
				peripheral);

			/*
			 * Sleep, inorder to reduce the frequency of
			 * retry by user-space modules and to avoid
			 * possible watchdog bite.
			 */
			msleep((smd_tty[n].open_wait * 1000));
			res = PTR_ERR(info->pil);
			goto out;
		}

		/* Wait for the modem SMSM to be inited for the SMD
		 * Loopback channel to be allocated at the modem. Since
		 * the wait need to be done atmost once, using msleep
		 * doesn't degrade the performance.
		 */
		if (n == LOOPBACK_IDX) {
			if (!is_modem_smsm_inited())
				msleep(5000);
			smsm_change_state(SMSM_APPS_STATE,
					  0, SMSM_SMD_LOOPBACK);
			msleep(100);
		}

		/*
		 * Wait for a channel to be allocated so we know
		 * the modem is ready enough.
		 */
		if (smd_tty[n].open_wait) {
			res = wait_for_completion_interruptible_timeout(
					&info->ch_allocated,
					msecs_to_jiffies(smd_tty[n].open_wait *
									1000));

			if (res == 0) {
				SMD_TTY_INFO(
					"Timed out waiting for SMD channel %s",
					smd_tty[n].smd->port_name);
				res = -ETIMEDOUT;
				goto release_pil;
			} else if (res < 0) {
				SMD_TTY_INFO(
					"Error waiting for SMD channel %s : %d\n",
					smd_tty[n].smd->port_name, res);
				goto release_pil;
			}
#ifdef CONFIG_MSM_SMD_TTY_DS_LEGACY
			/*
			 * on boot, process tried to open smd0 sleeps until
			 * modem is ready or timeout.
			 */
			if (n == DS_IDX) {
				/* wait for open ready status in seconds */
				pr_info("%s: checking DS modem status\n", __func__);
				res = wait_event_interruptible_timeout(
						info->ch_opened_wait_queue,
						info->is_dsmodem_ready,
						(smd_tty_ds_modem_wait * HZ));
				if (!res) {
					res = -ETIMEDOUT;
					pr_err("%s: timeout to wait for %s modem: %d\n",
							__func__,
							smd_tty[n].smd->port_name,
							res);
					goto release_pil;
				} else if (res < 0) {
					pr_err("%s: Error waiting for %s modem: %d\n",
							__func__,
							smd_tty[n].smd->port_name,
							res);
					goto release_pil;
				}
				pr_info("%s: DS modem is OK, open smd0..\n",
						__func__);
			}
#endif
		}
	}

	tasklet_init(&info->tty_tsklt, smd_tty_read, (unsigned long)info);
	wake_lock_init(&info->wake_lock, WAKE_LOCK_SUSPEND,
			smd_tty[n].smd->port_name);
	scnprintf(info->ra_wake_lock_name, MAX_RA_WAKE_LOCK_NAME_LEN,
		  "SMD_TTY_%s_RA", smd_tty[n].smd->port_name);
	wake_lock_init(&info->ra_wake_lock, WAKE_LOCK_SUSPEND,
			info->ra_wake_lock_name);

	res = smd_named_open_on_edge(smd_tty[n].smd->port_name,
				     smd_tty[n].smd->edge, &info->ch, info,
				     smd_tty_notify);
	if (res < 0) {
		SMD_TTY_INFO("%s: %s open failed %d\n",
			      __func__, smd_tty[n].smd->port_name, res);
		goto release_wl_tl;
	}

	res = wait_event_interruptible_timeout(info->ch_opened_wait_queue,
					       info->is_open, (2 * HZ));
	if (res == 0)
		res = -ETIMEDOUT;
	if (res < 0) {
		SMD_TTY_INFO("%s: wait for %s smd_open failed %d\n",
			      __func__, smd_tty[n].smd->port_name, res);
		goto close_ch;
	}
	SMD_TTY_INFO("%s with PID %u opened port %s",
		      current->comm, current->pid, smd_tty[n].smd->port_name);
	smd_disable_read_intr(info->ch);
	mutex_unlock(&smd_tty_lock);
	return 0;

close_ch:
	smd_close(info->ch);
	info->ch = NULL;

release_wl_tl:
	tasklet_kill(&info->tty_tsklt);
	wake_lock_destroy(&info->wake_lock);
	wake_lock_destroy(&info->ra_wake_lock);

release_pil:
	subsystem_put(info->pil);
out:
	mutex_unlock(&smd_tty_lock);

	return res;
}
static int
wcnss_trigger_config(struct platform_device *pdev)
{
	int ret;
	struct qcom_wcnss_opts *pdata;
	unsigned long wcnss_phys_addr;
	int size = 0;
	struct resource *res;
	int has_pronto_hw = of_property_read_bool(pdev->dev.of_node,
									"qcom,has_pronto_hw");

	/* make sure we are only triggered once */
	if (penv->triggered)
		return 0;
	penv->triggered = 1;

	/* initialize the WCNSS device configuration */
	pdata = pdev->dev.platform_data;
	if (WCNSS_CONFIG_UNSPECIFIED == has_48mhz_xo) {
		if (has_pronto_hw) {
			has_48mhz_xo = of_property_read_bool(pdev->dev.of_node,
										"qcom,has_48mhz_xo");
		} else {
			has_48mhz_xo = pdata->has_48mhz_xo;
		}
	}
	penv->wcnss_hw_type = (has_pronto_hw) ? WCNSS_PRONTO_HW : WCNSS_RIVA_HW;
	penv->wlan_config.use_48mhz_xo = has_48mhz_xo;

	penv->thermal_mitigation = 0;
	strlcpy(penv->wcnss_version, "INVALID", WCNSS_VERSION_LEN);

	/* Configure 5 wire GPIOs */
	if (!has_pronto_hw) {
		penv->gpios_5wire = platform_get_resource_byname(pdev,
					IORESOURCE_IO, "wcnss_gpios_5wire");

		/* allocate 5-wire GPIO resources */
		if (!penv->gpios_5wire) {
			dev_err(&pdev->dev, "insufficient IO resources\n");
			ret = -ENOENT;
			goto fail_gpio_res;
		}
		ret = wcnss_gpios_config(penv->gpios_5wire, true);
	} else
		ret = wcnss_pronto_gpios_config(&pdev->dev, true);

	if (ret) {
		dev_err(&pdev->dev, "WCNSS gpios config failed.\n");
		goto fail_gpio_res;
	}

	/* power up the WCNSS */
	ret = wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
					WCNSS_WLAN_SWITCH_ON);
	if (ret) {
		dev_err(&pdev->dev, "WCNSS Power-up failed.\n");
		goto fail_power;
	}

	/* trigger initialization of the WCNSS */
	penv->pil = subsystem_get(WCNSS_PIL_DEVICE);
	if (IS_ERR(penv->pil)) {
		dev_err(&pdev->dev, "Peripheral Loader failed on WCNSS.\n");
		ret = PTR_ERR(penv->pil);
		penv->pil = NULL;
		goto fail_pil;
	}

	/* allocate resources */
	penv->mmio_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
							"wcnss_mmio");
	penv->tx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlantx_irq");
	penv->rx_irq_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
							"wcnss_wlanrx_irq");

	if (!(penv->mmio_res && penv->tx_irq_res && penv->rx_irq_res)) {
		dev_err(&pdev->dev, "insufficient resources\n");
		ret = -ENOENT;
		goto fail_res;
	}
	INIT_WORK(&penv->wcnssctrl_rx_work, wcnssctrl_rx_handler);
	INIT_WORK(&penv->wcnssctrl_version_work, wcnss_send_version_req);
	INIT_WORK(&penv->wcnssctrl_nvbin_dnld_work, wcnss_nvbin_dnld_req);

	wake_lock_init(&penv->wcnss_wake_lock, WAKE_LOCK_SUSPEND, "wcnss");

	if (wcnss_hardware_type() == WCNSS_PRONTO_HW) {
		size = 0x3000;
		wcnss_phys_addr = MSM_PRONTO_PHYS;
	} else {
		wcnss_phys_addr = MSM_RIVA_PHYS;
		size = SZ_256;
	}

	penv->msm_wcnss_base = ioremap(wcnss_phys_addr, size);
	if (!penv->msm_wcnss_base) {
		ret = -ENOMEM;
		pr_err("%s: ioremap wcnss physical failed\n", __func__);
		goto fail_wake;
	}

	if (wcnss_hardware_type() == WCNSS_RIVA_HW) {
		penv->riva_ccu_base =  ioremap(MSM_RIVA_CCU_BASE, SZ_512);
		if (!penv->riva_ccu_base) {
			ret = -ENOMEM;
			pr_err("%s: ioremap wcnss physical failed\n", __func__);
			goto fail_ioremap;
		}
	} else {
		penv->pronto_a2xb_base =  ioremap(MSM_PRONTO_A2XB_BASE, SZ_512);
		if (!penv->pronto_a2xb_base) {
			ret = -ENOMEM;
			pr_err("%s: ioremap wcnss physical failed\n", __func__);
			goto fail_ioremap;
		}
		penv->pronto_ccpu_base =  ioremap(MSM_PRONTO_CCPU_BASE, SZ_512);
		if (!penv->pronto_ccpu_base) {
			ret = -ENOMEM;
			pr_err("%s: ioremap wcnss physical failed\n", __func__);
			goto fail_ioremap2;
		}
		/* for reset FIQ */
		res = platform_get_resource_byname(penv->pdev,
				IORESOURCE_MEM, "wcnss_fiq");
		if (!res) {
			dev_err(&pdev->dev, "insufficient irq mem resources\n");
			ret = -ENOENT;
			goto fail_ioremap3;
		}
		penv->fiq_reg = ioremap_nocache(res->start, resource_size(res));
		if (!penv->fiq_reg) {
			pr_err("wcnss: %s: ioremap_nocache() failed fiq_reg addr:%pr\n",
				__func__, &res->start);
			ret = -ENOMEM;
			goto fail_ioremap3;
		}
	}
	penv->cold_boot_done = 1;

	return 0;

fail_ioremap3:
	iounmap(penv->pronto_ccpu_base);
fail_ioremap2:
	iounmap(penv->pronto_a2xb_base);
fail_ioremap:
	iounmap(penv->msm_wcnss_base);
fail_wake:
	wake_lock_destroy(&penv->wcnss_wake_lock);
fail_res:
	if (penv->pil)
		subsystem_put(penv->pil);
fail_pil:
	wcnss_wlan_power(&pdev->dev, &penv->wlan_config,
				WCNSS_WLAN_SWITCH_OFF);
fail_power:
	if (has_pronto_hw)
		wcnss_pronto_gpios_config(&pdev->dev, false);
	else
		wcnss_gpios_config(penv->gpios_5wire, false);
fail_gpio_res:
	penv = NULL;
	return ret;
}
static void msm_rmnet_unload_modem(void *pil)
{
	if (pil)
		subsystem_put(pil);
}