Example #1
0
static acpi_status acpi_i2c_add_device(acpi_handle handle, u32 level,
				       void *data, void **return_value)
{
	struct i2c_adapter *adapter = data;
	struct list_head resource_list;
	struct i2c_board_info info;
	struct acpi_device *adev;
	int ret;

	if (acpi_bus_get_device(handle, &adev))
		return AE_OK;
	if (acpi_bus_get_status(adev) || !adev->status.present)
		return AE_OK;

	memset(&info, 0, sizeof(info));
	info.acpi_node.handle = handle;
	info.irq = -1;

	INIT_LIST_HEAD(&resource_list);
	ret = acpi_dev_get_resources(adev, &resource_list,
				     acpi_i2c_add_resource, &info);
	acpi_dev_free_resource_list(&resource_list);

	if (ret < 0 || !info.addr)
		return AE_OK;

	strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type));
	if (!i2c_new_device(adapter, &info)) {
		dev_err(&adapter->dev,
			"failed to add I2C device %s from ACPI\n",
			dev_name(&adev->dev));
	}

	return AE_OK;
}
static int __devinit asus_acpi_init(struct asus_laptop *asus)
{
	int result = 0;

	result = acpi_bus_get_status(asus->device);
	if (result)
		return result;
	if (!asus->device->status.present) {
		pr_err("Hotkey device not present, aborting\n");
		return -ENODEV;
	}

	result = asus_laptop_get_info(asus);
	if (result)
		return result;

	if (!strcmp(bled_type, "led"))
		asus->bled_type = TYPE_LED;
	else if (!strcmp(bled_type, "rfkill"))
		asus->bled_type = TYPE_RFKILL;

	if (!strcmp(wled_type, "led"))
		asus->wled_type = TYPE_LED;
	else if (!strcmp(wled_type, "rfkill"))
		asus->wled_type = TYPE_RFKILL;

	if (bluetooth_status >= 0)
		asus_bluetooth_set(asus, !!bluetooth_status);

	if (wlan_status >= 0)
		asus_wlan_set(asus, !!wlan_status);

	if (wimax_status >= 0)
		asus_wimax_set(asus, !!wimax_status);

	if (wwan_status >= 0)
		asus_wwan_set(asus, !!wwan_status);

	
	if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
		asus_kled_set(asus, 1);

	
	asus->ledd_status = 0xFFF;

	
	asus->light_switch = !!als_status;
	asus->light_level = 5;	

	if (asus->is_pega_lucid) {
		asus_als_switch(asus, asus->light_switch);
	} else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
		   !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
		asus_als_switch(asus, asus->light_switch);
		asus_als_level(asus, asus->light_level);
	}

	return result;
}
Example #3
0
static int
acpi_battery_check (
	struct acpi_battery	*battery)
{
	int			result = 0;
	acpi_status		status = AE_OK;
	acpi_handle		handle = NULL;
	struct acpi_device	*device = NULL;
	struct acpi_battery_info *bif = NULL;

	ACPI_FUNCTION_TRACE("acpi_battery_check");
	
	if (!battery)
		return_VALUE(-EINVAL);

	result = acpi_bus_get_device(battery->handle, &device);
	if (result)
		return_VALUE(result);

	result = acpi_bus_get_status(device);
	if (result)
		return_VALUE(result);

	/* Insertion? */

