foc_odroid_x2: basic configuration for gpio pins

Fixes #1669
This commit is contained in:
Alexy Gallardo Segura 2015-09-08 00:30:41 -04:00 committed by Christian Helmuth
parent 49b3d520a9
commit de87ecfc62
6 changed files with 545 additions and 3 deletions

View File

@ -67,12 +67,30 @@ struct Genode::Board_base : Exynos4
/* HDMI base */
HDMI_BASE = 0x12D00000,
/* IC2 BASE*/
/* IC2 BASE */
I2C_BASE = 0x138E0000,
/* HDMI IRQ*/
/* HDMI IRQ */
I2C_HDMI_IRQ = 125,
/* GPIO */
GPIO1_MMIO_BASE = 0x11400000,
GPIO1_MMIO_SIZE = 0x0F88,
GPIO1_IRQ = 79, /* TODO Check the irq number */
GPIO2_MMIO_BASE = 0x11000000,
GPIO2_MMIO_SIZE = 0x0F88,
GPIO2_IRQ = 79, /* TODO Check the irq number */
GPIO3_MMIO_BASE = 0x03860000,
GPIO3_MMIO_SIZE = 0x0F88,
GPIO3_IRQ = 79, /* TODO Check the irq number */
GPIO4_MMIO_BASE = 0x106E0000,
GPIO4_MMIO_SIZE = 0x0F88,
GPIO4_IRQ = 79, /* TODO Check the irq number */
/* wether board provides security extension */
SECURITY_EXTENSION = 0, /* TODO Check this value */
};

View File

@ -7,7 +7,7 @@
#
# denote specs that are fullfilled by this spec
SPECS += exynos exynos4 cortex_a9 usb framebuffer
SPECS += exynos exynos4 cortex_a9 usb framebuffer gpio
# add repository relative paths
REP_INC_DIR += include/spec/odroid_x2

View File

