From 6cc604796237a03eb7a10de4be2c3b0d634bd1c0 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Mon, 6 Dec 2021 14:37:03 +0100 Subject: [PATCH] platform_drv: introduce clocks, power, reset Share datastructures for clock, power and reset related configurations per device. In the generic platform driver component these structures are kept empty. Driver derivates can fill the clocks settings, power and reset switches with life. The former Driver::Env gets removed. Fix #4338 --- .../platform/rpi/device_model_policy.cc | 81 --------- repos/os/src/drivers/platform/rpi/env.h | 43 ----- repos/os/src/drivers/platform/rpi/main.cc | 54 ++++++ .../src/drivers/platform/rpi/power_domains.h | 67 +++++++ .../os/src/drivers/platform/rpi/rpi_device.cc | 72 -------- .../os/src/drivers/platform/rpi/rpi_device.h | 90 --------- repos/os/src/drivers/platform/rpi/target.mk | 5 +- .../os/src/drivers/platform/spec/arm/clock.h | 107 +++++++++++ .../src/drivers/platform/spec/arm/device.cc | 86 ++++++++- .../os/src/drivers/platform/spec/arm/device.h | 171 ++++++++++++++++-- .../platform/spec/arm/device_component.cc | 4 +- .../platform/spec/arm/device_component.h | 1 - .../platform/spec/arm/device_model_policy.cc | 47 ++++- repos/os/src/drivers/platform/spec/arm/env.h | 41 ----- .../os/src/drivers/platform/spec/arm/main.cc | 21 ++- .../platform/spec/arm/named_registry.h | 90 +++++++++ .../os/src/drivers/platform/spec/arm/power.h | 56 ++++++ .../os/src/drivers/platform/spec/arm/reset.h | 56 ++++++ .../os/src/drivers/platform/spec/arm/root.cc | 15 +- repos/os/src/drivers/platform/spec/arm/root.h | 9 +- .../platform/spec/arm/session_component.cc | 45 +++-- .../platform/spec/arm/session_component.h | 32 ++-- .../os/src/drivers/platform/spec/arm/types.h | 73 ++++++++ 23 files changed, 859 insertions(+), 407 deletions(-) delete mode 100644 repos/os/src/drivers/platform/rpi/device_model_policy.cc delete mode 100644 repos/os/src/drivers/platform/rpi/env.h create mode 100644 repos/os/src/drivers/platform/rpi/main.cc create mode 100644 repos/os/src/drivers/platform/rpi/power_domains.h delete mode 100644 repos/os/src/drivers/platform/rpi/rpi_device.cc delete mode 100644 repos/os/src/drivers/platform/rpi/rpi_device.h create mode 100644 repos/os/src/drivers/platform/spec/arm/clock.h delete mode 100644 repos/os/src/drivers/platform/spec/arm/env.h create mode 100644 repos/os/src/drivers/platform/spec/arm/named_registry.h create mode 100644 repos/os/src/drivers/platform/spec/arm/power.h create mode 100644 repos/os/src/drivers/platform/spec/arm/reset.h create mode 100644 repos/os/src/drivers/platform/spec/arm/types.h diff --git a/repos/os/src/drivers/platform/rpi/device_model_policy.cc b/repos/os/src/drivers/platform/rpi/device_model_policy.cc deleted file mode 100644 index 6b0d4791e3..0000000000 --- a/repos/os/src/drivers/platform/rpi/device_model_policy.cc +++ /dev/null @@ -1,81 +0,0 @@ -/* - * \brief Platform driver - Device model policy for rpi - * \author Stefan Kalkowski - * \date 2020-08-20 - */ - -/* - * 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. - */ - -#include -#include - -using Driver::Device_model; -using Driver::Device; -using Driver::Rpi_device; - -void Device_model::destroy_element(Device & dev) -{ - Rpi_device & device = static_cast(dev); - - { - Irq_update_policy policy(_env.heap); - device._irq_list.destroy_all_elements(policy); - } - - { - Io_mem_update_policy policy(_env.heap); - device._io_mem_list.destroy_all_elements(policy); - } - - { - Property_update_policy policy(_env.heap); - device._property_list.destroy_all_elements(policy); - } - - { - Power_domain_update_policy policy(_env.heap); - device._power_domain_list.destroy_all_elements(policy); - } - - Genode::destroy(_env.heap, &device); -} - - -Device & Device_model::create_element(Genode::Xml_node node) -{ - Device::Name name = node.attribute_value("name", Device::Name()); - Device::Type type = node.attribute_value("type", Device::Type()); - return *(new (_env.heap) Rpi_device(name, type)); -} - - -void Device_model::update_element(Device & dev, - Genode::Xml_node node) -{ - Rpi_device & device = static_cast(dev); - - { - Irq_update_policy policy(_env.heap); - device._irq_list.update_from_xml(policy, node); - } - - { - Io_mem_update_policy policy(_env.heap); - device._io_mem_list.update_from_xml(policy, node); - } - - { - Property_update_policy policy(_env.heap); - device._property_list.update_from_xml(policy, node); - } - - { - Power_domain_update_policy policy(_env.heap); - device._power_domain_list.update_from_xml(policy, node); - } -} diff --git a/repos/os/src/drivers/platform/rpi/env.h b/repos/os/src/drivers/platform/rpi/env.h deleted file mode 100644 index 93ebabf018..0000000000 --- a/repos/os/src/drivers/platform/rpi/env.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * \brief Platform driver for rpi - * \author Stefan Kalkowski - * \date 2020-08-20 - */ - -/* - * 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. - */ - -#ifndef _SRC__DRIVERS__PLATFORM__RPI__ENV_H_ -#define _SRC__DRIVERS__PLATFORM__RPI__ENV_H_ - -#include -#include -#include - -#include -#include - -namespace Driver { - using namespace Genode; - - struct Env; -}; - - -struct Driver::Env -{ - Genode::Env & env; - Heap heap { env.ram(), env.rm() }; - Sliced_heap sliced_heap { env.ram(), env.rm() }; - Attached_rom_dataspace config { env, "config" }; - Device_model devices { *this }; - Mbox mbox { env }; - - Env(Genode::Env &env) : env(env) { } -}; - -#endif /* _SRC__DRIVERS__PLATFORM__RPI__ENV_H_ */ diff --git a/repos/os/src/drivers/platform/rpi/main.cc b/repos/os/src/drivers/platform/rpi/main.cc new file mode 100644 index 0000000000..3bc557b4a4 --- /dev/null +++ b/repos/os/src/drivers/platform/rpi/main.cc @@ -0,0 +1,54 @@ +/* + * \brief Platform driver for Raspberry Pi 1 + * \author Stefan Kalkowski + * \date 2020-04-12 + */ + +/* + * 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. + */ + +#include +#include +#include + +namespace Driver { struct Main; }; + +struct Driver::Main +{ + void update_config(); + + Env & env; + Heap heap { env.ram(), env.rm() }; + Sliced_heap sliced_heap { env.ram(), env.rm() }; + Attached_rom_dataspace config { env, "config" }; + Device_model devices { heap }; + Mbox mbox { env }; + Power_domains power_domains { devices.powers(), mbox }; + Signal_handler
config_handler { env.ep(), *this, + &Main::update_config }; + Driver::Root root { env, sliced_heap, + config, devices }; + + Main(Genode::Env & e) + : env(e) + { + devices.update(config.xml()); + config.sigh(config_handler); + env.parent().announce(env.ep().manage(root)); + } +}; + + +void Driver::Main::update_config() +{ + config.update(); + devices.update(config.xml()); + root.update_policy(); +} + +void Component::construct(Genode::Env &env) { + static Driver::Main main(env); } diff --git a/repos/os/src/drivers/platform/rpi/power_domains.h b/repos/os/src/drivers/platform/rpi/power_domains.h new file mode 100644 index 0000000000..dd971976a9 --- /dev/null +++ b/repos/os/src/drivers/platform/rpi/power_domains.h @@ -0,0 +1,67 @@ +/* + * \brief Platform driver for Raspberry Pi 1 + * \author Stefan Kalkowski + * \date 2021-12-06 + */ + +/* + * Copyright (C) 2021 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. + */ + +#include +#include +#include +#include + +namespace Driver { struct Power_domains; } + + +struct Driver::Power_domains +{ + struct Domain : Driver::Power + { + Mbox & mbox; + unsigned const id; + + Domain(Powers & powers, + Power::Name name, + Mbox & mbox, + unsigned id) + : + Power(powers, name), mbox(mbox), id(id) {} + + void _on() override + { + auto & msg = mbox.message(); + msg.append_no_response(id, + true, + true); + mbox.call(); + } + + void _off() override + { + auto & msg = mbox.message(); + msg.append_no_response(id, + false, + true); + mbox.call(); + } + }; + + Powers & powers; + Mbox & mbox; + + Domain sdhci { powers, "sdhci", mbox, 0 }; + Domain uart_0 { powers, "uart_0", mbox, 1 }; + Domain uart_1 { powers, "uart_1", mbox, 2 }; + Domain usb { powers, "usb", mbox, 3 }; + Domain i2c_0 { powers, "i2c_0", mbox, 4 }; + Domain i2c_1 { powers, "i2c_1", mbox, 5 }; + Domain i2c_2 { powers, "i2c_2", mbox, 6 }; + Domain spi { powers, "spi", mbox, 7 }; + Domain ccp2tx { powers, "ccp2tx", mbox, 8 }; +}; diff --git a/repos/os/src/drivers/platform/rpi/rpi_device.cc b/repos/os/src/drivers/platform/rpi/rpi_device.cc deleted file mode 100644 index bbf7f359f3..0000000000 --- a/repos/os/src/drivers/platform/rpi/rpi_device.cc +++ /dev/null @@ -1,72 +0,0 @@ -/* - * \brief Platform driver - Device abstraction for rpi - * \author Stefan Kalkowski - * \date 2020-08-17 - */ - -/* - * 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. - */ - -#include -#include -#include -#include - - -unsigned Driver::Rpi_device::Power_domain::id() -{ - if (name == "sdhci") { return 0; } - if (name == "uart_0") { return 1; } - if (name == "uart_1") { return 2; } - if (name == "usb") { return 3; } - if (name == "i2c_0") { return 4; } - if (name == "i2c_1") { return 5; } - if (name == "i2c_2") { return 6; } - if (name == "spi") { return 7; } - if (name == "ccp2tx") { return 8; } - - warning("Invalid power-domain ", name); - return ~0U; -}; - - -void Driver::Rpi_device::acquire(Driver::Session_component & sc) -{ - Driver::Device::acquire(sc); - - _power_domain_list.for_each([&] (Power_domain & p) { - auto & msg = sc.env().mbox.message(); - msg.append_no_response(p.id(), - true, - true); - sc.env().mbox.call(); - }); -} - - -void Driver::Rpi_device::release(Session_component & sc) -{ - _power_domain_list.for_each([&] (Power_domain & p) { - auto & msg = sc.env().mbox.message(); - msg.append_no_response(p.id(), - true, - true); - sc.env().mbox.call(); - }); - - return Driver::Device::release(sc); -} - - -void Driver::Rpi_device::_report_platform_specifics(Genode::Xml_generator &, - Driver::Session_component &) -{ - /* - * Normally, the platform driver should report about clock settings of the - * device etc. here. But we do not implement clocking for RPI yet. - */ -} diff --git a/repos/os/src/drivers/platform/rpi/rpi_device.h b/repos/os/src/drivers/platform/rpi/rpi_device.h deleted file mode 100644 index fe738fd16c..0000000000 --- a/repos/os/src/drivers/platform/rpi/rpi_device.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * \brief Platform driver - Device abstraction for rpi - * \author Stefan Kalkowski - * \date 2020-08-20 - */ - -/* - * 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. - */ - -#ifndef _SRC__DRIVERS__PLATFORM__IMX8MQ__RPI_DEVICE_H_ -#define _SRC__DRIVERS__PLATFORM__IMX8MQ__RPI_DEVICE_H_ - -#include - -namespace Driver { - using namespace Genode; - - class Rpi_device; - struct Power_domain_update_policy; -} - - -class Driver::Rpi_device : public Driver::Device -{ - public: - - struct Power_domain : List_model::Element - { - using Name = Genode::String<64>; - - Name name; - - Power_domain(Name name) : name(name) {} - - unsigned id(); - }; - - void acquire(Session_component &) override; - void release(Session_component &) override; - - Rpi_device(Device::Name name, Device::Type type) - : Device(name, type) {} - - protected: - - friend class Driver::Device_model; - friend class List_model; - - void _report_platform_specifics(Xml_generator &, - Session_component &) override; - - List_model _power_domain_list {}; -}; - - -struct Driver::Power_domain_update_policy -: Genode::List_model::Update_policy -{ - Genode::Allocator & alloc; - - Power_domain_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} - - void destroy_element(Element & pd) { - Genode::destroy(alloc, &pd); } - - Element & create_element(Genode::Xml_node node) - { - Element::Name name = node.attribute_value("name", Element::Name()); - return *(new (alloc) Element(name)); - } - - void update_element(Element &, Genode::Xml_node) {} - - static bool element_matches_xml_node(Element const & pd, Genode::Xml_node node) - { - Element::Name name = node.attribute_value("name", Element::Name()); - return name == pd.name; - } - - static bool node_is_element(Genode::Xml_node node) - { - return node.has_type("power-domain"); - } -}; - -#endif /* _SRC__DRIVERS__PLATFORM__IMX8MQ__RPI_DEVICE_H_ */ diff --git a/repos/os/src/drivers/platform/rpi/target.mk b/repos/os/src/drivers/platform/rpi/target.mk index ad6ee86253..3091093746 100644 --- a/repos/os/src/drivers/platform/rpi/target.mk +++ b/repos/os/src/drivers/platform/rpi/target.mk @@ -3,12 +3,11 @@ REQUIRES = arm_v6 SRC_CC = device.cc SRC_CC += device_component.cc SRC_CC += device_model_policy.cc -SRC_CC += rpi_device.cc SRC_CC += main.cc SRC_CC += session_component.cc SRC_CC += root.cc INC_DIR = $(PRG_DIR) $(REP_DIR)/src/drivers/platform/spec/arm LIBS = base -vpath %.cc $(PRG_DIR) -vpath %.cc $(REP_DIR)/src/drivers/platform/spec/arm +vpath main.cc $(PRG_DIR) +vpath %.cc $(REP_DIR)/src/drivers/platform/spec/arm diff --git a/repos/os/src/drivers/platform/spec/arm/clock.h b/repos/os/src/drivers/platform/spec/arm/clock.h new file mode 100644 index 0000000000..13328456b7 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/clock.h @@ -0,0 +1,107 @@ +/* + * \brief Clock interface for platform driver + * \author Stefan Kalkowski + * \author Norman Feske + * \date 2020-06-12 + */ + +/* + * Copyright (C) 2020-2021 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 _CLOCK_H_ +#define _CLOCK_H_ + +#include +#include + +namespace Driver { + + using namespace Genode; + + class Clock; + class Fixed_clock; + class Fixed_divider; + + using Clocks = Named_registry; +} + + +class Driver::Clock : Clocks::Element, Interface +{ + private: + + /* friendships needed to make 'Clocks::Element' private */ + friend class Clocks::Element; + friend class Avl_node; + friend class Avl_tree; + + Switch _switch { *this, &Clock::_enable, &Clock::_disable }; + + protected: + + virtual void _enable() { } + virtual void _disable() { } + + public: + + using Name = Clocks::Element::Name; + using Clocks::Element::name; + using Clocks::Element::Element; + + struct Rate { unsigned long value; }; + + virtual void rate(Rate) { } + virtual Rate rate() const { return Rate { }; } + virtual void parent(Name) { } + + void enable() { _switch.use(); } + void disable() { _switch.unuse(); } +}; + + +class Driver::Fixed_clock : public Driver::Clock +{ + private: + + Rate const _rate; + + public: + + Fixed_clock(Clocks &clocks, Name const &name, Rate rate) + : + Clock(clocks, name), _rate(rate) + { } + + Rate rate() const override { return _rate; } +}; + + +class Driver::Fixed_divider : public Driver::Clock +{ + private: + + Clock &_parent; + + unsigned const _divider; + + public: + + Fixed_divider(Clocks &clocks, + Name const &name, + Clock &parent, + unsigned divider) + : + Clock(clocks, name), _parent(parent), _divider(divider) + { } + + Rate rate() const override + { + return Rate { _parent.rate().value / _divider }; + } +}; + +#endif /* _CLOCK_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/device.cc b/repos/os/src/drivers/platform/spec/arm/device.cc index 216267d11e..83d47a40e6 100644 --- a/repos/os/src/drivers/platform/spec/arm/device.cc +++ b/repos/os/src/drivers/platform/spec/arm/device.cc @@ -29,12 +29,81 @@ Driver::Device::Type Driver::Device::type() const { return _type; } Driver::Device::Owner Driver::Device::owner() const { return _owner; } -void Driver::Device::acquire(Session_component & sc) { - if (!_owner.valid()) _owner = sc; } +void Driver::Device::acquire(Session_component & sc) +{ + if (!_owner.valid()) _owner = sc; + + _power_domain_list.for_each([&] (Power_domain & p) { + + bool ok = false; + sc.devices().powers().apply(p.name, [&] (Driver::Power &power) { + power.on(); + ok = true; + }); + + if (!ok) + warning("power domain ", p.name, " is unknown"); + }); + + _reset_domain_list.for_each([&] (Reset_domain & r) { + + bool ok = false; + sc.devices().resets().apply(r.name, [&] (Driver::Reset &reset) { + reset.deassert(); + ok = true; + }); + + if (!ok) + warning("reset domain ", r.name, " is unknown"); + }); + + _clock_list.for_each([&] (Clock &c) { + + bool ok = false; + sc.devices().clocks().apply(c.name, [&] (Driver::Clock &clock) { + + if (c.parent.valid()) + clock.parent(c.parent); + + if (c.rate) + clock.rate(Driver::Clock::Rate { c.rate }); + + clock.enable(); + ok = true; + }); + + if (!ok) { + warning("clock ", c.name, " is unknown"); + return; + } + }); + + sc.update_devices_rom(); +} -void Driver::Device::release(Session_component & sc) { - if (_owner == sc) _owner = Owner();; } +void Driver::Device::release(Session_component & sc) +{ + _reset_domain_list.for_each([&] (Reset_domain & r) + { + sc.devices().resets().apply(r.name, [&] (Driver::Reset &reset) { + reset.assert(); }); + }); + + _power_domain_list.for_each([&] (Power_domain & p) + { + sc.devices().powers().apply(p.name, [&] (Driver::Power &power) { + power.off(); }); + }); + + _clock_list.for_each([&] (Clock & c) + { + sc.devices().clocks().apply(c.name, [&] (Driver::Clock &clock) { + clock.disable(); }); + }); + + if (_owner == sc) _owner = Owner(); +} void Driver::Device::report(Xml_generator & xml, Session_component & sc) @@ -59,6 +128,15 @@ void Driver::Device::report(Xml_generator & xml, Session_component & sc) xml.attribute("value", p.value); }); }); + _clock_list.for_each([&] (Clock &c) { + sc.devices().clocks().apply(c.name, [&] (Driver::Clock &clock) { + xml.node("clock", [&] () { + xml.attribute("rate", clock.rate().value); + xml.attribute("name", c.driver_name); + }); + }); + }); + _report_platform_specifics(xml, sc); }); } diff --git a/repos/os/src/drivers/platform/spec/arm/device.h b/repos/os/src/drivers/platform/spec/arm/device.h index f4bf840a89..17772775e0 100644 --- a/repos/os/src/drivers/platform/spec/arm/device.h +++ b/repos/os/src/drivers/platform/spec/arm/device.h @@ -15,23 +15,30 @@ #define _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ #include +#include #include #include #include #include #include +#include +#include +#include + namespace Driver { using namespace Genode; - class Env; class Device; struct Device_model; class Session_component; struct Irq_update_policy; struct Io_mem_update_policy; struct Property_update_policy; + struct Clock_update_policy; + struct Reset_domain_update_policy; + struct Power_domain_update_policy; } @@ -83,6 +90,41 @@ class Driver::Device : private List_model::Element : name(name), value(value) {} }; + struct Clock : List_model::Element + { + using Name = Genode::String<64>; + + Name name; + Name parent; + Name driver_name; + unsigned long rate; + + Clock(Name name, + Name parent, + Name driver_name, + unsigned long rate) + : name(name), parent(parent), + driver_name(driver_name), rate(rate) {} + }; + + struct Power_domain : List_model::Element + { + using Name = Genode::String<64>; + + Name name; + + Power_domain(Name name) : name(name) {} + }; + + struct Reset_domain : List_model::Element + { + using Name = Genode::String<64>; + + Name name; + + Reset_domain(Name name) : name(name) {} + }; + Device(Name name, Type type); virtual ~Device(); @@ -118,12 +160,15 @@ class Driver::Device : private List_model::Element friend class List_model; friend class List; - Name _name; - Type _type; - Owner _owner {}; - List_model _io_mem_list {}; - List_model _irq_list {}; - List_model _property_list {}; + Name _name; + Type _type; + Owner _owner {}; + List_model _io_mem_list {}; + List_model _irq_list {}; + List_model _property_list {}; + List_model _clock_list {}; + List_model _power_domain_list {}; + List_model _reset_domain_list {}; /* * Noncopyable @@ -138,8 +183,11 @@ class Driver::Device_model : { private: - Driver::Env & _env; - List_model _model {}; + Heap & _heap; + List_model _model { }; + Clocks _clocks { }; + Resets _resets { }; + Powers _powers { }; public: @@ -147,8 +195,8 @@ class Driver::Device_model : _model.update_from_xml(*this, node); } - Device_model(Driver::Env & env) - : _env(env) { } + Device_model(Heap & heap) + : _heap(heap) { } ~Device_model() { _model.destroy_all_elements(*this); } @@ -173,6 +221,10 @@ class Driver::Device_model : static bool node_is_element(Genode::Xml_node node) { return node.has_type("device"); } + + Clocks & clocks() { return _clocks; }; + Resets & resets() { return _resets; }; + Powers & powers() { return _powers; }; }; @@ -267,4 +319,101 @@ struct Driver::Property_update_policy : Genode::List_model::Up return node.has_type("property"); } }; + +struct Driver::Clock_update_policy +: Genode::List_model::Update_policy +{ + Genode::Allocator & alloc; + + Clock_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} + + void destroy_element(Element & clock) { + Genode::destroy(alloc, &clock); } + + Element & create_element(Genode::Xml_node node) + { + Element::Name name = node.attribute_value("name", Element::Name()); + Element::Name parent = node.attribute_value("parent", Element::Name()); + Element::Name driver = node.attribute_value("driver_name", Element::Name()); + unsigned long rate = node.attribute_value("rate", 0); + return *(new (alloc) Element(name, parent, driver, rate)); + } + + void update_element(Element &, Genode::Xml_node) {} + + static bool element_matches_xml_node(Element const & clock, Genode::Xml_node node) + { + Element::Name name = node.attribute_value("name", Element::Name()); + Element::Name driver_name = node.attribute_value("driver_name", Element::Name()); + return name == clock.name && driver_name == clock.driver_name; + } + + static bool node_is_element(Genode::Xml_node node) + { + return node.has_type("clock"); + } +}; + + +struct Driver::Power_domain_update_policy +: Genode::List_model::Update_policy +{ + Genode::Allocator & alloc; + + Power_domain_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} + + void destroy_element(Element & pd) { + Genode::destroy(alloc, &pd); } + + Element & create_element(Genode::Xml_node node) + { + Element::Name name = node.attribute_value("name", Element::Name()); + return *(new (alloc) Element(name)); + } + + void update_element(Element &, Genode::Xml_node) {} + + static bool element_matches_xml_node(Element const & pd, Genode::Xml_node node) + { + Element::Name name = node.attribute_value("name", Element::Name()); + return name == pd.name; + } + + static bool node_is_element(Genode::Xml_node node) + { + return node.has_type("power-domain"); + } +}; + + +struct Driver::Reset_domain_update_policy +: Genode::List_model::Update_policy +{ + Genode::Allocator & alloc; + + Reset_domain_update_policy(Genode::Allocator & alloc) : alloc(alloc) {} + + void destroy_element(Element & pd) { + Genode::destroy(alloc, &pd); } + + Element & create_element(Genode::Xml_node node) + { + Element::Name name = node.attribute_value("name", Element::Name()); + return *(new (alloc) Element(name)); + } + + void update_element(Element &, Genode::Xml_node) {} + + static bool element_matches_xml_node(Element const & pd, Genode::Xml_node node) + { + Element::Name name = node.attribute_value("name", Element::Name()); + return name == pd.name; + } + + static bool node_is_element(Genode::Xml_node node) + { + return node.has_type("reset-domain"); + } +}; + #endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__DEVICE_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/device_component.cc b/repos/os/src/drivers/platform/spec/arm/device_component.cc index f4ac1c7751..c8e3cb5fa1 100644 --- a/repos/os/src/drivers/platform/spec/arm/device_component.cc +++ b/repos/os/src/drivers/platform/spec/arm/device_component.cc @@ -48,7 +48,7 @@ Device_component::io_mem(unsigned idx, Range &range, Cache cache) return; if (!iomem.io_mem.constructed()) - iomem.io_mem.construct(_session.env().env, + iomem.io_mem.construct(_session.env(), iomem.range.start, iomem.range.size, cache == WRITE_COMBINED); @@ -72,7 +72,7 @@ Genode::Irq_session_capability Device_component::irq(unsigned idx) return; if (!irq.irq.constructed()) - irq.irq.construct(_session.env().env, irq.number); + irq.irq.construct(_session.env(), irq.number); cap = irq.irq->cap(); }); diff --git a/repos/os/src/drivers/platform/spec/arm/device_component.h b/repos/os/src/drivers/platform/spec/arm/device_component.h index 1c045bded0..6998cd8ed8 100644 --- a/repos/os/src/drivers/platform/spec/arm/device_component.h +++ b/repos/os/src/drivers/platform/spec/arm/device_component.h @@ -22,7 +22,6 @@ #include #include -#include #include namespace Driver { diff --git a/repos/os/src/drivers/platform/spec/arm/device_model_policy.cc b/repos/os/src/drivers/platform/spec/arm/device_model_policy.cc index 9442a8c895..bb72ab98b2 100644 --- a/repos/os/src/drivers/platform/spec/arm/device_model_policy.cc +++ b/repos/os/src/drivers/platform/spec/arm/device_model_policy.cc @@ -11,7 +11,6 @@ * under the terms of the GNU Affero General Public License version 3. */ -#include #include using Driver::Device_model; @@ -20,21 +19,36 @@ using Driver::Device; void Device_model::destroy_element(Device & device) { { - Irq_update_policy policy(_env.heap); + Irq_update_policy policy(_heap); device._irq_list.destroy_all_elements(policy); } { - Io_mem_update_policy policy(_env.heap); + Io_mem_update_policy policy(_heap); device._io_mem_list.destroy_all_elements(policy); } { - Property_update_policy policy(_env.heap); + Property_update_policy policy(_heap); device._property_list.destroy_all_elements(policy); } - Genode::destroy(_env.heap, &device); + { + Clock_update_policy policy(_heap); + device._clock_list.destroy_all_elements(policy); + } + + { + Power_domain_update_policy policy(_heap); + device._power_domain_list.destroy_all_elements(policy); + } + + { + Reset_domain_update_policy policy(_heap); + device._reset_domain_list.destroy_all_elements(policy); + } + + Genode::destroy(_heap, &device); } @@ -42,7 +56,7 @@ Device & Device_model::create_element(Genode::Xml_node node) { Device::Name name = node.attribute_value("name", Device::Name()); Device::Type type = node.attribute_value("type", Device::Type()); - return *(new (_env.heap) Device(name, type)); + return *(new (_heap) Device(name, type)); } @@ -50,17 +64,32 @@ void Device_model::update_element(Device & device, Genode::Xml_node node) { { - Irq_update_policy policy(_env.heap); + Irq_update_policy policy(_heap); device._irq_list.update_from_xml(policy, node); } { - Io_mem_update_policy policy(_env.heap); + Io_mem_update_policy policy(_heap); device._io_mem_list.update_from_xml(policy, node); } { - Property_update_policy policy(_env.heap); + Property_update_policy policy(_heap); device._property_list.update_from_xml(policy, node); } + + { + Clock_update_policy policy(_heap); + device._clock_list.update_from_xml(policy, node); + } + + { + Power_domain_update_policy policy(_heap); + device._power_domain_list.update_from_xml(policy, node); + } + + { + Reset_domain_update_policy policy(_heap); + device._reset_domain_list.update_from_xml(policy, node); + } } diff --git a/repos/os/src/drivers/platform/spec/arm/env.h b/repos/os/src/drivers/platform/spec/arm/env.h deleted file mode 100644 index 95e53abaec..0000000000 --- a/repos/os/src/drivers/platform/spec/arm/env.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * \brief Platform driver for ARM - * \author Stefan Kalkowski - * \date 2020-04-12 - */ - -/* - * 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. - */ - -#ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__ENV_H_ -#define _SRC__DRIVERS__PLATFORM__SPEC__ARM__ENV_H_ - -#include -#include -#include - -#include - -namespace Driver { - using namespace Genode; - - struct Env; -}; - - -struct Driver::Env -{ - Genode::Env & env; - Heap heap { env.ram(), env.rm() }; - Sliced_heap sliced_heap { env.ram(), env.rm() }; - Attached_rom_dataspace config { env, "config" }; - Device_model devices { *this }; - - Env(Genode::Env &env) : env(env) {} -}; - -#endif /* _SRC__DRIVERS__PLATFORM__SPEC__ARM__ENV_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/main.cc b/repos/os/src/drivers/platform/spec/arm/main.cc index 6a04c2885b..71c3b0442f 100644 --- a/repos/os/src/drivers/platform/spec/arm/main.cc +++ b/repos/os/src/drivers/platform/spec/arm/main.cc @@ -12,7 +12,6 @@ */ #include -#include #include namespace Driver { struct Main; }; @@ -21,25 +20,29 @@ struct Driver::Main { void update_config(); - Driver::Env env; - Signal_handler
config_handler { env.env.ep(), *this, + Env & env; + Heap heap { env.ram(), env.rm() }; + Sliced_heap sliced_heap { env.ram(), env.rm() }; + Attached_rom_dataspace config { env, "config" }; + Device_model devices { heap }; + Signal_handler
config_handler { env.ep(), *this, &Main::update_config }; - Driver::Root root { env }; + Driver::Root root { env, sliced_heap, config, devices }; Main(Genode::Env & e) : env(e) { - env.devices.update(env.config.xml()); - env.config.sigh(config_handler); - env.env.parent().announce(env.env.ep().manage(root)); + devices.update(config.xml()); + config.sigh(config_handler); + env.parent().announce(env.ep().manage(root)); } }; void Driver::Main::update_config() { - env.config.update(); - env.devices.update(env.config.xml()); + config.update(); + devices.update(config.xml()); root.update_policy(); } diff --git a/repos/os/src/drivers/platform/spec/arm/named_registry.h b/repos/os/src/drivers/platform/spec/arm/named_registry.h new file mode 100644 index 0000000000..5a00135c61 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/named_registry.h @@ -0,0 +1,90 @@ +/* + * \brief Utility for finding objecs by name + * \author Norman Feske + * \date 2021-11-11 + */ + +/* + * Copyright (C) 2021 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 _NAMED_REGISTRY_H_ +#define _NAMED_REGISTRY_H_ + +#include +#include +#include + +namespace Driver { template class Named_registry; } + + +template +class Driver::Named_registry : Noncopyable +{ + private: + + Avl_tree _tree { }; + + public: + + class Element : private Avl_node + { + public: + + using Name = Genode::String<64>; + Name const name; + + private: + + Named_registry &_registry; + + bool higher(T const *other) const { return name > other->name; } + + friend class Avl_tree; + friend class Avl_node; + friend class Named_registry; + + static T *_matching_sub_tree(T &curr, Name const &name) + { + typename Avl_node::Side side = (curr.name > name); + + return curr.Avl_node::child(side); + } + + public: + + Element(Named_registry ®istry, Name const &name) + : + name(name), _registry(registry) + { + _registry._tree.insert(this); + } + + ~Element() + { + _registry._tree.remove(this); + } + }; + + template + void apply(typename Element::Name const &name, FN const &fn) + { + T *curr_ptr = _tree.first(); + for (;;) { + if (!curr_ptr) + return; + + if (curr_ptr->name == name) { + fn(*curr_ptr); + return; + } + + curr_ptr = Element::_matching_sub_tree(*curr_ptr, name); + } + } +}; + +#endif /* _NAMED_REGISTRY_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/power.h b/repos/os/src/drivers/platform/spec/arm/power.h new file mode 100644 index 0000000000..b35b1ce5d5 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/power.h @@ -0,0 +1,56 @@ +/* + * \brief Power-domain interface + * \author Norman Feske + * \date 2021-11-18 + */ + +/* + * Copyright (C) 2021 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 _POWER_H_ +#define _POWER_H_ + +#include +#include + +namespace Driver { + + using namespace Genode; + + struct Power; + + using Powers = Named_registry; +} + + +class Driver::Power : Powers::Element, Interface +{ + private: + + /* friendships needed to make 'Powers::Element' private */ + friend class Powers::Element; + friend class Avl_node; + friend class Avl_tree; + + Switch _switch { *this, &Power::_on, &Power::_off }; + + protected: + + virtual void _on() { } + virtual void _off() { } + + public: + + using Name = Powers::Element::Name; + using Powers::Element::name; + using Powers::Element::Element; + + void on() { _switch.use(); } + void off() { _switch.unuse(); } +}; + +#endif /* _POWER_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/reset.h b/repos/os/src/drivers/platform/spec/arm/reset.h new file mode 100644 index 0000000000..f7e85b9264 --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/reset.h @@ -0,0 +1,56 @@ +/* + * \brief Reset-domain interface + * \author Norman Feske + * \date 2021-11-03 + */ + +/* + * Copyright (C) 2021 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 _RESET_H_ +#define _RESET_H_ + +#include +#include + +namespace Driver { + + using namespace Genode; + + struct Reset; + + using Resets = Named_registry; +} + + +class Driver::Reset : Resets::Element, Interface +{ + private: + + /* friendships needed to make 'Resets::Element' private */ + friend class Resets::Element; + friend class Avl_node; + friend class Avl_tree; + + Switch _switch { *this, &Reset::_deassert, &Reset::_assert }; + + protected: + + virtual void _deassert() { } + virtual void _assert() { } + + public: + + using Name = Resets::Element::Name; + using Resets::Element::name; + using Resets::Element::Element; + + void deassert() { _switch.use(); } + void assert() { _switch.unuse(); } +}; + +#endif /* _RESET_H_ */ diff --git a/repos/os/src/drivers/platform/spec/arm/root.cc b/repos/os/src/drivers/platform/spec/arm/root.cc index f1c90503a4..ccd18bebc9 100644 --- a/repos/os/src/drivers/platform/spec/arm/root.cc +++ b/repos/os/src/drivers/platform/spec/arm/root.cc @@ -20,7 +20,7 @@ void Driver::Root::update_policy() _sessions.for_each([&] (Session_component & sc) { try { - Session_policy const policy { sc._label, _env.config.xml() }; + Session_policy const policy { sc._label, _config.xml() }; sc.update_policy(policy.attribute_value("info", false), policy.attribute_value("version", Version())); } @@ -39,10 +39,10 @@ Driver::Session_component * Driver::Root::_create_session(const char *args) try { Session::Label const label { session_label_from_args(args) }; - Session_policy const policy { label, _env.config.xml() }; + Session_policy const policy { label, _config.xml() }; sc = new (md_alloc()) - Session_component(_env, _sessions, label, + Session_component(_env, _config, _devices, _sessions, label, session_resources_from_args(args), session_diag_from_args(args), policy.attribute_value("info", false), @@ -67,6 +67,9 @@ void Driver::Root::_upgrade_session(Session_component * sc, const char * args) } -Driver::Root::Root(Driver::Env & env) -: Root_component(env.env.ep(), env.sliced_heap), - _env(env) { } +Driver::Root::Root(Env & env, + Sliced_heap & sliced_heap, + Attached_rom_dataspace & config, + Device_model & devices) +: Root_component(env.ep(), sliced_heap), + _env(env), _config(config), _devices(devices) { } diff --git a/repos/os/src/drivers/platform/spec/arm/root.h b/repos/os/src/drivers/platform/spec/arm/root.h index 56644ddeb2..a5f964e713 100644 --- a/repos/os/src/drivers/platform/spec/arm/root.h +++ b/repos/os/src/drivers/platform/spec/arm/root.h @@ -27,7 +27,10 @@ class Driver::Root : public Root_component { public: - Root(Driver::Env & env); + Root(Env & env, + Sliced_heap & sliced_heap, + Attached_rom_dataspace & config, + Device_model & devices); void update_policy(); @@ -37,7 +40,9 @@ class Driver::Root : public Root_component void _upgrade_session(Session_component *, const char *) override; - Driver::Env & _env; + Env & _env; + Attached_rom_dataspace & _config; + Device_model & _devices; Registry _sessions {}; }; diff --git a/repos/os/src/drivers/platform/spec/arm/session_component.cc b/repos/os/src/drivers/platform/spec/arm/session_component.cc index 08fd2fd840..21ab0be9f4 100644 --- a/repos/os/src/drivers/platform/spec/arm/session_component.cc +++ b/repos/os/src/drivers/platform/spec/arm/session_component.cc @@ -25,17 +25,17 @@ Session_component::_acquire(Device & device) Device_component * dc = new (heap()) Device_component(_device_registry, *this, device); device.acquire(*this); - return _env.env.ep().rpc_ep().manage(dc); + return _env.ep().rpc_ep().manage(dc); }; void Session_component::_release_device(Device_component & dc) { Device::Name name = dc.device(); - _env.env.ep().rpc_ep().dissolve(&dc); + _env.ep().rpc_ep().dissolve(&dc); destroy(heap(), &dc); - _env.devices.for_each([&] (Device & dev) { + _devices.for_each([&] (Device & dev) { if (name == dev.name()) dev.release(*this); }); } @@ -53,7 +53,7 @@ bool Session_component::matches(Device & dev) const bool ret = false; try { - Session_policy const policy { label(), _env.config.xml() }; + Session_policy const policy { label(), _config.xml() }; policy.for_each_sub_node("device", [&] (Xml_node node) { if (dev.name() == node.attribute_value("name", Device::Name())) ret = true; @@ -73,7 +73,7 @@ void Session_component::update_policy(bool info, Policy_version version) _device_registry.for_each([&] (Device_component & dc) { Device_state state = AWAY; - _env.devices.for_each([&] (Device & dev) { + _devices.for_each([&] (Device & dev) { if (dev.name() != dc.device()) return; state = (dev.owner() == _owner_id) ? UNCHANGED : CHANGED; @@ -103,17 +103,20 @@ void Session_component::produce_xml(Xml_generator &xml) if (_version.valid()) xml.attribute("version", _version); - _env.devices.for_each([&] (Device & dev) { + _devices.for_each([&] (Device & dev) { if (matches(dev)) dev.report(xml, *this); }); } +Genode::Env & Session_component::env() { return _env; } + + +Driver::Device_model & Session_component::devices() { return _devices; } + + Genode::Heap & Session_component::heap() { return _md_alloc; } -Driver::Env & Session_component::env() { return _env; } - - void Session_component::update_devices_rom() { _rom_session.trigger_update(); @@ -138,7 +141,7 @@ Session_component::acquire_device(Platform::Session::Device_name const &name) if (cap.valid()) return cap; - _env.devices.for_each([&] (Device & dev) + _devices.for_each([&] (Device & dev) { if (dev.name() != name || !matches(dev)) return; @@ -164,7 +167,7 @@ Session_component::acquire_single_device() if (cap.valid()) return cap; - _env.devices.for_each([&] (Device & dev) { + _devices.for_each([&] (Device & dev) { if (matches(dev) && !dev.owner().valid()) cap = _acquire(dev); }); @@ -231,18 +234,20 @@ Genode::addr_t Session_component::dma_addr(Ram_dataspace_capability ram_cap) } -Session_component::Session_component(Driver::Env & env, - Session_registry & registry, - Label const & label, - Resources const & resources, - Diag const & diag, - bool const info, - Policy_version const version) +Session_component::Session_component(Env & env, + Attached_rom_dataspace & config, + Device_model & devices, + Session_registry & registry, + Label const & label, + Resources const & resources, + Diag const & diag, + bool const info, + Policy_version const version) : - Session_object(env.env.ep(), resources, label, diag), + Session_object(env.ep(), resources, label, diag), Session_registry::Element(registry, *this), Dynamic_rom_session::Xml_producer("devices"), - _env(env), _info(info), _version(version) + _env(env), _config(config), _devices(devices), _info(info), _version(version) { /* * FIXME: As the ROM session does not propagate Out_of_* diff --git a/repos/os/src/drivers/platform/spec/arm/session_component.h b/repos/os/src/drivers/platform/spec/arm/session_component.h index 76f25a533a..c4e6185011 100644 --- a/repos/os/src/drivers/platform/spec/arm/session_component.h +++ b/repos/os/src/drivers/platform/spec/arm/session_component.h @@ -14,6 +14,7 @@ #ifndef _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_ #define _SRC__DRIVERS__PLATFORM__SPEC__ARM__SESSION_COMPONENT_H_ +#include #include #include #include @@ -42,18 +43,21 @@ class Driver::Session_component using Session_registry = Registry; using Policy_version = String<64>; - Session_component(Driver::Env & env, - Session_registry & registry, - Label const & label, - Resources const & resources, - Diag const & diag, - bool const info, - Policy_version const version); + Session_component(Env & env, + Attached_rom_dataspace & config, + Device_model & devices, + Session_registry & registry, + Label const & label, + Resources const & resources, + Diag const & diag, + bool const info, + Policy_version const version); ~Session_component(); + Env & env(); Heap & heap(); - Driver::Env & env(); + Device_model & devices(); bool matches(Device &) const; void update_devices_rom(); @@ -92,16 +96,18 @@ class Driver::Session_component : Registry::Element(registry, *this), cap(cap) {} }; - Driver::Env & _env; + Env & _env; + Attached_rom_dataspace & _config; + Device_model & _devices; Device::Owner _owner_id { *this }; - Constrained_ram_allocator _env_ram { _env.env.pd(), + Constrained_ram_allocator _env_ram { _env.pd(), _ram_quota_guard(), _cap_quota_guard() }; - Heap _md_alloc { _env_ram, _env.env.rm() }; + Heap _md_alloc { _env_ram, _env.rm() }; Registry _device_registry { }; Registry _buffer_registry { }; - Dynamic_rom_session _rom_session { _env.env.ep(), _env.env.ram(), - _env.env.rm(), *this }; + Dynamic_rom_session _rom_session { _env.ep(), _env.ram(), + _env.rm(), *this }; bool _info; Policy_version _version; diff --git a/repos/os/src/drivers/platform/spec/arm/types.h b/repos/os/src/drivers/platform/spec/arm/types.h new file mode 100644 index 0000000000..788aac18ee --- /dev/null +++ b/repos/os/src/drivers/platform/spec/arm/types.h @@ -0,0 +1,73 @@ +/* + * \brief Common types used by the platform driver + * \author Norman Feske + * \date 2021-11-03 + */ + +/* + * Copyright (C) 2021 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 _TYPES_H_ +#define _TYPES_H_ + +#include + +namespace Driver { + + using namespace Genode; + + template + static inline bool operator > (String const &s1, String const &s2) + { + return strcmp(s1.string(), s2.string()) > 0; + } + + /** + * Utility for switching clocks/resets/powers on/off depending on the + * number of users + */ + template + class Switch : Noncopyable + { + private: + + unsigned _count = 0; + + DEV &_dev; + + void (DEV::*_activate) (); + void (DEV::*_deactivate) (); + + public: + + Switch(DEV &dev, void (DEV::*activate) (), void (DEV::*deactivate) ()) + : + _dev(dev), _activate(activate), _deactivate(deactivate) + { } + + void use() + { + if (_count == 0) + (_dev.*_activate)(); + + _count++; + } + + void unuse() + { + if (_count == 0) + return; + + _count--; + + if (--_count == 0) + (_dev.*_deactivate)(); + } + }; +} + +#endif /* _TYPES_H_ */