	if (!battery->flags.present && device->status.battery_present) {

		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));

		/* Evalute _BIF to get certain static information */

		result = acpi_battery_get_info(battery, &bif);
		if (result)
			return_VALUE(result);

		battery->flags.power_unit = bif->power_unit;
		battery->trips.warning = bif->design_capacity_warning;
		battery->trips.low = bif->design_capacity_low;
		kfree(bif);

		/* See if alarms are supported, and if so, set default */

		status = acpi_get_handle(battery->handle, "_BTP", &handle);
		if (ACPI_SUCCESS(status)) {
			battery->flags.alarm = 1;
			acpi_battery_set_alarm(battery, battery->trips.warning);
		}
	}

	/* Removal? */

	else if (battery->flags.present && !device->status.battery_present) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
	}

	battery->flags.present = device->status.battery_present;

	return_VALUE(result);
}
Example #4
0
static int
acpi_bus_check_device (
	struct acpi_device	*device,
	int			*status_changed)
{
	acpi_status             status = 0;
	struct acpi_device_status old_status;

	ACPI_FUNCTION_TRACE("acpi_bus_check_device");

	if (!device)
		return_VALUE(-EINVAL);

	if (status_changed)
		*status_changed = 0;

	old_status = device->status;

	/*
	 * Make sure this device's parent is present before we go about
	 * messing with the device.
	 */
	if (device->parent && !device->parent->status.present) {
		device->status = device->parent->status;
		if (STRUCT_TO_INT(old_status) != STRUCT_TO_INT(device->status)) {
			if (status_changed)
				*status_changed = 1;
		}
		return_VALUE(0);
	}

	status = acpi_bus_get_status(device);
	if (ACPI_FAILURE(status))
		return_VALUE(-ENODEV);

	if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
		return_VALUE(0);

	if (status_changed)
		*status_changed = 1;
	
	/*
	 * Device Insertion/Removal
	 */
	if ((device->status.present) && !(old_status.present)) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
		/* TBD: Handle device insertion */
	}
	else if (!(device->status.present) && (old_status.present)) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
		/* TBD: Handle device removal */
	}

	return_VALUE(0);
}
Example #5
0
static int __devinit asus_acpi_init(struct asus_laptop *asus)
{
	int result = 0;

	result = acpi_bus_get_status(asus->device);
	if (result)
		return result;
	if (!asus->device->status.present) {
		pr_err("Hotkey device not present, aborting\n");
		return -ENODEV;
	}

	result = asus_laptop_get_info(asus);
	if (result)
		return result;

	/* WLED and BLED are on by default */
	if (bluetooth_status >= 0)
		asus_bluetooth_set(asus, !!bluetooth_status);

	if (wlan_status >= 0)
		asus_wlan_set(asus, !!wlan_status);

	if (wimax_status >= 0)
		asus_wimax_set(asus, !!wimax_status);

	if (wwan_status >= 0)
		asus_wwan_set(asus, !!wwan_status);

	/* Keyboard Backlight is on by default */
	if (!acpi_check_handle(asus->handle, METHOD_KBD_LIGHT_SET, NULL))
		asus_kled_set(asus, 1);

	/* LED display is off by default */
	asus->ledd_status = 0xFFF;

	/* Set initial values of light sensor and level */
	asus->light_switch = !!als_status;
	asus->light_level = 5;	/* level 5 for sensor sensitivity */

	if (asus->is_pega_lucid) {
		asus_als_switch(asus, asus->light_switch);
	} else if (!acpi_check_handle(asus->handle, METHOD_ALS_CONTROL, NULL) &&
		   !acpi_check_handle(asus->handle, METHOD_ALS_LEVEL, NULL)) {
		asus_als_switch(asus, asus->light_switch);
		asus_als_level(asus, asus->light_level);
	}

	return result;
}
Example #6
0
static int sdhci_acpi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	acpi_handle handle = ACPI_HANDLE(dev);
	struct acpi_device *device;
	struct sdhci_acpi_host *c;
	struct sdhci_host *host;
	struct resource *iomem;
	resource_size_t len;
	const char *hid;
	int err;

	if (acpi_bus_get_device(handle, &device))
		return -ENODEV;

	if (acpi_bus_get_status(device) || !device->status.present)
		return -ENODEV;

	hid = acpi_device_hid(device);

	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!iomem)
		return -ENOMEM;

	len = resource_size(iomem);
	if (len < 0x100)
		dev_err(dev, "Invalid iomem size!\n");

	if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev)))
		return -ENOMEM;

	host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host));
	if (IS_ERR(host))
		return PTR_ERR(host);

	c = sdhci_priv(host);
	c->host = host;
	c->slot = sdhci_acpi_get_slot(handle, hid);
	c->pdev = pdev;
	c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);

	platform_set_drvdata(pdev, c);

	host->hw_name	= "ACPI";
	host->ops	= &sdhci_acpi_ops_dflt;
	host->irq	= platform_get_irq(pdev, 0);

	host->ioaddr = devm_ioremap_nocache(dev, iomem->start,
					    resource_size(iomem));
	if (host->ioaddr == NULL) {
		err = -ENOMEM;
		goto err_free;
	}

	if (!dev->dma_mask) {
		u64 dma_mask;

		if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) {
			/* 64-bit DMA is not supported at present */
			dma_mask = DMA_BIT_MASK(32);
		} else {
			dma_mask = DMA_BIT_MASK(32);
		}

		err = dma_coerce_mask_and_coherent(dev, dma_mask);
		if (err)
			goto err_free;
	}

	if (c->slot) {
		if (c->slot->chip) {
			host->ops            = c->slot->chip->ops;
			host->quirks        |= c->slot->chip->quirks;
			host->quirks2       |= c->slot->chip->quirks2;
			host->mmc->caps     |= c->slot->chip->caps;
			host->mmc->caps2    |= c->slot->chip->caps2;
			host->mmc->pm_caps  |= c->slot->chip->pm_caps;
		}
		host->quirks        |= c->slot->quirks;
		host->quirks2       |= c->slot->quirks2;
		host->mmc->caps     |= c->slot->caps;
		host->mmc->caps2    |= c->slot->caps2;
		host->mmc->pm_caps  |= c->slot->pm_caps;
	}

	host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;

	err = sdhci_add_host(host);
	if (err)
		goto err_free;

	if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) {
		if (sdhci_acpi_add_own_cd(dev, host->mmc))
			c->use_runtime_pm = false;
	}

	if (c->use_runtime_pm) {
		pm_runtime_set_active(dev);
		pm_suspend_ignore_children(dev, 1);
		pm_runtime_set_autosuspend_delay(dev, 50);
		pm_runtime_use_autosuspend(dev);
		pm_runtime_enable(dev);
	}

	return 0;

