/** * acpi_dev_pm_attach - Prepare device for ACPI power management. * @dev: Device to prepare. * @power_on: Whether or not to power on the device. * * If @dev has a valid ACPI handle that has a valid struct acpi_device object * attached to it, install a wakeup notification handler for the device and * add it to the general ACPI PM domain. If @power_on is set, the device will * be put into the ACPI D0 state before the function returns. * * This assumes that the @dev's bus type uses generic power management callbacks * (or doesn't use any power management callbacks at all). * * Callers must ensure proper synchronization of this function with power * management callbacks. */ int acpi_dev_pm_attach(struct device *dev, bool power_on) { struct acpi_device *adev = ACPI_COMPANION(dev); if (!adev) return -ENODEV; if (dev->pm_domain) return -EEXIST; /* * Only attach the power domain to the first device if the * companion is shared by multiple. This is to prevent doing power * management twice. */ if (!acpi_device_is_first_physical_node(adev, dev)) return -EBUSY; acpi_add_pm_notifier(adev, dev, acpi_pm_notify_work_func); dev->pm_domain = &acpi_general_pm_domain; if (power_on) { acpi_dev_pm_full_power(adev); acpi_device_wakeup(adev, ACPI_STATE_S0, false); } return 0; }
static void snd_byt_rt5651_mc_add_amp_en_gpio_mapping(struct device *codec) { struct byt_rt5651_acpi_resource_data data = { 0, -1 }; LIST_HEAD(resources); int ret; ret = acpi_dev_get_resources(ACPI_COMPANION(codec), &resources, snd_byt_rt5651_acpi_resource, &data); if (ret < 0) { dev_warn(codec, "Failed to get ACPI resources, not adding external amplifier GPIO mapping\n"); return; } /* All info we need is gathered during the walk */ acpi_dev_free_resource_list(&resources); switch (data.gpio_int_idx) { case 0: devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_second); break; case 1: devm_acpi_dev_add_driver_gpios(codec, byt_rt5651_amp_en_first); break; default: dev_warn(codec, "Unknown GpioInt index %d, not adding external amplifier GPIO mapping\n", data.gpio_int_idx); } }
/* * On some platforms, there is a companion ACPI device, which adds * passive trip temperature using _PSV method. There is no specific * passive temperature setting in MMIO interface of this PCI device. */ static void pch_wpt_add_acpi_psv_trip(struct pch_thermal_device *ptd, int *nr_trips) { struct acpi_device *adev; ptd->psv_trip_id = -1; adev = ACPI_COMPANION(&ptd->pdev->dev); if (adev) { unsigned long long r; acpi_status status; status = acpi_evaluate_integer(adev->handle, "_PSV", NULL, &r); if (ACPI_SUCCESS(status)) { unsigned long trip_temp; trip_temp = DECI_KELVIN_TO_MILLICELSIUS(r); if (trip_temp) { ptd->psv_temp = trip_temp; ptd->psv_trip_id = *nr_trips; ++(*nr_trips); } } } }
/** * acpi_dev_suspend_late - Put device into a low-power state using ACPI. * @dev: Device to put into a low-power state. * * Put the given device into a low-power state during system transition to a * sleep state using the standard ACPI mechanism. Set up system wakeup if * desired, choose the state to put the device into (this checks if system * wakeup is expected to work too), and set the power state of the device. */ int acpi_dev_suspend_late(struct device *dev) { struct acpi_device *adev = ACPI_COMPANION(dev); u32 target_state; bool wakeup; bool can_wakeup; int error; if (!adev) return 0; target_state = acpi_target_system_state(); wakeup = device_may_wakeup(dev); can_wakeup = acpi_device_can_wakeup(adev); if (can_wakeup) { error = __acpi_device_sleep_wake(adev, target_state, wakeup); if (wakeup && error) return error; } else if (wakeup) { dev_warn(dev, "device is not wakeup-capable, not enabling wakeup\n"); } error = acpi_dev_pm_low_power(dev, adev, target_state); if (error && can_wakeup) __acpi_device_sleep_wake(adev, ACPI_STATE_UNKNOWN, false); return error; }
static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev) { struct tpm_chip *chip = spi_get_drvdata(spi_dev); struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); struct st33zp24_spi_phy *phy = tpm_dev->phy_id; struct gpio_desc *gpiod_lpcpd; struct device *dev = &spi_dev->dev; int ret; ret = acpi_dev_add_driver_gpios(ACPI_COMPANION(dev), acpi_st33zp24_gpios); if (ret) return ret; /* Get LPCPD GPIO from ACPI */ gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH); if (IS_ERR(gpiod_lpcpd)) { dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n"); phy->io_lpcpd = -1; /* * lpcpd pin is not specified. This is not an issue as * power management can be also managed by TPM specific * commands. So leave with a success status code. */ return 0; } phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd); return 0; }
/** * acpi_dev_pm_attach - Prepare device for ACPI power management. * @dev: Device to prepare. * @power_on: Whether or not to power on the device. * * If @dev has a valid ACPI handle that has a valid struct acpi_device object * attached to it, install a wakeup notification handler for the device and * add it to the general ACPI PM domain. If @power_on is set, the device will * be put into the ACPI D0 state before the function returns. * * This assumes that the @dev's bus type uses generic power management callbacks * (or doesn't use any power management callbacks at all). * * Callers must ensure proper synchronization of this function with power * management callbacks. */ int acpi_dev_pm_attach(struct device *dev, bool power_on) { struct acpi_device *adev = ACPI_COMPANION(dev); if (!adev) return -ENODEV; if (!strcmp(dev_name(dev), "80860F28:00")) { dev_info(dev, "Skipping ACPI power domain attach\n"); return -ENODEV; } if (dev->pm_domain) return -EEXIST; acpi_add_pm_notifier(adev, acpi_wakeup_device, dev); dev->pm_domain = &acpi_general_pm_domain; if (power_on) { acpi_dev_pm_full_power(adev); __acpi_device_run_wake(adev, false); } dev->pm_domain->detach = acpi_dev_pm_detach; return 0; }
/** * device_property_present - check if a property of a device is present * @dev: Device whose property is being checked * @propname: Name of the property * * Check if property @propname is present in the device firmware description. */ bool device_property_present(struct device *dev, const char *propname) { if (IS_ENABLED(CONFIG_OF) && dev->of_node) return of_property_read_bool(dev->of_node, propname); return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL); }
void *lm3554_platform_data_func(struct i2c_client *client) { static struct lm3554_platform_data platform_data; if (ACPI_COMPANION(&client->dev)) { platform_data.gpio_reset = desc_to_gpio(gpiod_get_index(&(client->dev), "lm3554_gpio2", 2)); platform_data.gpio_strobe = desc_to_gpio(gpiod_get_index(&(client->dev), "lm3554_gpio0", 0)); platform_data.gpio_torch = desc_to_gpio(gpiod_get_index(&(client->dev), "lm3554_gpio1", 1)); }else { platform_data.gpio_reset = -1; platform_data.gpio_strobe = -1; platform_data.gpio_torch = -1; } dev_info(&client->dev, "camera pdata: lm3554: reset: %d strobe %d torch %d\n", platform_data.gpio_reset, platform_data.gpio_strobe, platform_data.gpio_torch); /* Set to TX2 mode, then ENVM/TX2 pin is a power amplifier sync input: * ENVM/TX pin asserted, flash forced into torch; * ENVM/TX pin desserted, flash set back; */ platform_data.envm_tx2 = 1; platform_data.tx2_polarity = 0; /* set peak current limit to be 1000mA */ platform_data.current_limit = 0; return &platform_data; }
static int inv_mpu_process_acpi_config(struct i2c_client *client, unsigned short *primary_addr, unsigned short *secondary_addr) { const struct acpi_device_id *id; struct acpi_device *adev; u32 i2c_addr = 0; LIST_HEAD(resources); int ret; id = acpi_match_device(client->dev.driver->acpi_match_table, &client->dev); if (!id) return -ENODEV; adev = ACPI_COMPANION(&client->dev); if (!adev) return -ENODEV; ret = acpi_dev_get_resources(adev, &resources, acpi_i2c_check_resource, &i2c_addr); if (ret < 0) return ret; acpi_dev_free_resource_list(&resources); *primary_addr = i2c_addr & 0x0000ffff; *secondary_addr = (i2c_addr & 0xffff0000) >> 16; return 0; }
static int ulpi_register(struct device *dev, struct ulpi *ulpi) { int ret; ulpi->dev.parent = dev; /* needed early for ops */ ulpi->dev.bus = &ulpi_bus; ulpi->dev.type = &ulpi_dev_type; dev_set_name(&ulpi->dev, "%s.ulpi", dev_name(dev)); ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev)); ret = ulpi_of_register(ulpi); if (ret) return ret; ret = ulpi_read_id(ulpi); if (ret) return ret; ret = device_register(&ulpi->dev); if (ret) return ret; dev_dbg(&ulpi->dev, "registered ULPI PHY: vendor %04x, product %04x\n", ulpi->id.vendor, ulpi->id.product); return 0; }
/** * platform_get_irq - get an IRQ for a device * @dev: platform device * @num: IRQ number index */ int platform_get_irq(struct platform_device *dev, unsigned int num) { #ifdef CONFIG_SPARC /* sparc does not have irqs represented as IORESOURCE_IRQ resources */ if (!dev || num >= dev->archdata.num_irqs) return -ENXIO; return dev->archdata.irqs[num]; #else struct resource *r; if (IS_ENABLED(CONFIG_OF_IRQ) && dev->dev.of_node) { int ret; ret = of_irq_get(dev->dev.of_node, num); if (ret > 0 || ret == -EPROBE_DEFER) return ret; } r = platform_get_resource(dev, IORESOURCE_IRQ, num); if (has_acpi_companion(&dev->dev)) { if (r && r->flags & IORESOURCE_DISABLED) { int ret; ret = acpi_irq_get(ACPI_HANDLE(&dev->dev), num, r); if (ret) return ret; } } /* * The resources may pass trigger flags to the irqs that need * to be set up. It so happens that the trigger flags for * IORESOURCE_BITS correspond 1-to-1 to the IRQF_TRIGGER* * settings. */ if (r && r->flags & IORESOURCE_BITS) { struct irq_data *irqd; irqd = irq_get_irq_data(r->start); if (!irqd) return -ENXIO; irqd_set_trigger_type(irqd, r->flags & IORESOURCE_BITS); } if (r) return r->start; /* * For the index 0 interrupt, allow falling back to GpioInt * resources. While a device could have both Interrupt and GpioInt * resources, making this fallback ambiguous, in many common cases * the device will only expose one IRQ, and this fallback * allows a common code path across either kind of resource. */ if (num == 0 && has_acpi_companion(&dev->dev)) return acpi_dev_gpio_irq_get(ACPI_COMPANION(&dev->dev), num); return -ENXIO; #endif }
/** * device_property_read_string - return a string property of a device * @dev: Device to get the property of * @propname: Name of the property * @val: The value is stored here * * Function reads property @propname from the device firmware description and * stores the value into @val if found. The value is checked to be a string. * * Return: %0 if the property was found (success), * %-EINVAL if given arguments are not valid, * %-ENODATA if the property does not have a value, * %-EPROTO or %-EILSEQ if the property type is not a string. */ int device_property_read_string(struct device *dev, const char *propname, const char **val) { return IS_ENABLED(CONFIG_OF) && dev->of_node ? of_property_read_string(dev->of_node, propname, val) : acpi_dev_prop_read(ACPI_COMPANION(dev), propname, DEV_PROP_STRING, val, 1); }
static int dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { struct resource res[2]; struct platform_device *dwc3; int ret; struct device *dev = &pci->dev; ret = pcim_enable_device(pci); if (ret) { dev_err(dev, "failed to enable pci device\n"); return -ENODEV; } pci_set_master(pci); dwc3 = platform_device_alloc("dwc3", PLATFORM_DEVID_AUTO); if (!dwc3) { dev_err(dev, "couldn't allocate dwc3 device\n"); return -ENOMEM; } memset(res, 0x00, sizeof(struct resource) * ARRAY_SIZE(res)); res[0].start = pci_resource_start(pci, 0); res[0].end = pci_resource_end(pci, 0); res[0].name = "dwc_usb3"; res[0].flags = IORESOURCE_MEM; res[1].start = pci->irq; res[1].name = "dwc_usb3"; res[1].flags = IORESOURCE_IRQ; ret = platform_device_add_resources(dwc3, res, ARRAY_SIZE(res)); if (ret) { dev_err(dev, "couldn't add resources to dwc3 device\n"); return ret; } pci_set_drvdata(pci, dwc3); ret = dwc3_pci_quirks(pci); if (ret) goto err; dwc3->dev.parent = dev; ACPI_COMPANION_SET(&dwc3->dev, ACPI_COMPANION(dev)); ret = platform_device_add(dwc3); if (ret) { dev_err(dev, "failed to register dwc3 device\n"); goto err; } return 0; err: platform_device_put(dwc3); return ret; }
static int acpi_processor_start(struct device *dev) { struct acpi_device *device = ACPI_COMPANION(dev); if (!device) return -ENODEV; return __acpi_processor_start(device); }
static void dwc3_pci_remove(struct pci_dev *pci) { struct dwc3_pci *dwc = pci_get_drvdata(pci); device_init_wakeup(&pci->dev, false); pm_runtime_get(&pci->dev); acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pci->dev)); platform_device_unregister(dwc->dwc3); }
static int acpi_pci_set_power_state(struct pci_dev *dev, pci_power_t state) { struct acpi_device *adev = ACPI_COMPANION(&dev->dev); static const u8 state_conv[] = { [PCI_D0] = ACPI_STATE_D0, [PCI_D1] = ACPI_STATE_D1, [PCI_D2] = ACPI_STATE_D2, [PCI_D3hot] = ACPI_STATE_D3_HOT, [PCI_D3cold] = ACPI_STATE_D3_COLD, };
bool device_dma_supported(struct device *dev) { /* For DT, this is always supported. * For ACPI, this depends on CCA, which * is determined by the acpi_dma_supported(). */ if (IS_ENABLED(CONFIG_OF) && dev->of_node) return true; return acpi_dma_supported(ACPI_COMPANION(dev)); }
static int rfkill_gpio_remove(struct platform_device *pdev) { struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev); rfkill_unregister(rfkill->rfkill_dev); rfkill_destroy(rfkill->rfkill_dev); acpi_dev_remove_driver_gpios(ACPI_COMPANION(&pdev->dev)); return 0; }
bool device_dma_is_coherent(struct device *dev) { bool coherent = false; if (IS_ENABLED(CONFIG_OF) && dev->of_node) coherent = of_dma_is_coherent(dev->of_node); else acpi_check_dma(ACPI_COMPANION(dev), &coherent); return coherent; }
/** * acpi_dev_resume_early - Put device into the full-power state using ACPI. * @dev: Device to put into the full-power state. * * Put the given device into the full-power state using the standard ACPI * mechanism during system transition to the working state. Set the power * state of the device to ACPI D0 and disable remote wakeup. */ int acpi_dev_resume_early(struct device *dev) { struct acpi_device *adev = ACPI_COMPANION(dev); int error; if (!adev) return 0; error = acpi_dev_pm_full_power(adev); acpi_device_wakeup(adev, ACPI_STATE_UNKNOWN, false); return error; }
/* * st33zp24_spi_remove remove the TPM device * @param: client, the spi_device drescription (TPM SPI description). * @return: 0 in case of success. */ static int st33zp24_spi_remove(struct spi_device *dev) { struct tpm_chip *chip = spi_get_drvdata(dev); int ret; ret = st33zp24_remove(chip); if (ret) return ret; acpi_dev_remove_driver_gpios(ACPI_COMPANION(&dev->dev)); return 0; }
static int acpi_container_offline(struct container_dev *cdev) { struct acpi_device *adev = ACPI_COMPANION(&cdev->dev); struct acpi_device *child; /* Check all of the dependent devices' physical companions. */ list_for_each_entry(child, &adev->children, node) if (!acpi_scan_is_offline(child, false)) return -EBUSY; return 0; }
/** * acpi_dev_runtime_resume - Put device into the full-power state using ACPI. * @dev: Device to put into the full-power state. * * Put the given device into the full-power state using the standard ACPI * mechanism at run time. Set the power state of the device to ACPI D0 and * disable remote wakeup. */ int acpi_dev_runtime_resume(struct device *dev) { struct acpi_device *adev = ACPI_COMPANION(dev); int error; if (!adev) return 0; error = acpi_dev_pm_full_power(adev); __acpi_device_run_wake(adev, false); return error; }
static int acpi_ac_probe(struct platform_device *pdev) { int result = 0; struct acpi_ac *ac = NULL; struct acpi_device *adev; if (!pdev) return -EINVAL; adev = ACPI_COMPANION(&pdev->dev); if (!adev) return -ENODEV; ac = kzalloc(sizeof(struct acpi_ac), GFP_KERNEL); if (!ac) return -ENOMEM; strcpy(acpi_device_name(adev), ACPI_AC_DEVICE_NAME); strcpy(acpi_device_class(adev), ACPI_AC_CLASS); ac->pdev = pdev; platform_set_drvdata(pdev, ac); result = acpi_ac_get_state(ac); if (result) goto end; ac->charger.name = acpi_device_bid(adev); ac->charger.type = POWER_SUPPLY_TYPE_MAINS; ac->charger.properties = ac_props; ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.get_property = get_ac_property; result = power_supply_register(&pdev->dev, &ac->charger); if (result) goto end; result = acpi_install_notify_handler(ACPI_HANDLE(&pdev->dev), ACPI_ALL_NOTIFY, acpi_ac_notify_handler, ac); if (result) { power_supply_unregister(&ac->charger); goto end; } printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(adev), acpi_device_bid(adev), ac->state ? "on-line" : "off-line"); end: if (result) kfree(ac); dmi_check_system(ac_dmi_table); return result; }
/* * acpi_companion_match() - Can we match via ACPI companion device * @dev: Device in question * * Check if the given device has an ACPI companion and if that companion has * a valid list of PNP IDs, and if the device is the first (primary) physical * device associated with it. Return the companion pointer if that's the case * or NULL otherwise. * * If multiple physical devices are attached to a single ACPI companion, we need * to be careful. The usage scenario for this kind of relationship is that all * of the physical devices in question use resources provided by the ACPI * companion. A typical case is an MFD device where all the sub-devices share * the parent's ACPI companion. In such cases we can only allow the primary * (first) physical device to be matched with the help of the companion's PNP * IDs. * * Additional physical devices sharing the ACPI companion can still use * resources available from it but they will be matched normally using functions * provided by their bus types (and analogously for their modalias). */ struct acpi_device *acpi_companion_match(const struct device *dev) { struct acpi_device *adev; adev = ACPI_COMPANION(dev); if (!adev) return NULL; if (list_empty(&adev->pnp.ids)) return NULL; return acpi_primary_dev_companion(adev, dev); }
/** * device_get_next_child_node - Return the next child node handle for a device * @dev: Device to find the next child node for. * @child: Handle to one of the device's child nodes or a null handle. */ struct fwnode_handle *device_get_next_child_node(struct device *dev, struct fwnode_handle *child) { struct acpi_device *adev = ACPI_COMPANION(dev); struct fwnode_handle *fwnode = NULL; if (dev->of_node) fwnode = &dev->of_node->fwnode; else if (adev) fwnode = acpi_fwnode_handle(adev); return fwnode_get_next_child_node(fwnode, child); }
int inv_mpu_acpi_create_mux_client(struct i2c_client *client) { struct inv_mpu6050_state *st = iio_priv(dev_get_drvdata(&client->dev)); st->mux_client = NULL; if (ACPI_HANDLE(&client->dev)) { struct i2c_board_info info; struct acpi_device *adev; int ret = -1; adev = ACPI_COMPANION(&client->dev); memset(&info, 0, sizeof(info)); dmi_check_system(inv_mpu_dev_list); switch (matched_product_name) { case INV_MPU_ASUS_T100TA: ret = asus_acpi_get_sensor_info(adev, client, &info); break; /* Add more matched product processing here */ default: break; } if (ret < 0) { /* No matching DMI, so create device on INV6XX type */ unsigned short primary, secondary; ret = inv_mpu_process_acpi_config(client, &primary, &secondary); if (!ret && secondary) { char *name; info.addr = secondary; strlcpy(info.type, dev_name(&adev->dev), sizeof(info.type)); name = strchr(info.type, ':'); if (name) *name = '\0'; strlcat(info.type, "-client", sizeof(info.type)); } else return 0; /* no secondary addr, which is OK */ } st->mux_client = i2c_new_device(st->muxc->adapter[0], &info); if (!st->mux_client) return -ENODEV; } return 0; }
enum dev_dma_attr device_get_dma_attr(struct device *dev) { enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED; if (IS_ENABLED(CONFIG_OF) && dev->of_node) { if (of_dma_is_coherent(dev->of_node)) attr = DEV_DMA_COHERENT; else attr = DEV_DMA_NON_COHERENT; } else attr = acpi_get_dma_attr(ACPI_COMPANION(dev)); return attr; }
static int xlp9xx_i2c_probe(struct platform_device *pdev) { struct xlp9xx_i2c_dev *priv; struct resource *res; int err = 0; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(priv->base)) return PTR_ERR(priv->base); priv->irq = platform_get_irq(pdev, 0); if (priv->irq <= 0) { dev_err(&pdev->dev, "invalid irq!\n"); return priv->irq; } xlp9xx_i2c_get_frequency(pdev, priv); xlp9xx_i2c_init(priv); err = devm_request_irq(&pdev->dev, priv->irq, xlp9xx_i2c_isr, 0, pdev->name, priv); if (err) { dev_err(&pdev->dev, "IRQ request failed!\n"); return err; } init_completion(&priv->msg_complete); priv->adapter.dev.parent = &pdev->dev; priv->adapter.algo = &xlp9xx_i2c_algo; ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&pdev->dev)); priv->adapter.dev.of_node = pdev->dev.of_node; priv->dev = &pdev->dev; snprintf(priv->adapter.name, sizeof(priv->adapter.name), "xlp9xx-i2c"); i2c_set_adapdata(&priv->adapter, priv); err = i2c_add_adapter(&priv->adapter); if (err) return err; platform_set_drvdata(pdev, priv); dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr); return 0; }
/** * acpi_pm_device_run_wake - Enable/disable remote wakeup for given device. * @dev: Device to enable/disable the platform to wake up. * @enable: Whether to enable or disable the wakeup functionality. */ int acpi_pm_device_run_wake(struct device *phys_dev, bool enable) { struct acpi_device *adev; if (!device_run_wake(phys_dev)) return -EINVAL; adev = ACPI_COMPANION(phys_dev); if (!adev) { dev_dbg(phys_dev, "ACPI companion missing in %s!\n", __func__); return -ENODEV; } return acpi_device_wakeup(adev, ACPI_STATE_S0, enable); }