static void acpi_virtual_gpio_request_interrupts(struct virtual_gpio_data *gd)
{
	struct device *dev = &gd->pdev->dev;
	struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
	struct acpi_resource *res;
	acpi_handle handle, ev_handle;
	acpi_status status;
	unsigned int pin;
	int ret;
	char ev_name[5];

	handle = ACPI_HANDLE(dev);
	if (!handle)
		return;

	status = acpi_get_event_resources(handle, &buf);
	if (ACPI_FAILURE(status))
		return;

	/*
	 * If a GPIO interrupt has an ACPI event handler method, set
	 * up an interrupt handler that calls the ACPI event handler.
	 */
	for (res = buf.pointer;
	     res && (res->type != ACPI_RESOURCE_TYPE_END_TAG);
	     res = ACPI_NEXT_RESOURCE(res)) {

		if (res->type != ACPI_RESOURCE_TYPE_GPIO ||
		    res->data.gpio.connection_type !=
		    ACPI_RESOURCE_GPIO_TYPE_INT)
			continue;

		pin = res->data.gpio.pin_table[0];
		dev_info(dev, "virtual gpio pin = %d\n", pin);
		if (pin > 255)
			continue;

		sprintf(ev_name, "_%c%02X",
			res->data.gpio.triggering ? 'E' : 'L', pin);
		status = acpi_get_handle(handle, ev_name, &ev_handle);
		if (ACPI_FAILURE(status))
			continue;

		/* Assume BIOS sets the triggering, so no flags */
		ret = devm_request_irq(dev, gd->irq,
						virtual_gpio_irq_handler_isr,
						0,
						VIRTUAL_GPIO_DRIVER_NAME,
						ev_handle);
		if (ret)
			dev_err(dev,
				"Failed to request IRQ %d ACPI event handler\n",
				gd->irq);
	}
}
Esempio n. 2
0
static acpi_status
acpi_db_device_resources(acpi_handle obj_handle,
			 u32 nesting_level, void *context, void **return_value)
{
	struct acpi_namespace_node *node;
	struct acpi_namespace_node *prt_node = NULL;
	struct acpi_namespace_node *crs_node = NULL;
	struct acpi_namespace_node *prs_node = NULL;
	struct acpi_namespace_node *aei_node = NULL;
	char *parent_path;
	struct acpi_buffer return_buffer;
	acpi_status status;

	node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
	parent_path = acpi_ns_get_normalized_pathname(node, TRUE);
	if (!parent_path) {
		return (AE_NO_MEMORY);
	}

	/* Get handles to the resource methods for this device */

	(void)acpi_get_handle(node, METHOD_NAME__PRT,
			      ACPI_CAST_PTR(acpi_handle, &prt_node));
	(void)acpi_get_handle(node, METHOD_NAME__CRS,
			      ACPI_CAST_PTR(acpi_handle, &crs_node));
	(void)acpi_get_handle(node, METHOD_NAME__PRS,
			      ACPI_CAST_PTR(acpi_handle, &prs_node));
	(void)acpi_get_handle(node, METHOD_NAME__AEI,
			      ACPI_CAST_PTR(acpi_handle, &aei_node));

	if (!prt_node && !crs_node && !prs_node && !aei_node) {
		goto cleanup;	/* Nothing to do */
	}

	acpi_os_printf("\nDevice: %s\n", parent_path);

	/* Prepare for a return object of arbitrary size */

	return_buffer.pointer = acpi_gbl_db_buffer;
	return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

	/* _PRT */

	if (prt_node) {
		acpi_os_printf("Evaluating _PRT\n");

		status =
		    acpi_evaluate_object(prt_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _PRT: %s\n",
				       acpi_format_exception(status));
			goto get_crs;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_irq_routing_table(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("GetIrqRoutingTable failed: %s\n",
				       acpi_format_exception(status));
			goto get_crs;
		}

		acpi_rs_dump_irq_list(ACPI_CAST_PTR(u8, acpi_gbl_db_buffer));
	}

	/* _CRS */

get_crs:
	if (crs_node) {
		acpi_os_printf("Evaluating _CRS\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(crs_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _CRS: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* This code exercises the acpi_walk_resources interface */

		status = acpi_walk_resources(node, METHOD_NAME__CRS,
					     acpi_db_resource_callback, NULL);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiWalkResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* Get the _CRS resource list (test ALLOCATE buffer) */

		return_buffer.pointer = NULL;
		return_buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;

		status = acpi_get_current_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetCurrentResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_prs;
		}

		/* This code exercises the acpi_walk_resource_buffer interface */

		status = acpi_walk_resource_buffer(&return_buffer,
						   acpi_db_resource_callback,
						   NULL);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiWalkResourceBuffer failed: %s\n",
				       acpi_format_exception(status));
			goto end_crs;
		}

		/* Dump the _CRS resource list */

		acpi_rs_dump_resource_list(ACPI_CAST_PTR(struct acpi_resource,
							 return_buffer.
							 pointer));

		/*
		 * Perform comparison of original AML to newly created AML. This
		 * tests both the AML->Resource conversion and the Resource->AML
		 * conversion.
		 */
		(void)acpi_dm_test_resource_conversion(node, METHOD_NAME__CRS);

		/* Execute _SRS with the resource list */

		acpi_os_printf("Evaluating _SRS\n");

		status = acpi_set_current_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiSetCurrentResources failed: %s\n",
				       acpi_format_exception(status));
			goto end_crs;
		}

