dde_linux: adjust fec_nic_drv to use platform_drv

Fix #3947
This commit is contained in:
Stefan Kalkowski 2020-11-10 16:40:32 +01:00 committed by Christian Helmuth
parent a4c7837fb3
commit 4e90dc4512
10 changed files with 267 additions and 132 deletions

View File

@ -1,2 +1,3 @@
_/src/platform_drv
_/src/fec_nic_drv _/src/fec_nic_drv
_/raw/drivers_nic-imx53_qsb _/raw/drivers_nic-imx53_qsb

View File

@ -1,2 +1,3 @@
_/src/platform_drv
_/src/fec_nic_drv _/src/fec_nic_drv
_/raw/drivers_nic-imx6q_sabrelite _/raw/drivers_nic-imx6q_sabrelite

View File

@ -1,2 +1,3 @@
_/src/platform_drv
_/src/fec_nic_drv _/src/fec_nic_drv
_/raw/drivers_nic-imx7d_sabre _/raw/drivers_nic-imx7d_sabre

View File

@ -1,2 +1,3 @@
_/src/platform_drv
_/src/fec_nic_drv _/src/fec_nic_drv
_/raw/drivers_nic-imx8q_evk _/raw/drivers_nic-imx8q_evk

View File

@ -8,7 +8,6 @@
<service name="CPU"/> <service name="CPU"/>
<service name="LOG"/> <service name="LOG"/>
<service name="Timer"/> <service name="Timer"/>
<service name="Gpio"/>
</parent-provides> </parent-provides>
<default caps="100"/> <default caps="100"/>
@ -16,11 +15,33 @@
<service name="Nic"> <service name="Nic">
<default-policy> <child name="nic_drv"/> </default-policy> </service> <default-policy> <child name="nic_drv"/> </default-policy> </service>
<start name="platform_drv" caps="150">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<config>
<device name="fec">
<io_mem address="0x63fec000" size="0x4000"/>
<irq number="87"/>
<property name="compatible" value="fsl,imx25-fec"/>
<property name="mii" value="rmii"/>
</device>
<policy label="nic_drv -> "> <device name="fec"/> </policy>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="nic_drv" caps="130"> <start name="nic_drv" caps="130">
<binary name="fec_nic_drv"/> <binary name="fec_nic_drv"/>
<resource name="RAM" quantum="20M"/> <resource name="RAM" quantum="20M"/>
<provides> <service name="Nic"/> </provides> <provides> <service name="Nic"/> </provides>
<config><card type="fsl,imx25-fec" mii="rmii" irq="87" mmio="0x63fec000"/></config> <route>
<route> <any-service> <parent/> </any-service> </route> <service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="Platform"> <child name="platform_drv"/> </service>
</route>
</start> </start>
</config> </config>

View File

@ -8,7 +8,6 @@
<service name="CPU"/> <service name="CPU"/>
<service name="LOG"/> <service name="LOG"/>
<service name="Timer"/> <service name="Timer"/>
<service name="Gpio"/>
</parent-provides> </parent-provides>
<default caps="100"/> <default caps="100"/>
@ -16,11 +15,34 @@
<service name="Nic"> <service name="Nic">
<default-policy> <child name="nic_drv"/> </default-policy> </service> <default-policy> <child name="nic_drv"/> </default-policy> </service>
<start name="platform_drv" caps="150">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<config>
<device name="fec">
<io_mem address="0x2188000" size="0x4000"/>
<irq number="150"/>
<irq number="151"/>
<property name="compatible" value="fsl,imx6q-fec"/>
<property name="mii" value="rgmii"/>
</device>
<policy label="nic_drv -> "> <device name="fec"/> </policy>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="nic_drv" caps="130"> <start name="nic_drv" caps="130">
<binary name="fec_nic_drv"/> <binary name="fec_nic_drv"/>
<resource name="RAM" quantum="20M"/> <resource name="RAM" quantum="20M"/>
<provides> <service name="Nic"/> </provides> <provides> <service name="Nic"/> </provides>
<config><card type="fsl,imx6q-fec" mii="rgmii" irq="150" mmio="0x2188000"/></config> <route>
<route> <any-service> <parent/> </any-service> </route> <service name="ROM"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="Platform"> <child name="platform_drv"/> </service>
</route>
</start> </start>
</config> </config>