err_free:
	sdhci_free_host(c->host);
	return err;
}
Example #7
0
File: bus.c Project: DVSB/linux
static void acpi_bus_osc_support(void)
{
	u32 capbuf[2];
	struct acpi_osc_context context = {
		.uuid_str = sb_uuid_str,
		.rev = 1,
		.cap.length = 8,
		.cap.pointer = capbuf,
	};
	acpi_handle handle;

	capbuf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE;
	capbuf[OSC_SUPPORT_TYPE] = OSC_SB_PR3_SUPPORT; /* _PR3 is in use */
#if defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR) ||\
			defined(CONFIG_ACPI_PROCESSOR_AGGREGATOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PAD_SUPPORT;
#endif

#if defined(CONFIG_ACPI_PROCESSOR) || defined(CONFIG_ACPI_PROCESSOR_MODULE)
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_PPC_OST_SUPPORT;
#endif

#ifdef ACPI_HOTPLUG_OST
	capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_HOTPLUG_OST_SUPPORT;
#endif

	if (!ghes_disable)
		capbuf[OSC_SUPPORT_TYPE] |= OSC_SB_APEI_SUPPORT;
	if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_SB", &handle)))
		return;
	if (ACPI_SUCCESS(acpi_run_osc(handle, &context))) {
		u32 *capbuf_ret = context.ret.pointer;
		if (context.ret.length > OSC_SUPPORT_TYPE)
			osc_sb_apei_support_acked =
				capbuf_ret[OSC_SUPPORT_TYPE] & OSC_SB_APEI_SUPPORT;
		kfree(context.ret.pointer);
	}
	/* do we need to check other returned cap? Sounds no */
}

/* --------------------------------------------------------------------------
                             Notification Handling
   -------------------------------------------------------------------------- */

static void acpi_bus_check_device(acpi_handle handle)
{
	struct acpi_device *device;
	acpi_status status;
	struct acpi_device_status old_status;

	if (acpi_bus_get_device(handle, &device))
		return;
	if (!device)
		return;

	old_status = device->status;

	/*
	 * Make sure this device's parent is present before we go about
	 * messing with the device.
	 */
	if (device->parent && !device->parent->status.present) {
		device->status = device->parent->status;
		return;
	}

	status = acpi_bus_get_status(device);
	if (ACPI_FAILURE(status))
		return;

	if (STRUCT_TO_INT(old_status) == STRUCT_TO_INT(device->status))
		return;

	/*
	 * Device Insertion/Removal
	 */
	if ((device->status.present) && !(old_status.present)) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device insertion detected\n"));
		/* TBD: Handle device insertion */
	} else if (!(device->status.present) && (old_status.present)) {
		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Device removal detected\n"));
		/* TBD: Handle device removal */
	}
}

