dde_linux: turn imx8_fb_drv into Platform client

* Requests its I/O resources and clock settings from the platform driver

Fix #3877
This commit is contained in:
Stefan Kalkowski 2020-09-03 16:03:08 +02:00 committed by Norman Feske
parent 5913cdae89
commit fd161cd814
5 changed files with 200 additions and 51 deletions

View File

@ -50,7 +50,46 @@
<property name="compatible" value="snps,dwc3"/>
<property name="dr_mode" value="host"/>
</device>
<device name="dcss">
<io_mem address="0x32e00000" size="0x30000"/>
<irq number="50"/>
<clock name="display_apb_clk_root"
driver_name="apb"/>
<clock name="display_axi_clk_root"
parent="system_pll1_clk"
rate="800000000"
driver_name="axi"/>
<clock name="display_rtrm_clk_root"
parent="system_pll1_clk"
rate="400000000"
driver_name="rtrm"/>
<clock name="video2_pll2_clk"
parent="27m_ref_clk"
driver_name="pix"/>
<clock name="display_dtrc_clk_root"
driver_name="dtrc"/>
<clock name="dc_pixel_clk_root"
parent="video_pll1_clk"
rate="594000000"/>
<property name="compatible" value="nxp,imx8mq-dcss"/>
<property name="disp-dev" value="hdmi_disp"/>
</device>
<device name="hdmi">
<io_mem address="0x32c00000" size="0x100000"/>
<io_mem address="0x32e40000" size="0x40000"/>
<io_mem address="0x32e2f000" size="0x10"/>
<irq number="48"/>
<irq number="57"/>
<property name="compatible" value="fsl,imx8mq-hdmi"/>
</device>
<policy label="usb_drv -> "> <device name="usb_host_2"/> </policy>
<policy label="fb_drv -> ">
<device name="dcss"/>
<device name="hdmi"/>
</policy>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
@ -94,6 +133,7 @@
<service name="LOG"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="Capture"> <parent/> </service>
<service name="Platform"> <child name="platform_drv"/> </service>
</route>
</start>

View File

@ -1748,6 +1748,26 @@ enum {
};
/*****************************
** IO resource definitions **
*****************************/
enum {
IOMEM_BASE_DCSS = 0x100000,
IOMEM_END_DCSS = 0x1fffff,
IOMEM_BASE_IRQSTEER = IOMEM_BASE_DCSS + 0x2d000,
IOMEM_END_IRQSTEER = IOMEM_BASE_IRQSTEER + 0xfff,
IOMEM_BASE_HDMI_CTRL = 0x200000,
IOMEM_END_HDMI_CTRL = 0x2fffff,
IOMEM_BASE_HDMI_CRS = 0x300000,
IOMEM_END_HDMI_CRS = 0x33ffff,
IOMEM_BASE_HDMI_RST = 0x340000,
IOMEM_END_HDMI_RST = 0x34000f,
IRQ_IRQSTEER = 32,
IRQ_HDMI_IN = 33,
IRQ_HDMI_OUT = 34
};
#include <lx_emul/extern_c_end.h>
#endif /* _LX_EMUL_H_ */

View File

