genode/repos/os/src/drivers/gpio/spec/exynos4/driver.h

221 lines
5.7 KiB
C++

/*
* \brief Gpio driver for the Odroid-x2
* \author Alexy Gallardo Segura <alexy@uclv.cu>
* \author Humberto Lopéz Leon <humberto@uclv.cu>
* \author Reinier Millo Sánchez <rmillo@uclv.cu>
* \date 2015-07-03
*/
/*
* Copyright (C) 2012 Ksys Labs LLC
* Copyright (C) 2012-2017 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DRIVER_H_
#define _DRIVER_H_
/* Genode includes */
#include <gpio/driver.h>
#include <irq_session/connection.h>
#include <timer_session/connection.h>
/* local includes */
#include <gpio.h>
namespace Gpio { class Odroid_x2_driver; }
class Gpio::Odroid_x2_driver : public Driver
{
private:
Reg _reg1;
Reg _reg2;
Reg _reg3;
Reg _reg4;
Genode::Irq_connection _irq;
Genode::Signal_handler<Odroid_x2_driver> _dispatcher;
Genode::Signal_context_capability _sig_cap[MAX_PINS];
bool _irq_enabled[MAX_PINS];
bool _async;
void _handle()
{
handle_irq();
}
void handle_irq() { }
Gpio::Reg *_gpio_reg(int gpio_pin)
{
int pos = gpio_bank_index(gpio_pin, true);
switch(pos) {
case 0 ... 13:
return &_reg1;
case 14 ... 38:
return &_reg2;
case 39:
return &_reg3;
case 40 ... 46:
return &_reg4;
default:
Genode::error("no Gpio_bank for pin ", gpio_pin, " available");
return 0;
}
}
int _gpio_index(int gpio) { return gpio & 0x1f; }
Odroid_x2_driver(Genode::Env &env)
:
_reg1(env, 0x11400000, 1000),
_reg2(env, 0x11000000, 1000),
_reg3(env, 0x03860000, 1000),
_reg4(env, 0x106E0000, 1000),
_irq(env, 104),
_dispatcher(env.ep(), *this, &Odroid_x2_driver::_handle),
_async(false)
{
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
public:
static Odroid_x2_driver& factory(Genode::Env &env);
/******************************
** Gpio::Driver interface **
******************************/
void direction(unsigned gpio_pin, bool input) override
{
int pos_gpio = gpio_bank_index(gpio_pin, true);
int sum_gpio = gpio_bank_index(gpio_pin, false);
Genode::off_t offset = _bank_offset[pos_gpio];
int gpio = gpio_pin - sum_gpio;
Reg* reg = _gpio_reg(gpio_pin);
reg->set_direction(gpio, input, offset);
}
void write(unsigned gpio_pin, bool level) override
{
int pos_gpio = gpio_bank_index(gpio_pin, true);
int sum_gpio = gpio_bank_index(gpio_pin, false);
Genode::off_t offset = _bank_offset[pos_gpio];
int gpio = gpio_pin - sum_gpio;
Reg* reg = _gpio_reg(gpio_pin);
reg->write_pin(gpio, level, offset);
}
bool read(unsigned gpio_pin) override
{
int pos_gpio = gpio_bank_index(gpio_pin, true);
int sum_gpio = gpio_bank_index(gpio_pin, false);
Genode::off_t offset = _bank_offset[pos_gpio];
int gpio = gpio_pin - sum_gpio;
Reg* reg = _gpio_reg(gpio_pin);
return reg->read_pin(gpio, offset) ;
}
void debounce_enable(unsigned /* gpio */, bool /* enable */) override {
Genode::warning("debounce_enable not supported!"); }
void debounce_time(unsigned /* gpio */, unsigned long /* us */) override {
Genode::warning("debounce_time not supported!"); }
void falling_detect(unsigned gpio_pin) override
{
int pos_gpio = gpio_bank_index(gpio_pin, true);
int sum_gpio = gpio_bank_index(gpio_pin, false);
Genode::off_t offset = _irq_offset[pos_gpio];
int gpio = gpio_pin - sum_gpio;
Reg* reg = _gpio_reg(gpio_pin);
reg->set_enable_triggers(gpio, offset, FALLING);
}
void rising_detect(unsigned gpio_pin) override
{
int pos_gpio = gpio_bank_index(gpio_pin, true);
int sum_gpio = gpio_bank_index(gpio_pin, false);
Genode::off_t offset = _irq_offset[pos_gpio];
int gpio = gpio_pin - sum_gpio;
Reg* reg = _gpio_reg(gpio_pin);
reg->set_enable_triggers(gpio, offset, RISING);
}
void high_detect(unsigned gpio_pin) override
{
int pos_gpio = gpio_bank_index(gpio_pin, true);
int sum_gpio = gpio_bank_index(gpio_pin, false);
Genode::off_t offset = _irq_offset[pos_gpio];
int gpio = gpio_pin-sum_gpio;
Reg* reg = _gpio_reg(gpio_pin);
reg->set_enable_triggers(gpio, offset, HIGH);
}
void low_detect(unsigned gpio_pin) override
{
int pos_gpio = gpio_bank_index(gpio_pin, true);
int sum_gpio = gpio_bank_index(gpio_pin, false);
Genode::off_t offset = _irq_offset[pos_gpio];
int gpio = gpio_pin - sum_gpio;
Reg* reg = _gpio_reg(gpio_pin);
reg->set_enable_triggers(gpio, offset, LOW);
}
void irq_enable(unsigned gpio_pin, bool enable) override
{
_irq_enabled[gpio_pin] = enable;
}
void ack_irq(unsigned /* gpio_pin */) override
{
_irq.ack_irq();
}
void register_signal(unsigned gpio_pin,
Genode::Signal_context_capability cap) override
{
_sig_cap[gpio_pin] = cap;
}
void unregister_signal(unsigned gpio_pin) override
{
Genode::Signal_context_capability cap;
_sig_cap[gpio_pin] = cap;
}
int gpio_bank_index(int pin, bool pos)
{
int i = 0 ,sum = 0;
while (i<MAX_BANKS && ((sum + _bank_sizes[i]) <= pin)) {
sum += 1 + _bank_sizes[i++];
}
return pos ? i : sum;
}
bool gpio_valid(unsigned gpio) override { return gpio < (MAX_PINS); }
};
#endif /* _DRIVER_H_ */