View File

@ -8,24 +8,51 @@
<service name="CPU"/> <service name="CPU"/>
<service name="LOG"/> <service name="LOG"/>
<service name="Timer"/> <service name="Timer"/>
<service name="Gpio"/>
</parent-provides> </parent-provides>
<default caps="100"/> <default caps="100"/>
<service name="Nic"> <service name="Nic">
<default-policy> <child name="nic_drv"/> </default-policy> </service> <default-policy> <child name="nic_drv" label="fec0"/> </default-policy> </service>
<start name="platform_drv" caps="150">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<config>
<device name="fec0">
<io_mem address="0x30be0000" size="0x4000"/>
<irq number="152"/>
<irq number="153"/>
<property name="compatible" value="fsl,imx6sx-fec"/>
<property name="mii" value="rgmii"/>
</device>
<device name="fec1">
<io_mem address="0x30bf0000" size="0x4000"/>
<irq number="134"/>
<irq number="135"/>
<property name="compatible" value="fsl,imx6sx-fec"/>
<property name="mii" value="rgmii"/>
</device>
<policy label="nic_drv -> ">
<device name="fec0"/>
<device name="fec1"/>
</policy>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="nic_drv" caps="150"> <start name="nic_drv" caps="150">
<binary name="fec_nic_drv"/> <binary name="fec_nic_drv"/>
<resource name="RAM" quantum="20M"/> <resource name="RAM" quantum="20M"/>
<provides> <service name="Nic"/> </provides> <provides> <service name="Nic"/> </provides>
<config> <route>
<!-- ENET1: IRQ 120 + 32 = 152 --> <service name="ROM"> <parent/> </service>
<card type="fsl,imx6sx-fec" mii="rgmii" irq="152" mmio="0x30be0000"/> <service name="PD"> <parent/> </service>
<!-- ENET2: IRQ 102 + 32 = 134 --> <service name="RM"> <parent/> </service>
<card type="fsl,imx6sx-fec" mii="rgmii" irq="134" mmio="0x30bf0000"/> <service name="CPU"> <parent/> </service>
</config> <service name="LOG"> <parent/> </service>
<route> <any-service> <parent/> </any-service> </route> <service name="Timer"> <parent/> </service>
<service name="Platform"> <child name="platform_drv"/> </service>
</route>
</start> </start>
</config> </config>

View File

@ -8,7 +8,6 @@
<service name="CPU"/> <service name="CPU"/>
<service name="LOG"/> <service name="LOG"/>
<service name="Timer"/> <service name="Timer"/>
<service name="Gpio"/>
</parent-provides> </parent-provides>
<default caps="100"/> <default caps="100"/>
@ -16,13 +15,36 @@
<service name="Nic"> <service name="Nic">
<default-policy> <child name="nic_drv"/> </default-policy> </service> <default-policy> <child name="nic_drv"/> </default-policy> </service>
<start name="platform_drv" caps="150">
<binary name="imx8mq_platform_drv"/>
<resource name="RAM" quantum="1M"/>
<provides> <service name="Platform"/> </provides>
<config>
<device name="fec">
<io_mem address="0x30be0000" size="0x4000"/>
<irq number="152"/>
<irq number="151"/>
<irq number="150"/>
<property name="compatible" value="fsl,imx6sx-fec"/>
<property name="mii" value="rgmii-id"/>
</device>
<policy label="nic_drv -> "> <device name="fec"/> </policy>
</config>
<route> <any-service> <parent/> </any-service> </route>
</start>
<start name="nic_drv" caps="130"> <start name="nic_drv" caps="130">
<binary name="fec_nic_drv"/> <binary name="fec_nic_drv"/>
<resource name="RAM" quantum="20M"/> <resource name="RAM" quantum="20M"/>
<provides> <service name="Nic"/> </provides> <provides> <service name="Nic"/> </provides>
<config> <route>
<card type="fsl,imx6sx-fec" mii="rgmii" irq="152" mmio="0x30be0000"/> <service name="ROM"> <parent/> </service>
</config> <service name="PD"> <parent/> </service>
<route> <any-service> <parent/> </any-service> </route> <service name="RM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="Platform"> <child name="platform_drv"/> </service>
</route>
</start> </start>
</config> </config>