@ -14,8 +14,8 @@
*/
/* Genode includes */
#include <base/attached_io_mem_dataspace.h>
#include <irq_session/connection.h>
#include <base/attached_dataspace.h>
#include <platform_session/connection.h>
/* local includes */
#include <driver.h>
@ -53,6 +53,41 @@
#include <lx_kit/malloc.h>
enum Device_id { DCSS, HDMI, UNKNOWN };
namespace Lx_kit {
Platform::Connection & platform_connection();
Platform::Device_client & platform_device(Device_id);
}
Platform::Connection & Lx_kit::platform_connection()
{
static Platform::Connection plat { Lx_kit::env().env() };
return plat;
}
Platform::Device_client & Lx_kit::platform_device(Device_id id)
{
if (id == DCSS) {
static Platform::Device_client dcss {
platform_connection().device_by_property("compatible",
"nxp,imx8mq-dcss") };
return dcss;
}
if (id == HDMI) {
static Platform::Device_client hdmi {
platform_connection().device_by_property("compatible",
"fsl,imx8mq-hdmi") };
return hdmi;
}
throw 1;
}
/********************************
** drivers/base/dma-mapping.c **
********************************/
@ -252,23 +287,28 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
{
/* numbers from running Linux system */
static struct clk clocks[] {
{ "apb", 133333334 },
{ "axi", 800000000 },
{ "ipg", 133333334 },
{ "pix", 27000000 },
{ "rtrm", 400000000 },
{ "dtrc", 25000000 },
};
using namespace Genode;
for (unsigned i = 0; i < (sizeof(clocks) / sizeof(struct clk)); i++)
if (Genode::strcmp(clocks[i].name, id) == 0)
return &clocks[i];
const char * clock_name = id;
if (String<32>("ipg") == id) { clock_name = "apb"; }
if (DEBUG_DRIVER)
Genode::warning("MISSING CLOCK: ", id);
unsigned long rate = 0;
Lx_kit::platform_connection().with_xml([&] (Xml_node node) {
node.for_each_sub_node("device", [&] (Xml_node node) {
node.for_each_sub_node("clock", [&] (Xml_node node) {
if (node.attribute_value("name", String<64>()) != clock_name) {
return; }
rate = node.attribute_value<unsigned long>("rate", 0);
});
});
});
return nullptr;
if (!rate) return nullptr;
struct clk * clock = (struct clk*) kzalloc(sizeof(struct clk), GFP_KERNEL);
clock->name = id;
clock->rate = rate;
return clock;
}
@ -565,9 +605,7 @@ void irq_set_chained_handler_and_data(unsigned int irq,
irqsteer_irq_desc.irq_data.chip = irqsteer_chip;
irqsteer_irq_desc.handle_irq = handle;
Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq,
Lx::Irq::irq().request_irq(Lx_kit::platform_device(DCSS).irq(), irq,
irqsteer_irq_handler, nullptr, nullptr);
}
@ -586,9 +624,17 @@ int devm_request_threaded_irq(struct device *dev, unsigned int irq,
return -1;
}
Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev_id, thread_fn);
Device_id id = UNKNOWN;
unsigned off = 0;
switch (irq) {
case IRQ_IRQSTEER: id = DCSS; break;
case IRQ_HDMI_IN: id = HDMI; break;
case IRQ_HDMI_OUT: id = HDMI; off = 1; break;
default: ;
};
Lx::Irq::irq().request_irq(Lx_kit::platform_device(id).irq(off),
irq, handler, dev_id, thread_fn);
return 0;
}
@ -703,14 +749,46 @@ int disable_irq_nosync(unsigned int irq)
static void *_ioremap(phys_addr_t phys_addr, unsigned long size, int wc)
{
try {
Genode::Attached_io_mem_dataspace *ds = new(Lx::Malloc::mem())
Genode::Attached_io_mem_dataspace(Lx_kit::env().env(), phys_addr, size, !!wc);
return ds->local_addr<void>();
} catch (...) {
panic("Failed to request I/O memory: [%lx,%lx)", phys_addr, phys_addr + size);
return 0;
}
using namespace Genode;
Region_map & rm = Lx_kit::env().env().rm();
if (phys_addr >= IOMEM_BASE_DCSS &&
(phys_addr+size-1) <= IOMEM_END_DCSS) {
static Attached_dataspace ds {
rm, Lx_kit::platform_device(DCSS).io_mem_dataspace() };
addr_t off = phys_addr - IOMEM_BASE_DCSS;
return (void*)(((addr_t)ds.local_addr<void>()) + off);
};
if (phys_addr >= IOMEM_BASE_HDMI_CTRL &&
(phys_addr+size-1) <= IOMEM_END_HDMI_RST) {
switch (phys_addr) {
case IOMEM_BASE_HDMI_CTRL:
{
static Attached_dataspace ds {
rm, Lx_kit::platform_device(HDMI).io_mem_dataspace(0) };
return ds.local_addr<void>();
}
case IOMEM_BASE_HDMI_CRS:
{
static Attached_dataspace ds {
rm, Lx_kit::platform_device(HDMI).io_mem_dataspace(1) };
return ds.local_addr<void>();
}
case IOMEM_BASE_HDMI_RST:
{
static Attached_dataspace ds {
rm, Lx_kit::platform_device(HDMI).io_mem_dataspace(2) };
return ds.local_addr<void>();
}
default: ;
};
};
panic("Failed to request I/O memory: [%lx,%lx)",
phys_addr, phys_addr + size);
return nullptr;
}
void *devm_ioremap(struct device *dev, resource_size_t offset,
@ -890,9 +968,16 @@ int devm_request_irq(struct device *dev, unsigned int irq,
irqsteer_dev_id[irq] = dev_id;
enable_irq(irq);
} else {
Genode::Irq_connection * irq_con = new (Lx_kit::env().heap())
Genode::Irq_connection(Lx_kit::env().env(), irq);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev_id);
Device_id id = UNKNOWN;
unsigned off = 0;
switch (irq) {
case IRQ_IRQSTEER: id = DCSS; break;
case IRQ_HDMI_IN: id = HDMI; break;
case IRQ_HDMI_OUT: id = HDMI; off = 1; break;
default: ;
};
Lx::Irq::irq().request_irq(Lx_kit::platform_device(id).irq(off),
irq, handler, dev_id);
}
return 0;

