mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
Implement input driver for i.MX53 tablet (fix #724)
The input driver implements support for the Egalaxy touchscreen and for Freescale's MPR121 capacitative touch buttons.
This commit is contained in:
parent
ca92984bcc
commit
ef4a4ea654
@ -92,6 +92,14 @@ namespace Genode
|
|||||||
CCM_BASE = 0x53FD4000,
|
CCM_BASE = 0x53FD4000,
|
||||||
CCM_SIZE = 0x00004000,
|
CCM_SIZE = 0x00004000,
|
||||||
|
|
||||||
|
I2C_2_IRQ = 63,
|
||||||
|
I2C_2_BASE = 0x63fc4000,
|
||||||
|
I2C_2_SIZE = 0x00004000,
|
||||||
|
|
||||||
|
I2C_3_IRQ = 64,
|
||||||
|
I2C_3_BASE = 0x53fec000,
|
||||||
|
I2C_3_SIZE = 0x00004000,
|
||||||
|
|
||||||
IIM_BASE = 0x63f98000,
|
IIM_BASE = 0x63f98000,
|
||||||
IIM_SIZE = 0x00004000,
|
IIM_SIZE = 0x00004000,
|
||||||
|
|
||||||
|
@ -21,7 +21,12 @@ namespace Platform {
|
|||||||
|
|
||||||
struct Session : Genode::Session
|
struct Session : Genode::Session
|
||||||
{
|
{
|
||||||
enum Device { IPU };
|
enum Device {
|
||||||
|
IPU,
|
||||||
|
I2C_2,
|
||||||
|
I2C_3,
|
||||||
|
BUTTONS,
|
||||||
|
};
|
||||||
|
|
||||||
enum Board_revision {
|
enum Board_revision {
|
||||||
SMD = 2, /* Freescale i.MX53 SMD Tablet */
|
SMD = 2, /* Freescale i.MX53 SMD Tablet */
|
||||||
|
@ -75,7 +75,11 @@ append_if [have_spec imx53] config {
|
|||||||
<provides><service name="Platform"/></provides>
|
<provides><service name="Platform"/></provides>
|
||||||
<config/>
|
<config/>
|
||||||
</start>
|
</start>
|
||||||
}
|
<start name="input_drv">
|
||||||
|
<resource name="RAM" quantum="1M"/>
|
||||||
|
<provides><service name="Input"/></provides>
|
||||||
|
<config/>
|
||||||
|
</start> }
|
||||||
|
|
||||||
append_if [have_spec ps2] config {
|
append_if [have_spec ps2] config {
|
||||||
<start name="ps2_drv">
|
<start name="ps2_drv">
|
||||||
@ -126,6 +130,7 @@ lappend_if [have_spec framebuffer] boot_modules fb_drv
|
|||||||
lappend_if [have_spec usb] boot_modules usb_drv
|
lappend_if [have_spec usb] boot_modules usb_drv
|
||||||
lappend_if [have_spec gpio] boot_modules gpio_drv
|
lappend_if [have_spec gpio] boot_modules gpio_drv
|
||||||
lappend_if [have_spec imx53] boot_modules platform_drv
|
lappend_if [have_spec imx53] boot_modules platform_drv
|
||||||
|
lappend_if [have_spec imx53] boot_modules input_drv
|
||||||
|
|
||||||
build_boot_image $boot_modules
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
|
106
os/src/drivers/input/imx53/driver.h
Normal file
106
os/src/drivers/input/imx53/driver.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* \brief Input-driver
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2013-03-15
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 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 <base/env.h>
|
||||||
|
#include <base/thread.h>
|
||||||
|
#include <base/signal.h>
|
||||||
|
#include <gpio_session/connection.h>
|
||||||
|
|
||||||
|
/* local includes */
|
||||||
|
#include <egalax_ts.h>
|
||||||
|
#include <mpr121.h>
|
||||||
|
|
||||||
|
namespace Input {
|
||||||
|
class Tablet_driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Input::Tablet_driver : Genode::Thread<8192>
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum Gpio_irqs {
|
||||||
|
GPIO_TOUCH = 84,
|
||||||
|
GPIO_BUTTON = 132,
|
||||||
|
};
|
||||||
|
|
||||||
|
Event_queue &_ev_queue;
|
||||||
|
Gpio::Connection _gpio_ts;
|
||||||
|
Gpio::Connection _gpio_bt;
|
||||||
|
Genode::Signal_receiver _receiver;
|
||||||
|
Genode::Signal_context _ts_rx;
|
||||||
|
Genode::Signal_context _bt_rx;
|
||||||
|
Genode::Signal_context_capability _ts_sig_cap;
|
||||||
|
Genode::Signal_context_capability _bt_sig_cap;
|
||||||
|
Touchscreen _touchscreen;
|
||||||
|
Buttons _buttons;
|
||||||
|
|
||||||
|
Genode::Signal_context_capability _init_ts_gpio()
|
||||||
|
{
|
||||||
|
Genode::Signal_context_capability ret = _receiver.manage(&_ts_rx);
|
||||||
|
_gpio_ts.direction(Gpio::Session::OUT);
|
||||||
|
_gpio_ts.write(true);
|
||||||
|
_gpio_ts.direction(Gpio::Session::IN);
|
||||||
|
_gpio_ts.irq_sigh(_ts_sig_cap);
|
||||||
|
_gpio_ts.irq_type(Gpio::Session::LOW_LEVEL);
|
||||||
|
_gpio_ts.irq_enable(true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Genode::Signal_context_capability _init_bt_gpio()
|
||||||
|
{
|
||||||
|
Genode::Signal_context_capability ret = _receiver.manage(&_bt_rx);
|
||||||
|
_gpio_bt.direction(Gpio::Session::OUT);
|
||||||
|
_gpio_bt.write(true);
|
||||||
|
_gpio_bt.direction(Gpio::Session::IN);
|
||||||
|
_gpio_bt.irq_sigh(_bt_sig_cap);
|
||||||
|
_gpio_bt.irq_type(Gpio::Session::FALLING_EDGE);
|
||||||
|
_gpio_bt.irq_enable(true);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tablet_driver(Event_queue &ev_queue)
|
||||||
|
: _ev_queue(ev_queue),
|
||||||
|
_gpio_ts(GPIO_TOUCH),
|
||||||
|
_gpio_bt(GPIO_BUTTON),
|
||||||
|
_ts_sig_cap(_init_ts_gpio()),
|
||||||
|
_bt_sig_cap(_init_bt_gpio()) { start(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static Tablet_driver* factory(Event_queue &ev_queue);
|
||||||
|
|
||||||
|
void entry()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
Genode::Signal sig = _receiver.wait_for_signal();
|
||||||
|
if (sig.context() == &_ts_rx)
|
||||||
|
_touchscreen.event(_ev_queue);
|
||||||
|
else if (sig.context() == &_bt_rx)
|
||||||
|
_buttons.event(_ev_queue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Input::Tablet_driver* Input::Tablet_driver::factory(Event_queue &ev_queue)
|
||||||
|
{
|
||||||
|
static Input::Tablet_driver driver(ev_queue);
|
||||||
|
return &driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _DRIVER_H_ */
|
93
os/src/drivers/input/imx53/egalax_ts.h
Normal file
93
os/src/drivers/input/imx53/egalax_ts.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* \brief EETI eGalaxy touchscreen driver
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2013-03-15
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 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 _EGALAX_TS_H_
|
||||||
|
#define _EGALAX_TS_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/board_base.h>
|
||||||
|
#include <os/attached_io_mem_dataspace.h>
|
||||||
|
#include <input/event_queue.h>
|
||||||
|
#include <input/event.h>
|
||||||
|
#include <input/keycodes.h>
|
||||||
|
|
||||||
|
/* local includes */
|
||||||
|
#include <i2c.h>
|
||||||
|
|
||||||
|
namespace Input {
|
||||||
|
class Touchscreen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Input::Touchscreen {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum I2c_addresses { I2C_ADDR = 0x4 };
|
||||||
|
enum Finger_state { PRESSED, RELEASED };
|
||||||
|
|
||||||
|
Genode::Attached_io_mem_dataspace _i2c_ds;
|
||||||
|
I2c::I2c _i2c;
|
||||||
|
Genode::uint8_t _buf[10];
|
||||||
|
Finger_state _state;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Touchscreen() : _i2c_ds(Genode::Board_base::I2C_3_BASE,
|
||||||
|
Genode::Board_base::I2C_3_SIZE),
|
||||||
|
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(),
|
||||||
|
Genode::Board_base::I2C_3_IRQ),
|
||||||
|
_state(RELEASED)
|
||||||
|
{
|
||||||
|
/* ask for touchscreen firmware version */
|
||||||
|
Genode::uint8_t cmd[10] = { 0x03, 0x03, 0xa, 0x01, 0x41 };
|
||||||
|
_i2c.send(I2C_ADDR, cmd, sizeof(cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
void event(Event_queue &ev_queue)
|
||||||
|
{
|
||||||
|
_i2c.recv(I2C_ADDR, _buf, sizeof(_buf));
|
||||||
|
|
||||||
|
/* ignore all events except of multitouch*/
|
||||||
|
if (_buf[0] != 4)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int x = (_buf[3] << 8) | _buf[2];
|
||||||
|
int y = (_buf[5] << 8) | _buf[4];
|
||||||
|
|
||||||
|
Genode::uint8_t state = _buf[1];
|
||||||
|
bool valid = state & (1 << 7);
|
||||||
|
int id = (state >> 2) & 0xf;
|
||||||
|
int down = state & 1;
|
||||||
|
|
||||||
|
if (!valid || id > 5)
|
||||||
|
return; /* invalid point */
|
||||||
|
|
||||||
|
x = 102400 / (3276700 / x);
|
||||||
|
y = 76800 / (3276700 / y);
|
||||||
|
|
||||||
|
/* motion event */
|
||||||
|
ev_queue.add(Input::Event(Input::Event::MOTION, 0, x, y, 0, 0));
|
||||||
|
|
||||||
|
/* button event */
|
||||||
|
if ((down && (_state == RELEASED)) ||
|
||||||
|
(!down && (_state == PRESSED))) {
|
||||||
|
ev_queue.add(Input::Event(down ? Input::Event::PRESS
|
||||||
|
: Input::Event::RELEASE,
|
||||||
|
Input::BTN_LEFT, 0, 0, 0, 0));
|
||||||
|
_state = down ? PRESSED : RELEASED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _EGALAX_TS_H_ */
|
178
os/src/drivers/input/imx53/i2c.h
Normal file
178
os/src/drivers/input/imx53/i2c.h
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
/*
|
||||||
|
* \brief Driver for the i.MX53 i2c controller
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2013-03-15
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 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 _I2C_H_
|
||||||
|
#define _I2C_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <util/mmio.h>
|
||||||
|
#include <timer_session/connection.h>
|
||||||
|
#include <irq_session/connection.h>
|
||||||
|
|
||||||
|
namespace I2c
|
||||||
|
{
|
||||||
|
class I2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class I2c::I2c : Genode::Mmio
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
struct Address : public Register<0x0, 8>
|
||||||
|
{
|
||||||
|
struct Addr : Bitfield<1,7> {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Freq_divider : public Register<0x4, 8> {};
|
||||||
|
|
||||||
|
struct Control : public Register<0x8, 8>
|
||||||
|
{
|
||||||
|
struct Repeat_start : Bitfield<2,1> {};
|
||||||
|
struct Tx_ack_enable : Bitfield<3,1> {};
|
||||||
|
struct Tx_rx_select : Bitfield<4,1> {};
|
||||||
|
struct Master_slave_select : Bitfield<5,1> {};
|
||||||
|
struct Irq_enable : Bitfield<6,1> {};
|
||||||
|
struct Enable : Bitfield<7,1> {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Status : public Register<0xc, 8>
|
||||||
|
{
|
||||||
|
struct Rcv_ack : Bitfield<0,1> {};
|
||||||
|
struct Irq : Bitfield<1,1> {};
|
||||||
|
struct Slave_rw : Bitfield<2,1> {};
|
||||||
|
struct Arbitration_lost : Bitfield<4,1> {};
|
||||||
|
struct Busy : Bitfield<5,1> {};
|
||||||
|
struct Addressed_as_slave : Bitfield<6,1> {};
|
||||||
|
struct Data_transfer : Bitfield<7,1> {};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Data : public Register<0x10, 8> { };
|
||||||
|
|
||||||
|
|
||||||
|
class No_ack : Genode::Exception {};
|
||||||
|
class No_irq : Genode::Exception {};
|
||||||
|
|
||||||
|
|
||||||
|
Timer::Connection _timer;
|
||||||
|
Genode::Irq_connection _irq;
|
||||||
|
|
||||||
|
void _busy() { while (!read<Status::Busy>()); }
|
||||||
|
|
||||||
|
void _start()
|
||||||
|
{
|
||||||
|
/* clock enable */
|
||||||
|
|
||||||
|
write<Freq_divider>(0x2c);
|
||||||
|
write<Status>(0);
|
||||||
|
write<Control>(Control::Enable::bits(1));
|
||||||
|
|
||||||
|
_timer.msleep(1);
|
||||||
|
|
||||||
|
write<Control::Master_slave_select>(1);
|
||||||
|
|
||||||
|
_busy();
|
||||||
|
|
||||||
|
write<Control>(Control::Tx_rx_select::bits(1) |
|
||||||
|
Control::Tx_ack_enable::bits(1) |
|
||||||
|
Control::Irq_enable::bits(1) |
|
||||||
|
Control::Master_slave_select::bits(1) |
|
||||||
|
Control::Enable::bits(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _stop()
|
||||||
|
{
|
||||||
|
write<Control>(0);
|
||||||
|
|
||||||
|
/* clock disable */
|
||||||
|
}
|
||||||
|
|
||||||
|
void _write(Genode::uint8_t value)
|
||||||
|
{
|
||||||
|
write<Data>(value);
|
||||||
|
|
||||||
|
_irq.wait_for_irq();
|
||||||
|
if (!read<Status::Irq>()) throw No_irq();
|
||||||
|
write<Status::Irq>(0);
|
||||||
|
if (read<Status::Rcv_ack>()) throw No_ack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
I2c(Genode::addr_t const base, unsigned irq) : Mmio(base), _irq(irq)
|
||||||
|
{
|
||||||
|
write<Control>(0);
|
||||||
|
write<Status>(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void send(Genode::uint8_t addr, const Genode::uint8_t *buf,
|
||||||
|
Genode::size_t num)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
_start();
|
||||||
|
|
||||||
|
_write(addr << 1);
|
||||||
|
for (Genode::size_t i = 0; i < num; i++)
|
||||||
|
_write(buf[i]);
|
||||||
|
|
||||||
|
_stop();
|
||||||
|
return;
|
||||||
|
} catch(No_ack) {
|
||||||
|
} catch(No_irq) {
|
||||||
|
}
|
||||||
|
_stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void recv(Genode::uint8_t addr, Genode::uint8_t *buf,
|
||||||
|
Genode::size_t num)
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
try {
|
||||||
|
_start();
|
||||||
|
_write(addr << 1 | 1);
|
||||||
|
write<Control::Tx_rx_select>(0);
|
||||||
|
if (num > 1)
|
||||||
|
write<Control::Tx_ack_enable>(0);
|
||||||
|
read<Data>(); /* dummy read */
|
||||||
|
|
||||||
|
for (Genode::size_t i = 0; i < num; i++) {
|
||||||
|
|
||||||
|
_irq.wait_for_irq();
|
||||||
|
if (!read<Status::Irq>()) throw No_irq();
|
||||||
|
write<Status::Irq>(0);
|
||||||
|
|
||||||
|
if (i == num-1) {
|
||||||
|
write<Control::Tx_rx_select>(0);
|
||||||
|
write<Control::Master_slave_select>(0);
|
||||||
|
while (read<Status::Busy>()) ;
|
||||||
|
} else if (i == num-2) {
|
||||||
|
write<Control::Tx_ack_enable>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[i] = read<Data>();
|
||||||
|
}
|
||||||
|
|
||||||
|
_stop();
|
||||||
|
return;
|
||||||
|
} catch(No_irq) {
|
||||||
|
}
|
||||||
|
_stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _I2C_H_ */
|
78
os/src/drivers/input/imx53/main.cc
Normal file
78
os/src/drivers/input/imx53/main.cc
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
/**
|
||||||
|
* \brief Input driver front-end
|
||||||
|
* \author Norman Feske
|
||||||
|
* \author Christian Helmuth
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2006-08-30
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2006-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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode */
|
||||||
|
#include <base/env.h>
|
||||||
|
#include <base/sleep.h>
|
||||||
|
#include <base/rpc_server.h>
|
||||||
|
#include <root/component.h>
|
||||||
|
#include <cap_session/connection.h>
|
||||||
|
#include <platform_session/connection.h>
|
||||||
|
#include <input/component.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
|
||||||
|
#include <driver.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
static Event_queue ev_queue;
|
||||||
|
|
||||||
|
namespace Input {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Event handling is disabled on queue creation and will be enabled later if a
|
||||||
|
* session is created.
|
||||||
|
*/
|
||||||
|
void event_handling(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
ev_queue.enable();
|
||||||
|
else
|
||||||
|
ev_queue.disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool event_pending() { return !ev_queue.empty(); }
|
||||||
|
Event get_event() { return ev_queue.get(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* initialize server entry point */
|
||||||
|
enum { STACK_SIZE = 4096 };
|
||||||
|
static Cap_connection cap;
|
||||||
|
static Rpc_entrypoint ep(&cap, STACK_SIZE, "input_ep");
|
||||||
|
|
||||||
|
Platform::Connection plat_drv;
|
||||||
|
switch (plat_drv.revision()) {
|
||||||
|
case Platform::Session::SMD:
|
||||||
|
plat_drv.enable(Platform::Session::I2C_2);
|
||||||
|
plat_drv.enable(Platform::Session::I2C_3);
|
||||||
|
plat_drv.enable(Platform::Session::BUTTONS);
|
||||||
|
Input::Tablet_driver::factory(ev_queue);
|
||||||
|
default:
|
||||||
|
PWRN("No input driver available for this board");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* entry point serving input root interface */
|
||||||
|
static Input::Root input_root(&ep, env()->heap());
|
||||||
|
|
||||||
|
/* tell parent about the service */
|
||||||
|
env()->parent()->announce(ep.manage(&input_root));
|
||||||
|
|
||||||
|
/* main's done - go to sleep */
|
||||||
|
sleep_forever();
|
||||||
|
return 0;
|
||||||
|
}
|
118
os/src/drivers/input/imx53/mpr121.h
Normal file
118
os/src/drivers/input/imx53/mpr121.h
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* \brief Freescale MPR121 capacitative button driver
|
||||||
|
* \author Stefan Kalkowski
|
||||||
|
* \date 2013-03-15
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 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 _MPR121_H_
|
||||||
|
#define _MPR121_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <drivers/board_base.h>
|
||||||
|
#include <os/attached_io_mem_dataspace.h>
|
||||||
|
#include <input/event_queue.h>
|
||||||
|
#include <input/event.h>
|
||||||
|
#include <input/keycodes.h>
|
||||||
|
|
||||||
|
/* local includes */
|
||||||
|
#include <i2c.h>
|
||||||
|
|
||||||
|
namespace Input {
|
||||||
|
class Buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Input::Buttons {
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum {
|
||||||
|
I2C_ADDR = 0x5a,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Events {
|
||||||
|
RELEASE = 0,
|
||||||
|
BACK = 1,
|
||||||
|
HOME = 2,
|
||||||
|
MENU = 4,
|
||||||
|
POWER = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
Genode::Attached_io_mem_dataspace _i2c_ds;
|
||||||
|
I2c::I2c _i2c;
|
||||||
|
int _button;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Buttons() : _i2c_ds(Genode::Board_base::I2C_2_BASE,
|
||||||
|
Genode::Board_base::I2C_2_SIZE),
|
||||||
|
_i2c((Genode::addr_t)_i2c_ds.local_addr<void>(),
|
||||||
|
Genode::Board_base::I2C_2_IRQ),
|
||||||
|
_button(0)
|
||||||
|
{
|
||||||
|
static Genode::uint8_t init_cmd[][2] = {
|
||||||
|
{0x41, 0x8 }, {0x42, 0x5 }, {0x43, 0x8 },
|
||||||
|
{0x44, 0x5 }, {0x45, 0x8 }, {0x46, 0x5 },
|
||||||
|
{0x47, 0x8 }, {0x48, 0x5 }, {0x49, 0x8 },
|
||||||
|
{0x4a, 0x5 }, {0x4b, 0x8 }, {0x4c, 0x5 },
|
||||||
|
{0x4d, 0x8 }, {0x4e, 0x5 }, {0x4f, 0x8 },
|
||||||
|
{0x50, 0x5 }, {0x51, 0x8 }, {0x52, 0x5 },
|
||||||
|
{0x53, 0x8 }, {0x54, 0x5 }, {0x55, 0x8 },
|
||||||
|
{0x56, 0x5 }, {0x57, 0x8 }, {0x58, 0x5 },
|
||||||
|
{0x59, 0x8 }, {0x5a, 0x5 }, {0x2b, 0x1 },
|
||||||
|
{0x2c, 0x1 }, {0x2d, 0x0 }, {0x2e, 0x0 },
|
||||||
|
{0x2f, 0x1 }, {0x30, 0x1 }, {0x31, 0xff},
|
||||||
|
{0x32, 0x2 }, {0x5d, 0x4 }, {0x5c, 0xb },
|
||||||
|
{0x7b, 0xb }, {0x7d, 0xc9}, {0x7e, 0x82},
|
||||||
|
{0x7f, 0xb4}, {0x5e, 0x84}};
|
||||||
|
|
||||||
|
/* initialize mpr121 touch button device */
|
||||||
|
for (unsigned i = 0; i < sizeof(init_cmd)/2; i++)
|
||||||
|
_i2c.send(I2C_ADDR, init_cmd[i], 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void event(Event_queue &ev_queue)
|
||||||
|
{
|
||||||
|
Genode::uint8_t buf = 0;
|
||||||
|
|
||||||
|
_i2c.send(I2C_ADDR, &buf, 1);
|
||||||
|
_i2c.recv(I2C_ADDR, &buf, 1);
|
||||||
|
switch (buf) {
|
||||||
|
case RELEASE:
|
||||||
|
ev_queue.add(Input::Event(Input::Event::RELEASE,
|
||||||
|
_button, 0, 0, 0, 0));
|
||||||
|
break;
|
||||||
|
case BACK:
|
||||||
|
ev_queue.add(Input::Event(Input::Event::PRESS,
|
||||||
|
Input::KEY_BACK, 0, 0, 0, 0));
|
||||||
|
_button = Input::KEY_BACK;
|
||||||
|
break;
|
||||||
|
case HOME:
|
||||||
|
ev_queue.add(Input::Event(Input::Event::PRESS,
|
||||||
|
Input::KEY_HOME, 0, 0, 0, 0));
|
||||||
|
_button = Input::KEY_HOME;
|
||||||
|
break;
|
||||||
|
case MENU:
|
||||||
|
ev_queue.add(Input::Event(Input::Event::PRESS,
|
||||||
|
Input::KEY_MENU, 0, 0, 0, 0));
|
||||||
|
_button = Input::KEY_MENU;
|
||||||
|
break;
|
||||||
|
case POWER:
|
||||||
|
ev_queue.add(Input::Event(Input::Event::PRESS,
|
||||||
|
Input::KEY_POWER, 0, 0, 0, 0));
|
||||||
|
_button = Input::KEY_POWER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* just ignore everything else */;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* _MPR121_H_ */
|
5
os/src/drivers/input/imx53/target.mk
Normal file
5
os/src/drivers/input/imx53/target.mk
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
TARGET = input_drv
|
||||||
|
REQUIRES = imx53
|
||||||
|
SRC_CC = main.cc
|
||||||
|
LIBS = base
|
||||||
|
INC_DIR += $(PRG_DIR)
|
@ -51,9 +51,16 @@ class Ccm : public Genode::Attached_io_mem_dataspace,
|
|||||||
struct Bypass_ipu_hs : Bitfield<18, 1> { };
|
struct Bypass_ipu_hs : Bitfield<18, 1> { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Ccgr1 : Register<0x6c, 32>
|
||||||
|
{
|
||||||
|
struct I2c_1 : Bitfield<18, 2> { };
|
||||||
|
struct I2c_2 : Bitfield<20, 2> { };
|
||||||
|
struct I2c_3 : Bitfield<22, 2> { };
|
||||||
|
};
|
||||||
|
|
||||||
struct Ccgr5 : Register<0x7c, 32>
|
struct Ccgr5 : Register<0x7c, 32>
|
||||||
{
|
{
|
||||||
struct Ipu_clk_en : Bitfield<10, 2> { };
|
struct Ipu : Bitfield<10, 2> { };
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -61,11 +68,15 @@ class Ccm : public Genode::Attached_io_mem_dataspace,
|
|||||||
Ccm()
|
Ccm()
|
||||||
: Genode::Attached_io_mem_dataspace(Genode::Board_base::CCM_BASE,
|
: Genode::Attached_io_mem_dataspace(Genode::Board_base::CCM_BASE,
|
||||||
Genode::Board_base::CCM_SIZE),
|
Genode::Board_base::CCM_SIZE),
|
||||||
Genode::Mmio((Genode::addr_t)local_addr<void>()) {}
|
Genode::Mmio((Genode::addr_t)local_addr<void>()) { }
|
||||||
|
|
||||||
|
void i2c_1_enable(void) { write<Ccgr1::I2c_1>(3); }
|
||||||
|
void i2c_2_enable(void) { write<Ccgr1::I2c_2>(3); }
|
||||||
|
void i2c_3_enable(void) { write<Ccgr1::I2c_3>(3); }
|
||||||
|
|
||||||
void ipu_clk_enable(void)
|
void ipu_clk_enable(void)
|
||||||
{
|
{
|
||||||
write<Ccgr5::Ipu_clk_en>(3);
|
write<Ccgr5::Ipu>(3);
|
||||||
write<Ccdr::Ipu_hs_mask>(0);
|
write<Ccdr::Ipu_hs_mask>(0);
|
||||||
write<Clpcr::Bypass_ipu_hs>(0);
|
write<Clpcr::Bypass_ipu_hs>(0);
|
||||||
write<Cscmr2>(0xa2b32f0b);
|
write<Cscmr2>(0xa2b32f0b);
|
||||||
@ -74,7 +85,7 @@ class Ccm : public Genode::Attached_io_mem_dataspace,
|
|||||||
|
|
||||||
void ipu_clk_disable(void)
|
void ipu_clk_disable(void)
|
||||||
{
|
{
|
||||||
write<Ccgr5::Ipu_clk_en>(0);
|
write<Ccgr5::Ipu>(0);
|
||||||
write<Ccdr::Ipu_hs_mask>(1);
|
write<Ccdr::Ipu_hs_mask>(1);
|
||||||
write<Clpcr::Bypass_ipu_hs>(1);
|
write<Clpcr::Bypass_ipu_hs>(1);
|
||||||
}
|
}
|
||||||
|
@ -35,22 +35,67 @@ class Iomux : public Genode::Attached_io_mem_dataspace,
|
|||||||
struct Di1_vs_polarity : Bitfield<10,1> { };
|
struct Di1_vs_polarity : Bitfield<10,1> { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Key_col3 : Register<0x3c, 32> {};
|
||||||
|
struct Key_row3 : Register<0x40, 32> {};
|
||||||
|
|
||||||
|
struct Eim_a24 : Register<0x15c, 32> { };
|
||||||
|
|
||||||
|
template <unsigned OFF>
|
||||||
|
struct Sw_mux_ctl_pad_gpio : Register<0x314 + OFF*4, 32> { };
|
||||||
|
|
||||||
|
struct Sw_pad_ctl_pad_key_col3 : Register<0x364, 32> { };
|
||||||
|
struct Sw_pad_ctl_pad_key_row3 : Register<0x368, 32> { };
|
||||||
|
|
||||||
|
struct Sw_pad_ctl_pad_eim_a24 : Register<0x4a8, 32> { };
|
||||||
|
|
||||||
|
template <unsigned OFF>
|
||||||
|
struct Sw_pad_ctl_pad_gpio : Register<0x6a4 + OFF*4, 32> { };
|
||||||
|
|
||||||
|
struct I2c2_ipp_scl_in_select_input : Register<0x81c, 32> { };
|
||||||
|
struct I2c2_ipp_sda_in_select_input : Register<0x820, 32> { };
|
||||||
|
struct I2c3_ipp_scl_in_select_input : Register<0x824, 32> { };
|
||||||
|
struct I2c3_ipp_sda_in_select_input : Register<0x828, 32> { };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Iomux()
|
Iomux()
|
||||||
: Genode::Attached_io_mem_dataspace(Genode::Board_base::IOMUXC_BASE,
|
: Genode::Attached_io_mem_dataspace(Genode::Board_base::IOMUXC_BASE,
|
||||||
Genode::Board_base::IOMUXC_SIZE),
|
Genode::Board_base::IOMUXC_SIZE),
|
||||||
Genode::Mmio((Genode::addr_t)local_addr<void>())
|
Genode::Mmio((Genode::addr_t)local_addr<void>()) { }
|
||||||
|
|
||||||
|
void i2c_2_enable()
|
||||||
{
|
{
|
||||||
|
write<Key_col3>(0x14);
|
||||||
|
write<I2c2_ipp_scl_in_select_input>(0);
|
||||||
|
write<Sw_pad_ctl_pad_key_col3>(0x12d);
|
||||||
|
write<Key_row3>(0x14);
|
||||||
|
write<I2c2_ipp_sda_in_select_input>(0);
|
||||||
|
write<Sw_pad_ctl_pad_key_row3>(0x12d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_di1()
|
void i2c_3_enable()
|
||||||
|
{
|
||||||
|
write<Sw_mux_ctl_pad_gpio<3> >(0x12);
|
||||||
|
write<I2c3_ipp_scl_in_select_input>(0x1);
|
||||||
|
write<Sw_pad_ctl_pad_gpio<3> >(0x12d);
|
||||||
|
write<Sw_mux_ctl_pad_gpio<4> >(0x12);
|
||||||
|
write<I2c3_ipp_sda_in_select_input>(0x1);
|
||||||
|
write<Sw_pad_ctl_pad_gpio<4> >(0x12d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipu_enable()
|
||||||
{
|
{
|
||||||
write<Gpr2::Di1_vs_polarity>(1);
|
write<Gpr2::Di1_vs_polarity>(1);
|
||||||
write<Gpr2::Data_width_ch1>(Gpr2::Data_width_ch1::PX_18_BITS);
|
write<Gpr2::Data_width_ch1>(Gpr2::Data_width_ch1::PX_18_BITS);
|
||||||
write<Gpr2::Bit_mapping_ch1>(Gpr2::Bit_mapping_ch1::SPWG);
|
write<Gpr2::Bit_mapping_ch1>(Gpr2::Bit_mapping_ch1::SPWG);
|
||||||
write<Gpr2::Ch1_mode>(Gpr2::Ch1_mode::ROUTED_TO_DI1);
|
write<Gpr2::Ch1_mode>(Gpr2::Ch1_mode::ROUTED_TO_DI1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void buttons_enable()
|
||||||
|
{
|
||||||
|
write<Eim_a24>(1);
|
||||||
|
write<Sw_pad_ctl_pad_eim_a24>(0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _DRIVERS__PLATFORM__IMX53__IOMUX_H_ */
|
#endif /* _DRIVERS__PLATFORM__IMX53__IOMUX_H_ */
|
||||||
|
@ -58,7 +58,18 @@ class Platform::Session_component : public Genode::Rpc_object<Platform::Session>
|
|||||||
case Session::IPU:
|
case Session::IPU:
|
||||||
_src.reset_ipu();
|
_src.reset_ipu();
|
||||||
_ccm.ipu_clk_enable();
|
_ccm.ipu_clk_enable();
|
||||||
_iomux.enable_di1();
|
_iomux.ipu_enable();
|
||||||
|
break;
|
||||||
|
case Session::I2C_2:
|
||||||
|
_ccm.i2c_2_enable();
|
||||||
|
_iomux.i2c_2_enable();
|
||||||
|
break;
|
||||||
|
case Session::I2C_3:
|
||||||
|
_ccm.i2c_3_enable();
|
||||||
|
_iomux.i2c_3_enable();
|
||||||
|
break;
|
||||||
|
case Session::BUTTONS:
|
||||||
|
_iomux.buttons_enable();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
PWRN("Invalid device");
|
PWRN("Invalid device");
|
||||||
|
Loading…
Reference in New Issue
Block a user