From 49b4b8597dc4e0ff5bc3319eb4b8cd1e61bc6f45 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Mon, 10 Oct 2022 18:18:01 +0200 Subject: [PATCH] os/pin_driver: support for time-multiplexed in/out This patch equips the pin-driver framework with support for the time-multiplexed operation of a pin as output or input. This is needed when implementing I2C communication via a bit-banging driver. To operate pin in both directions, a driver obtains both a pin-state and a pin-control session for the same pin. The pin-state session can be used to sense the current pin state. The control session allows the client to set the pin to high or low (using the 'state' method), or to set it to high-impedance via the 'yield' method. Once switched to high-impedance, the pin can be used as input. Issue genodelabs/genode-allwinner#10 --- repos/os/include/os/pin_driver.h | 4 +++- .../os/include/pin_control_session/component.h | 17 +++++++++++++++-- .../os/include/pin_control_session/connection.h | 2 ++ .../pin_control_session/pin_control_session.h | 5 ++++- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/repos/os/include/os/pin_driver.h b/repos/os/include/os/pin_driver.h index 18f470f91c..edefddd807 100644 --- a/repos/os/include/os/pin_driver.h +++ b/repos/os/include/os/pin_driver.h @@ -39,6 +39,8 @@ namespace Pin { { using Pin::Root, Direction::IN>::Root; }; + + enum class Level { LOW, HIGH, HIGH_IMPEDANCE }; } @@ -53,7 +55,7 @@ struct Pin::Driver : Interface /** * Set pin state */ - virtual void pin_state(ID, bool enabled) = 0; + virtual void pin_state(ID, Level) = 0; /** * Return pin ID assigned to the specified session label diff --git a/repos/os/include/pin_control_session/component.h b/repos/os/include/pin_control_session/component.h index d82e90471c..1a52695c50 100644 --- a/repos/os/include/pin_control_session/component.h +++ b/repos/os/include/pin_control_session/component.h @@ -39,6 +39,12 @@ class Pin_control::Session_component : public Session_object using Session_object::label; + void _state(Pin::Level level) + { + if (_assignment.target.constructed()) + _assignment.driver.pin_state(_assignment.target->id, level); + } + public: using Pin_id = ID; @@ -57,8 +63,15 @@ class Pin_control::Session_component : public Session_object */ void state(bool enabled) override { - if (_assignment.target.constructed()) - _assignment.driver.pin_state(_assignment.target->id, enabled); + _state(enabled ? Pin::Level::HIGH : Pin::Level::LOW); + } + + /** + * Pin_control::Session interface + */ + void yield() override + { + _state(Pin::Level::HIGH_IMPEDANCE); } void update_assignment() diff --git a/repos/os/include/pin_control_session/connection.h b/repos/os/include/pin_control_session/connection.h index 3b2bf1782b..0806c2bf08 100644 --- a/repos/os/include/pin_control_session/connection.h +++ b/repos/os/include/pin_control_session/connection.h @@ -35,6 +35,8 @@ struct Pin_control::Connection : private Genode::Connection, { } void state(bool enabled) override { call(enabled); } + + void yield() override { call(); } }; #endif /* _INCLUDE__PIN_CONTROL_SESSION__CONNECTION_H_ */ diff --git a/repos/os/include/pin_control_session/pin_control_session.h b/repos/os/include/pin_control_session/pin_control_session.h index 909c55bf22..a222550d7a 100644 --- a/repos/os/include/pin_control_session/pin_control_session.h +++ b/repos/os/include/pin_control_session/pin_control_session.h @@ -40,8 +40,11 @@ struct Pin_control::Session : Genode::Session virtual void state(bool) = 0; + virtual void yield() = 0; + GENODE_RPC(Rpc_state, void, state, bool); - GENODE_RPC_INTERFACE(Rpc_state); + GENODE_RPC(Rpc_yield, void, yield); + GENODE_RPC_INTERFACE(Rpc_state, Rpc_yield); }; #endif /* _INCLUDE__PIN_CONTROL_SESSION__PIN_CONTROL_SESSION_H_ */