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