@ -0,0 +1,268 @@
/*
* \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-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _DRIVER_H_
#define _DRIVER_H_
/* Genode includes */
#include <drivers/board_base.h>
#include <gpio/driver.h>
#include <irq_session/connection.h>
#include <timer_session/connection.h>
/* local includes */
#include <gpio.h>
static int verbose = 1;
namespace Gpio { class Odroid_x2_driver; }
class Gpio::Odroid_x2_driver : public Driver
{
private:
Server::Entrypoint &_ep;
Reg _reg1;
Reg _reg2;
Reg _reg3;
Reg _reg4;
Genode::Irq_connection _irq;
Genode::Signal_rpc_member<Odroid_x2_driver> _dispatcher;
Genode::Signal_context_capability _sig_cap[MAX_PINS];
bool _irq_enabled[MAX_PINS];
bool _async;
void _handle(unsigned)
{
handle_irq();
}
void handle_irq(){
PDBG("IRQ\n");
}
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:
PERR("no Gpio_bank for pin %d available", gpio_pin);
return 0;
}
}
int _gpio_index(int gpio) { return gpio & 0x1f; }
Odroid_x2_driver(Server::Entrypoint &ep)
: _ep(ep),
_reg1(0x11400000, 1000),
_reg2(0x11000000, 1000),
_reg3(0x03860000, 1000),
_reg4(0x106E0000, 1000),
_irq(104),
_dispatcher(ep, *this, &Odroid_x2_driver::_handle),
_async(false)
{
_irq.sigh(_dispatcher);
_irq.ack_irq();
}
public:
static Odroid_x2_driver& factory(Server::Entrypoint &ep);
/******************************
** Gpio::Driver interface **
******************************/
void direction(unsigned gpio_pin, bool input)
{
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;
if ( verbose) {
PDBG("gpio=%d", gpio);
PDBG("gpio_pin=%d", gpio_pin);
PDBG("gpio_input=%d", input ? 0: 0x1);
PDBG("gpio_pos=%d", pos_gpio);
PDBG("gpio_sum=%d", sum_gpio);
PDBG("gpio_off_set=%d", (int)offset);
}
Reg* reg = _gpio_reg(gpio_pin);
reg->set_direction(gpio, input, offset);
}
void write(unsigned gpio_pin, bool level)
{
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;
if ( verbose) {
PDBG("gpio=%d", gpio);
PDBG("gpio_pin=%d", gpio_pin);
PDBG("gpio_level=%d", level ? 0: 0x1);
PDBG("gpio_pos=%d", pos_gpio);
PDBG("gpio_sum=%d", sum_gpio);
PDBG("gpio_off_set=%d", (int)offset);
}
Reg* reg = _gpio_reg(gpio_pin);
reg->write_pin(gpio, level, offset);
}
bool read(unsigned gpio_pin)
{
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;
if ( verbose) {
PDBG("gpio=%d", gpio);
PDBG("gpio_pin=%d", gpio_pin);
PDBG("gpio_pos=%d", pos_gpio);
PDBG("gpio_sum=%d", sum_gpio);
PDBG("gpio_off_set=%d", (int)offset);
}
Reg* reg = _gpio_reg(gpio_pin);
return reg->read_pin(gpio, offset) ;
}
void debounce_enable(unsigned gpio, bool enable) {
PWRN("Not supported!"); }
void debounce_time(unsigned gpio, unsigned long us) {
PWRN("Not supported!"); }
void falling_detect(unsigned gpio_pin)
{
if (verbose) PDBG("gpio=%d", gpio_pin);
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)
{
if (verbose) PDBG("gpio=%d", gpio_pin);
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)
{
if (verbose) PDBG("gpio=%d", gpio_pin);
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)
{
if (verbose) PDBG("gpio=%d", gpio_pin);
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)
{
if (verbose) PDBG("gpio=%d enable=%d", gpio_pin, enable);
_irq_enabled[gpio_pin] = enable;
}
void ack_irq(unsigned gpio_pin)
{
if (verbose) PDBG("gpio=%d", gpio_pin);
_irq.ack_irq();
}
void register_signal(unsigned gpio_pin,
Genode::Signal_context_capability cap)
{
if (verbose) PDBG("gpio=%d", gpio_pin);
_sig_cap[gpio_pin] = cap;
}
void unregister_signal(unsigned gpio_pin)
{
if (verbose) PDBG("gpio=%d", gpio_pin);
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) { return gpio < (MAX_PINS); }
};
Gpio::Odroid_x2_driver& Gpio::Odroid_x2_driver::factory(Server::Entrypoint &ep)
{
static Odroid_x2_driver driver(ep);
return driver;
}
#endif /* _DRIVER_H_ */

View File