static void acpi_bus_check_scope(acpi_handle handle)
{
	/* Status Change? */
	acpi_bus_check_device(handle);

	/*
	 * TBD: Enumerate child devices within this device's scope and
	 *       run acpi_bus_check_device()'s on them.
	 */
}
static int sdhci_acpi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	acpi_handle handle = ACPI_HANDLE(dev);
	struct acpi_device *device;
	struct sdhci_acpi_host *c;
	struct sdhci_host *host;
	struct resource *iomem;
	resource_size_t len;
	const char *hid;
	const char *uid;
	int err;

	if (acpi_bus_get_device(handle, &device))
		return -ENODEV;

	if (acpi_bus_get_status(device) || !device->status.present)
		return -ENODEV;

	hid = acpi_device_hid(device);
	uid = device->pnp.unique_id;

	iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!iomem)
		return -ENOMEM;

	len = resource_size(iomem);
	if (len < 0x100)
		dev_err(dev, "Invalid iomem size!\n");

	if (!devm_request_mem_region(dev, iomem->start, len, dev_name(dev)))
		return -ENOMEM;

	host = sdhci_alloc_host(dev, sizeof(struct sdhci_acpi_host));
	if (IS_ERR(host))
		return PTR_ERR(host);

	c = sdhci_priv(host);
	c->host = host;
	c->slot = sdhci_acpi_get_slot(hid, uid);
	c->pdev = pdev;
	c->use_runtime_pm = sdhci_acpi_flag(c, SDHCI_ACPI_RUNTIME_PM);

	platform_set_drvdata(pdev, c);

	host->hw_name	= "ACPI";
	host->ops	= &sdhci_acpi_ops_dflt;
	host->irq	= platform_get_irq(pdev, 0);

	host->ioaddr = devm_ioremap_nocache(dev, iomem->start,
					    resource_size(iomem));
	if (host->ioaddr == NULL) {
		err = -ENOMEM;
		goto err_free;
	}

	if (c->slot) {
		if (c->slot->probe_slot) {
			err = c->slot->probe_slot(pdev, hid, uid);
			if (err)
				goto err_free;
		}
		if (c->slot->chip) {
			host->ops            = c->slot->chip->ops;
			host->quirks        |= c->slot->chip->quirks;
			host->quirks2       |= c->slot->chip->quirks2;
			host->mmc->caps     |= c->slot->chip->caps;
			host->mmc->caps2    |= c->slot->chip->caps2;
			host->mmc->pm_caps  |= c->slot->chip->pm_caps;
		}
		host->quirks        |= c->slot->quirks;
		host->quirks2       |= c->slot->quirks2;
		host->mmc->caps     |= c->slot->caps;
		host->mmc->caps2    |= c->slot->caps2;
		host->mmc->pm_caps  |= c->slot->pm_caps;
	}

	host->mmc->caps2 |= MMC_CAP2_NO_PRESCAN_POWERUP;

	if (sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD)) {
		bool v = sdhci_acpi_flag(c, SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL);

		if (mmc_gpiod_request_cd(host->mmc, NULL, 0, v, 0, NULL)) {
			dev_warn(dev, "failed to setup card detect gpio\n");
			c->use_runtime_pm = false;
		}
	}

	err = sdhci_add_host(host);
	if (err)
		goto err_free;

	if (c->use_runtime_pm) {
		pm_runtime_set_active(dev);
		pm_suspend_ignore_children(dev, 1);
		pm_runtime_set_autosuspend_delay(dev, 50);
		pm_runtime_use_autosuspend(dev);
		pm_runtime_enable(dev);
	}

	return 0;

