imx8mq_platform_drv: introduce reset domains

A reset domain can consist of one or several reset-pins
denoted by name that are assigned to a device.
When the device gets acquired via the Platform RPC API,
the pins are de-asserted, and asserted again when the
device gets released.

A configuration looks like the following:

  <device name="mipi_dsi>
    <reset-domain name="mipi_dsi_pclk"/>
    ...
  </device>

Fixes #4171
This commit is contained in:
Stefan Kalkowski 2021-05-25 14:19:37 +02:00 committed by Christian Helmuth
parent ed7d6c74f4
commit 7f6f710bd2
5 changed files with 116 additions and 0 deletions

View File

@ -47,6 +47,11 @@ void Device_model::destroy_element(Device & dev)
device._power_domain_list.destroy_all_elements(policy);
}
{
Reset_domain_update_policy policy(_env.heap);
device._reset_domain_list.destroy_all_elements(policy);
}
Genode::destroy(_env.heap, &device);
}
@ -88,4 +93,9 @@ void Device_model::update_element(Device & dev,
Power_domain_update_policy policy(_env.heap);
device._power_domain_list.update_from_xml(policy, node);
}
{
Reset_domain_update_policy policy(_env.heap);
device._reset_domain_list.update_from_xml(policy, node);
}
}

View File

@ -20,6 +20,7 @@
#include <ccm.h>
#include <gpc.h>
#include <src.h>
#include <device.h>
namespace Driver {
@ -37,6 +38,7 @@ struct Driver::Env
Attached_rom_dataspace config { env, "config" };
Ccm ccm { env };
Gpc gpc { env };
Src src { env };
Device_model devices { *this };
Env(Genode::Env &env) : env(env) { }

View File

@ -23,6 +23,8 @@ bool Driver::Imx_device::acquire(Driver::Session_component & sc)
if (ret) {
_power_domain_list.for_each([&] (Power_domain & p) {
sc.env().gpc.enable(p.name); });
_reset_domain_list.for_each([&] (Reset_domain & r) {
sc.env().src.enable(r.name); });
_clock_list.for_each([&] (Clock & c) {
Avl_string_base * asb =
sc.env().ccm.tree.first()->find_by_name(c.name.string());
@ -46,6 +48,8 @@ bool Driver::Imx_device::acquire(Driver::Session_component & sc)
void Driver::Imx_device::release(Session_component & sc)
{
_reset_domain_list.for_each([&] (Reset_domain & r) {
sc.env().src.disable(r.name); });
_power_domain_list.for_each([&] (Power_domain & p) {
sc.env().gpc.disable(p.name); });
_clock_list.for_each([&] (Clock & c) {

View File

@ -22,6 +22,7 @@ namespace Driver {
class Imx_device;
struct Clock_update_policy;
struct Power_domain_update_policy;
struct Reset_domain_update_policy;
}
@ -55,6 +56,15 @@ class Driver::Imx_device : public Driver::Device
Power_domain(Name name) : name(name) {}
};
struct Reset_domain : List_model<Reset_domain>::Element
{
using Name = Genode::String<64>;
Name name;
Reset_domain(Name name) : name(name) {}
};
bool acquire(Session_component &) override;
void release(Session_component &) override;
@ -71,6 +81,7 @@ class Driver::Imx_device : public Driver::Device
List_model<Clock> _clock_list {};
List_model<Power_domain> _power_domain_list {};
List_model<Reset_domain> _reset_domain_list {};
};
@ -138,4 +149,35 @@ struct Driver::Power_domain_update_policy
}
};
struct Driver::Reset_domain_update_policy
: Genode::List_model<Imx_device::Reset_domain>::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__IMX8MQ__IMX_DEVICE_H_ */

View File

@ -0,0 +1,58 @@
/*
* \brief System reset controller for i.MX8
* \author Stefan Kalkowski
* \date 2021-05-21
*/
/*
* 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.
*/
#pragma once
#include <base/env.h>
#include <base/log.h>
#include <os/attached_mmio.h>
#include <util/string.h>
struct Src : Genode::Attached_mmio
{
struct Mipi_phy : Register<0x28, 32>
{
struct Byte : Bitfield<1, 1> {};
struct Reset : Bitfield<2, 1> {};
struct Dpi : Bitfield<3, 1> {};
struct Esc : Bitfield<4, 1> {};
struct Pclk : Bitfield<5, 1> {};
};
void enable(Genode::String<64> name)
{
if (name == "mipi_dsi_byte") { write<Mipi_phy::Byte>(1); return; }
if (name == "mipi_dsi_dpi") { write<Mipi_phy::Dpi>(1); return; }
if (name == "mipi_dsi_esc") { write<Mipi_phy::Esc>(1); return; }
if (name == "mipi_dsi_pclk") { write<Mipi_phy::Pclk>(1); return; }
warning("Reset domain ", name, " is unknown!");
}
void disable(Genode::String<64> name)
{
if (name == "mipi_dsi_byte") { write<Mipi_phy::Byte>(0); return; }
if (name == "mipi_dsi_dpi") { write<Mipi_phy::Dpi>(0); return; }
if (name == "mipi_dsi_esc") { write<Mipi_phy::Esc>(0); return; }
if (name == "mipi_dsi_pclk") { write<Mipi_phy::Pclk>(0); return; }
warning("Reset domain ", name, " is unknown!");
}
enum {
SRC_MMIO_BASE = 0x30390000,
SRC_MMIO_SIZE = 0x10000,
};
Src(Genode::Env & env)
: Attached_mmio(env, SRC_MMIO_BASE, SRC_MMIO_SIZE) { };
};