diff --git a/src/drivers/input/imx53_tablet/driver.h b/src/drivers/input/imx53_tablet/driver.h
new file mode 100644
index 0000000..b9f86f7
--- /dev/null
+++ b/src/drivers/input/imx53_tablet/driver.h
@@ -0,0 +1,96 @@
+/*
+ * \brief Input-driver
+ * \author Stefan Kalkowski
+ * \date 2013-03-15
+ */
+
+/*
+ * Copyright (C) 2013-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 _DRIVERS__INPUT__SPEC__IMX53__DRIVER_H_
+#define _DRIVERS__INPUT__SPEC__IMX53__DRIVER_H_
+
+/* Genode includes */
+#include
+#include
+#include
+
+/* local includes */
+#include
+#include
+
+namespace Input {
+ class Tablet_driver;
+}
+
+
+class Input::Tablet_driver
+{
+ private:
+
+ enum Gpio_irqs {
+ GPIO_TOUCH = 84,
+ GPIO_BUTTON = 132,
+ };
+
+ Event_queue &_ev_queue;
+ Gpio::Connection _gpio_ts;
+ Gpio::Connection _gpio_bt;
+ Genode::Irq_session_client _irq_ts;
+ Genode::Irq_session_client _irq_bt;
+ Genode::Io_signal_handler _ts_dispatcher;
+ Genode::Io_signal_handler _bt_dispatcher;
+ Touchscreen _touchscreen;
+ Buttons _buttons;
+
+ void _handle_ts()
+ {
+ _touchscreen.event(_ev_queue);
+ _irq_ts.ack_irq();
+ }
+
+ void _handle_bt()
+ {
+ _buttons.event(_ev_queue);
+ _irq_bt.ack_irq();
+ }
+
+ Tablet_driver(Genode::Env &env, Event_queue &ev_queue)
+ :
+ _ev_queue(ev_queue),
+ _gpio_ts(env, GPIO_TOUCH),
+ _gpio_bt(env, GPIO_BUTTON),
+ _irq_ts(_gpio_ts.irq_session(Gpio::Session::LOW_LEVEL)),
+ _irq_bt(_gpio_bt.irq_session(Gpio::Session::FALLING_EDGE)),
+ _ts_dispatcher(env.ep(), *this, &Tablet_driver::_handle_ts),
+ _bt_dispatcher(env.ep(), *this, &Tablet_driver::_handle_bt),
+ _touchscreen(env),
+ _buttons(env)
+ {
+ /* GPIO touchscreen handling */
+ _gpio_ts.direction(Gpio::Session::OUT);
+ _gpio_ts.write(true);
+ _gpio_ts.direction(Gpio::Session::IN);
+
+ _irq_ts.sigh(_ts_dispatcher);
+ _irq_ts.ack_irq();
+
+ /* GPIO button handling */
+ _gpio_bt.direction(Gpio::Session::OUT);
+ _gpio_bt.write(true);
+ _gpio_bt.direction(Gpio::Session::IN);
+
+ _irq_bt.sigh(_bt_dispatcher);
+ _irq_bt.ack_irq();
+ }
+
+ public:
+
+ static Tablet_driver* factory(Genode::Env &env, Event_queue &ev_queue);
+};
+
+#endif /* _DRIVERS__INPUT__SPEC__IMX53__DRIVER_H_ */
diff --git a/src/drivers/input/imx53_tablet/egalax_ts.h b/src/drivers/input/imx53_tablet/egalax_ts.h
new file mode 100644
index 0000000..776e890
--- /dev/null
+++ b/src/drivers/input/imx53_tablet/egalax_ts.h
@@ -0,0 +1,96 @@
+/*
+ * \brief EETI eGalaxy touchscreen driver
+ * \author Stefan Kalkowski
+ * \date 2013-03-15
+ */
+
+/*
+ * Copyright (C) 2013-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 _DRIVERS__INPUT__SPEC__IMX53__EGALAX_TS_H_
+#define _DRIVERS__INPUT__SPEC__IMX53__EGALAX_TS_H_
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+/* local includes */
+#include
+
+namespace Input {
+ class Touchscreen;
+}
+
+
+class Input::Touchscreen {
+
+ private:
+
+ enum I2c_addresses { I2C_ADDR = 0x4 };
+ enum Finger_state { PRESSED, RELEASED };
+
+ Irq_handler _irq_handler;
+ Genode::Attached_io_mem_dataspace _i2c_ds;
+ I2c::I2c _i2c;
+ Genode::uint8_t _buf[10];
+ Finger_state _state;
+
+ public:
+
+ Touchscreen(Genode::Env &env)
+ :
+ _irq_handler(env, Imx53::I2C_3_IRQ),
+ _i2c_ds(env, Imx53::I2C_3_BASE, Imx53::I2C_3_SIZE),
+ _i2c((Genode::addr_t)_i2c_ds.local_addr(),
+ _irq_handler),
+ _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::Absolute_motion{x, y});
+
+ /* button event */
+ if ((down && (_state == RELEASED)) || (!down && (_state == PRESSED))) {
+
+ if (down) ev_queue.add(Input::Press {Input::BTN_LEFT});
+ else ev_queue.add(Input::Release{Input::BTN_LEFT});
+
+ _state = down ? PRESSED : RELEASED;
+ }
+ }
+};
+
+#endif /* _DRIVERS__INPUT__SPEC__IMX53__EGALAX_TS_H_ */
diff --git a/src/drivers/input/imx53_tablet/i2c.h b/src/drivers/input/imx53_tablet/i2c.h
new file mode 100644
index 0000000..c727a84
--- /dev/null
+++ b/src/drivers/input/imx53_tablet/i2c.h
@@ -0,0 +1,181 @@
+/*
+ * \brief Driver for the i.MX53 i2c controller
+ * \author Stefan Kalkowski
+ * \date 2013-03-15
+ */
+
+/*
+ * Copyright (C) 2013-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 _DRIVERS__INPUT__SPEC__IMX53__I2C_H_
+#define _DRIVERS__INPUT__SPEC__IMX53__I2C_H_
+
+/* Genode includes */
+#include
+#include
+
+/* local includes */
+#include "irq_handler.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 {};
+
+ Irq_handler & _irq_handler;
+
+ void _busy() { while (!read()); }
+
+ void _start()
+ {
+ /* clock enable */
+
+ write(0x2c);
+ write(0);
+ write(Control::Enable::bits(1));
+
+ while (!read()) { ; }
+
+ write(1);
+
+ _busy();
+
+ write(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(0);
+
+ /* clock disable */
+ }
+
+ void _write(Genode::uint8_t value)
+ {
+ write(value);
+
+ do { _irq_handler.wait(); }
+ while (!read());
+
+ write(0);
+ if (read()) throw No_ack();
+
+ _irq_handler.ack();
+ }
+
+ public:
+
+ I2c(Genode::addr_t const base, Irq_handler &irq_handler)
+ : Mmio(base),
+ _irq_handler(irq_handler)
+ {
+ write(0);
+ write(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) { }
+ _stop();
+ }
+ }
+
+
+ void recv(Genode::uint8_t addr, Genode::uint8_t *buf,
+ Genode::size_t num)
+ {
+ while (true) {
+ try {
+ _start();
+ _write(addr << 1 | 1);
+ write(0);
+ if (num > 1)
+ write(0);
+ read(); /* dummy read */
+
+ for (Genode::size_t i = 0; i < num; i++) {
+
+ do { _irq_handler.wait(); }
+ while (!read());
+
+ write(0);
+
+ if (i == num-1) {
+ write(0);
+ write(0);
+ while (read()) ;
+ } else if (i == num-2) {
+ write(1);
+ }
+
+ buf[i] = read();
+ _irq_handler.ack();
+ }
+
+ _stop();
+ return;
+ } catch(No_ack) { }
+ _stop();
+ }
+ }
+
+};
+
+#endif /* _DRIVERS__INPUT__SPEC__IMX53__I2C_H_ */
diff --git a/src/drivers/input/imx53_tablet/irq_handler.h b/src/drivers/input/imx53_tablet/irq_handler.h
new file mode 100644
index 0000000..bce7788
--- /dev/null
+++ b/src/drivers/input/imx53_tablet/irq_handler.h
@@ -0,0 +1,53 @@
+/*
+ * \brief Input-interrupt handler
+ * \author Josef Soentgen
+ * \date 2015-04-08
+ */
+
+/*
+ * Copyright (C) 2015-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 _IRQ_HANDLER_H_
+#define _IRQ_HANDLER_H_
+
+/* Genode includes */
+#include
+
+class Irq_handler
+{
+ private:
+
+ Genode::Env &_env;
+ Genode::Irq_connection _irq;
+ Genode::Io_signal_handler _handler;
+
+ unsigned _sem_cnt = 1;
+
+ void _handle() { _sem_cnt = 0; }
+
+ public:
+
+ Irq_handler(Genode::Env &env, int irq_number)
+ :
+ _env(env), _irq(env, irq_number),
+ _handler(env.ep(), *this, &Irq_handler::_handle)
+ {
+ _irq.sigh(_handler);
+ _irq.ack_irq();
+ }
+
+ void wait()
+ {
+ _sem_cnt++;
+ while (_sem_cnt > 0)
+ _env.ep().wait_and_dispatch_one_io_signal();
+ }
+
+ void ack() { _irq.ack_irq(); }
+};
+
+#endif /* _IRQ_HANDLER_H_ */
diff --git a/src/drivers/input/imx53_tablet/main.cc b/src/drivers/input/imx53_tablet/main.cc
new file mode 100644
index 0000000..da0559f
--- /dev/null
+++ b/src/drivers/input/imx53_tablet/main.cc
@@ -0,0 +1,65 @@
+/**
+ * \brief Input driver front-end
+ * \author Norman Feske
+ * \author Christian Helmuth
+ * \author Stefan Kalkowski
+ * \date 2006-08-30
+ */
+
+/*
+ * Copyright (C) 2006-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.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+#include
+
+/* local includes */
+#include
+
+using namespace Genode;
+
+
+Input::Tablet_driver* Input::Tablet_driver::factory(Genode::Env &env,
+ Event_queue &ev_queue)
+{
+ static Input::Tablet_driver driver(env, ev_queue);
+ return &driver;
+}
+
+
+struct Main
+{
+ Genode::Env &env;
+
+ Input::Session_component session { env, env.ram() };
+ Input::Root_component root { env.ep().rpc_ep(), session };
+
+ Main(Genode::Env &env) : env(env)
+ {
+ Platform::Connection plat_drv { env };
+ 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(env, session.event_queue());
+ break;
+ default:
+ warning("No input driver available for this board");
+ }
+
+ /* tell parent about the service */
+ env.parent().announce(env.ep().manage(root));
+ }
+};
+
+
+void Component::construct(Genode::Env &env) { static Main main(env); }
diff --git a/src/drivers/input/imx53_tablet/mpr121.h b/src/drivers/input/imx53_tablet/mpr121.h
new file mode 100644
index 0000000..f1a734d
--- /dev/null
+++ b/src/drivers/input/imx53_tablet/mpr121.h
@@ -0,0 +1,107 @@
+/*
+ * \brief Freescale MPR121 capacitative button driver
+ * \author Stefan Kalkowski
+ * \date 2013-03-15
+ */
+
+/*
+ * Copyright (C) 2013-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 _DRIVERS__INPUT__SPEC__IMX53__MPR121_H_
+#define _DRIVERS__INPUT__SPEC__IMX53__MPR121_H_
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+/* local includes */
+#include
+
+namespace Input {
+ class Buttons;
+}
+
+
+class Input::Buttons {
+
+ private:
+
+ enum {
+ I2C_ADDR = 0x5a,
+ };
+
+ enum Events {
+ RELEASE = 0,
+ BACK = 1,
+ HOME = 2,
+ MENU = 4,
+ POWER = 8,
+ };
+
+ Irq_handler _irq_handler;
+ Genode::Attached_io_mem_dataspace _i2c_ds;
+ I2c::I2c _i2c;
+ Genode::uint8_t _state;
+
+ public:
+
+ Buttons(Genode::Env &env)
+ :
+ _irq_handler(env, Imx53::I2C_2_IRQ),
+ _i2c_ds(env, Imx53::I2C_2_BASE, Imx53::I2C_2_SIZE),
+ _i2c((Genode::addr_t)_i2c_ds.local_addr(),
+ _irq_handler),
+ _state(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)
+ {
+ int buttons[] = { BACK, HOME, MENU, POWER };
+ int codes[] = { Input::KEY_BACK, Input::KEY_HOME,
+ Input::KEY_MENU, Input::KEY_POWER};
+
+ Genode::uint8_t buf = 0;
+ _i2c.send(I2C_ADDR, &buf, 1);
+ _i2c.recv(I2C_ADDR, &buf, 1);
+
+ for (unsigned i = 0; i < (sizeof(buttons)/sizeof(int)); i++) {
+ if ((_state & buttons[i]) == (buf & buttons[i]))
+ continue;
+
+ Input::Keycode const key = Input::Keycode(codes[i]);
+
+ if (buf & buttons[i]) ev_queue.add(Input::Press {key});
+ else ev_queue.add(Input::Release{key});
+ };
+ _state = buf;
+ }
+};
+
+#endif /* _DRIVERS__INPUT__SPEC__IMX53__MPR121_H_ */
diff --git a/src/drivers/input/imx53_tablet/target.mk b/src/drivers/input/imx53_tablet/target.mk
new file mode 100644
index 0000000..cdf0b9d
--- /dev/null
+++ b/src/drivers/input/imx53_tablet/target.mk
@@ -0,0 +1,6 @@
+TARGET = imx53_tablet_input_drv
+REQUIRES = arm_v7
+SRC_CC = main.cc
+LIBS = base
+INC_DIR += $(PRG_DIR)
+INC_DIR += $(call select_from_repositories,include/spec/imx53)
diff --git a/src/drivers/pwm/imx53/main.cc b/src/drivers/pwm/imx53/main.cc
new file mode 100644
index 0000000..ddf86af
--- /dev/null
+++ b/src/drivers/pwm/imx53/main.cc
@@ -0,0 +1,86 @@
+/*
+ * \brief Pulse width modulation
+ * \author Stefan Kalkowski
+ * \date 2020-04-22
+ */
+
+/*
+ * Copyright (C) 2020 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.
+ */
+
+/* Genode includes */
+#include
+#include
+#include
+#include
+#include
+
+struct Pwm : Genode::Mmio
+{
+ enum Clk_src { OFF, IPG, IPG_HIGHFREQ, IPG_32K };
+
+ struct Control : Register<0x0, 32>
+ {
+ struct Enable : Bitfield<0, 1> {};
+ struct Clock_source : Bitfield<16, 2> {};
+ struct Dbgen : Bitfield<22, 1> {};
+ struct Waiten : Bitfield<23, 1> {};
+ struct Dozen : Bitfield<24, 1> {};
+ struct Stopen : Bitfield<25, 1> {};
+ };
+
+ struct Sample : Register<0xc, 32> {};
+ struct Period : Register<0x10,32> {};
+
+ Pwm(Genode::addr_t const mmio_base,
+ unsigned period,
+ unsigned sample,
+ Clk_src clk_src)
+ : Genode::Mmio(mmio_base)
+ {
+ write(period);
+ write(sample);
+
+ Control::access_t ctrl = 0;
+ Control::Enable::set(ctrl, 1);
+ Control::Dbgen::set(ctrl, 1);
+ Control::Waiten::set(ctrl, 1);
+ Control::Dozen::set(ctrl, 1);
+ Control::Stopen::set(ctrl, 1);
+ Control::Clock_source::set(ctrl, clk_src);
+ write(ctrl);
+ }
+};
+
+
+struct Main
+{
+ Genode::Env & _env;
+ Genode::Attached_rom_dataspace _config { _env, "config" };
+ /** FIXME: currently use PWM2 of i.MX53, use platform driver in future **/
+ Genode::Attached_io_mem_dataspace _ds { _env, 0x53fb8000, 0x4000 };
+ Genode::Constructible _pwm {};
+
+ Main(Genode::Env &env) : _env(env)
+ {
+ Genode::log("--- i.MX53 Pulse-width-modulation driver ---");
+
+ Genode::Xml_node config = _config.xml();
+ unsigned period = config.attribute_value("period", 0);
+ unsigned sample = config.attribute_value("sample", 0);
+ Genode::String<16> clk = config.attribute_value("clock_source",
+ Genode::String<16>());
+ Pwm::Clk_src src = Pwm::OFF;
+ if (clk == "ipg") src = Pwm::IPG;
+ if (clk == "ipg_highfreq") src = Pwm::IPG_HIGHFREQ;
+ if (clk == "ipg_32k") src = Pwm::IPG_32K;
+
+ _pwm.construct((Genode::addr_t)_ds.local_addr(), period, sample, src);
+ }
+};
+
+
+void Component::construct(Genode::Env &env) { static Main main(env); }
diff --git a/src/drivers/pwm/imx53/pwm.h b/src/drivers/pwm/imx53/pwm.h
new file mode 100644
index 0000000..4bcc853
--- /dev/null
+++ b/src/drivers/pwm/imx53/pwm.h
@@ -0,0 +1,36 @@
+/*
+ * \brief Pulse width modulation
+ * \author Stefan Kalkowski
+ * \date 2013-03-05
+ */
+
+/*
+ * Copyright (C) 2013-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 _DRIVERS__PWM__IMX53__PWM_H_
+#define _DRIVERS__PWM__IMX53__PWM_H_
+
+/* Genode includes */
+#include
+
+struct Pwm : Genode::Mmio
+{
+ struct Control : Register<0x0, 32> {};
+ struct Sample : Register<0xc, 32> {};
+ struct Period : Register<0x10,32> {};
+
+ Pwm(Genode::addr_t const mmio_base) : Genode::Mmio(mmio_base) { }
+
+ void enable_display()
+ {
+ write(0x64);
+ write(0x64);
+ write(0x3c20001);
+ }
+};
+
+#endif /* _DRIVERS__PWM__IMX53__PWM_H_ */
diff --git a/src/drivers/pwm/imx53/target.mk b/src/drivers/pwm/imx53/target.mk
new file mode 100644
index 0000000..1e0b684
--- /dev/null
+++ b/src/drivers/pwm/imx53/target.mk
@@ -0,0 +1,4 @@
+TARGET = imx53_pwd_drv
+REQUIRES = arm_v7
+SRC_CC = main.cc
+LIBS = base