err_free:
	sdhci_free_host(c->host);
	return err;
}
int __devinit sst_acpi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	acpi_handle handle = ACPI_HANDLE(dev);
	struct acpi_device *device;
	const char *hid;
	int i, ret = 0;
	struct sst_probe_info *info;
	struct intel_sst_drv *ctx;

	ret = acpi_bus_get_device(handle, &device);
	if (ret) {
		pr_err("%s: could not get acpi device - %d\n", __func__, ret);
		return -ENODEV;
	}

	if (acpi_bus_get_status(device) || !device->status.present) {
		pr_err("%s: device has invalid status", __func__);
		return -ENODEV;
	}

	hid = acpi_device_hid(device);
	pr_debug("%s for %s", __func__, hid);
	ret = sst_alloc_drv_context(dev);
	if (ret)
		return ret;
	ctx = sst_drv_ctx;
	ctx->dev = dev;
	ctx->pci_id = SST_BYT_PCI_ID;

	/* need to save shim registers in BYT */
	ctx->shim_regs64 = devm_kzalloc(dev, sizeof(*ctx->shim_regs64),
					GFP_KERNEL);
	if (!ctx->shim_regs64)
		return -ENOMEM;


	ctx->use_32bit_ops = true;

	ret = sst_driver_ops(ctx);
	if (ret != 0)
		return -EINVAL;

	sst_init_locks(ctx);

	ctx->stream_cnt = 0;
	ctx->fw_in_mem = NULL;
	ctx->use_dma = 1;
	ctx->use_lli = 1;

	if (sst_workqueue_init(ctx))
		goto do_free_wq;

	info = sst_get_acpi_driver_data(hid);
	if (!info)
		return -EINVAL;

	memcpy(&ctx->info, info, sizeof(ctx->info));

	ctx->ipc_reg.ipcx = SST_PRH_IPCX;
	ctx->ipc_reg.ipcd = SST_PRH_IPCD;

	pr_debug("Got drv data max stream %d\n",
				ctx->info.max_streams);
	for (i = 1; i <= ctx->info.max_streams; i++) {
		struct stream_info *stream = &ctx->streams[i];
		mutex_init(&stream->lock);
	}

	ret = sst_platform_get_resources(ctx, pdev);
	if (ret)
		goto do_free_wq;

	/*Register LPE Control as misc driver*/
	ret = misc_register(&lpe_ctrl);
	if (ret) {
		pr_err("couldn't register control device\n");
		goto do_free_wq;
	}
	/* mask all SSP and DMA interrupts to IA - enable when needed */
	sst_shim_write64(ctx->shim, SST_IMRX, 0xFFFF0038);

	if (ctx->use_32bit_ops) {
		pr_debug("allocate mem for context save/restore\n ");
		/*allocate mem for fw context save during suspend*/
		ctx->fw_cntx = devm_kzalloc(ctx->dev, FW_CONTEXT_MEM, GFP_KERNEL);
		if (!ctx->fw_cntx) {
			ret = -ENOMEM;
			goto do_free_misc;
		}
		/*setting zero as that is valid mem to restore*/
		ctx->fw_cntx_size = 0;
	}

	platform_set_drvdata(pdev, ctx);
	pm_runtime_enable(dev);
	register_sst(dev);
	sst_debugfs_init(ctx);
	sst_set_fw_state_locked(ctx, SST_UN_INIT);
	sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
	pr_info("%s successfully done!\n", __func__);
	return ret;

do_free_misc:
	misc_deregister(&lpe_ctrl);
