blob: 26d5849ebfe2705ca93f0e088a474923d832a6f1 [file] [log] [blame]
/*
* Copyright (c) 2016 Intel Corporation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file Implementation of the API 1.0 GPIO compatibility layer
*/
#include <errno.h>
#include <gpio.h>
#include <misc/util.h>
#include "gpio_api_compat.h"
/** These are maintained in a dedicated .gpio_compat section
* See relevant arch's linker definitions in include/arch/
*/
extern struct gpio_compat_cb __gpio_compat_start[];
extern struct gpio_compat_cb __gpio_compat_end[];
static struct gpio_compat_cb *_gpio_compat_dev_lookup(struct device *dev)
{
struct gpio_compat_cb *cb;
for (cb = __gpio_compat_start; cb != __gpio_compat_end; cb++) {
if (cb->dev == dev) {
return cb;
}
}
return NULL;
}
static void _gpio_compat_handler(struct device *dev,
struct gpio_callback *cb, uint32_t pins)
{
struct _gpio_compat_data *data;
int bit;
data = CONTAINER_OF(cb, struct _gpio_compat_data, cb);
for (bit = 0; bit < 32; bit++) {
if (pins & BIT(bit)) {
data->handler(dev, bit);
}
}
}
int gpio_set_callback(struct device *dev, gpio_callback_t callback)
{
struct gpio_compat_cb *compat = _gpio_compat_dev_lookup(dev);
int ret;
if (!compat) {
return -EIO;
}
ret = gpio_remove_callback(dev, &compat->d->cb);
if (ret != 0) {
return ret;
}
if (!callback) {
return 0;
}
compat->d->handler = callback;
compat->d->cb.handler = _gpio_compat_handler;
return gpio_add_callback(dev, &compat->d->cb);
}
void _gpio_enable_callback(struct device *dev, uint32_t pins)
{
struct gpio_compat_cb *compat = _gpio_compat_dev_lookup(dev);
if (compat) {
compat->d->cb.pin_mask |= pins;
}
}
void _gpio_disable_callback(struct device *dev, uint32_t pins)
{
struct gpio_compat_cb *compat = _gpio_compat_dev_lookup(dev);
if (compat) {
compat->d->cb.pin_mask &= ~(pins);
}
}