View File

@ -14,6 +14,7 @@
*/
/* Genode includes */
#include <base/attached_io_mem_dataspace.h>
#include <base/log.h>
#include <base/component.h>
#include <base/heap.h>
@ -124,7 +125,6 @@ void Framebuffer::Main::_run_linux()
module_dcss_crtc_driver_init();
module_imx_hdp_imx_platform_driver_init();
/**
* This device is originally created with the name '32e2d000.irqsteer'
* via 'of_platform_bus_create()'. Here it is called 'imx-irqsteer' to match
@ -135,8 +135,9 @@ void Framebuffer::Main::_run_linux()
platform_device_alloc("imx-irqsteer", 0);
static resource imx_irqsteer_resources[] = {
{ 0x32e2d000, 0x32e2dfff, "imx-irqsteer", IORESOURCE_MEM },
{ 50, 50, "imx-irqsteer", IORESOURCE_IRQ },
{ IOMEM_BASE_IRQSTEER, IOMEM_END_IRQSTEER,
"imx-irqsteer", IORESOURCE_MEM },
{ IRQ_IRQSTEER, IRQ_IRQSTEER, "imx-irqsteer", IORESOURCE_IRQ },
};
imx_irqsteer_pdev->num_resources = 2;
@ -159,15 +160,15 @@ void Framebuffer::Main::_run_linux()
platform_device_alloc("dcss-core", 0);
static resource dcss_resources[] = {
{ 0x32e00000, 0x32efffff, "dcss", IORESOURCE_MEM },
{ 3, 3, "dpr_dc_ch0", IORESOURCE_IRQ },
{ 4, 4, "dpr_dc_ch1", IORESOURCE_IRQ },
{ 5, 5, "dpr_dc_ch2", IORESOURCE_IRQ },
{ 6, 6, "ctx_ld", IORESOURCE_IRQ },
{ 8, 8, "ctxld_kick", IORESOURCE_IRQ },
{ 9, 9, "dtg_prg1", IORESOURCE_IRQ },
{ 16, 16, "dtrc_ch1", IORESOURCE_IRQ },
{ 17, 17, "dtrc_ch2", IORESOURCE_IRQ },
{ IOMEM_BASE_DCSS, IOMEM_END_DCSS, "dcss", IORESOURCE_MEM },
{ 3, 3, "dpr_dc_ch0", IORESOURCE_IRQ },
{ 4, 4, "dpr_dc_ch1", IORESOURCE_IRQ },
{ 5, 5, "dpr_dc_ch2", IORESOURCE_IRQ },
{ 6, 6, "ctx_ld", IORESOURCE_IRQ },
{ 8, 8, "ctxld_kick", IORESOURCE_IRQ },
{ 9, 9, "dtg_prg1", IORESOURCE_IRQ },
{ 16, 16, "dtrc_ch1", IORESOURCE_IRQ },
{ 17, 17, "dtrc_ch2", IORESOURCE_IRQ },
};
dcss_pdev->num_resources = 9;
@ -193,11 +194,14 @@ void Framebuffer::Main::_run_linux()
platform_device_alloc("i.mx8-hdp", 0);
static resource hdp_resources[] = {
{ 0x32c00000, 0x32cfffff, "hdp_ctrl", IORESOURCE_MEM },
{ 0x32e40000, 0x32e7ffff, "hdp_crs", IORESOURCE_MEM },
{ 0x32e2f000, 0x32e2f00f, "hdp_reset", IORESOURCE_MEM },
{ 48, 48, "plug_in", IORESOURCE_IRQ },
{ 57, 57, "plug_out", IORESOURCE_IRQ },
{ IOMEM_BASE_HDMI_CTRL, IOMEM_END_HDMI_CTRL,
"hdp_ctrl", IORESOURCE_MEM },
{ IOMEM_BASE_HDMI_CRS, IOMEM_END_HDMI_CRS,
"hdp_crs", IORESOURCE_MEM },
{ IOMEM_BASE_HDMI_RST, IOMEM_END_HDMI_RST,
"hdp_reset", IORESOURCE_MEM },
{ 33, 33, "plug_in", IORESOURCE_IRQ },
{ 34, 34, "plug_out", IORESOURCE_IRQ },
};
hdp_pdev->num_resources = 5;
@ -212,7 +216,6 @@ void Framebuffer::Main::_run_linux()
platform_device_register(hdp_pdev);
/**
* This device is originally created with the name 'display-subsystem'
* via 'of_platform_bus_create()'. Here it is called 'imx-drm' to match

View File

@ -17,6 +17,7 @@
#define _LX_KIT__IRQ_H_
/* Genode includes */
#include <base/allocator.h>
#include <platform_device/platform_device.h>