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
This commit is contained in:
Norman Feske 2022-10-10 18:18:01 +02:00 committed by Christian Helmuth
parent cd8538da9a
commit 49b4b8597d
4 changed files with 24 additions and 4 deletions

View File

@ -39,6 +39,8 @@ namespace Pin {
{
using Pin::Root<Irq_session_component<ID>, 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

View File

@ -39,6 +39,12 @@ class Pin_control::Session_component : public Session_object<Session>
using Session_object<Session>::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<Session>
*/
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()

View File

@ -35,6 +35,8 @@ struct Pin_control::Connection : private Genode::Connection<Session>,
{ }
void state(bool enabled) override { call<Rpc_state>(enabled); }
void yield() override { call<Rpc_yield>(); }
};
#endif /* _INCLUDE__PIN_CONTROL_SESSION__CONNECTION_H_ */

View File

@ -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_ */