end_crs:
		ACPI_FREE(return_buffer.pointer);
	}

	/* _PRS */

get_prs:
	if (prs_node) {
		acpi_os_printf("Evaluating _PRS\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(prs_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _PRS: %s\n",
				       acpi_format_exception(status));
			goto get_aei;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_possible_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetPossibleResources failed: %s\n",
				       acpi_format_exception(status));
			goto get_aei;
		}

		acpi_rs_dump_resource_list(ACPI_CAST_PTR
					   (struct acpi_resource,
					    acpi_gbl_db_buffer));
	}

	/* _AEI */

get_aei:
	if (aei_node) {
		acpi_os_printf("Evaluating _AEI\n");

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status =
		    acpi_evaluate_object(aei_node, NULL, NULL, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("Could not evaluate _AEI: %s\n",
				       acpi_format_exception(status));
			goto cleanup;
		}

		return_buffer.pointer = acpi_gbl_db_buffer;
		return_buffer.length = ACPI_DEBUG_BUFFER_SIZE;

		status = acpi_get_event_resources(node, &return_buffer);
		if (ACPI_FAILURE(status)) {
			acpi_os_printf("AcpiGetEventResources failed: %s\n",
				       acpi_format_exception(status));
			goto cleanup;
		}

		acpi_rs_dump_resource_list(ACPI_CAST_PTR
					   (struct acpi_resource,
					    acpi_gbl_db_buffer));
	}

cleanup:
	ACPI_FREE(parent_path);
	return (AE_OK);
}
Esempio n. 3
0
/**
 * acpi_gpiochip_request_interrupts() - Register isr for gpio chip ACPI events
 * @chip:      gpio chip
 *
 * ACPI5 platforms can use GPIO signaled ACPI events. These GPIO interrupts are
 * handled by ACPI event methods which need to be called from the GPIO
 * chip's interrupt handler. acpi_gpiochip_request_interrupts finds out which
 * gpio pins have acpi event methods and assigns interrupt handlers that calls
 * the acpi event methods for those pins.
 */
void acpi_gpiochip_request_interrupts(struct gpio_chip *chip)
{
    struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
    struct acpi_resource *res;
    acpi_handle handle, evt_handle;
    struct list_head *evt_pins = NULL;
    acpi_status status;
    unsigned int pin;
    int irq, ret;
    char ev_name[5];

    if (!chip->dev || !chip->to_irq)
        return;

    handle = ACPI_HANDLE(chip->dev);
    if (!handle)
        return;

    status = acpi_get_event_resources(handle, &buf);
    if (ACPI_FAILURE(status))
        return;

    status = acpi_get_handle(handle, "_EVT", &evt_handle);
    if (ACPI_SUCCESS(status)) {
        evt_pins = kzalloc(sizeof(*evt_pins), GFP_KERNEL);
        if (evt_pins) {
            INIT_LIST_HEAD(evt_pins);
            status = acpi_attach_data(handle, acpi_gpio_evt_dh,
                                      evt_pins);
            if (ACPI_FAILURE(status)) {
                kfree(evt_pins);
                evt_pins = NULL;
            }
        }
    }

    /*
     * If a GPIO interrupt has an ACPI event handler method, or _EVT is
     * present, set up an interrupt handler that calls the ACPI event
     * handler.
     */
    for (res = buf.pointer;
            res && (res->type != ACPI_RESOURCE_TYPE_END_TAG);
            res = ACPI_NEXT_RESOURCE(res)) {
        irq_handler_t handler = NULL;
        void *data;

        if (res->type != ACPI_RESOURCE_TYPE_GPIO ||
                res->data.gpio.connection_type !=
                ACPI_RESOURCE_GPIO_TYPE_INT)
            continue;

        pin = res->data.gpio.pin_table[0];
        if (pin > chip->ngpio)
            continue;

        irq = chip->to_irq(chip, pin);
        if (irq < 0)
            continue;

        if (pin <= 255) {
            acpi_handle ev_handle;

            sprintf(ev_name, "_%c%02X",
                    res->data.gpio.triggering ? 'E' : 'L', pin);
            status = acpi_get_handle(handle, ev_name, &ev_handle);
            if (ACPI_SUCCESS(status)) {
                handler = acpi_gpio_irq_handler;
                data = ev_handle;
            }
        }
        if (!handler && evt_pins) {
            struct acpi_gpio_evt_pin *evt_pin;

            evt_pin = kzalloc(sizeof(*evt_pin), GFP_KERNEL);
            if (!evt_pin)
                continue;

            list_add_tail(&evt_pin->node, evt_pins);
            evt_pin->evt_handle = evt_handle;
            evt_pin->pin = pin;
            evt_pin->irq = irq;
            handler = acpi_gpio_irq_handler_evt;
            data = evt_pin;
        }
        if (!handler)
            continue;

        /* Assume BIOS sets the triggering, so no flags */
        ret = devm_request_threaded_irq(chip->dev, irq, NULL, handler,
                                        0, "GPIO-signaled-ACPI-event",
                                        data);
        if (ret)
            dev_err(chip->dev,
                    "Failed to request IRQ %d ACPI event handler\n",
                    irq);
    }
}