do_free_wq:
	sst_destroy_workqueue(ctx);

	sst_drv_ctx = NULL;
	platform_set_drvdata(pdev, NULL);
	pr_err("%s: failed with %d\n", __func__, ret);
	return ret;
}
int sst_acpi_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	acpi_handle handle = ACPI_HANDLE(dev);
	struct acpi_device *device;
	const char *hid;
	int i, ret = 0;
	struct intel_sst_drv *ctx;

	ret = acpi_bus_get_device(handle, &device);
	if (ret) {
		pr_err("%s: could not get acpi device - %d\n", __func__, ret);
		return -ENODEV;
	}

	if (acpi_bus_get_status(device) || !device->status.present) {
		pr_err("%s: device has invalid status", __func__);
		return -ENODEV;
	}

	hid = acpi_device_hid(device);
	pr_debug("%s for %s", __func__, hid);
	ret = sst_alloc_drv_context(dev);
	if (ret)
		return ret;
	ctx = sst_drv_ctx;
	ctx->dev = dev;
	ctx->hid = hid;

	ret = sst_platform_get_resources(hid, ctx, pdev);
	if (ret)
		return ret;
	/* need to save shim registers in BYT */
	ctx->shim_regs64 = devm_kzalloc(dev, sizeof(*ctx->shim_regs64),
					GFP_KERNEL);
	if (!ctx->shim_regs64)
		return -ENOMEM;

	ret = sst_driver_ops(ctx);
	if (ret != 0)
		return -EINVAL;

	sst_init_locks(ctx);

	ctx->stream_cnt = 0;
	ctx->fw_in_mem = NULL;
	ctx->use_dma = 1;
	ctx->use_lli = 1;

	if (sst_workqueue_init(ctx))
		goto do_free_wq;

	ctx->pdata = sst_get_acpi_driver_data(hid);
	if (!ctx->pdata)
		return -EINVAL;
	if (INTEL_MID_BOARD(3, TABLET, BYT, BLK, PRO, CRV2)) {
		/* BYT-CR V2 has only mono speaker, while
		 * byt has stereo speaker, for both
		 * HID is same, so platform data also is
		 * same, hence overriding bdata based on spid
		 */
		ctx->pdata->bdata = &sst_byt_crv2_bdata;
		pr_info("Overriding bdata for byt-crv2\n");
	}

	ctx->use_32bit_ops = ctx->pdata->ipc_info->use_32bit_ops;
	ctx->mailbox_recv_offset = ctx->pdata->ipc_info->mbox_recv_off;

	memcpy(&ctx->info, ctx->pdata->probe_data, sizeof(ctx->info));

	ctx->ipc_reg.ipcx = SST_IPCX + ctx->pdata->ipc_info->ipc_offset;
	ctx->ipc_reg.ipcd = SST_IPCD + ctx->pdata->ipc_info->ipc_offset;

	pr_debug("Got drv data max stream %d\n",
				ctx->info.max_streams);
	for (i = 1; i <= ctx->info.max_streams; i++) {
		struct stream_info *stream = &ctx->streams[i];
		mutex_init(&stream->lock);
	}
	ret = sst_request_firmware_async(ctx);
	if (ret) {
		pr_err("Firmware download failed:%d\n", ret);
		goto do_free_wq;
	}

	ret = devm_request_threaded_irq(ctx->dev, ctx->irq_num, ctx->ops->interrupt,
					ctx->ops->irq_thread, 0, SST_DRV_NAME,
					ctx);
	if (ret)
		return ret;
	pr_debug("Registered IRQ %#x\n", ctx->irq_num);

	/*Register LPE Control as misc driver*/
	ret = misc_register(&lpe_ctrl);
	if (ret) {
		pr_err("couldn't register control device\n");
		goto do_free_wq;
	}
	/* mask all SSP and DMA irq to IA - enabled in acpi kernel driver */
	sst_shim_write64(ctx->shim, SST_IMRX, 0xFFFF0038);

	if (ctx->use_32bit_ops) {
		pr_debug("allocate mem for context save/restore\n ");
		/*allocate mem for fw context save during suspend*/
		ctx->fw_cntx = devm_kzalloc(ctx->dev, FW_CONTEXT_MEM, GFP_KERNEL);
		if (!ctx->fw_cntx) {
			ret = -ENOMEM;
			goto do_free_misc;
		}
		/*setting zero as that is valid mem to restore*/
		ctx->fw_cntx_size = 0;
	}

	platform_set_drvdata(pdev, ctx);
	pm_runtime_set_active(dev);
	pm_runtime_enable(dev);
	register_sst(dev);
	sst_debugfs_init(ctx);
	sst_set_fw_state_locked(ctx, SST_UN_INIT);
	sst_save_shim64(ctx, ctx->shim, ctx->shim_regs64);
	pr_info("%s successfully done!\n", __func__);
	return ret;

do_free_misc:
	misc_deregister(&lpe_ctrl);
do_free_wq:
	sst_destroy_workqueue(ctx);

	sst_drv_ctx = NULL;
	platform_set_drvdata(pdev, NULL);
	pr_err("%s: failed with %d\n", __func__, ret);
	return ret;
}