@ -0,0 +1,187 @@
/*
* \brief Odroid-x2 GPIO definitions
* \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-2013 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _GPIO_H_
#define _GPIO_H_
/* Genode includes */
#include <os/attached_io_mem_dataspace.h>
#include <util/mmio.h>
#include <base/printf.h>
namespace Gpio {
class Reg;
using namespace Genode;
}
struct Gpio::Reg : Attached_io_mem_dataspace, Mmio
{
struct Regs : Genode::Mmio
{
struct Con : Register<0x00, 32> {};
struct Dat : Register<0x04, 8> {};
Regs(Genode::addr_t base) : Genode::Mmio(base) {}
void set_con(unsigned int con) { write<Con>(con); }
void set_dat(unsigned int dat) { write<Dat>(dat); }
unsigned int get_con() { return read<Con>();}
unsigned int get_dat() { return read<Dat>();}
};
struct Irq_regs : Genode::Mmio
{
struct Int_con : Register <0x00,32>
{
struct Con0 : Bitfield<0, 3> {};
struct Con1 : Bitfield<4, 3> {};
struct Con2 : Bitfield<8, 3> {};
struct Con3 : Bitfield<12, 3> {};
struct Con4 : Bitfield<16, 3> {};
struct Con5 : Bitfield<20, 3> {};
struct Con6 : Bitfield<24, 3> {};
struct Con7 : Bitfield<28, 3> {};
};
Irq_regs(Genode::addr_t base) : Genode::Mmio(base) {}
void enable_triggers(unsigned gpio, unsigned value)
{
write<Int_con>(0);
switch(gpio) {
case 0: write<Int_con::Con0>(value); break;
case 1: write<Int_con::Con1>(value); break;
case 2: write<Int_con::Con2>(value); break;
case 3: write<Int_con::Con3>(value); break;
case 4: write<Int_con::Con4>(value); break;
case 5: write<Int_con::Con5>(value); break;
case 6: write<Int_con::Con6>(value); break;
case 7: write<Int_con::Con7>(value); break;
default: PWRN("Not is valid irq con!");
}
}
};
Reg(addr_t base, size_t size)
: Attached_io_mem_dataspace(base, size),
Mmio((addr_t)local_addr<Reg>()) { }
void set_direction(int gpio, bool input, Genode::off_t offset)
{
Regs _reg((Genode::addr_t)local_addr<void>() + offset);
unsigned int value;
int id = (input ? 0 : 0x1);
value = _reg.get_con();
value &= ~(0xf << (gpio << 2));
value |= (id << (gpio << 2));
_reg.set_con(value);
}
void write_pin(unsigned gpio, bool level, Genode::off_t offset)
{
Regs _reg((Genode::addr_t)local_addr<void>() + offset);
unsigned int value;
value = _reg.get_dat();
value &= ~(0x1 << gpio);
if (level)
value |= 0x1 << gpio;
_reg.set_dat(value);
}
bool read_pin(unsigned gpio, Genode::off_t offset)
{
Regs _reg((Genode::addr_t)local_addr<void>() + offset);
return (_reg.get_dat() & (1 << gpio)) !=0;
}
void set_enable_triggers(unsigned gpio, Genode::off_t offset,unsigned value)
{
Irq_regs _irq_regs((Genode::addr_t)local_addr<void>() + offset);
_irq_regs.enable_triggers(gpio,value);
}
};
enum {
MAX_BANKS = 48,
MAX_PINS = 361
};
enum Irqs_triggers {
LOW = 0x0,
HIGH = 0x1,
FALLING = 0x2,
RISING = 0x3,
BOTH = 0x4
};
const int _bank_sizes[MAX_PINS] = {
/* TODO check value of registes type ETC. */
/* GPIO Part1 */
/* GPA0 GPA1 GPB GPC0 GPC1 GPD0 GPD1 GPF0 GPF1 GPF2 GPF3 ETC1 GPJ0 GPJ1 */
8, 6, 8, 5, 5, 4, 4, 8, 8, 8, 6, 6, 8, 5,
/* GPIO Part2 */ /* index 14 */
/* GPK0 GPK1 GPK2 GPK3 GPL0 GPL1 GPL2 GPY0 GPY1 GPY2 GPY3 GPY4 GPY5 GPY6 */
7, 7, 7, 7, 7, 2, 8, 6, 4, 6, 8, 8, 8, 8,
/* ETC0 ETC6 GPM0 GPM1 GPM2 GPM3 GPM4 GPX0 GPX1 GPX2 GPX3 */
6, 8, 8, 7, 5, 8, 8, 8, 8, 8, 8, /* index 35,36,37 */
/* GPIO Part3 */
/* GPZ */ /* index 39 */
7,
/* GPIO Part4 */ //index 40
/* GPV0 GPV1 ETC7 GPV2 GPV3 ETC8 GPV4 */
8, 8, 2, 8, 8, 2, 8
};
const Genode::off_t _bank_offset[MAX_BANKS]=
{
/* Part1 */
/* GPA0 GPA1 GPB GPC0 GPC1 GPD0 GPD1 GPF0 GPF1 GPF2 GPF3 ETC1 GPJ0 GPJ1 */
0x0000, 0x0020, 0x0040, 0x0060, 0x0080, 0x00A0, 0x00C0, 0x0180, 0x01A0, 0x01C0, 0x01E0, 0x0228, 0x0240, 0x0260,
/* Part2 */
/* GPK0 GPK1 GPK2 GPK3 GPL0 GPL1 GPL2 GPY0 GPY1 GPY2 GPY3 GPY4 GPY5 GPY6 */
0x0040, 0x0060, 0x0080, 0x00A0, 0x00C0, 0x00E0, 0x0100, 0x0120, 0x0140, 0x0160, 0x0180, 0x01A0, 0x01C0, 0x01E0,
/* ETC0 ETC6 GPM0 GPM1 GPM2 GPM3 GPM4 GPX0 GPX1 GPX2 GPX3 */
0x0208, 0x0228, 0x0260, 0x0280, 0x02A0, 0x02C0, 0x02E0, 0x0C00, 0x0C20, 0x0C40, 0x0C60,
/* Part3 */
0x0000, /*GPZ */
/* Part4 */
/* GPV0 GPV1 ETC7 GPV2 GPV3 ETC8 GPV4 */
0x0000, 0x0020, 0x0048, 0x0060, 0x0080, 0x00A8, 0x00C0,
};
const Genode::off_t _irq_offset[MAX_BANKS]=
{
/* Bank 1 irq */
/* con1 con2 con3 con4 con5 con6 con7 con13 con14 con15 con16 ETC con21 con22 */
0x0700, 0x0704, 0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x0730, 0x0734, 0x0738, 0x073C, -1, 0x0740, 0x0744,
/* Bank 2 irq */
/* con23 con24 con25 con26 con27 con28 con29 */
0x0708, 0x070C, 0x0710, 0x0714, 0x0718, 0x071C, 0x0720, -1, -1, -1, -1, -1, -1, -1,
/* con8 con9 con10 con11 con12 x0 x1 x2 x3 */
-1, -1, 0x0724, 0x0728, 0x072C, 0x0730, 0x0734, 0x0E00, 0x0E04, 0x0E08, 0x0E0C, //TODO Check values de x0-x3.
/* Bank 3 irq */
/* con50 */
0x0700,
/* Bank 4 irq */
/* con30 con31 con32 con33 con34 */
0x0700, 0x0704, -1, 0x0708, 0x070C, -1, 0x0710,
};
#endif /* _GPIO_H_ */

