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; }
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); }
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); }
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; }
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; }
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; }