mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 09:46:20 +00:00
parent
433f859cb9
commit
98da445269
@ -49,6 +49,9 @@ struct Genode::Board_base
|
||||
IRQ_CONTROLLER_BASE = 0x2000b200,
|
||||
IRQ_CONTROLLER_SIZE = 0x100,
|
||||
|
||||
GPIO_CONTROLLER_BASE = 0x20200000,
|
||||
GPIO_CONTROLLER_SIZE = 0x1000,
|
||||
|
||||
USB_DWC_OTG_BASE = 0x20980000,
|
||||
USB_DWC_OTG_SIZE = 0x20000,
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
#
|
||||
|
||||
# denote wich specs are also fullfilled by this spec
|
||||
SPECS += arm_v6 usb framebuffer
|
||||
SPECS += arm_v6 usb framebuffer gpio
|
||||
|
||||
# add repository relative include paths
|
||||
REP_INC_DIR += include/platform/rpi
|
||||
|
2
repos/os/lib/mk/foc_rpi/gpio.mk
Normal file
2
repos/os/lib/mk/foc_rpi/gpio.mk
Normal file
@ -0,0 +1,2 @@
|
||||
INC_DIR += $(REP_DIR)/src/drivers/gpio/rpi/foc
|
||||
include $(REP_DIR)/lib/mk/rpi/gpio.inc
|
2
repos/os/lib/mk/hw_rpi/gpio.mk
Normal file
2
repos/os/lib/mk/hw_rpi/gpio.mk
Normal file
@ -0,0 +1,2 @@
|
||||
INC_DIR += $(REP_DIR)/src/drivers/gpio/rpi/hw
|
||||
include $(REP_DIR)/lib/mk/rpi/gpio.inc
|
5
repos/os/lib/mk/rpi/gpio.inc
Normal file
5
repos/os/lib/mk/rpi/gpio.inc
Normal file
@ -0,0 +1,5 @@
|
||||
SRC_CC += main.cc
|
||||
LIBS += base config server
|
||||
INC_DIR += $(REP_DIR)/src/drivers/gpio/rpi
|
||||
|
||||
vpath % $(REP_DIR)/src/drivers/gpio/rpi
|
207
repos/os/src/drivers/gpio/rpi/driver.h
Normal file
207
repos/os/src/drivers/gpio/rpi/driver.h
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* \brief Gpio driver for the RaspberryPI
|
||||
* \author Reinier Millo Sánchez <rmillo@uclv.cu>
|
||||
* \author Alexy Gallardo Segura <alexy@uclv.cu>
|
||||
* \author Humberto Lopéz Leon <humberto@uclv.cu>
|
||||
* \date 2015-07-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Ksys Labs LLC
|
||||
* Copyright (C) 2012-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.
|
||||
*/
|
||||
|
||||
#ifndef _DRIVER_H_
|
||||
#define _DRIVER_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <drivers/board_base.h>
|
||||
#include <gpio/driver.h>
|
||||
#include <irq_session/connection.h>
|
||||
|
||||
/* local includes */
|
||||
#include <irq.h>
|
||||
#include <gpio.h>
|
||||
|
||||
static int verbose = 1;
|
||||
|
||||
namespace Gpio { class Rpi_driver; }
|
||||
|
||||
class Gpio::Rpi_driver : public Driver
|
||||
{
|
||||
private:
|
||||
|
||||
enum { MAX_PINS = 54 };
|
||||
|
||||
Server::Entrypoint &_ep;
|
||||
Reg _reg;
|
||||
Genode::Irq_connection _irq;
|
||||
Genode::Signal_rpc_member<Rpi_driver> _dispatcher;
|
||||
Genode::Signal_context_capability _sig_cap[MAX_PINS];
|
||||
bool _irq_enabled[MAX_PINS];
|
||||
bool _async;
|
||||
|
||||
void _handle(unsigned)
|
||||
{
|
||||
_reg.for_each_gpio_status([&] (unsigned i, bool s) {
|
||||
if (!s || !_irq_enabled[i] || !_sig_cap[i].valid()) { return; }
|
||||
Genode::Signal_transmitter(_sig_cap[i]).submit();
|
||||
});
|
||||
}
|
||||
|
||||
Rpi_driver(Server::Entrypoint &ep)
|
||||
:
|
||||
_ep(ep),
|
||||
_reg(Genode::Board_base::GPIO_CONTROLLER_BASE,
|
||||
0, Genode::Board_base::GPIO_CONTROLLER_SIZE),
|
||||
_irq(IRQ),
|
||||
_dispatcher(ep,*this,&Rpi_driver::_handle),
|
||||
_async(false)
|
||||
{
|
||||
_irq.sigh(_dispatcher);
|
||||
_irq.ack_irq();
|
||||
}
|
||||
|
||||
void _invalid_gpio(unsigned gpio) {
|
||||
PERR("invalid GPIO pin number %u", gpio); }
|
||||
|
||||
public:
|
||||
|
||||
void set_async_events(bool async) { _async = async; }
|
||||
|
||||
void set_func(unsigned gpio, Reg::Function function)
|
||||
{
|
||||
if (verbose) PDBG("gpio=%d function=%d", gpio, function);
|
||||
|
||||
_reg.set_gpio_function(gpio, function);
|
||||
}
|
||||
|
||||
static Rpi_driver& factory(Server::Entrypoint &ep);
|
||||
|
||||
|
||||
/******************************
|
||||
** Driver interface **
|
||||
******************************/
|
||||
|
||||
bool gpio_valid(unsigned gpio) { return gpio < MAX_PINS; }
|
||||
|
||||
void direction(unsigned gpio, bool input)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d input=%d", gpio, input);
|
||||
Reg::Function f = input ? Reg::FSEL_INPUT : Reg::FSEL_OUTPUT;
|
||||
_reg.set_gpio_function(gpio, f);
|
||||
}
|
||||
|
||||
void write(unsigned gpio, bool level)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d level=%d", gpio, level);
|
||||
|
||||
if (_reg.get_gpio_function(gpio)!=Reg::FSEL_OUTPUT)
|
||||
PWRN("GPIO pin (%d) is not configured for output.", gpio);
|
||||
|
||||
if (level)
|
||||
_reg.set_gpio_level(gpio);
|
||||
else
|
||||
_reg.clear_gpio_level(gpio);
|
||||
}
|
||||
|
||||
bool read(unsigned gpio)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return 0; }
|
||||
if(_reg.get_gpio_function(gpio) != Reg::FSEL_INPUT)
|
||||
PWRN("GPIO pin (%d) is not configured for input.", gpio);
|
||||
|
||||
return _reg.get_gpio_level(gpio);
|
||||
}
|
||||
|
||||
void debounce_enable(unsigned, bool) { PWRN("Not supported!"); }
|
||||
void debounce_time(unsigned, unsigned long) { PWRN("Not supported!"); }
|
||||
|
||||
void falling_detect(unsigned gpio)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d", gpio);
|
||||
|
||||
if(_async)
|
||||
_reg.set_gpio_async_falling_detect(gpio);
|
||||
else
|
||||
_reg.set_gpio_falling_detect(gpio);
|
||||
}
|
||||
|
||||
void rising_detect(unsigned gpio)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d", gpio);
|
||||
|
||||
if(_async)
|
||||
_reg.set_gpio_async_rising_detect(gpio);
|
||||
else
|
||||
_reg.set_gpio_rising_detect(gpio);
|
||||
}
|
||||
|
||||
void high_detect(unsigned gpio)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d", gpio);
|
||||
|
||||
_reg.set_gpio_high_detect(gpio);
|
||||
}
|
||||
|
||||
void low_detect(unsigned gpio)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d", gpio);
|
||||
|
||||
_reg.set_gpio_low_detect(gpio);
|
||||
}
|
||||
|
||||
void irq_enable(unsigned gpio, bool enable)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d enable=%d", gpio, enable);
|
||||
|
||||
_irq_enabled[gpio] = enable;
|
||||
}
|
||||
|
||||
void ack_irq(unsigned gpio)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d", gpio);
|
||||
|
||||
_reg.clear_event(gpio);
|
||||
_irq.ack_irq();
|
||||
}
|
||||
|
||||
void register_signal(unsigned gpio,
|
||||
Genode::Signal_context_capability cap)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d", gpio);
|
||||
|
||||
_sig_cap[gpio] = cap;
|
||||
}
|
||||
|
||||
void unregister_signal(unsigned gpio)
|
||||
{
|
||||
if (!gpio_valid(gpio)) { _invalid_gpio(gpio); return; }
|
||||
if (verbose) PDBG("gpio=%d", gpio);
|
||||
Genode::Signal_context_capability cap;
|
||||
|
||||
_sig_cap[gpio] = cap;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Gpio::Rpi_driver& Gpio::Rpi_driver::factory(Server::Entrypoint &ep)
|
||||
{
|
||||
static Rpi_driver driver(ep);
|
||||
return driver;
|
||||
}
|
||||
|
||||
#endif /* _DRIVER_H_ */
|
25
repos/os/src/drivers/gpio/rpi/foc/irq.h
Normal file
25
repos/os/src/drivers/gpio/rpi/foc/irq.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief GPIO interrupt number
|
||||
* \author Reinier Millo Sánchez <rmillo@uclv.cu>
|
||||
* \date 2015-07-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _IRQ_H_
|
||||
#define _IRQ_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
namespace Gpio
|
||||
{
|
||||
enum { IRQ = 49 };
|
||||
}
|
||||
|
||||
#endif /* _IRQ_H_ */
|
238
repos/os/src/drivers/gpio/rpi/gpio.h
Normal file
238
repos/os/src/drivers/gpio/rpi/gpio.h
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* \brief Gpio driver for the RaspberryPI
|
||||
* \author Reinier Millo Sánchez <rmillo@uclv.cu>
|
||||
* \author Alexy Gallardo Segura <alexy@uclv.cu>
|
||||
* \author Humberto Lopéz Leon <humberto@uclv.cu>
|
||||
* \date 2015-07-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 Ksys Labs LLC
|
||||
* Copyright (C) 2012-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.
|
||||
*/
|
||||
|
||||
#ifndef _GPIO_H_
|
||||
#define _GPIO_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/printf.h>
|
||||
#include <os/attached_io_mem_dataspace.h>
|
||||
#include <util/mmio.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
namespace Gpio {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
class Reg;
|
||||
}
|
||||
|
||||
class Gpio::Reg : Attached_io_mem_dataspace, Mmio
|
||||
{
|
||||
private:
|
||||
|
||||
/**
|
||||
* GPIO Function Select Registers
|
||||
*/
|
||||
struct Gpfsel : Register_array <0x00,32,6,32> {
|
||||
struct Sel0 : Bitfield <0,3> {};
|
||||
struct Sel1 : Bitfield <3,3> {};
|
||||
struct Sel2 : Bitfield <6,3> {};
|
||||
struct Sel3 : Bitfield <9,3> {};
|
||||
struct Sel4 : Bitfield <12,3> {};
|
||||
struct Sel5 : Bitfield <15,3> {};
|
||||
struct Sel6 : Bitfield <18,3> {};
|
||||
struct Sel7 : Bitfield <21,3> {};
|
||||
struct Sel8 : Bitfield <24,3> {};
|
||||
struct Sel9 : Bitfield <27,3> {};
|
||||
};
|
||||
|
||||
/**
|
||||
* GPIO Pin Output Set Registers
|
||||
*/
|
||||
struct Gpset : Register_array <0x1c,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Output Clear Registers
|
||||
*/
|
||||
struct Gpclr : Register_array <0x28,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Level Registers
|
||||
*/
|
||||
struct Gplev : Register_array <0x34,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Event Detect Status Registers
|
||||
*/
|
||||
struct Gppeds : Register_array <0x40,32,64,1> {};
|
||||
struct Gppeds_raw : Register <0x40,64> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Rising Edge Detect Enable Registers
|
||||
*/
|
||||
struct Gpren : Register_array <0x4c,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Falling Edge Detect Enable Registers
|
||||
*/
|
||||
struct Gpfen : Register_array <0x58,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin High Detect Enable Registers
|
||||
*/
|
||||
struct Gphen : Register_array <0x64,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Low Detect Enable Registers
|
||||
*/
|
||||
struct Gplen : Register_array <0x70,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Aync. Rising Edge Detect Registers
|
||||
*/
|
||||
struct Gparen : Register_array <0x7c,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Async. Falling Edge Detect Registers
|
||||
*/
|
||||
struct Gpafen : Register_array <0x88,32,64,1> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Pull-up/down Enable Registers
|
||||
*/
|
||||
struct Gppud : Register <0x94,32> {};
|
||||
|
||||
/**
|
||||
* GPIO Pin Pull-up/down Enable Clock Registers
|
||||
*/
|
||||
struct Gppudclk : Register_array <0x98,32,64,1> {};
|
||||
|
||||
struct Timer_delayer : Timer::Connection, Mmio::Delayer
|
||||
{
|
||||
/**
|
||||
* Implementation of 'Delayer' interface
|
||||
*/
|
||||
void usleep(unsigned us) { Timer::Connection::usleep(us); }
|
||||
|
||||
} _delayer;
|
||||
|
||||
template <typename T0, typename T1, typename T2,
|
||||
typename T3, typename T4, typename T5>
|
||||
void _set_gpio_det(unsigned gpio)
|
||||
{
|
||||
write<T0>(0, gpio);
|
||||
write<T1>(0, gpio);
|
||||
write<T2>(0, gpio);
|
||||
write<T3>(0, gpio);
|
||||
write<T4>(0, gpio);
|
||||
write<T5>(1, gpio);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Reg(addr_t base, off_t offset, size_t size)
|
||||
:
|
||||
Attached_io_mem_dataspace(base, size),
|
||||
Mmio((addr_t)local_addr<Reg>() + offset)
|
||||
{ }
|
||||
|
||||
enum Function {
|
||||
FSEL_INPUT = 0,
|
||||
FSEL_OUTPUT = 1,
|
||||
FSEL_ALT0 = 4,
|
||||
FSEL_ALT1 = 5,
|
||||
FSEL_ALT2 = 6,
|
||||
FSEL_ALT3 = 7,
|
||||
FSEL_ALT4 = 3,
|
||||
FSEL_ALT5 = 2,
|
||||
};
|
||||
|
||||
void set_gpio_function(unsigned gpio, Function function)
|
||||
{
|
||||
/*
|
||||
* Set a pull-up internal resistor in the input pin to avoid
|
||||
* electromagnetic radiation or static noise
|
||||
*/
|
||||
if (function == FSEL_INPUT) {
|
||||
write<Gppud>(1);
|
||||
_delayer.usleep(1);
|
||||
write<Gppudclk>(1, gpio);
|
||||
_delayer.usleep(1);
|
||||
write<Gppud>(0);
|
||||
write<Gppudclk>(0, gpio);
|
||||
}
|
||||
/* set the pin function */
|
||||
unsigned sel_id = gpio % 10;
|
||||
unsigned reg_id = gpio / 10;
|
||||
switch(sel_id){
|
||||
case 0: write<Gpfsel::Sel0>(function, reg_id); break;
|
||||
case 1: write<Gpfsel::Sel1>(function, reg_id); break;
|
||||
case 2: write<Gpfsel::Sel2>(function, reg_id); break;
|
||||
case 3: write<Gpfsel::Sel3>(function, reg_id); break;
|
||||
case 4: write<Gpfsel::Sel4>(function, reg_id); break;
|
||||
case 5: write<Gpfsel::Sel5>(function, reg_id); break;
|
||||
case 6: write<Gpfsel::Sel6>(function, reg_id); break;
|
||||
case 7: write<Gpfsel::Sel7>(function, reg_id); break;
|
||||
case 8: write<Gpfsel::Sel8>(function, reg_id); break;
|
||||
case 9: write<Gpfsel::Sel9>(function, reg_id); break;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned get_gpio_function(unsigned gpio)
|
||||
{
|
||||
unsigned sel_id = gpio % 10;
|
||||
unsigned reg_id = gpio / 10;
|
||||
switch(sel_id){
|
||||
case 0: return read<Gpfsel::Sel0>(reg_id);
|
||||
case 1: return read<Gpfsel::Sel1>(reg_id);
|
||||
case 2: return read<Gpfsel::Sel2>(reg_id);
|
||||
case 3: return read<Gpfsel::Sel3>(reg_id);
|
||||
case 4: return read<Gpfsel::Sel4>(reg_id);
|
||||
case 5: return read<Gpfsel::Sel5>(reg_id);
|
||||
case 6: return read<Gpfsel::Sel6>(reg_id);
|
||||
case 7: return read<Gpfsel::Sel7>(reg_id);
|
||||
case 8: return read<Gpfsel::Sel8>(reg_id);
|
||||
case 9: return read<Gpfsel::Sel9>(reg_id);
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int get_gpio_level(unsigned gpio) { return read<Gppudclk>(gpio); }
|
||||
void set_gpio_level(unsigned gpio) { write<Gpset>(1, gpio); }
|
||||
void clear_gpio_level(unsigned gpio) { write<Gpclr>(1, gpio); }
|
||||
|
||||
void set_gpio_falling_detect(unsigned gpio) {
|
||||
_set_gpio_det<Gpren, Gphen, Gplen, Gparen, Gpafen, Gpfen>(gpio); }
|
||||
|
||||
void set_gpio_rising_detect(unsigned gpio) {
|
||||
_set_gpio_det<Gphen, Gplen, Gparen, Gpafen, Gpfen, Gpren>(gpio); }
|
||||
|
||||
void set_gpio_high_detect(unsigned gpio) {
|
||||
_set_gpio_det<Gpren, Gplen, Gparen, Gpafen, Gpfen, Gphen>(gpio); }
|
||||
|
||||
void set_gpio_low_detect(unsigned gpio) {
|
||||
_set_gpio_det<Gpren, Gphen, Gparen, Gpafen, Gpfen, Gplen>(gpio); }
|
||||
|
||||
void set_gpio_async_falling_detect(unsigned gpio) {
|
||||
_set_gpio_det<Gpren, Gphen, Gplen, Gparen, Gpfen, Gpafen>(gpio); }
|
||||
|
||||
void set_gpio_async_rising_detect(unsigned gpio) {
|
||||
_set_gpio_det<Gpren, Gphen, Gplen, Gpafen, Gpfen, Gparen>(gpio); }
|
||||
|
||||
template <typename F>
|
||||
void for_each_gpio_status(F f)
|
||||
{
|
||||
Gppeds_raw::access_t const gppeds = read<Gppeds_raw>();
|
||||
for(unsigned i = 0; i < Gppeds_raw::ACCESS_WIDTH; i++) {
|
||||
f(i, gppeds & (1 << i)); }
|
||||
}
|
||||
|
||||
void clear_event(unsigned gpio) { write<Gppeds>(1, gpio); }
|
||||
};
|
||||
|
||||
#endif /* _GPIO_H_ */
|
25
repos/os/src/drivers/gpio/rpi/hw/irq.h
Normal file
25
repos/os/src/drivers/gpio/rpi/hw/irq.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* \brief GPIO interrupt number
|
||||
* \author Reinier Millo Sánchez <rmillo@uclv.cu>
|
||||
* \date 2015-07-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _IRQ_H_
|
||||
#define _IRQ_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <drivers/board_base.h>
|
||||
|
||||
namespace Gpio
|
||||
{
|
||||
enum { IRQ = Genode::Board_base::GPU_IRQ_BASE + 49 };
|
||||
}
|
||||
|
||||
#endif /* _IRQ_H_ */
|
103
repos/os/src/drivers/gpio/rpi/main.cc
Normal file
103
repos/os/src/drivers/gpio/rpi/main.cc
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* \brief Gpio driver for the RaspberryPI
|
||||
* \author Reinier Millo Sánchez <rmillo@uclv.cu>
|
||||
* \author Alexy Gallardo Segura <alexy@uclv.cu>
|
||||
* \author Humberto Lopéz Leon <humberto@uclv.cu>
|
||||
* \date 2015-07-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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::Rpi_driver &driver;
|
||||
Gpio::Root root;
|
||||
|
||||
Main(Server::Entrypoint &ep)
|
||||
:
|
||||
ep(ep),
|
||||
sliced_heap(Genode::env()->ram_session(), Genode::env()->rm_session()),
|
||||
driver(Gpio::Rpi_driver::factory(ep)),
|
||||
root(&ep.rpc_ep(), &sliced_heap, driver)
|
||||
{
|
||||
using namespace Genode;
|
||||
printf("--- RaspberryPI gpio driver ---\n");
|
||||
|
||||
/*
|
||||
* Check configuration for async events detect
|
||||
*/
|
||||
unsigned int async = 0;
|
||||
try {
|
||||
config()->xml_node().attribute("async_events").value(&async);
|
||||
} catch (...) { }
|
||||
driver.set_async_events(async>0);
|
||||
|
||||
/*
|
||||
* Check for common GPIO configuration
|
||||
*/
|
||||
Gpio::process_config(driver);
|
||||
|
||||
/*
|
||||
* Check configuration for specific function
|
||||
*/
|
||||
try {
|
||||
Xml_node gpio_node = config()->xml_node().sub_node("gpio");
|
||||
|
||||
for (;; gpio_node = gpio_node.next("gpio")) {
|
||||
unsigned num = 0;
|
||||
unsigned function = 0;
|
||||
|
||||
try {
|
||||
gpio_node.attribute("num").value(&num);
|
||||
gpio_node.attribute("function").value(&function);
|
||||
|
||||
switch(function){
|
||||
case 0: driver.set_func(num, Gpio::Reg::FSEL_ALT0); break;
|
||||
case 1: driver.set_func(num, Gpio::Reg::FSEL_ALT1); break;
|
||||
case 2: driver.set_func(num, Gpio::Reg::FSEL_ALT2); break;
|
||||
case 3: driver.set_func(num, Gpio::Reg::FSEL_ALT3); break;
|
||||
case 4: driver.set_func(num, Gpio::Reg::FSEL_ALT4); break;
|
||||
case 5: driver.set_func(num, Gpio::Reg::FSEL_ALT5); break;
|
||||
default: PWRN("Wrong pin function. Ignore node.");
|
||||
}
|
||||
} catch(Xml_node::Nonexistent_attribute) {
|
||||
PWRN("Missing attribute. Ignore node.");
|
||||
}
|
||||
if (gpio_node.is_last("gpio")) break;
|
||||
}
|
||||
} catch (Xml_node::Nonexistent_sub_node) { PWRN("No GPIO config"); }
|
||||
|
||||
/*
|
||||
* 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); }
|
||||
}
|
3
repos/os/src/drivers/gpio/rpi/target.mk
Normal file
3
repos/os/src/drivers/gpio/rpi/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = gpio_drv
|
||||
REQUIRES = rpi
|
||||
LIBS += gpio
|
Loading…
x
Reference in New Issue
Block a user