View File

@ -0,0 +1,62 @@
/*
* \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) 2015 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Genode includes */
#include <base/printf.h>
#include <base/sleep.h>
#include <cap_session/connection.h>
#include <gpio/component.h>
#include <gpio/config.h>
#include <os/server.h>
/* local includes */
#include <driver.h>
struct Main
{
Server::Entrypoint &ep;
Genode::Sliced_heap sliced_heap;
Gpio::Odroid_x2_driver &driver;
Gpio::Root root;
Main(Server::Entrypoint &ep)
: ep(ep),
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
driver(Gpio::Odroid_x2_driver::factory(ep)),
root(&ep.rpc_ep(), &sliced_heap, driver)
{
using namespace Genode;
printf("--- Odroid_x2 gpio driver ---\n");
Gpio::process_config(driver);
/*
* Announce service
*/
env()->parent()->announce(ep.manage(root));
}
};
/************
** Server **
************/
namespace Server {
char const *name() { return "gpio_drv_ep"; }
size_t stack_size() { return 1024*sizeof(long); }
void construct(Entrypoint &ep) { static Main server(ep); }
}

View File

@ -0,0 +1,7 @@
TARGET = gpio_drv
REQUIRES = exynos4
SRC_CC = main.cc
LIBS = base config server
INC_DIR += $(PRG_DIR)
vpath main.cc $(PRG_DIR)