From de87ecfc621aac709f5333739d0018ffd182f5da Mon Sep 17 00:00:00 2001 From: Alexy Gallardo Segura Date: Tue, 8 Sep 2015 00:30:41 -0400 Subject: [PATCH] foc_odroid_x2: basic configuration for gpio pins Fixes #1669 --- .../spec/odroid_x2/drivers/board_base.h | 22 +- repos/base/mk/spec/odroid_x2.mk | 2 +- .../os/src/drivers/gpio/spec/exynos4/driver.h | 268 ++++++++++++++++++ repos/os/src/drivers/gpio/spec/exynos4/gpio.h | 187 ++++++++++++ .../os/src/drivers/gpio/spec/exynos4/main.cc | 62 ++++ .../src/drivers/gpio/spec/exynos4/target.mk | 7 + 6 files changed, 545 insertions(+), 3 deletions(-) create mode 100644 repos/os/src/drivers/gpio/spec/exynos4/driver.h create mode 100644 repos/os/src/drivers/gpio/spec/exynos4/gpio.h create mode 100644 repos/os/src/drivers/gpio/spec/exynos4/main.cc create mode 100644 repos/os/src/drivers/gpio/spec/exynos4/target.mk diff --git a/repos/base/include/spec/odroid_x2/drivers/board_base.h b/repos/base/include/spec/odroid_x2/drivers/board_base.h index 38be7af21..a173c18ce 100644 --- a/repos/base/include/spec/odroid_x2/drivers/board_base.h +++ b/repos/base/include/spec/odroid_x2/drivers/board_base.h @@ -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 */ }; diff --git a/repos/base/mk/spec/odroid_x2.mk b/repos/base/mk/spec/odroid_x2.mk index dc1426949..7304194ef 100644 --- a/repos/base/mk/spec/odroid_x2.mk +++ b/repos/base/mk/spec/odroid_x2.mk @@ -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 diff --git a/repos/os/src/drivers/gpio/spec/exynos4/driver.h b/repos/os/src/drivers/gpio/spec/exynos4/driver.h new file mode 100644 index 000000000..3ae4c22c9 --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/exynos4/driver.h @@ -0,0 +1,268 @@ +/* + * \brief Gpio driver for the Odroid-x2 + * \author Alexy Gallardo Segura + * \author Humberto Lopéz Leon + * \author Reinier Millo Sánchez + * \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 +#include +#include +#include + +/* local includes */ +#include + +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 _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 + * \author Humberto Lopéz Leon + * \author Reinier Millo Sánchez + * \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 +#include + +#include + +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); } + void set_dat(unsigned int dat) { write(dat); } + unsigned int get_con() { return read();} + unsigned int get_dat() { return read();} + }; + + 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(0); + switch(gpio) { + case 0: write(value); break; + case 1: write(value); break; + case 2: write(value); break; + case 3: write(value); break; + case 4: write(value); break; + case 5: write(value); break; + case 6: write(value); break; + case 7: write(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()) { } + + void set_direction(int gpio, bool input, Genode::off_t offset) + { + Regs _reg((Genode::addr_t)local_addr() + 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() + 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() + 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() + 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_ */ diff --git a/repos/os/src/drivers/gpio/spec/exynos4/main.cc b/repos/os/src/drivers/gpio/spec/exynos4/main.cc new file mode 100644 index 000000000..c0a23f92f --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/exynos4/main.cc @@ -0,0 +1,62 @@ +/* + * \brief Gpio driver for the Odroid-x2 + * \author Alexy Gallardo Segura + * \author Humberto Lopéz Leon + * \author Reinier Millo Sánchez + * \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 +#include +#include +#include +#include +#include + +/* local includes */ +#include + + +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); } +} diff --git a/repos/os/src/drivers/gpio/spec/exynos4/target.mk b/repos/os/src/drivers/gpio/spec/exynos4/target.mk new file mode 100644 index 000000000..0094f5ca4 --- /dev/null +++ b/repos/os/src/drivers/gpio/spec/exynos4/target.mk @@ -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)