2016-03-23 19:01:06 +08:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
|
2016-04-26 22:54:08 +08:00
|
|
|
#include <errno.h>
|
|
|
|
|
2016-03-23 19:01:06 +08:00
|
|
|
#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) {
|
2016-04-26 22:54:08 +08:00
|
|
|
return -EIO;
|
2016-03-23 19:01:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = gpio_remove_callback(dev, &compat->d->cb);
|
2016-04-26 22:54:08 +08:00
|
|
|
if (ret != 0) {
|
2016-03-23 19:01:06 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!callback) {
|
2016-04-26 22:54:08 +08:00
|
|
|
return 0;
|
2016-03-23 19:01:06 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|