in extcon-gpio.c [65:135]
static int gpio_extcon_probe(struct platform_device *pdev)
{
struct gpio_extcon_data *data;
struct device *dev = &pdev->dev;
unsigned long irq_flags;
int irq;
int ret;
data = devm_kzalloc(dev, sizeof(struct gpio_extcon_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
/*
* FIXME: extcon_id represents the unique identifier of external
* connectors such as EXTCON_USB, EXTCON_DISP_HDMI and so on. extcon_id
* is necessary to register the extcon device. But, it's not yet
* developed to get the extcon id from device-tree or others.
* On later, it have to be solved.
*/
if (data->extcon_id > EXTCON_NONE)
return -EINVAL;
data->gpiod = devm_gpiod_get(dev, "extcon", GPIOD_IN);
if (IS_ERR(data->gpiod))
return PTR_ERR(data->gpiod);
irq = gpiod_to_irq(data->gpiod);
if (irq <= 0)
return irq;
/*
* It is unlikely that this is an acknowledged interrupt that goes
* away after handling, what we are looking for are falling edges
* if the signal is active low, and rising edges if the signal is
* active high.
*/
if (gpiod_is_active_low(data->gpiod))
irq_flags = IRQF_TRIGGER_FALLING;
else
irq_flags = IRQF_TRIGGER_RISING;
/* Allocate the memory of extcon devie and register extcon device */
data->edev = devm_extcon_dev_allocate(dev, &data->extcon_id);
if (IS_ERR(data->edev)) {
dev_err(dev, "failed to allocate extcon device\n");
return -ENOMEM;
}
ret = devm_extcon_dev_register(dev, data->edev);
if (ret < 0)
return ret;
ret = devm_delayed_work_autocancel(dev, &data->work, gpio_extcon_work);
if (ret)
return ret;
/*
* Request the interrupt of gpio to detect whether external connector
* is attached or detached.
*/
ret = devm_request_any_context_irq(dev, irq,
gpio_irq_handler, irq_flags,
pdev->name, data);
if (ret < 0)
return ret;
platform_set_drvdata(pdev, data);
/* Perform initial detection */
gpio_extcon_work(&data->work.work);
return 0;
}