View File

@ -241,11 +241,6 @@ int of_phy_register_fixed_link(struct device_node *np)
return -1; return -1;
} }
bool of_property_read_bool(const struct device_node *np, const char *propname)
{
TRACE_AND_STOP;
}
void phy_led_triggers_unregister(struct phy_device *phy) void phy_led_triggers_unregister(struct phy_device *phy)
{ {
TRACE_AND_STOP; TRACE_AND_STOP;
@ -305,13 +300,6 @@ int regulator_disable(struct regulator *r)
return -1; return -1;
} }
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn,
unsigned long flags, const char *name, void *dev)
{
TRACE_AND_STOP;
}
void sk_free(struct sock *sk) void sk_free(struct sock *sk)
{ {
TRACE_AND_STOP; TRACE_AND_STOP;

View File

@ -15,12 +15,14 @@
* Unconditionally include common Genode headers _before_ lx_emul.h to * Unconditionally include common Genode headers _before_ lx_emul.h to
* prevent shenanigans with macro definitions. * prevent shenanigans with macro definitions.
*/ */
#include <base/attached_io_mem_dataspace.h> #include <base/attached_dataspace.h>
#include <base/attached_rom_dataspace.h> #include <base/attached_rom_dataspace.h>
#include <base/env.h> #include <base/env.h>
#include <base/snprintf.h> #include <base/snprintf.h>
#include <gpio_session/connection.h> #include <gpio_session/connection.h>
#include <irq_session/connection.h> #include <irq_session/client.h>
#include <platform_session/connection.h>
#include <platform_device/client.h>
#include <component.h> #include <component.h>
#include <lx_emul.h> #include <lx_emul.h>
@ -225,79 +227,116 @@ struct Gpio_irq : public Genode::List<Gpio_irq>::Element
}; };
struct Fec static unsigned irq_counter = 32;
struct Fec : public Genode::List<Fec>::Element
{ {
using String = Genode::String<128>; using String = Genode::String<128>;
struct Mdio struct Mdio
{ {
struct Phy struct Phy : public Genode::List<Phy>::Element
{ {
String name; String name;
String phy_driver; String phy_driver { };
const unsigned phy_reg; String mdio_bus { };
const unsigned gpio_irq; unsigned phy_reg { 0 };
unsigned gpio_irq { 0 };
struct phy_device * phy_dev { nullptr }; struct phy_device * phy_dev { nullptr };
Phy(String name, String driver, const unsigned reg, const unsigned irq) Phy(String name, Genode::Xml_node xml, Platform::Device_capability)
: name(name), phy_driver(driver), phy_reg(reg), gpio_irq(irq) {} : name(name)
{
using namespace Genode;
xml.for_each_sub_node("property", [&] (Xml_node node) {
if (String("compatible") == node.attribute_value("name", String())) {
phy_driver = node.attribute_value("value", String()); }
if (String("mdio_bus") == node.attribute_value("name", String())) {
mdio_bus = node.attribute_value("value", String()); }
if (String("mdio_reg") == node.attribute_value("name", String())) {
phy_reg = node.attribute_value("value", 0U); }
if (String("gpio_irq") == node.attribute_value("name", String())) {
gpio_irq = node.attribute_value("value", 0U); }
});
}
}; };
enum { MAX = 10 }; Genode::List<Phy> phys;
Genode::Constructible<Phy> phys[MAX];
template <typename FUNC> template <typename FUNC>
void for_each(FUNC && f) void for_each(FUNC && f) {
{ for (Phy * p = phys.first(); p; p = p->next()) { f(*p); } }
for (unsigned i = 0; i < MAX; i++)
if (phys[i].constructed()) f(*phys[i]);
}
}; };
String name; String name;
String device; String type;
const unsigned irq; Platform::Device_client device;
const size_t mmio; const unsigned irq { irq_counter };
String phy_mode; String phy_mode {};
const bool magic_packet; String phy_name {};
const int tx_queues; bool magic_packet { true };
const int rx_queues; int tx_queues { 1 };
int rx_queues { 1 };
struct net_device * net_dev { nullptr }; struct net_device * net_dev { nullptr };
Session_component * session { nullptr }; Session_component * session { nullptr };
Genode::Attached_io_mem_dataspace io_ds { Lx_kit::env().env(), mmio, 0x4000 }; Genode::Attached_dataspace io_ds { Lx_kit::env().env().rm(),
device.io_mem_dataspace() };
Genode::Constructible<Mdio> mdio; Genode::Constructible<Mdio> mdio;
Mdio::Phy * phy { nullptr }; Mdio::Phy * phy { nullptr };
Fec(String name, String device, const unsigned irq, Fec(String name,
const size_t mmio, String mode, const bool magic = true, Genode::Xml_node xml,
const int tx_queues = 1, const int rx_queues = 1) Platform::Device_capability cap)
: name(name), device(device), irq(irq), mmio(mmio), phy_mode(mode), magic_packet(magic), : name(name), device(cap)
tx_queues(tx_queues), rx_queues(rx_queues) {}; {
using namespace Genode;
xml.for_each_sub_node("property", [&] (Xml_node node) {
if (String("compatible") == node.attribute_value("name", String())) {
type = node.attribute_value("value", String()); }
if (String("mii") == node.attribute_value("name", String())) {
phy_mode = node.attribute_value("value", String()); }
if (String("phy") == node.attribute_value("name", String())) {
phy_name = node.attribute_value("value", String()); }
if (String("magic_packet") == node.attribute_value("name", String())) {
magic_packet = node.attribute_value("value", true); }
if (String("tx-queues") == node.attribute_value("name", String())) {
tx_queues = node.attribute_value("value", 1UL); }
if (String("rx-queues") == node.attribute_value("name", String())) {
rx_queues = node.attribute_value("value", 1UL); }
});
irq_counter += 10;
}
}; };
static const unsigned FEC_MAX = 2; static Genode::List<Fec> & fec_devices()
static Genode::Constructible<Fec> fec_devices[FEC_MAX]; {
static Genode::List<Fec> list;
return list;
}
net_device * Session_component::_register_session_component(Session_component & s, net_device * Session_component::_register_session_component(Session_component & s,
Genode::Session_label policy) Genode::Session_label policy)
{ {
Genode::Session_label name = policy.last_element(); unsigned number = 0;
for (Fec * f = fec_devices().first(); f; f = f->next()) { number++; }
for (unsigned i = 0; i < FEC_MAX; i++) { for (Fec * f = fec_devices().first(); f; f = f->next()) {
/* If there is more than one device, check session label against card name */
if (number > 1) {
Genode::Session_label name = policy.last_element();
if (f->name != name) continue;
}
/* No more cards available */ /* Session already in use? */
if (!fec_devices[i].constructed()) return nullptr; if (f->session) continue;
/* Session does not match cards policy */ f->session = &s;
if (fec_devices[i]->name.length() > 1 && return f->net_dev;
fec_devices[i]->name != name) continue;
/* Session already in use */
if (fec_devices[i]->session) return nullptr;
fec_devices[i]->session = &s;
return fec_devices[i]->net_dev;
} }
return nullptr; return nullptr;
} }
@ -317,68 +356,66 @@ void lx_backtrace()
#endif #endif
} }
static Platform::Connection & platform_connection()
{
static Genode::Constructible<Platform::Connection> plat;
if (!plat.constructed()) plat.construct(Lx_kit::env().env());
return *plat;
}
int platform_driver_register(struct platform_driver * drv) int platform_driver_register(struct platform_driver * drv)
{ {
using namespace Genode;
using String = Fec::String; using String = Fec::String;
try { platform_connection().with_xml([&] (Xml_node & xml) {
unsigned i = 0; xml.for_each_sub_node("device", [&] (Xml_node node) {
Genode::Attached_rom_dataspace config { Lx_kit::env().env(), "config" };
config.xml().for_each_sub_node("card", [&] (Genode::Xml_node const node) { String name = node.attribute_value("name", String());
if (i == FEC_MAX) { String compatible;
Genode::error("More cards defined than available!"); node.for_each_sub_node("property", [&] (Xml_node node) {
if (String("compatible") == node.attribute_value("name", String())) {
compatible = node.attribute_value("value", String()); }});
if (compatible == "fsl,imx6q-fec" ||
compatible == "fsl,imx6sx-fec" ||
compatible == "fsl,imx25-fec") {
Fec * f = new (Lx_kit::env().heap())
Fec(name, node, platform_connection().acquire_device(name.string()));
/* order of devices is important, therefore insert it at the end */
Fec * last = fec_devices().first();
for (; last; last = last->next()) {
if (!last->next()) { break; }
}
fec_devices().insert(f, last);
return; return;
} }
String name = node.attribute_value("name", String()); if (compatible == "ethernet-phy-ieee802.3-c22") {
String type = node.attribute_value("type", String()); Fec::Mdio::Phy * p = new (Lx_kit::env().heap())
String mdio = node.attribute_value("mii", String()); Fec::Mdio::Phy(name, node, platform_connection().acquire_device(name.string()));
String phy = node.attribute_value("phy", String()); for (Fec * f = fec_devices().first(); f; f = f->next()) {
unsigned irq = node.attribute_value("irq", 0UL); if (f->phy_name == name) { f->phy = p; }
Genode::addr_t mmio = node.attribute_value("mmio", 0UL); if (f->name == p->mdio_bus) {
bool magic = node.attribute_value("magic_packet", true); if (!f->mdio.constructed()) { f->mdio.construct(); }
unsigned txq = node.attribute_value("tx-queues", 1UL); f->mdio->phys.insert(p);
unsigned rxq = node.attribute_value("rx-queues", 1UL); }
fec_devices[i].construct(name, type, irq, mmio, mdio, magic, txq, rxq);
node.for_each_sub_node("mdio", [&] (Genode::Xml_node const node) {
fec_devices[i]->mdio.construct();
unsigned j = 0;
node.for_each_sub_node("phy", [&] (Genode::Xml_node const node) {
String name = node.attribute_value("name", String());
String type = node.attribute_value("type", String());
unsigned irq = node.attribute_value("gpio_irq", 0UL);
unsigned reg = node.attribute_value("reg_num", 0UL);
fec_devices[i]->mdio->phys[j].construct(name, type, reg, irq);
j++;
});
});
for (unsigned k = 0; k <= i; k++)
if (fec_devices[k]->mdio.constructed()) {
fec_devices[k]->mdio->for_each([&] (Fec::Mdio::Phy & p) {
if (p.name == phy) fec_devices[i]->phy = &p; });
} }
}
i++;
}); });
} catch(...) { } });
if (!fec_devices[0].constructed()) {
Genode::warning("No valid configuration provided, use default values");
fec_devices[0].construct(String(), "fsl,imx6q-fec", 150, 0x2188000, "rgmii");
}
for (unsigned i = 0; i < FEC_MAX; i++) {
if (!fec_devices[i].constructed()) break;
for (Fec * f = fec_devices().first(); f; f = f->next()) {
platform_device * pd = new (Lx::Malloc::dma()) platform_device(); platform_device * pd = new (Lx::Malloc::dma()) platform_device();
pd->name = fec_devices[i]->name.string(); pd->name = f->name.string();
pd->dev.of_node = (device_node*) &fec_devices[i]; pd->dev.of_node = (device_node*) f;
pd->dev.plat_dev = pd; pd->dev.plat_dev = pd;
drv->probe(pd); drv->probe(pd);
{ {
net_device * dev = fec_devices[i]->net_dev; net_device * dev = f->net_dev;
int err = dev ? dev->netdev_ops->ndo_open(dev) : -1; int err = dev ? dev->netdev_ops->ndo_open(dev) : -1;
if (err) { if (err) {
Genode::error("ndo_open() failed: ", err); Genode::error("ndo_open() failed: ", err);
@ -430,7 +467,7 @@ const struct of_device_id *of_match_device(const struct of_device_id *matches,
{ {
Fec * fec = (Fec*) dev->plat_dev->dev.of_node; Fec * fec = (Fec*) dev->plat_dev->dev.of_node;
for (; matches && matches->compatible[0]; matches++) for (; matches && matches->compatible[0]; matches++)
if (Genode::strcmp(matches->compatible, fec->device.string()) == 0) if (Genode::strcmp(matches->compatible, fec->type.string()) == 0)
return matches; return matches;
return nullptr; return nullptr;
@ -586,9 +623,8 @@ int platform_get_irq(struct platform_device * d, unsigned int i)
int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id) int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)
{ {
Genode::Irq_connection * irq_con = new (Lx_kit::env().heap()) Fec * fec = (Fec*) dev->plat_dev->dev.of_node;
Genode::Irq_connection(Lx_kit::env().env(), irq); Lx::Irq::irq().request_irq(fec->device.irq(irq - fec->irq), irq, handler, dev_id);
Lx::Irq::irq().request_irq(irq_con->cap(), irq, handler, dev_id);
return 0; return 0;
} }
@ -984,9 +1020,9 @@ static int of_mdiobus_register_phy(Fec::Mdio::Phy & ph, struct mii_bus *mdio)
{ {
struct phy_device * phy = get_phy_device(mdio, ph.phy_reg, false); struct phy_device * phy = get_phy_device(mdio, ph.phy_reg, false);
if (!phy || IS_ERR(phy)) return 1; if (!phy) return 1;
phy->irq = ph.gpio_irq; phy->irq = ph.gpio_irq;
phy->mdio.dev.of_node = (device_node*) &ph; phy->mdio.dev.of_node = (device_node*) &ph;
/* All data is now stored in the phy struct; /* All data is now stored in the phy struct;
@ -1031,8 +1067,9 @@ int of_driver_match_device(struct device *dev, const struct device_driver *drv)
{ {
Fec::Mdio::Phy * phy = (Fec::Mdio::Phy*) dev->of_node; Fec::Mdio::Phy * phy = (Fec::Mdio::Phy*) dev->of_node;
return phy ? (Genode::strcmp(drv->name, if (!phy) return 0;
phy->phy_driver.string()) == 0) : 0;
return (Genode::strcmp(drv->name, "Atheros 8035 ethernet") == 0) ? 1 : 0;
} }
@ -1077,6 +1114,14 @@ int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, co
} }
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
irq_handler_t thread_fn,
unsigned long flags, const char *name, void *dev)
{
return request_irq(irq, thread_fn, flags, name, dev);
}
int enable_irq(unsigned int irq) int enable_irq(unsigned int irq)
{ {
for (Gpio_irq *girq = Gpio_irq::list()->first(); girq; girq = girq->next()) for (Gpio_irq *girq = Gpio_irq::list()->first(); girq; girq = girq->next())
@ -1265,6 +1310,12 @@ bool of_phy_is_fixed_link(struct device_node *np)
return 0; return 0;
} }
bool of_property_read_bool(const struct device_node *np, const char *propname)
{
TRACE;
return false;
}
void phy_led_trigger_change_speed(struct phy_device *phy) void phy_led_trigger_change_speed(struct phy_device *phy)
{ {
TRACE; TRACE;