mirror of
https://github.com/genodelabs/genode.git
synced 2025-06-19 07:38:28 +00:00
dde_linux: usb host controller driver version 4.16
This commit is contained in:
committed by
Christian Helmuth
parent
9d712b2ce9
commit
b02f483841
66
repos/dde_linux/src/drivers/usb_host/README
Normal file
66
repos/dde_linux/src/drivers/usb_host/README
Normal file
@ -0,0 +1,66 @@
|
||||
USB host controller driver
|
||||
##########################
|
||||
|
||||
Allows access to USB devices via the 'Usb' session interface.
|
||||
|
||||
Configuration snippet:
|
||||
|
||||
!<start name="usb_host_drv">
|
||||
! <resource name="RAM" quantum="10M"/>
|
||||
! <provides><service name="Usb"/></provides>
|
||||
! <config>
|
||||
! <report devices="yes"/>
|
||||
! </config>
|
||||
!</start>
|
||||
|
||||
The optional 'devices' report lists the connected devices and gets updated
|
||||
when devices are added or removed.
|
||||
|
||||
Example report:
|
||||
|
||||
!<devices>
|
||||
! <device label="usb-1-2" vendor_id="0x046d" product_id="0xc077" bus="0x0001" dev="0x0002" class="0x03"/>
|
||||
! <device label="usb-1-1" vendor_id="0x1d6b" product_id="0x0002" bus="0x0001" dev="0x0001" class="0x09"/>
|
||||
!</devices>
|
||||
|
||||
For every device a unique identifier is generated that is used to access the
|
||||
USB device. Only devices that have a valid policy configured at the USB driver
|
||||
can be accessed by a client. The following configuration allows 'comp1' to
|
||||
access the device 'usb-1-6':
|
||||
|
||||
!<start name="usb_drv">
|
||||
! <resource name="RAM" quantum="8M"/>
|
||||
! <provides><service name="Usb"/></provides>
|
||||
! <config uhci="yes" ohci="yes" ehci="yes" xhci="yes">
|
||||
! <raw>
|
||||
! <report devices="yes"/>
|
||||
! <policy label="comp1 -> usb-1-6" vendor_id="0x13fe" product_id="0x5200" bus="0x0001" dev="0x0006"/>
|
||||
! </raw>
|
||||
! </config>
|
||||
!</start>
|
||||
|
||||
In addition to the mandatory 'label' attribute the policy node also
|
||||
contains optional attribute tuples of which at least one has to be present.
|
||||
The 'vendor_id' and 'product_id' tuple selects a device regardless of its
|
||||
location on the USB bus and is mostly used in static configurations. The
|
||||
'bus' and 'dev' tuple selects a specific device via its bus locations and
|
||||
device address. It is mostly used in dynamic configurations because the device
|
||||
address is not fixed and may change every time the same device is plugged in.
|
||||
If the class attribute is defined only, the usb host controller driver allows
|
||||
access to all devives of that class. In that case the actual device is chosen
|
||||
by the last label given when a session gets opened.
|
||||
|
||||
|
||||
BIOS Handoff
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Per default the USB driver performs a hand off of the USB controller from the
|
||||
BIOS, since it still may access the controller when booting, for example, from
|
||||
a USB device. The BIOS hand off induces the execution of BIOS/SMM USB driver
|
||||
code and potentially DMA operations. Unfortunately, some ACPI tables report
|
||||
wrong RMRR information, which implicates IOMMU faults on illegal DMA
|
||||
operations and consequently the hand off may fail after noticeably long
|
||||
timeouts. Therefore, the hand off can be disabled in the USB driver
|
||||
configuration like follows.
|
||||
|
||||
! <config bios_handoff="no"/>
|
1229
repos/dde_linux/src/drivers/usb_host/dummies.c
Normal file
1229
repos/dde_linux/src/drivers/usb_host/dummies.c
Normal file
File diff suppressed because it is too large
Load Diff
1091
repos/dde_linux/src/drivers/usb_host/lx_emul.cc
Normal file
1091
repos/dde_linux/src/drivers/usb_host/lx_emul.cc
Normal file
File diff suppressed because it is too large
Load Diff
1825
repos/dde_linux/src/drivers/usb_host/lx_emul.h
Normal file
1825
repos/dde_linux/src/drivers/usb_host/lx_emul.h
Normal file
File diff suppressed because it is too large
Load Diff
171
repos/dde_linux/src/drivers/usb_host/main.cc
Normal file
171
repos/dde_linux/src/drivers/usb_host/main.cc
Normal file
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* \brief Startup USB driver library
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2013-02-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
#include <base/component.h>
|
||||
#include <base/attached_rom_dataspace.h>
|
||||
#include <base/sleep.h>
|
||||
|
||||
/* Local */
|
||||
#include <signal.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
#include <lx_kit/env.h>
|
||||
#include <lx_kit/pci.h>
|
||||
#include <lx_kit/irq.h>
|
||||
#include <lx_kit/malloc.h>
|
||||
#include <lx_kit/scheduler.h>
|
||||
#include <lx_kit/timer.h>
|
||||
#include <lx_kit/work.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
extern "C" int subsys_usb_init();
|
||||
extern "C" void module_raw_driver_init();
|
||||
extern "C" void start_input_service(void *ep, void *services);
|
||||
|
||||
struct workqueue_struct *system_power_efficient_wq;
|
||||
struct workqueue_struct *system_wq;
|
||||
struct workqueue_struct *tasklet_wq;
|
||||
|
||||
void breakpoint() { Genode::log("BREAK"); }
|
||||
|
||||
extern "C" int stdout_write(const char *);
|
||||
|
||||
static void run_linux(void *s)
|
||||
{
|
||||
Services *services = (Services *)s;
|
||||
|
||||
system_power_efficient_wq = alloc_workqueue("system_power_efficient_wq", 0, 0);
|
||||
system_wq = alloc_workqueue("system_wq", 0, 0);
|
||||
tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0);
|
||||
|
||||
/* low level interface */
|
||||
module_raw_driver_init();
|
||||
|
||||
/* USB */
|
||||
subsys_usb_init();
|
||||
|
||||
/* host controller */
|
||||
platform_hcd_init(services);
|
||||
|
||||
while (true)
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
}
|
||||
|
||||
|
||||
static void start_usb_driver(Genode::Env &env)
|
||||
{
|
||||
/* initialize USB env */
|
||||
Lx_kit::construct_env(env);
|
||||
|
||||
/* sets up backend alloc needed by malloc */
|
||||
backend_alloc_init(env, env.ram(), Lx_kit::env().heap());
|
||||
|
||||
Lx::malloc_init(env, Lx_kit::env().heap());
|
||||
|
||||
static Services services(env);
|
||||
|
||||
Raw::init(env, services.raw_report_device_list);
|
||||
|
||||
Lx::scheduler(&env);
|
||||
Lx::timer(&env, &env.ep(), &Lx_kit::env().heap(), &jiffies);
|
||||
|
||||
Lx::Irq::irq(&env.ep(), &Lx_kit::env().heap());
|
||||
Lx::Work::work_queue(&Lx_kit::env().heap());
|
||||
|
||||
static Lx::Task linux(run_linux, &services, "linux", Lx::Task::PRIORITY_0,
|
||||
Lx::scheduler());
|
||||
|
||||
Lx::scheduler().schedule();
|
||||
}
|
||||
|
||||
namespace Usb_driver {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
struct Driver_starter { virtual void start_driver() = 0; };
|
||||
struct Main;
|
||||
}
|
||||
|
||||
|
||||
struct Usb_driver::Main : Driver_starter
|
||||
{
|
||||
Env &_env;
|
||||
|
||||
/*
|
||||
* Defer the startup of the USB driver until the first configuration
|
||||
* becomes available. This is needed in scenarios where the configuration
|
||||
* is dynamically generated and supplied to the USB driver via the
|
||||
* report-ROM service.
|
||||
*/
|
||||
struct Initial_config_handler
|
||||
{
|
||||
Driver_starter &_driver_starter;
|
||||
|
||||
Attached_rom_dataspace _config;
|
||||
|
||||
Signal_handler<Initial_config_handler> _config_handler;
|
||||
|
||||
void _handle_config()
|
||||
{
|
||||
_config.update();
|
||||
|
||||
if (_config.xml().type() == "config")
|
||||
_driver_starter.start_driver();
|
||||
}
|
||||
|
||||
Initial_config_handler(Env &env, Driver_starter &driver_starter)
|
||||
:
|
||||
_driver_starter(driver_starter),
|
||||
_config(env, "config"),
|
||||
_config_handler(env.ep(), *this, &Initial_config_handler::_handle_config)
|
||||
{
|
||||
_config.sigh(_config_handler);
|
||||
_handle_config();
|
||||
}
|
||||
};
|
||||
|
||||
void _handle_start()
|
||||
{
|
||||
if (_initial_config_handler.constructed()) {
|
||||
_initial_config_handler.destruct();
|
||||
start_usb_driver(_env);
|
||||
}
|
||||
}
|
||||
|
||||
Signal_handler<Main> _start_handler {
|
||||
_env.ep(), *this, &Main::_handle_start };
|
||||
|
||||
Reconstructible<Initial_config_handler> _initial_config_handler { _env, *this };
|
||||
|
||||
/*
|
||||
* Called from 'Initial_config_handler'
|
||||
*/
|
||||
void start_driver() override
|
||||
{
|
||||
Signal_transmitter(_start_handler).submit();
|
||||
}
|
||||
|
||||
Main(Env &env) : _env(env) { }
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
/* XXX execute constructors of global statics */
|
||||
env.exec_static_constructors();
|
||||
|
||||
static Usb_driver::Main main(env);
|
||||
}
|
50
repos/dde_linux/src/drivers/usb_host/platform.h
Normal file
50
repos/dde_linux/src/drivers/usb_host/platform.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* \brief Platform specific definitions
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2012-07-06
|
||||
*
|
||||
* These functions have to be implemented on all supported platforms.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _PLATFORM_H_
|
||||
#define _PLATFORM_H_
|
||||
|
||||
#include <base/log.h>
|
||||
#include <util/xml_node.h>
|
||||
#include <irq_session/capability.h>
|
||||
|
||||
#include <lx_kit/env.h>
|
||||
|
||||
struct Services
|
||||
{
|
||||
Genode::Env &env;
|
||||
|
||||
/* report generation */
|
||||
bool raw_report_device_list = false;
|
||||
|
||||
Services(Genode::Env &env) : env(env)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
Genode::Xml_node config_node = Lx_kit::env().config_rom().xml();
|
||||
|
||||
try {
|
||||
Genode::Xml_node node_report = config_node.sub_node("report");
|
||||
raw_report_device_list = node_report.attribute_value("devices", false);
|
||||
} catch (...) { }
|
||||
}
|
||||
};
|
||||
|
||||
void backend_alloc_init(Genode::Env &env, Genode::Ram_session &ram, Genode::Allocator &alloc);
|
||||
|
||||
void platform_hcd_init(Services *services);
|
||||
Genode::Irq_session_capability platform_irq_activate(int irq);
|
||||
|
||||
#endif /* _PLATFORM_H_ */
|
1135
repos/dde_linux/src/drivers/usb_host/raw.cc
Normal file
1135
repos/dde_linux/src/drivers/usb_host/raw.cc
Normal file
File diff suppressed because it is too large
Load Diff
12
repos/dde_linux/src/drivers/usb_host/raw.h
Normal file
12
repos/dde_linux/src/drivers/usb_host/raw.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef _RAW_H_
|
||||
#define _RAW_H_
|
||||
|
||||
struct usb_device;
|
||||
struct usb_driver;
|
||||
|
||||
extern struct usb_device_driver raw_driver;
|
||||
extern struct usb_driver raw_intf_driver;
|
||||
|
||||
int raw_notify(struct notifier_block *nb, unsigned long action, void *data);
|
||||
|
||||
#endif /* _RAW_H_ */
|
94
repos/dde_linux/src/drivers/usb_host/raw_driver.c
Normal file
94
repos/dde_linux/src/drivers/usb_host/raw_driver.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* \brief Low level USB access driver
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2014-11-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <linux/usb.h>
|
||||
#include "raw.h"
|
||||
|
||||
static int raw_probe(struct usb_device *udev)
|
||||
{
|
||||
printk("RAW: vendor: %x product: %x dev %p\n",
|
||||
udev->descriptor.idVendor, udev->descriptor.idProduct, udev);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static void raw_disconnect(struct usb_device *udev)
|
||||
{
|
||||
printk("driver disconnect called\n");
|
||||
}
|
||||
|
||||
|
||||
struct usb_device_driver raw_driver =
|
||||
{
|
||||
.name = "raw",
|
||||
.probe = raw_probe,
|
||||
.disconnect = raw_disconnect,
|
||||
.supports_autosuspend = 0,
|
||||
};
|
||||
|
||||
|
||||
static int raw_intf_probe(struct usb_interface *intf,
|
||||
struct usb_device_id const *id)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
|
||||
printk("RAW_INTF: vendor: %04x product: %04x\n", udev->descriptor.idVendor,
|
||||
udev->descriptor.idProduct);
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void raw_intf_disconnect(struct usb_interface *intf) { }
|
||||
|
||||
static const struct usb_device_id raw_intf_id_table[] = {
|
||||
{ .driver_info = 1 }
|
||||
};
|
||||
|
||||
|
||||
struct usb_driver raw_intf_driver =
|
||||
{
|
||||
.name = "rawintf",
|
||||
.probe = raw_intf_probe,
|
||||
.disconnect = raw_intf_disconnect,
|
||||
.supports_autosuspend = 0,
|
||||
};
|
||||
|
||||
|
||||
struct notifier_block usb_nb =
|
||||
{
|
||||
.notifier_call = raw_notify
|
||||
};
|
||||
|
||||
|
||||
static int raw_driver_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if ((err = usb_register_device_driver(&raw_driver, THIS_MODULE)))
|
||||
return err;
|
||||
|
||||
printk("RAW: driver registered\n");
|
||||
|
||||
if ((err = usb_register(&raw_intf_driver)))
|
||||
return err;
|
||||
|
||||
printk("RAW: interface driver registered\n");
|
||||
|
||||
usb_register_notify(&usb_nb);
|
||||
|
||||
printk("RAW: notify function registered\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(raw_driver_init);
|
52
repos/dde_linux/src/drivers/usb_host/signal.h
Normal file
52
repos/dde_linux/src/drivers/usb_host/signal.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* \brief Main-signal receiver and signal-helper functions
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2012-05-23
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SIGNAL_H_
|
||||
#define _SIGNAL_H_
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#include <base/signal.h>
|
||||
|
||||
static bool const verbose = false;
|
||||
|
||||
/**
|
||||
* Helper that holds sender and entrypoint
|
||||
*/
|
||||
class Signal_helper
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
Genode::Signal_transmitter _sender;
|
||||
|
||||
public:
|
||||
|
||||
Signal_helper(Genode::Env &env) : _env(env) { }
|
||||
|
||||
Genode::Entrypoint &ep() { return _env.ep(); }
|
||||
Genode::Signal_transmitter &sender() { return _sender; }
|
||||
Genode::Parent &parent() { return _env.parent(); }
|
||||
Genode::Env &env() { return _env; }
|
||||
Genode::Ram_session &ram() { return _env.ram(); }
|
||||
Genode::Region_map &rm() { return _env.rm(); }
|
||||
};
|
||||
|
||||
|
||||
namespace Raw
|
||||
{
|
||||
void init(Genode::Env &env, bool report_device_list);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _SIGNAL_H_ */
|
87
repos/dde_linux/src/drivers/usb_host/spec/arm/platform.cc
Normal file
87
repos/dde_linux/src/drivers/usb_host/spec/arm/platform.cc
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* \brief ARM specific implemenations used on all SOCs
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2016-04-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <base/attached_io_mem_dataspace.h>
|
||||
#include <base/env.h>
|
||||
|
||||
#include <lx_emul.h>
|
||||
|
||||
#include <lx_kit/backend_alloc.h>
|
||||
#include <lx_kit/env.h>
|
||||
#include <lx_kit/irq.h>
|
||||
|
||||
|
||||
/****************************
|
||||
** lx_kit/backend_alloc.h **
|
||||
****************************/
|
||||
|
||||
void backend_alloc_init(Genode::Env&, Genode::Ram_session&,
|
||||
Genode::Allocator&)
|
||||
{
|
||||
/* intentionally left blank */
|
||||
}
|
||||
|
||||
|
||||
Genode::Ram_dataspace_capability
|
||||
Lx::backend_alloc(Genode::addr_t size, Genode::Cache_attribute cached) {
|
||||
return Lx_kit::env().env().ram().alloc(size, cached); }
|
||||
|
||||
|
||||
void Lx::backend_free(Genode::Ram_dataspace_capability cap) {
|
||||
return Lx_kit::env().env().ram().free(cap); }
|
||||
|
||||
|
||||
/***********************
|
||||
** linux/interrupt.h **
|
||||
***********************/
|
||||
|
||||
extern "C" int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
|
||||
const char *name, void *dev)
|
||||
{
|
||||
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), handler, dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int devm_request_irq(struct device *dev, unsigned int irq, irq_handler_t handler, unsigned long irqflags, const char *devname, void *dev_id)
|
||||
{
|
||||
Lx::Irq::irq().request_irq(Platform::Device::create(Lx_kit::env().env(), irq), handler, dev_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
** asm-generic/io.h **
|
||||
**********************/
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void *ioremap(phys_addr_t offset, unsigned long size)
|
||||
{
|
||||
return _ioremap(offset, size, 0);
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* \brief Platform_device implementation for ARM
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2016-04-25
|
||||
*
|
||||
* Note: Throw away when there exists a plaform device implementation for ARM
|
||||
* in generic code
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
|
||||
#define _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_
|
||||
|
||||
|
||||
#include <lx_emul/extern_c_begin.h>
|
||||
#include <lx_emul/printf.h>
|
||||
#include <lx_emul/extern_c_end.h>
|
||||
|
||||
#include <lx_kit/malloc.h>
|
||||
#include <platform_device/device.h>
|
||||
|
||||
#include <irq_session/connection.h>
|
||||
#include <util/list.h>
|
||||
#include <util/reconstructible.h>
|
||||
|
||||
|
||||
namespace Platform { struct Device; }
|
||||
|
||||
struct Platform::Device : Platform::Abstract_device, Genode::List<Device>::Element
|
||||
{
|
||||
Genode::Env &env;
|
||||
|
||||
unsigned irq_num;
|
||||
Genode::Constructible<Genode::Irq_connection> irq_connection;
|
||||
|
||||
Device(Genode::Env &env, unsigned irq) : env(env), irq_num(irq) { }
|
||||
|
||||
unsigned vendor_id() { return ~0U; }
|
||||
unsigned device_id() { return ~0U; }
|
||||
|
||||
Genode::Irq_session_capability irq(Genode::uint8_t) override
|
||||
{
|
||||
irq_connection.construct(env, irq_num);
|
||||
return irq_connection->cap();
|
||||
}
|
||||
|
||||
Genode::Io_mem_session_capability io_mem(Genode::uint8_t,
|
||||
Genode::Cache_attribute,
|
||||
Genode::addr_t, Genode::size_t) override
|
||||
{
|
||||
lx_printf("%s: not implemented\n", __PRETTY_FUNCTION__);
|
||||
return Genode::Io_mem_session_capability();
|
||||
}
|
||||
|
||||
static Genode::List<Device> &list()
|
||||
{
|
||||
static Genode::List<Device> l;
|
||||
return l;
|
||||
}
|
||||
|
||||
static Device &create(Genode::Env &env, unsigned irq_num)
|
||||
{
|
||||
Device *d;
|
||||
for (d = list().first(); d; d = d->next())
|
||||
if (d->irq_num == irq_num)
|
||||
return *d;
|
||||
|
||||
d = new (Lx::Malloc::mem()) Device(env, irq_num);
|
||||
list().insert(d);
|
||||
|
||||
return *d;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _ARM__PLATFORM_DEVICE__PLATFORM_DEVICE_H_ */
|
340
repos/dde_linux/src/drivers/usb_host/spec/arndale/platform.cc
Normal file
340
repos/dde_linux/src/drivers/usb_host/spec/arndale/platform.cc
Normal file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* \brief EHCI for Arndale initialization code
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2013-02-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
#include <drivers/defs/arndale.h>
|
||||
#include <base/attached_io_mem_dataspace.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <regulator/consts.h>
|
||||
#include <regulator_session/connection.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <util/mmio.h>
|
||||
|
||||
/* Emulation */
|
||||
#include <lx_emul.h>
|
||||
#include <platform.h>
|
||||
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
enum {
|
||||
EHCI_BASE = 0x12110000,
|
||||
DWC3_BASE = 0x12000000,
|
||||
DWC3_PHY_BASE = 0x12100000,
|
||||
GPIO_BASE = 0x11400000,
|
||||
EHCI_IRQ = Arndale::USB_HOST20_IRQ,
|
||||
DWC3_IRQ = Arndale::USB_DRD30_IRQ,
|
||||
};
|
||||
|
||||
static resource _ehci[] =
|
||||
{
|
||||
{ EHCI_BASE, EHCI_BASE + 0xfff, "ehci", IORESOURCE_MEM },
|
||||
{ EHCI_IRQ, EHCI_IRQ, "ehci-irq", IORESOURCE_IRQ },
|
||||
};
|
||||
|
||||
static resource _dwc3[] =
|
||||
{
|
||||
{ DWC3_BASE, DWC3_BASE + 0xcfff, "dwc3", IORESOURCE_MEM },
|
||||
{ DWC3_IRQ, DWC3_IRQ, "dwc3-irq", IORESOURCE_IRQ },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* EHCI controller
|
||||
*/
|
||||
struct Ehci : Genode::Mmio
|
||||
{
|
||||
Ehci(addr_t const mmio_base) : Mmio(mmio_base)
|
||||
{
|
||||
write<Cmd>(0);
|
||||
|
||||
/* reset */
|
||||
write<Cmd::Reset>(1);
|
||||
|
||||
while(read<Cmd::Reset>())
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
struct Cmd : Register<0x10, 32>
|
||||
{
|
||||
struct Reset : Bitfield<1, 1> { };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Gpio handling
|
||||
*/
|
||||
struct Gpio_bank {
|
||||
unsigned con;
|
||||
unsigned dat;
|
||||
};
|
||||
|
||||
|
||||
static inline
|
||||
unsigned con_mask(unsigned val) { return 0xf << ((val) << 2); }
|
||||
|
||||
|
||||
static inline
|
||||
unsigned con_sfr(unsigned x, unsigned v) { return (v) << ((x) << 2); }
|
||||
|
||||
|
||||
static void gpio_cfg_pin(Gpio_bank *bank, int gpio, int cfg)
|
||||
{
|
||||
unsigned int value;
|
||||
|
||||
value = readl(&bank->con);
|
||||
value &= ~con_mask(gpio);
|
||||
value |= con_sfr(gpio, cfg);
|
||||
writel(value, &bank->con);
|
||||
}
|
||||
|
||||
|
||||
static void gpio_direction_output(Gpio_bank *bank, int gpio, int en)
|
||||
{
|
||||
unsigned int value;
|
||||
enum { GPIO_OUTPUT = 0x1 };
|
||||
|
||||
gpio_cfg_pin(bank, gpio, GPIO_OUTPUT);
|
||||
|
||||
value = readl(&bank->dat);
|
||||
value &= ~(0x1 << gpio);
|
||||
if (en)
|
||||
value |= 0x1 << gpio;
|
||||
writel(value, &bank->dat);
|
||||
}
|
||||
|
||||
|
||||
static void arndale_ehci_init(Genode::Env &env)
|
||||
{
|
||||
enum Gpio_offset { D1 = 0x180, X3 = 0xc60 };
|
||||
|
||||
/* enable USB3 clock and power up */
|
||||
static Regulator::Connection reg_clk(env, Regulator::CLK_USB20);
|
||||
reg_clk.state(true);
|
||||
|
||||
static Regulator::Connection reg_pwr(env, Regulator::PWR_USB20);
|
||||
reg_pwr.state(true);
|
||||
|
||||
/* reset hub via GPIO */
|
||||
Io_mem_connection io_gpio(env, GPIO_BASE, 0x1000);
|
||||
addr_t gpio_base = (addr_t)env.rm().attach(io_gpio.dataspace());
|
||||
|
||||
Gpio_bank *d1 = reinterpret_cast<Gpio_bank *>(gpio_base + D1);
|
||||
Gpio_bank *x3 = reinterpret_cast<Gpio_bank *>(gpio_base + X3);
|
||||
|
||||
/* hub reset */
|
||||
gpio_direction_output(x3, 5, 0);
|
||||
/* hub connect */
|
||||
gpio_direction_output(d1, 7, 0);
|
||||
|
||||
gpio_direction_output(x3, 5, 1);
|
||||
gpio_direction_output(d1, 7, 1);
|
||||
|
||||
env.rm().detach(gpio_base);
|
||||
|
||||
/* reset ehci controller */
|
||||
Io_mem_connection io_ehci(env, EHCI_BASE, 0x1000);
|
||||
addr_t ehci_base = (addr_t)env.rm().attach(io_ehci.dataspace());
|
||||
|
||||
Ehci ehci(ehci_base);
|
||||
env.rm().detach(ehci_base);
|
||||
}
|
||||
|
||||
|
||||
struct Phy_usb3 : Genode::Mmio
|
||||
{
|
||||
struct Link_system : Register<0x4, 32>
|
||||
{
|
||||
struct Fladj : Bitfield<1, 6> { };
|
||||
struct Ehci_version_control : Bitfield<27, 1> { };
|
||||
};
|
||||
|
||||
struct Phy_utmi : Register<0x8, 32> { };
|
||||
|
||||
struct Phy_clk_rst : Register<0x10, 32>
|
||||
{
|
||||
struct Common_onn : Bitfield<0, 1> { };
|
||||
struct Port_reset : Bitfield<1, 1> { };
|
||||
struct Ref_clk_sel : Bitfield<2, 2> { };
|
||||
struct Retenablen : Bitfield<4, 1> { };
|
||||
struct Fsel : Bitfield<5, 6> { };
|
||||
struct Mpll_mult : Bitfield<11, 7> { };
|
||||
struct Ref_ssp_en : Bitfield<19, 1> { };
|
||||
struct Ssc_en : Bitfield<20, 1> { };
|
||||
struct Ssc_ref_clk_sel : Bitfield<23, 8> { };
|
||||
};
|
||||
|
||||
struct Phy_reg0 : Register<0x14, 32> { };
|
||||
|
||||
struct Phy_param0 : Register<0x1c, 32>
|
||||
{
|
||||
struct Loss_level : Bitfield<26, 5> { };
|
||||
struct Ref_use_pad : Bitfield<31, 1> { };
|
||||
};
|
||||
|
||||
struct Phy_param1 : Register<0x20, 32>
|
||||
{
|
||||
struct Pcs_txdeemph : Bitfield<0, 5> { };
|
||||
};
|
||||
|
||||
struct Phy_test : Register<0x28, 32>
|
||||
{
|
||||
struct Power_down_ssb_hsb : Bitfield<2, 2> { };
|
||||
};
|
||||
|
||||
struct Phy_batchg : Register<0x30, 32>
|
||||
{
|
||||
struct Utmi_clksel : Bitfield<2, 1> { };
|
||||
};
|
||||
|
||||
struct Phy_resume : Register<0x34, 32> { };
|
||||
|
||||
Phy_usb3 (Genode::Env & env, addr_t const base) : Mmio(base)
|
||||
{
|
||||
Timer::Connection timer(env);
|
||||
|
||||
/* reset */
|
||||
write<Phy_reg0>(0);
|
||||
|
||||
/* clock source */
|
||||
write<Phy_param0::Ref_use_pad>(0);
|
||||
|
||||
/* set Loss-of-Signal Detector sensitivity */
|
||||
write<Phy_param0::Loss_level>(0x9);
|
||||
write<Phy_resume>(0);
|
||||
|
||||
/*
|
||||
* Setting the Frame length Adj value[6:1] to default 0x20
|
||||
* See xHCI 1.0 spec, 5.2.4
|
||||
*/
|
||||
write<Link_system::Ehci_version_control>(1);
|
||||
write<Link_system::Fladj>(0x20);
|
||||
|
||||
/* set Tx De-Emphasis level */
|
||||
write<Phy_param1::Pcs_txdeemph>(0x1c);
|
||||
|
||||
/* set clock */
|
||||
write<Phy_batchg::Utmi_clksel>(1);
|
||||
|
||||
/* PHYTEST POWERDOWN Control */
|
||||
write<Phy_test::Power_down_ssb_hsb>(0);
|
||||
|
||||
/* UTMI power */
|
||||
enum { OTG_DISABLE = (1 << 6) };
|
||||
write<Phy_utmi>(OTG_DISABLE);
|
||||
|
||||
/* setup clock */
|
||||
Phy_clk_rst::access_t clk = 0;
|
||||
|
||||
/*
|
||||
* Use same reference clock for high speed
|
||||
* as for super speed
|
||||
*/
|
||||
Phy_clk_rst::Ref_clk_sel::set(clk, 0x2);
|
||||
/* 24 MHz */
|
||||
Phy_clk_rst::Fsel::set(clk, 0x2a);
|
||||
Phy_clk_rst::Mpll_mult::set(clk, 0x68);
|
||||
Phy_clk_rst::Ssc_ref_clk_sel::set(clk, 0x88);
|
||||
|
||||
/* port reset */
|
||||
Phy_clk_rst::Port_reset::set(clk, 1);
|
||||
|
||||
/* digital power supply in normal operating mode */
|
||||
Phy_clk_rst::Retenablen::set(clk, 1);
|
||||
/* enable ref clock for SS function */
|
||||
Phy_clk_rst::Ref_ssp_en::set(clk, 1);
|
||||
/* enable spread spectrum */
|
||||
Phy_clk_rst::Ssc_en::set(clk, 1);
|
||||
/* power down HS Bias and PLL blocks in suspend mode */
|
||||
Phy_clk_rst::Common_onn::set(clk, 1);
|
||||
|
||||
write<Phy_clk_rst>(clk);
|
||||
timer.usleep(10);
|
||||
write<Phy_clk_rst::Port_reset>(0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static void arndale_xhci_init(Genode::Env &env)
|
||||
{
|
||||
/* enable USB3 clock and power up */
|
||||
static Regulator::Connection reg_clk(env, Regulator::CLK_USB30);
|
||||
reg_clk.state(true);
|
||||
|
||||
static Regulator::Connection reg_pwr(env, Regulator::PWR_USB30);
|
||||
reg_pwr.state(true);
|
||||
|
||||
/* setup PHY */
|
||||
Attached_io_mem_dataspace io_phy(env, DWC3_PHY_BASE, 0x1000);
|
||||
Phy_usb3 phy(env, (addr_t)io_phy.local_addr<addr_t>());
|
||||
}
|
||||
|
||||
|
||||
extern "C" void module_ehci_exynos_init();
|
||||
extern "C" void module_dwc3_driver_init();
|
||||
extern "C" void module_xhci_plat_init();
|
||||
|
||||
|
||||
void ehci_setup(Services *services)
|
||||
{
|
||||
/* register EHCI controller */
|
||||
module_ehci_exynos_init();
|
||||
|
||||
/* setup controller */
|
||||
arndale_ehci_init(services->env);
|
||||
|
||||
/* setup EHCI-controller platform device */
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"exynos-ehci";
|
||||
pdev->id = 0;
|
||||
pdev->num_resources = 2;
|
||||
pdev->resource = _ehci;
|
||||
|
||||
/*needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */
|
||||
static u64 dma_mask = ~(u64)0;
|
||||
pdev->dev.dma_mask = &dma_mask;
|
||||
pdev->dev.coherent_dma_mask = ~0;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
||||
|
||||
|
||||
void xhci_setup(Services *services)
|
||||
{
|
||||
module_dwc3_driver_init();
|
||||
module_xhci_plat_init();
|
||||
|
||||
arndale_xhci_init(services->env);
|
||||
|
||||
/* setup DWC3-controller platform device */
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"dwc3";
|
||||
pdev->id = 0;
|
||||
pdev->num_resources = 2;
|
||||
pdev->resource = _dwc3;
|
||||
|
||||
/*needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */
|
||||
static u64 dma_mask = ~(u64)0;
|
||||
pdev->dev.dma_mask = &dma_mask;
|
||||
pdev->dev.coherent_dma_mask = ~0;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
||||
|
||||
|
||||
void platform_hcd_init(Services *services)
|
||||
{
|
||||
ehci_setup(services);
|
||||
xhci_setup(services);
|
||||
}
|
22
repos/dde_linux/src/drivers/usb_host/spec/arndale/target.mk
Normal file
22
repos/dde_linux/src/drivers/usb_host/spec/arndale/target.mk
Normal file
@ -0,0 +1,22 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/target.inc
|
||||
|
||||
TARGET = arndale_usb_host_drv
|
||||
REQUIRES = arndale
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
||||
SRC_CC += spec/arm/platform.cc
|
||||
SRC_CC += spec/arndale/platform.cc
|
||||
|
||||
SRC_C += usb/dwc3/core.c
|
||||
SRC_C += usb/dwc3/dwc3-exynos.c
|
||||
SRC_C += usb/dwc3/host.c
|
||||
SRC_C += usb/host/ehci-exynos.c
|
||||
SRC_C += usb/host/xhci-plat.c
|
||||
|
||||
CC_OPT += -DCONFIG_USB_EHCI_TT_NEWSCHED=1
|
||||
CC_OPT += -DCONFIG_USB_DWC3_HOST=1
|
||||
CC_OPT += -DCONFIG_USB_OTG_UTILS=1
|
||||
CC_OPT += -DCONFIG_USB_XHCI_PLATFORM=1
|
||||
CC_OPT += -DDWC3_QUIRK
|
207
repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/platform.cc
Normal file
207
repos/dde_linux/src/drivers/usb_host/spec/odroid_x2/platform.cc
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* \brief EHCI for Odroid-x2 initializaion code
|
||||
* \author Sebastian Sumpf
|
||||
* \author Alexy Gallardo Segura <alexy@uclv.cu>
|
||||
* \author Humberto Lopez Leon <humberto@uclv.cu>
|
||||
* \author Reinir Millo Sanchez <rmillo@uclv.cu>
|
||||
* \date 2015-07-08
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode */
|
||||
#include <drivers/defs/odroid_x2.h>
|
||||
#include <base/attached_io_mem_dataspace.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <regulator/consts.h>
|
||||
#include <regulator_session/connection.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <util/mmio.h>
|
||||
#include <gpio_session/connection.h>
|
||||
|
||||
/* Emulation */
|
||||
#include <lx_emul.h>
|
||||
#include <platform.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
|
||||
enum Usb_masks {
|
||||
PHY0_NORMAL_MASK = 0x39 << 0,
|
||||
PHY0_SWRST_MASK = 0x7 << 0,
|
||||
PHY1_STD_NORMAL_MASK = 0x7 << 6,
|
||||
EXYNOS4X12_HSIC0_NORMAL_MASK = 0x7 << 9,
|
||||
EXYNOS4X12_HSIC1_NORMAL_MASK = 0x7 << 12,
|
||||
EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK = 0xf << 7,
|
||||
EXYNOS4X12_PHY1_SWRST_MASK = 0xf << 3,
|
||||
};
|
||||
|
||||
enum {
|
||||
/*The EHCI base is taken from linux kernel */
|
||||
EHCI_BASE = 0x12580000,
|
||||
GPIO_BASE = 0x11000000,
|
||||
USBOTG = 0x125B0000,
|
||||
EHCI_IRQ = Odroid_x2::USB_HOST20_IRQ,
|
||||
};
|
||||
|
||||
static resource _ehci[] =
|
||||
{
|
||||
{ EHCI_BASE, EHCI_BASE + 0xfff, "ehci", IORESOURCE_MEM },
|
||||
{ EHCI_IRQ, EHCI_IRQ, "ehci-irq", IORESOURCE_IRQ },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* EHCI controller
|
||||
*/
|
||||
struct Ehci : Genode::Mmio
|
||||
{
|
||||
Ehci(addr_t const mmio_base) : Mmio(mmio_base)
|
||||
{
|
||||
write<Cmd>(0);
|
||||
|
||||
/* reset */
|
||||
write<Cmd::Reset>(1);
|
||||
|
||||
while(read<Cmd::Reset>())
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
struct Cmd : Register<0x10, 32>
|
||||
{
|
||||
struct Reset : Bitfield<1, 1> { };
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* USB OTG handling
|
||||
*/
|
||||
struct Usb_otg : Genode::Mmio
|
||||
{
|
||||
Usb_otg(Genode::Env &env, Genode::addr_t base)
|
||||
: Genode::Mmio (base)
|
||||
{
|
||||
Timer::Connection timer(env);
|
||||
unsigned int rstcon_mask = 0;
|
||||
unsigned int phyclk_mask = 5;
|
||||
unsigned int phypwr_mask = 0;
|
||||
|
||||
/*set the clock of device*/
|
||||
write<Phyclk>(phyclk_mask);
|
||||
rstcon_mask= read<Phyclk>();
|
||||
|
||||
/* set to normal of Device */
|
||||
phypwr_mask= read<Phypwr>() & ~PHY0_NORMAL_MASK;
|
||||
write<Phypwr>(phypwr_mask);
|
||||
|
||||
/* set to normal of Host */
|
||||
phypwr_mask=read<Phypwr>();
|
||||
phypwr_mask &= ~(PHY1_STD_NORMAL_MASK
|
||||
|EXYNOS4X12_HSIC0_NORMAL_MASK
|
||||
|EXYNOS4X12_HSIC1_NORMAL_MASK);
|
||||
write<Phypwr>(phypwr_mask);
|
||||
|
||||
/* reset both PHY and Link of Device */
|
||||
rstcon_mask = read<Rstcon>() | PHY0_SWRST_MASK;
|
||||
write<Rstcon>(rstcon_mask);
|
||||
timer.usleep(10);
|
||||
rstcon_mask &= ~PHY0_SWRST_MASK;
|
||||
write<Rstcon>(rstcon_mask);
|
||||
|
||||
/* reset both PHY and Link of Host */
|
||||
rstcon_mask = read<Rstcon>()
|
||||
|EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK
|
||||
|EXYNOS4X12_PHY1_SWRST_MASK;
|
||||
write<Rstcon>(rstcon_mask);
|
||||
timer.usleep(10);
|
||||
rstcon_mask &= ~(EXYNOS4X12_HOST_LINK_PORT_SWRST_MASK
|
||||
|EXYNOS4X12_PHY1_SWRST_MASK);
|
||||
write<Rstcon>(rstcon_mask);
|
||||
timer.usleep(10);
|
||||
}
|
||||
struct Phypwr : Register <0x0,32>{};
|
||||
struct Phyclk : Register <0x4,32>{};
|
||||
struct Rstcon : Register <0x8,32>{};
|
||||
};
|
||||
|
||||
static void clock_pwr_init(Genode::Env &env)
|
||||
{
|
||||
/* enable USB2 clock and power up */
|
||||
static Regulator::Connection reg_clk(env, Regulator::CLK_USB20);
|
||||
reg_clk.state(true);
|
||||
|
||||
static Regulator::Connection reg_pwr(env, Regulator::PWR_USB20);
|
||||
reg_pwr.state(true);
|
||||
}
|
||||
|
||||
static void usb_phy_init(Genode::Env &env)
|
||||
{
|
||||
Io_mem_connection io_usbotg(env, USBOTG, 0x1000);
|
||||
addr_t usbotg_base = (addr_t)env.rm().attach(io_usbotg.dataspace());
|
||||
Usb_otg usbotg(env, usbotg_base);
|
||||
env.rm().detach(usbotg_base);
|
||||
}
|
||||
|
||||
static void odroidx2_ehci_init(Genode::Env &env)
|
||||
{
|
||||
clock_pwr_init(env);
|
||||
usb_phy_init(env);
|
||||
|
||||
/* reset hub via GPIO */
|
||||
enum { X30 = 294, X34 = 298, X35 = 299 };
|
||||
|
||||
Gpio::Connection gpio_x30(env, X30);
|
||||
Gpio::Connection gpio_x34(env, X34);
|
||||
Gpio::Connection gpio_x35(env, X35);
|
||||
|
||||
/* Set Ref freq 0 => 24MHz, 1 => 26MHz*/
|
||||
/* Odroid Us have it at 24MHz, Odroid Xs at 26MHz */
|
||||
gpio_x30.write(true);
|
||||
|
||||
/* Disconnect, Reset, Connect */
|
||||
gpio_x34.write(false);
|
||||
gpio_x35.write(false);
|
||||
gpio_x35.write(true);
|
||||
gpio_x34.write(true);
|
||||
|
||||
/* reset ehci controller */
|
||||
Io_mem_connection io_ehci(env, EHCI_BASE, 0x1000);
|
||||
addr_t ehci_base = (addr_t)env.rm().attach(io_ehci.dataspace());
|
||||
|
||||
Ehci ehci(ehci_base);
|
||||
|
||||
env.rm().detach(ehci_base);
|
||||
}
|
||||
|
||||
extern "C" void module_ehci_exynos_init();
|
||||
extern "C" int module_usbnet_init();
|
||||
extern "C" int module_smsc95xx_driver_init();
|
||||
|
||||
|
||||
void platform_hcd_init(Services *services)
|
||||
{
|
||||
/* register EHCI controller */
|
||||
module_ehci_exynos_init();
|
||||
|
||||
/* setup controller */
|
||||
odroidx2_ehci_init(services->env);
|
||||
|
||||
/* setup EHCI-controller platform device */
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"exynos-ehci";
|
||||
pdev->id = 0;
|
||||
pdev->num_resources = 2;
|
||||
pdev->resource = _ehci;
|
||||
|
||||
/*needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */
|
||||
static u64 dma_mask = ~(u64)0;
|
||||
pdev->dev.dma_mask = &dma_mask;
|
||||
pdev->dev.coherent_dma_mask = ~0;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/target.inc
|
||||
|
||||
TARGET = odroid_x2_usb_host_drv
|
||||
REQUIRES = odroid_x2
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
||||
SRC_CC += spec/arm/platform.cc
|
||||
SRC_CC += spec/odroid_x2/platform.cc
|
||||
|
||||
SRC_C += usb/host/ehci-exynos.c
|
||||
|
||||
CC_OPT += -DCONFIG_USB_OTG_UTILS=1
|
309
repos/dde_linux/src/drivers/usb_host/spec/panda/platform.cc
Normal file
309
repos/dde_linux/src/drivers/usb_host/spec/panda/platform.cc
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
* \brief EHCI for OMAP4
|
||||
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
|
||||
* \date 2012-06-20
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#include <drivers/defs/panda.h>
|
||||
#include <gpio_session/connection.h>
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <util/mmio.h>
|
||||
|
||||
#include <lx_emul.h>
|
||||
|
||||
#include <linux/platform_data/usb-omap.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
/**
|
||||
* Base addresses
|
||||
*/
|
||||
enum {
|
||||
EHCI_BASE = 0x4a064c00,
|
||||
UHH_BASE = 0x4a064000,
|
||||
TLL_BASE = 0x4a062000,
|
||||
SCRM_BASE = 0x4a30a000,
|
||||
CAM_BASE = 0x4a009000, /* used for L3INIT_CM2 */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Inerrupt numbers
|
||||
*/
|
||||
enum { IRQ_EHCI = Panda::HSUSB_EHCI_IRQ };
|
||||
|
||||
|
||||
/**
|
||||
* Resources for platform device
|
||||
*/
|
||||
static resource _ehci[] =
|
||||
{
|
||||
{ EHCI_BASE, EHCI_BASE + 0x400 - 1, "ehci", IORESOURCE_MEM },
|
||||
{ IRQ_EHCI, IRQ_EHCI, "ehci-irq", IORESOURCE_IRQ },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Port informations for platform device
|
||||
*/
|
||||
static struct ehci_hcd_omap_platform_data _ehci_data;
|
||||
|
||||
|
||||
/**
|
||||
* Enables USB clocks
|
||||
*/
|
||||
struct Clocks : Genode::Mmio
|
||||
{
|
||||
Clocks(Genode::addr_t const mmio_base) : Mmio(mmio_base)
|
||||
{
|
||||
write<Usb_phy_clk>(0x101);
|
||||
write<Usb_host_clk>(0x1008002);
|
||||
write<Usb_tll_clk>(0x1);
|
||||
}
|
||||
|
||||
struct Usb_host_clk : Register<0x358, 32> { };
|
||||
struct Usb_tll_clk : Register<0x368, 32> { };
|
||||
struct Usb_phy_clk : Register<0x3e0, 32> { };
|
||||
|
||||
template <typename T> void update(unsigned val)
|
||||
{
|
||||
typename T::access_t access = read<T>();
|
||||
access |= val;
|
||||
write<T>(access);
|
||||
};
|
||||
|
||||
void dump()
|
||||
{
|
||||
Usb_host_clk::access_t a1 = read<Usb_host_clk>();
|
||||
Usb_tll_clk::access_t a3 = read<Usb_tll_clk>();
|
||||
Usb_phy_clk::access_t a4 = read<Usb_phy_clk>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Panda board reference USB clock
|
||||
*/
|
||||
struct Aux3 : Genode::Mmio
|
||||
{
|
||||
Aux3(addr_t const mmio_base) : Mmio(mmio_base)
|
||||
{
|
||||
enable();
|
||||
}
|
||||
|
||||
/* the clock register */
|
||||
struct Aux3_clk : Register<0x31c, 32>
|
||||
{
|
||||
struct Src_select : Bitfield<1, 2> { };
|
||||
struct Div : Bitfield<16, 4> { enum { DIV_2 = 1 }; };
|
||||
struct Enable : Bitfield<8, 1> { enum { ON = 1 }; };
|
||||
};
|
||||
|
||||
/* clock source register */
|
||||
struct Aux_src : Register<0x110, 32, true> { };
|
||||
|
||||
void enable()
|
||||
{
|
||||
/* select system clock */
|
||||
write<Aux3_clk::Src_select>(0);
|
||||
|
||||
/* set to 19.2 Mhz */
|
||||
write<Aux3_clk::Div>(Aux3_clk::Div::DIV_2);
|
||||
|
||||
/* enable clock */
|
||||
write<Aux3_clk::Enable>(Aux3_clk::Enable::ON);
|
||||
|
||||
/* enable_ext = 1 | enable_int = 1| mode = 0x01 */
|
||||
write<Aux_src>(0xd);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ULPI transceiverless link
|
||||
*/
|
||||
struct Tll : Genode::Mmio
|
||||
{
|
||||
Tll(addr_t const mmio_base) : Mmio(mmio_base)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
struct Sys_config : Register<0x10, 32>
|
||||
{
|
||||
struct Soft_reset : Bitfield<1, 1> { };
|
||||
struct Cactivity : Bitfield<8, 1> { };
|
||||
struct Sidle_mode : Bitfield<3, 2> { };
|
||||
struct Ena_wakeup : Bitfield<2, 1> { };
|
||||
};
|
||||
|
||||
struct Sys_status : Register<0x14, 32> { };
|
||||
|
||||
void reset()
|
||||
{
|
||||
write<Sys_config>(0x0);
|
||||
|
||||
/* reset */
|
||||
write<Sys_config::Soft_reset>(0x1);
|
||||
|
||||
while(!read<Sys_status>())
|
||||
msleep(1);
|
||||
|
||||
/* disable IDLE, enable wake up, enable auto gating */
|
||||
write<Sys_config::Cactivity>(1);
|
||||
write<Sys_config::Sidle_mode>(1);
|
||||
write<Sys_config::Ena_wakeup>(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* USB high-speed host
|
||||
*/
|
||||
struct Uhh : Genode::Mmio
|
||||
{
|
||||
Uhh(addr_t const mmio_base) : Mmio(mmio_base)
|
||||
{
|
||||
/* diable idle and standby */
|
||||
write<Sys_config::Idle>(1);
|
||||
write<Sys_config::Standby>(1);
|
||||
|
||||
/* set ports to external phy */
|
||||
write<Host_config::P1_mode>(0);
|
||||
write<Host_config::P2_mode>(0);
|
||||
}
|
||||
|
||||
struct Sys_config : Register<0x10, 32>
|
||||
{
|
||||
struct Idle : Bitfield<2, 2> { };
|
||||
struct Standby : Bitfield<4, 2> { };
|
||||
};
|
||||
|
||||
struct Host_config : Register<0x40, 32>
|
||||
{
|
||||
struct P1_mode : Bitfield<16, 2> { };
|
||||
struct P2_mode : Bitfield<18, 2> { };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* EHCI controller
|
||||
*/
|
||||
struct Ehci : Genode::Mmio
|
||||
{
|
||||
Ehci(addr_t const mmio_base) : Mmio(mmio_base)
|
||||
{
|
||||
write<Cmd>(0);
|
||||
|
||||
/* reset */
|
||||
write<Cmd::Reset>(1);
|
||||
|
||||
while(read<Cmd::Reset>())
|
||||
msleep(1);
|
||||
}
|
||||
|
||||
struct Cmd : Register<0x10, 32>
|
||||
{
|
||||
struct Reset : Bitfield<1, 1> { };
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the USB controller from scratch, since the boot loader might not
|
||||
* do it or even disable USB.
|
||||
*/
|
||||
static void omap_ehci_init(Genode::Env &env)
|
||||
{
|
||||
/* taken from the Panda board manual */
|
||||
enum { HUB_POWER = 1, HUB_NRESET = 62, ULPI_PHY_TYPE = 182 };
|
||||
|
||||
/* SCRM */
|
||||
Io_mem_connection io_scrm(env, SCRM_BASE, 0x1000);
|
||||
addr_t scrm_base = (addr_t)env.rm().attach(io_scrm.dataspace());
|
||||
|
||||
/* enable reference clock */
|
||||
Aux3 aux3(scrm_base);
|
||||
|
||||
/* init GPIO */
|
||||
Gpio::Connection gpio_power(env, HUB_POWER);
|
||||
Gpio::Connection gpio_reset(env, HUB_NRESET);
|
||||
|
||||
/* disable the hub power and reset before init */
|
||||
gpio_power.direction(Gpio::Session::OUT);
|
||||
gpio_reset.direction(Gpio::Session::OUT);
|
||||
gpio_power.write(false);
|
||||
gpio_reset.write(true);
|
||||
|
||||
/* enable clocks */
|
||||
Io_mem_connection io_clock(env, CAM_BASE, 0x1000);
|
||||
addr_t clock_base = (addr_t)env.rm().attach(io_clock.dataspace());
|
||||
Clocks c(clock_base);
|
||||
|
||||
/* reset TLL */
|
||||
Io_mem_connection io_tll(env, TLL_BASE, 0x1000);
|
||||
addr_t tll_base = (addr_t)env.rm().attach(io_tll.dataspace());
|
||||
Tll t(tll_base);
|
||||
|
||||
/* reset host */
|
||||
Io_mem_connection io_uhh(env, UHH_BASE, 0x1000);
|
||||
addr_t uhh_base = (addr_t)env.rm().attach(io_uhh.dataspace());
|
||||
Uhh uhh(uhh_base);
|
||||
|
||||
/* enable hub power */
|
||||
gpio_power.write(true);
|
||||
|
||||
/* reset EHCI */
|
||||
addr_t ehci_base = uhh_base + 0xc00;
|
||||
Ehci ehci(ehci_base);
|
||||
|
||||
addr_t base[] = { scrm_base, clock_base, tll_base, uhh_base, 0 };
|
||||
for (int i = 0; base[i]; i++)
|
||||
env.rm().detach(base[i]);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void module_ehci_omap_init();
|
||||
extern "C" int module_usbnet_init();
|
||||
extern "C" int module_smsc95xx_driver_init();
|
||||
|
||||
void platform_hcd_init(Services *services)
|
||||
{
|
||||
/* register EHCI controller */
|
||||
module_ehci_omap_init();
|
||||
|
||||
/* initialize EHCI */
|
||||
omap_ehci_init(services->env);
|
||||
|
||||
/* setup EHCI-controller platform device */
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"ehci-omap";
|
||||
pdev->id = 0;
|
||||
pdev->num_resources = 2;
|
||||
pdev->resource = _ehci;
|
||||
|
||||
|
||||
_ehci_data.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY;
|
||||
_ehci_data.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED;
|
||||
_ehci_data.phy_reset = 0;
|
||||
pdev->dev.platform_data = &_ehci_data;
|
||||
|
||||
/*
|
||||
* Needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c'
|
||||
*/
|
||||
static u64 dma_mask = ~(u64)0;
|
||||
pdev->dev.dma_mask = &dma_mask;
|
||||
pdev->dev.coherent_dma_mask = ~0;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
15
repos/dde_linux/src/drivers/usb_host/spec/panda/target.mk
Normal file
15
repos/dde_linux/src/drivers/usb_host/spec/panda/target.mk
Normal file
@ -0,0 +1,15 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/target.inc
|
||||
|
||||
TARGET = panda_usb_host_drv
|
||||
REQUIRES = panda
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
||||
SRC_CC += spec/arm/platform.cc
|
||||
SRC_CC += spec/panda/platform.cc
|
||||
SRC_C += usb/host/ehci-omap.c
|
||||
|
||||
CC_OPT += -DCONFIG_USB_EHCI_HCD_OMAP=1
|
||||
CC_OPT += -DCONFIG_USB_EHCI_TT_NEWSCHED=1
|
||||
CC_OPT += -DCONFIG_EXTCON=1
|
84
repos/dde_linux/src/drivers/usb_host/spec/rpi/platform.cc
Normal file
84
repos/dde_linux/src/drivers/usb_host/spec/rpi/platform.cc
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* \brief USB initialization for Raspberry Pi
|
||||
* \author Norman Feske
|
||||
* \date 2013-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <io_mem_session/connection.h>
|
||||
#include <util/mmio.h>
|
||||
#include <platform_session/connection.h>
|
||||
|
||||
|
||||
/* emulation */
|
||||
#include <platform.h>
|
||||
#include <lx_emul.h>
|
||||
#include <timer_session/connection.h>
|
||||
|
||||
/* dwc-otg */
|
||||
#define new new_
|
||||
#include <dwc_otg_dbg.h>
|
||||
#undef new
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
unsigned dwc_irq();
|
||||
|
||||
|
||||
/************************************************
|
||||
** Resource info passed to the dwc_otg driver **
|
||||
************************************************/
|
||||
|
||||
enum {
|
||||
DWC_BASE = 0x20980000,
|
||||
DWC_SIZE = 0x20000,
|
||||
};
|
||||
|
||||
|
||||
static resource _dwc_otg_resource[] =
|
||||
{
|
||||
{ DWC_BASE, DWC_BASE + DWC_SIZE - 1, "dwc_otg", IORESOURCE_MEM },
|
||||
{ dwc_irq(), dwc_irq(), "dwc_otg-irq" /* name unused */, IORESOURCE_IRQ }
|
||||
};
|
||||
|
||||
|
||||
/*******************
|
||||
** Init function **
|
||||
*******************/
|
||||
|
||||
extern "C" void module_dwc_otg_driver_init();
|
||||
extern bool fiq_enable, fiq_fsm_enable;
|
||||
|
||||
void platform_hcd_init(Services *services)
|
||||
{
|
||||
/* enable USB power */
|
||||
Platform::Connection platform(services->env);
|
||||
platform.power_state(Platform::Session::POWER_USB_HCD, true);
|
||||
|
||||
/* disable fiq optimization */
|
||||
fiq_enable = false;
|
||||
fiq_fsm_enable = false;
|
||||
|
||||
module_dwc_otg_driver_init();
|
||||
|
||||
/* setup host-controller platform device */
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"dwc_otg";
|
||||
pdev->id = 0;
|
||||
pdev->num_resources = sizeof(_dwc_otg_resource)/sizeof(resource);
|
||||
pdev->resource = _dwc_otg_resource;
|
||||
|
||||
/* needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c' */
|
||||
static u64 dma_mask = ~(u64)0;
|
||||
pdev->dev.dma_mask = &dma_mask;
|
||||
pdev->dev.coherent_dma_mask = ~0;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
49
repos/dde_linux/src/drivers/usb_host/spec/rpi/target.mk
Normal file
49
repos/dde_linux/src/drivers/usb_host/spec/rpi/target.mk
Normal file
@ -0,0 +1,49 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/target.inc
|
||||
|
||||
TARGET = rpi_usb_host_drv
|
||||
REQUIRES = rpi
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
||||
SRC_CC += spec/arm/platform.cc
|
||||
SRC_CC += spec/rpi/platform.cc
|
||||
|
||||
SRC_C += dwc_common_port/dwc_cc.c
|
||||
SRC_C += dwc_common_port/dwc_common_linux.c
|
||||
SRC_C += dwc_common_port/dwc_crypto.c
|
||||
SRC_C += dwc_common_port/dwc_dh.c
|
||||
SRC_C += dwc_common_port/dwc_mem.c
|
||||
SRC_C += dwc_common_port/dwc_modpow.c
|
||||
SRC_C += dwc_common_port/dwc_notifier.c
|
||||
SRC_C += dwc_otg/dwc_otg_adp.c
|
||||
SRC_C += dwc_otg/dwc_otg_attr.c
|
||||
SRC_C += dwc_otg/dwc_otg_cfi.c
|
||||
SRC_C += dwc_otg/dwc_otg_cil.c
|
||||
SRC_C += dwc_otg/dwc_otg_cil_intr.c
|
||||
SRC_C += dwc_otg/dwc_otg_driver.c
|
||||
SRC_C += dwc_otg/dwc_otg_hcd.c
|
||||
SRC_C += dwc_otg/dwc_otg_hcd_ddma.c
|
||||
SRC_C += dwc_otg/dwc_otg_hcd_intr.c
|
||||
SRC_C += dwc_otg/dwc_otg_hcd_linux.c
|
||||
SRC_C += dwc_otg/dwc_otg_hcd_queue.c
|
||||
|
||||
CC_OPT += -DDWC_LINUX -DPLATFORM_INTERFACE
|
||||
|
||||
# needed for 'ehci-hcd.c', which we don't use on the rpi, but it is still
|
||||
# part of the generic usb USB driver
|
||||
CC_OPT += -DCONFIG_USB_EHCI_PCI=1
|
||||
|
||||
# for 'dwc_otg_hcd_linux.c' for enabling the FIQ, which we don't use anyway
|
||||
CC_OPT += -DINTERRUPT_VC_USB=9
|
||||
|
||||
# for 'dwc_otg_driver.c' for preventing calls to set_irq_type
|
||||
CC_OPT += -DIRQF_TRIGGER_LOW=1
|
||||
|
||||
INC_DIR += $(LX_CONTRIB_DIR)/drivers/usb/host/dwc_common_port \
|
||||
$(LX_CONTRIB_DIR)/drivers/usb/host/dwc_otg \
|
||||
$(REP_DIR)/src/lib/usb_host/spec/arm
|
||||
|
||||
vpath %.c $(LX_CONTRIB_DIR)/drivers/usb/host
|
||||
|
||||
LIBS += rpi_usb
|
132
repos/dde_linux/src/drivers/usb_host/spec/wand_quad/platform.cc
Normal file
132
repos/dde_linux/src/drivers/usb_host/spec/wand_quad/platform.cc
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* \brief EHCI for Freescale i.MX6
|
||||
* \author Stefan Kalkowski
|
||||
* \date 2018-04-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <platform.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
extern "C" int module_ci_hdrc_platform_register();
|
||||
extern "C" int module_ci_hdrc_imx_driver_init();
|
||||
extern "C" int module_usbmisc_imx_driver_init();
|
||||
extern "C" int postcore_mxs_phy_module_init();
|
||||
|
||||
extern "C" void module_ehci_hcd_init();
|
||||
extern "C" void module_xhci_hcd_init();
|
||||
|
||||
void platform_hcd_init(Services *services)
|
||||
{
|
||||
module_ehci_hcd_init();
|
||||
module_ci_hdrc_platform_register();
|
||||
postcore_mxs_phy_module_init();
|
||||
module_usbmisc_imx_driver_init();
|
||||
module_ci_hdrc_imx_driver_init();
|
||||
|
||||
/* USB PHY initialization */
|
||||
{
|
||||
static resource usbphy_res[] =
|
||||
{
|
||||
{ 0x020ca000, 0x020cafff, "usbphy", IORESOURCE_MEM },
|
||||
{ 77, 77, "usbphy-irq", IORESOURCE_IRQ },
|
||||
};
|
||||
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"mxs_phy";
|
||||
pdev->id = 0;
|
||||
pdev->num_resources = 2;
|
||||
pdev->resource = usbphy_res;
|
||||
|
||||
pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
|
||||
pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0);
|
||||
pdev->dev.of_node->properties->name = "compatible";
|
||||
pdev->dev.of_node->properties->value = (void*)"fsl,imx6q-usbphy";
|
||||
pdev->dev.of_node->properties->next = (property*)kzalloc(sizeof(property), 0);
|
||||
pdev->dev.of_node->properties->next->name = "fsl,anatop";
|
||||
pdev->dev.of_node->properties->next->value = (void*)0xdeaddead;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
||||
|
||||
device_node * usbmisc_of_node = nullptr;
|
||||
|
||||
/* USB MISC initialization */
|
||||
{
|
||||
static resource usbmisc_res[] = { { 0x02184800, 0x021849ff, "usbmisc", IORESOURCE_MEM }, };
|
||||
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"usbmisc_imx";
|
||||
pdev->id = 1;
|
||||
pdev->num_resources = 1;
|
||||
pdev->resource = usbmisc_res;
|
||||
|
||||
pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
|
||||
pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0);
|
||||
pdev->dev.of_node->properties->name = "compatible";
|
||||
pdev->dev.of_node->properties->value = (void*)"fsl,imx6q-usbmisc";
|
||||
pdev->dev.of_node->dev = &pdev->dev;
|
||||
usbmisc_of_node = pdev->dev.of_node;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
||||
|
||||
/* setup EHCI-controller platform device */
|
||||
{
|
||||
static resource ehci_res[] =
|
||||
{
|
||||
{ 0x02184200, 0x021843ff, "imx_usb", IORESOURCE_MEM },
|
||||
{ 72, 72, "imx_usb-irq", IORESOURCE_IRQ },
|
||||
};
|
||||
|
||||
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||
pdev->name = (char *)"imx_usb";
|
||||
pdev->id = 2;
|
||||
pdev->num_resources = 2;
|
||||
pdev->resource = ehci_res;
|
||||
|
||||
pdev->dev.of_node = (device_node*)kzalloc(sizeof(device_node), 0);
|
||||
pdev->dev.of_node->properties = (property*)kzalloc(sizeof(property), 0);
|
||||
pdev->dev.of_node->properties->name = "compatible";
|
||||
pdev->dev.of_node->properties->value = (void*)"fsl,imx6q-usb";
|
||||
pdev->dev.of_node->properties->next = (property*)kzalloc(sizeof(property), 0);
|
||||
pdev->dev.of_node->properties->next->name = "fsl,usbmisc";
|
||||
pdev->dev.of_node->properties->next->value = (void*)usbmisc_of_node;
|
||||
pdev->dev.of_node->properties->next->next = (property*)kzalloc(sizeof(property), 0);
|
||||
pdev->dev.of_node->properties->next->next->name = "dr_mode";
|
||||
pdev->dev.of_node->properties->next->next->value = (void*)"host";
|
||||
|
||||
/*
|
||||
* Needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c'
|
||||
*/
|
||||
static u64 dma_mask = ~(u64)0;
|
||||
pdev->dev.dma_mask = &dma_mask;
|
||||
pdev->dev.coherent_dma_mask = ~0;
|
||||
|
||||
platform_device_register(pdev);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int devm_extcon_register_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb)
|
||||
{
|
||||
BUG();
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" struct extcon_dev *extcon_get_edev_by_phandle(struct device *dev, int index)
|
||||
{
|
||||
BUG();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
extern "C" int extcon_get_state(struct extcon_dev *edev, unsigned int id)
|
||||
{
|
||||
BUG();
|
||||
return -1;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/target.inc
|
||||
|
||||
TARGET = wand_quad_usb_host_drv
|
||||
REQUIRES = wand_quad
|
||||
|
||||
SRC_C += usb/chipidea/ci_hdrc_imx.c
|
||||
SRC_C += usb/chipidea/core.c
|
||||
SRC_C += usb/chipidea/host.c
|
||||
SRC_C += usb/chipidea/otg.c
|
||||
SRC_C += usb/chipidea/usbmisc_imx.c
|
||||
SRC_C += usb/phy/phy-mxs-usb.c
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/usb_host/spec/arm
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/arm
|
||||
|
||||
SRC_CC += spec/arm/platform.cc
|
||||
SRC_CC += spec/wand_quad/platform.cc
|
||||
|
||||
CC_OPT += -DCONFIG_USB_CHIPIDEA
|
||||
CC_OPT += -DCONFIG_USB_CHIPIDEA_HOST
|
||||
CC_OPT += -DCONFIG_USB_EHCI_HCD
|
||||
CC_OPT += -DCONFIG_USB_EHCI_ROOT_HUB_TT
|
||||
CC_OPT += -DCONFIG_USB_MXS_PHY
|
||||
CC_OPT += -DCONFIG_USB_EHCI_TT_NEWSCHED=1
|
||||
CC_OPT += -DCONFIG_EXTCON=1
|
||||
|
||||
CC_C_OPT += -Wno-incompatible-pointer-types
|
223
repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc
Normal file
223
repos/dde_linux/src/drivers/usb_host/spec/x86/platform.cc
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
* \brief PCI device handling
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2016-04-25
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/allocator.h>
|
||||
#include <base/entrypoint.h>
|
||||
#include <base/lock.h>
|
||||
#include <base/signal.h>
|
||||
#include <util/misc_math.h>
|
||||
|
||||
#include <lx_emul.h>
|
||||
#include <platform.h>
|
||||
|
||||
#include <lx_kit/env.h>
|
||||
#include <lx_kit/irq.h>
|
||||
#include <lx_kit/pci_dev_registry.h>
|
||||
#include <lx_kit/malloc.h>
|
||||
#include <lx_kit/mapped_io_mem_range.h>
|
||||
|
||||
#include <lx_emul/impl/io.h>
|
||||
#include <lx_emul/impl/pci_resource.h>
|
||||
|
||||
|
||||
/**
|
||||
* Quirks
|
||||
*/
|
||||
extern "C" void __pci_fixup_quirk_usb_early_handoff(void *data);
|
||||
|
||||
|
||||
/**
|
||||
* List of pci devices from platform driver
|
||||
*/
|
||||
class Pci_dev_list
|
||||
{
|
||||
private:
|
||||
|
||||
struct Element : public Lx_kit::List<Element>::Element
|
||||
{
|
||||
Platform::Device_capability cap;
|
||||
|
||||
Element(Platform::Device_capability cap) : cap(cap) { }
|
||||
};
|
||||
|
||||
Lx_kit::List<Element> _pci_caps;
|
||||
|
||||
public:
|
||||
|
||||
Pci_dev_list()
|
||||
{
|
||||
/*
|
||||
* Obtain first device, the operation may exceed the session quota.
|
||||
* So we use the 'with_upgrade' mechanism.
|
||||
*/
|
||||
Platform::Device_capability cap =
|
||||
Lx::pci()->with_upgrade([&] () {
|
||||
return Lx::pci()->first_device(); });
|
||||
|
||||
/*
|
||||
* Iterate over the devices of the platform session.
|
||||
*/
|
||||
while (cap.valid()) {
|
||||
|
||||
_pci_caps.insert(new (Lx::Malloc::mem()) Element(cap));
|
||||
|
||||
/* try next one. Upgrade session quota on demand.*/
|
||||
Lx::pci()->with_upgrade([&] () {
|
||||
cap = Lx::pci()->next_device(cap); });
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each_pci_device(FUNC const &func)
|
||||
{
|
||||
for (Element *e = _pci_caps.first(); e; e = e->next())
|
||||
func(e->cap);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Pci_dev_list *pci_dev_list()
|
||||
{
|
||||
static Pci_dev_list _list;
|
||||
return &_list;
|
||||
}
|
||||
|
||||
|
||||
extern "C" int pci_register_driver(struct pci_driver *driver)
|
||||
{
|
||||
driver->driver.name = driver->name;
|
||||
|
||||
pci_device_id const *id_table = driver->id_table;
|
||||
if (!id_table)
|
||||
return -ENODEV;
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
bool found = false;
|
||||
|
||||
auto lamda = [&] (Platform::Device_capability cap) {
|
||||
|
||||
Platform::Device_client client(cap);
|
||||
|
||||
/* request device ID from platform driver */
|
||||
unsigned const class_code = client.class_code();
|
||||
|
||||
/* look if we find the device ID in the driver's 'id_table' */
|
||||
pci_device_id const *matching_id = nullptr;
|
||||
for (pci_device_id const *id = id_table; id->device; id++) {
|
||||
|
||||
lx_log(DEBUG_PCI,"idclass: %x idclassm: %x devclass %x", id->class_,
|
||||
id->class_mask, class_code);
|
||||
|
||||
/* check for drivers that support any device for a given class */
|
||||
if (id->device != (unsigned)PCI_ANY_ID || !id->class_mask)
|
||||
continue;
|
||||
|
||||
if ((id->class_ & id->class_mask) == (class_code & id->class_mask)) {
|
||||
matching_id = id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip device that is not handled by driver */
|
||||
if (!matching_id)
|
||||
return false;
|
||||
|
||||
/* create 'pci_dev' struct for matching device */
|
||||
Lx::Pci_dev *pci_dev = new (Lx::Malloc::mem()) Lx::Pci_dev(cap);
|
||||
|
||||
/* enable ioremap to work */
|
||||
Lx::pci_dev_registry()->insert(pci_dev);
|
||||
|
||||
/* register driver at the 'pci_dev' struct */
|
||||
pci_dev->dev.driver = &driver->driver;
|
||||
|
||||
/*
|
||||
* This quirk handles device handoff from BIOS, since the BIOS may still
|
||||
* access the USB controller after bootup. For this the ext cap register of
|
||||
* the PCI config space is checked
|
||||
*/
|
||||
if (Lx_kit::env().config_rom().xml().attribute_value("bios_handoff", true))
|
||||
__pci_fixup_quirk_usb_early_handoff(pci_dev);
|
||||
|
||||
/* call probe function of the Linux driver */
|
||||
if (driver->probe(pci_dev, matching_id)) {
|
||||
|
||||
/* if the probing failed, revert the creation of 'pci_dev' */
|
||||
pci_dev_put(pci_dev);
|
||||
return false;
|
||||
}
|
||||
|
||||
found = true;
|
||||
|
||||
/* multiple device support continue */
|
||||
return true;
|
||||
};
|
||||
|
||||
pci_dev_list()->for_each_pci_device(lamda);
|
||||
|
||||
return found ? 0 : -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
/***********************
|
||||
** linux/interrupt.h **
|
||||
***********************/
|
||||
|
||||
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
|
||||
const char *name, void *dev)
|
||||
{
|
||||
for (Lx::Pci_dev *pci_dev = Lx::pci_dev_registry()->first(); pci_dev; pci_dev = pci_dev->next())
|
||||
if (pci_dev->irq == irq) {
|
||||
Lx::Irq::irq().request_irq(pci_dev->client(), handler, dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
|
||||
/*********************************
|
||||
** Platform backend alloc init **
|
||||
*********************************/
|
||||
|
||||
void backend_alloc_init(Genode::Env &env, Genode::Ram_session &ram,
|
||||
Genode::Allocator &alloc)
|
||||
{
|
||||
Lx::pci_init(env, ram, alloc);
|
||||
}
|
||||
|
||||
|
||||
extern "C" void module_ehci_hcd_init();
|
||||
extern "C" void module_ehci_pci_init();
|
||||
extern "C" void module_ohci_hcd_mod_init();
|
||||
extern "C" void module_ohci_pci_init();
|
||||
extern "C" void module_uhci_hcd_init();
|
||||
extern "C" void module_xhci_hcd_init();
|
||||
extern "C" void module_xhci_pci_init();
|
||||
|
||||
void platform_hcd_init(Services *s)
|
||||
{
|
||||
module_xhci_hcd_init();
|
||||
module_xhci_pci_init();
|
||||
|
||||
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
|
||||
module_ehci_hcd_init();
|
||||
module_ehci_pci_init();
|
||||
|
||||
module_ohci_hcd_mod_init();
|
||||
module_ohci_pci_init();
|
||||
|
||||
module_uhci_hcd_init();
|
||||
}
|
24
repos/dde_linux/src/drivers/usb_host/spec/x86/target.inc
Normal file
24
repos/dde_linux/src/drivers/usb_host/spec/x86/target.inc
Normal file
@ -0,0 +1,24 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/target.inc
|
||||
|
||||
TARGET = x86_pc_usb_host_drv
|
||||
|
||||
INC_DIR += $(REP_DIR)/src_drivers/usb_host/spec/x86
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/x86
|
||||
|
||||
SRC_C += usb/core/hcd-pci.c
|
||||
SRC_C += usb/host/ehci-pci.c
|
||||
SRC_C += usb/host/ohci-hcd.c
|
||||
SRC_C += usb/host/ohci-pci.c
|
||||
SRC_C += usb/host/pci-quirks.c
|
||||
SRC_C += usb/host/uhci-hcd.c
|
||||
SRC_C += usb/host/xhci-pci.c
|
||||
|
||||
SRC_CC += lx_kit/mapped_io_mem_range.cc
|
||||
SRC_CC += lx_kit/pci.cc
|
||||
|
||||
SRC_CC += spec/x86/platform.cc
|
||||
|
||||
CC_OPT += -DCONFIG_PCI=1
|
||||
CC_OPT += -DCONFIG_USB_PCI=1
|
||||
CC_OPT += -DCONFIG_USB_EHCI_PCI=1
|
||||
CC_OPT += -DCONFIG_USB_XHCI_HCD=1
|
@ -0,0 +1,4 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/spec/x86/target.inc
|
||||
|
||||
REQUIRES = x86_32
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/x86_32
|
@ -0,0 +1,4 @@
|
||||
include $(REP_DIR)/src/drivers/usb_host/spec/x86/target.inc
|
||||
|
||||
REQUIRES = x86_64
|
||||
INC_DIR += $(REP_DIR)/src/include/spec/x86_64
|
66
repos/dde_linux/src/drivers/usb_host/target.inc
Normal file
66
repos/dde_linux/src/drivers/usb_host/target.inc
Normal file
@ -0,0 +1,66 @@
|
||||
LX_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_host
|
||||
SRC_CC = main.cc lx_emul.cc raw.cc
|
||||
SRC_C = dummies.c raw_driver.c
|
||||
LIBS = base usb_host_include lx_kit_setjmp
|
||||
CC_CXX_WARN_STRICT =
|
||||
|
||||
INC_DIR += $(REP_DIR)/src/drivers/usb_host
|
||||
INC_DIR += $(REP_DIR)/src/include
|
||||
|
||||
# lx_kit
|
||||
SRC_CC += lx_kit/printf.cc
|
||||
SRC_CC += lx_kit/work.cc
|
||||
SRC_CC += lx_kit/timer.cc
|
||||
SRC_CC += lx_kit/scheduler.cc
|
||||
SRC_CC += lx_kit/irq.cc
|
||||
SRC_CC += lx_kit/malloc.cc
|
||||
SRC_CC += lx_kit/env.cc
|
||||
|
||||
# contrib code
|
||||
SRC_C += usb/common/common.c
|
||||
SRC_C += usb/core/buffer.c
|
||||
SRC_C += usb/core/config.c
|
||||
SRC_C += usb/core/devices.c
|
||||
SRC_C += usb/core/driver.c
|
||||
SRC_C += usb/core/endpoint.c
|
||||
SRC_C += usb/core/file.c
|
||||
SRC_C += usb/core/generic.c
|
||||
SRC_C += usb/core/hcd.c
|
||||
SRC_C += usb/core/hub.c
|
||||
SRC_C += usb/core/message.c
|
||||
SRC_C += usb/core/notify.c
|
||||
SRC_C += usb/core/port.c
|
||||
SRC_C += usb/core/quirks.c
|
||||
SRC_C += usb/core/urb.c
|
||||
SRC_C += usb/core/usb.c
|
||||
SRC_C += usb/host/ehci-hcd.c
|
||||
SRC_C += usb/host/xhci-dbg.c
|
||||
SRC_C += usb/host/xhci-hub.c
|
||||
SRC_C += usb/host/xhci-mem.c
|
||||
SRC_C += usb/host/xhci-ring.c
|
||||
SRC_C += usb/host/xhci.c
|
||||
SRC_C += lib/ctype.c
|
||||
SRC_C += lib/find_bit.c
|
||||
|
||||
CC_OPT += -U__linux__
|
||||
CC_OPT += -D__KERNEL__
|
||||
CC_OPT += -DCONFIG_USB_DEVICEFS=1
|
||||
CC_OPT += -DCONFIG_HOTPLUG=1
|
||||
CC_OPT += -DCONFIG_USB_PHY=1
|
||||
CC_OPT += -DCONFIG_HAS_DMA=1
|
||||
CC_C_OPT += -std=gnu89
|
||||
CC_C_OPT += -Wno-pointer-sign
|
||||
CC_C_OPT += -Wno-unused-variable
|
||||
CC_C_OPT += -Wno-unused-function
|
||||
CC_C_OPT += -Wno-implicit-int
|
||||
CC_C_OPT += -Wno-unused-but-set-variable
|
||||
CC_C_OPT += -Wno-uninitialized
|
||||
CC_C_OPT += -Wno-maybe-uninitialized
|
||||
CC_C_OPT += -Wno-unused-label
|
||||
CC_C_OPT += -Wno-format
|
||||
|
||||
vpath lib/ctype.c $(LX_CONTRIB_DIR)
|
||||
vpath lib/find_bit.c $(LX_CONTRIB_DIR)
|
||||
vpath %.c $(LX_CONTRIB_DIR)/drivers
|
||||
vpath %.cc $(REP_DIR)/src
|
||||
vpath % $(REP_DIR)/src/drivers/usb_host
|
Reference in New Issue
Block a user