OMAP4 USB driver

This commit is contained in:
Sebastian Sumpf 2012-06-20 08:42:16 +02:00 committed by Norman Feske
parent 1030ac1c67
commit e23c334b90
22 changed files with 1034 additions and 121 deletions

View File

@ -7,7 +7,7 @@ CONTRIB_DIR = contrib
DOWNLOAD_DIR = download
VERBOSE ?= @
ECHO = @echo
PATCHES = $(shell find patches -name *.patch)
PATCHES := $(shell find patches -name \*.patch)
LINUX = linux-3.2.2
LINUX_TBZ2 = $(LINUX).tar.bz2
@ -31,7 +31,7 @@ CONTENT += include/linux/usbdevice_fs.h include/asm-generic/ioctl.h
# USB host-controller driver
CONTENT_USB_HOST := ehci.h ehci-hcd.c ehci-hub.c ehci-dbg.c ehci-mem.c \
ehci-q.c ehci-pci.c ehci-sched.c ehci-sysfs.c
ehci-omap.c ehci-q.c ehci-pci.c ehci-sched.c ehci-sysfs.c
CONTENT_USB_HOST += ohci.h ohci-hcd.c ohci-hub.c ohci-dbg.c ohci-mem.c \
ohci-q.c ohci-pci.c ehci-lpm.c
CONTENT_USB_HOST += uhci-hcd.h uhci-hcd.c uhci-debug.c uhci-q.c uhci-hub.c \
@ -57,7 +57,12 @@ CONTENT += $(addprefix drivers/input/,$(CONTENT_INPUT))
CONTENT += include/linux/input/mt.h
CONTRIB_CONTENT := $(addprefix $(CONTRIB_DIR)/,$(CONTENT))
# Panda board
#CONTENT += drivers/mfd/omap-usb-host.c
#CONTENT += arch/arm/plat-omap/include/plat/usb.h
#CONTENT_ARCH = usb-host.c mux.h mux2420.h mux2430.h mux34xx.h mux44xx.h
#CONTENT += $(addprefix arch/arm/mach-omap2/,$(CONTENT_ARCH))
#CONTRIB_CONTENT := $(addprefix $(CONTRIB_DIR)/,$(CONTENT))
#
#
# Utility to check if a tool is installed
@ -100,7 +105,7 @@ $(DOWNLOAD_DIR)/$(LINUX_TBZ2): $(DOWNLOAD_DIR)
$(VERBOSE)touch $@
clean:
$(VERBOSE)rm -f $(CONTRIB_DIR)
$(VERBOSE)rm -rf $(CONTRIB_DIR)
cleanall: clean
$(VERBOSE)rm -rf $(DOWNLOAD_DIR)

View File

@ -0,0 +1,178 @@
/*
* \brief Platform specific part of the Linux API emulation
* \author Sebastian Sumpf
* \date 2012-06-18
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _ARM__PLATFORM__LX_EMUL_H_
#define _ARM__PLATFORM__LX_EMUL_H_
/*************************
** asm-generic/sizes.h **
*************************/
enum {
SZ_1K = 0x00000400,
SZ_4K = 0x00001000a,
};
struct platform_device
{
const char *name;
int id;
struct device dev;
u32 num_resources;
struct resource *resource;
};
/**********************
** linux/usb/ulpi.h **
**********************/
enum {
ULPI_FUNC_CTRL_RESET = (1 << 5),
ULPI_FUNC_CTRL = (1 << 2),
};
/*
* Macros for Set and Clear
* See ULPI 1.1 specification to find the registers with Set and Clear offsets
*/
#define ULPI_SET(a) (a + 1)
/*******************************************
** arch/arm/plat-omap/include/plat/usb.h **
*******************************************/
enum { OMAP3_HS_USB_PORTS = 2 };
enum usbhs_omap_port_mode
{
OMAP_EHCI_PORT_MODE_NONE,
OMAP_EHCI_PORT_MODE_PHY,
};
struct ehci_hcd_omap_platform_data
{
enum usbhs_omap_port_mode port_mode[OMAP3_HS_USB_PORTS];
struct regulator *regulator[OMAP3_HS_USB_PORTS];
};
struct regulator;
/*********************************************
** arch/arm/plat-omap/include/plat/board.h **
*********************************************/
struct omap_usb_config;
/************************************************
** arch/arm/plat-omap/include/plat/omap34xx.h **
************************************************/
#define OMAP34XX_UHH_CONFIG_BASE 0
#define OMAP34XX_EHCI_BASE 0
#define OMAP34XX_USBTLL_BASE 0
#define INT_34XX_EHCI_IRQ 0
#define OMAP34XX_OHCI_BASE 0
#define INT_34XX_OHCI_IRQ 0
#define OMAP3430_REV_ES2_1 0
static inline int cpu_is_omap34xx(void) { return 0; }
static inline int cpu_is_omap3430(void) { return 0; }
/***************************************************
** platform definition os for OMAP44xx all under **
** 'arch/arm/plat-omap/include **
***************************************************/
enum {
OMAP44XX_IRQ_GIC_START = 32,
OMAP44XX_IRQ_EHCI = 77 + OMAP44XX_IRQ_GIC_START,
OMAP44XX_IRQ_OHCI =76 + OMAP44XX_IRQ_GIC_START,
};
enum {
L4_44XX_BASE = 0x4a000000,
OMAP44XX_USBTLL_BASE = L4_44XX_BASE + 0x62000,
OMAP44XX_UHH_CONFIG_BASE = L4_44XX_BASE + 0x64000,
OMAP44XX_HSUSB_OHCI_BASE = L4_44XX_BASE + 0x64800,
OMAP44XX_HSUSB_EHCI_BASE = L4_44XX_BASE + 0x64C00,
};
static inline int cpu_is_omap44xx(void) { return 1; }
/*****************************
** linux/platform_device.h **
*****************************/
struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
struct device_driver driver;
const struct platform_device_id *id_table;
};
struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *);
int platform_get_irq_byname(struct platform_device *, const char *);
int platform_driver_register(struct platform_driver *);
int platform_device_register(struct platform_device *);
/**********************
** asm/generic/io.h **
**********************/
static inline u32 __raw_readl(const volatile void __iomem *addr)
{
return *(const volatile u32 __force *) addr;
}
static inline void __raw_writel(u32 b, volatile void __iomem *addr)
{
*(volatile u32 __force *) addr = b;
}
static inline u8 __raw_readb(const volatile void __iomem *addr)
{
return *(const volatile u8 __force *) addr;
}
static inline void __raw_writeb(u8 b, volatile void __iomem *addr)
{
*(volatile u8 __force *) addr = b;
}
/********************************
** linux/regulator/consumer.h **
********************************/
int regulator_enable(struct regulator *);
int regulator_disable(struct regulator *);
void regulator_put(struct regulator *regulator);
struct regulator *regulator_get(struct device *dev, const char *id);
/*******************************************
** arch/arm/plat-omap/include/plat/usb.h **
*******************************************/
int omap_usbhs_enable(struct device *dev);
void omap_usbhs_disable(struct device *dev);
#endif /* _ARM__PLATFORM__LX_EMUL_H_ */

View File

@ -0,0 +1,395 @@
/**
* \brief EHCI for OMAP4
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-06-20
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <platform/platform.h>
#include <io_mem_session/connection.h>
#include <util/mmio.h>
#include <lx_emul.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_GIC_START = 32,
IRQ_EHCI = IRQ_GIC_START + 77,
};
/**
* 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
{
{ OMAP_EHCI_PORT_MODE_PHY, OMAP_EHCI_PORT_MODE_NONE },
{ 0, 0 }
};
extern "C" void module_ehci_hcd_init();
/**
* 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>();
PDBG("Host clock %x", a1);
Usb_tll_clk::access_t a3 = read<Usb_tll_clk>();
PDBG("TLL: %x", a3);
Usb_phy_clk::access_t a4 = read<Usb_phy_clk>();
PDBG("Phy: %x", a4);
}
};
/**
* 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> { };
};
};
/**
* Panda board GPIO bases 1 - 6
*/
static addr_t omap44xx_gpio_base[] =
{
0x4A310000, 0x48055000, 0x48057000, 0x48059000, 0x4805B000, 0x4805D000
};
/**
* General purpose I/O
*/
struct Gpio
{
enum { GPIO = 6 };
addr_t _io[GPIO];
Io_mem_session_capability _cap[GPIO];
void map()
{
for (int i = 0; i < GPIO; i++) {
Io_mem_connection io(omap44xx_gpio_base[i], 0x1000);
io.on_destruction(Io_mem_connection::KEEP_OPEN);
_io[i] = (addr_t)env()->rm_session()->attach(io.dataspace());
_cap[i] = io.cap();
}
}
Gpio()
{
map();
}
~Gpio()
{
for (int i = 0; i < GPIO; i++) {
env()->rm_session()->detach(_io[i]);
env()->parent()->close(_cap[i]);
}
}
addr_t base(unsigned gpio) { return _io[gpio >> 5]; }
int index(unsigned gpio) { return gpio & 0x1f; }
void _set_data_out(addr_t base, unsigned gpio, bool enable)
{
enum { SETDATAOUT = 0x194, CLEARDATAOUT = 0x190 };
writel(1U << gpio, base + (enable ? SETDATAOUT : CLEARDATAOUT));
}
void _set_gpio_direction(addr_t base, unsigned gpio, bool input)
{
enum { OE = 0x134 };
base += OE;
u32 val = readl(base);
if (input)
val |= 1U << gpio;
else
val &= ~(1U << gpio);
writel(val, base);
}
void direction_output(unsigned gpio, bool enable)
{
_set_data_out(base(gpio), index(gpio), enable);
_set_gpio_direction(base(gpio), index(gpio), false);
}
void direction_input(unsigned gpio)
{
_set_gpio_direction(base(gpio), index(gpio), true);
}
void set_value(unsigned gpio, int val)
{
_set_data_out(base(gpio), index(gpio), val);
}
unsigned get_value(int gpio)
{
enum { DATAIN = 0x138 };
return (readl(base(gpio) + DATAIN) & (1 << index(gpio))) != 0;
}
};
/**
* Initialize the USB controller from scratch, since the boot loader might not
* do it or even disable USB.
*/
static void omap_ehci_init()
{
/* taken from the Panda board manual */
enum { HUB_POWER = 1, HUB_NRESET = 62, ULPI_PHY_TYPE = 182 };
/* SCRM */
Io_mem_connection io_scrm(SCRM_BASE, 0x1000);
addr_t scrm_base = (addr_t)env()->rm_session()->attach(io_scrm.dataspace());
/* enable reference clock */
Aux3 aux3(scrm_base);
/* init GPIO */
Gpio gpio;
/* disable the hub power and reset before init */
gpio.direction_output(HUB_POWER, false);
gpio.direction_output(HUB_NRESET, false);
gpio.set_value(HUB_POWER, 0);
gpio.set_value(HUB_NRESET, 1);
/* enable clocks */
Io_mem_connection io_clock(CAM_BASE, 0x1000);
addr_t clock_base = (addr_t)env()->rm_session()->attach(io_clock.dataspace());
Clocks c(clock_base);
/* reset TLL */
Io_mem_connection io_tll(TLL_BASE, 0x1000);
addr_t tll_base = (addr_t)env()->rm_session()->attach(io_tll.dataspace());
Tll t(tll_base);
/* reset host */
Io_mem_connection io_uhh(UHH_BASE, 0x1000);
addr_t uhh_base = (addr_t)env()->rm_session()->attach(io_uhh.dataspace());
Uhh uhh(uhh_base);
/* enable hub power */
gpio.set_value(HUB_POWER, 1);
/* 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_session()->detach(base[i]);
}
void platform_hcd_init(void)
{
module_ehci_hcd_init();
omap_ehci_init();
/* setup EHCI-controller platform device */
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
pdev->name = "ehci-omap";
pdev->id = 0;
pdev->num_resources = 2;
pdev->resource = _ehci;
pdev->dev.platform_data = &_ehci_data;
/*
* Needed for DMA buffer allocation. See 'hcd_buffer_alloc' in 'buffer.c'
*/
static u64 dma_mask = ~(u32)0;
pdev->dev.dma_mask = &dma_mask;
pdev->dev.coherent_dma_mask = ~0;
platform_device_register(pdev);
}

View File

@ -0,0 +1,38 @@
/**
* \brief Platform specific code
* \author Sebastian Sumpf
* \date 2012-06-10
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _ARM__PLATFORM_H_
#define _ARM__PLATFORM_H_
#ifdef __cplusplus
extern "C" {
#endif
static inline
void platform_execute(void *sp, void *func, void *arg)
{
asm volatile ("mov r0, %2;" /* set arg */
"mov sp, %0;" /* set stack */
"mov pc, %1;" /* call func */
""
: : "r"(sp), "r"(func), "r"(arg) : "r0");
}
void platform_hcd_init(void);
#ifdef __cplusplus
}
#endif
#endif /* _ARM__PLATFORM_H_ */

View File

@ -0,0 +1,88 @@
/*
* \brief Linux platform_device emulation
* \author Sebastian Sumpf
* \date 2012-06-18
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <lx_emul.h>
#define to_platform_driver(drv) (container_of((drv), struct platform_driver, \
driver))
#define to_platform_device(x) container_of((x), struct platform_device, dev)
static int platform_match(struct device *dev, struct device_driver *drv)
{
if (!dev->name)
return 0;
return (strcmp(dev->name, drv->name) == 0);
}
static int platform_drv_probe(struct device *_dev)
{
struct platform_driver *drv = to_platform_driver(_dev->driver);
struct platform_device *dev = to_platform_device(_dev);
return drv->probe(dev);
}
struct bus_type platform_bus_type = {
.name = "platform",
.match = platform_match,
.probe = platform_drv_probe
};
int platform_driver_register(struct platform_driver *drv)
{
drv->driver.bus = &platform_bus_type;
if (drv->probe)
drv->driver.probe = platform_drv_probe;
return driver_register(&drv->driver);
}
struct resource *platform_get_resource_byname(struct platform_device *dev,
unsigned int type,
const char *name)
{
int i;
for (i = 0; i < dev->num_resources; i++) {
struct resource *r = &dev->resource[i];
if (type == r->flags && !strcmp(r->name, name))
return r;
}
return NULL;
}
int platform_get_irq_byname(struct platform_device *dev, const char *name)
{
struct resource *r = platform_get_resource_byname(dev, IORESOURCE_IRQ, name);
return r ? r->start : -1;
}
int platform_device_register(struct platform_device *pdev)
{
pdev->dev.bus = &platform_bus_type;
pdev->dev.name = pdev->name;
/* XXX: Fill with magic value to see page fault */
pdev->dev.parent = (struct device *)0xaaaaaaaa;
device_add(&pdev->dev);
return 0;
}

View File

@ -0,0 +1,94 @@
/*
* \brief DMA memory pool
* \author Sebastian Sumpf
* \date 2012-06-18
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _DMA_H_
#define _DMA_H_
#include <base/allocator_avl.h>
#include <dataspace/client.h>
#include <lx_emul.h>
/*********************
** linux/dmapool.h **
*********************/
namespace Genode {
/**
* Dma-pool manager
*/
class Dma
{
private:
enum { SIZE = 1024 * 1024 };
addr_t _base; /* virt base of pool */
addr_t _base_phys; /* phys base of pool */
Allocator_avl _range; /* range allocator for pool */
Dma() : _range(env()->heap())
{
Ram_dataspace_capability cap = env()->ram_session()->alloc(SIZE);
_base_phys = Dataspace_client(cap).phys_addr();
_base = (addr_t)env()->rm_session()->attach(cap);
dde_kit_log(DEBUG_DMA, "New DMA range [%lx-%lx)", _base, _base + SIZE);
_range.add_range(_base, SIZE);
}
public:
static Dma* pool()
{
static Dma _p;
return &_p;
}
addr_t base() const { return _base; };
addr_t end() const { return _base + SIZE -1; }
/**
* Alloc 'size' bytes of DMA memory
*/
void *alloc(size_t size, int align = 12)
{
void *addr;
if (!_range.alloc_aligned(size, &addr, align)) {
PERR("DMA of %zu bytes allocation failed", size);
return 0;
}
return addr;
}
/**
* Free DMA memory
*/
void free(void *addr) { _range.free(addr); }
/**
* Get phys for virt address
*/
addr_t phys_addr(void *addr)
{
addr_t a = (addr_t)addr;
if (a < _base || a >= _base + SIZE) {
PERR("No DMA phys addr for %lx", a);
return 0;
}
return (a - _base) + _base_phys;
}
};
}
#endif /* _DMA_H_ */

View File

@ -66,7 +66,7 @@ char *kasprintf(gfp_t gfp, const char *fmt, ...) { TRACE; return NULL; }
int kstrtouint(const char *s, unsigned int base, unsigned int *res) { TRACE; return 0; }
int sprintf(char *buf, const char *fmt, ...) { TRACE; return 0; }
int sscanf(const char *b, const char *s, ...) { TRACE; return 0; }
int scnprintf(char *buf, size_t size, const char *fmt, ...) { TRACE; return 0; }
int scnprintf(char *buf, size_t size, const char *fmt, ...);
int strict_strtoul(const char *s, unsigned int base, unsigned long *res) { TRACE; return 0; }
long simple_strtoul(const char *cp, char **endp, unsigned int base) { TRACE; return 0; }
@ -100,7 +100,6 @@ int ffs(int x) { TRACE; return 0; }
int memcmp(const void *dst, const void *src, size_t s) { TRACE; return 0; }
char *strcat(char *dest, const char *src) { TRACE; return 0; }
int strcmp(const char *s1, const char *s2) { TRACE; return 0; }
int strncmp(const char *cs, const char *ct, size_t count) { TRACE; return 0; }
char *strncpy(char *dst, const char *src, size_t s) { TRACE; return NULL; }
char *strchr(const char *s, int n) { TRACE; return NULL; }
@ -236,7 +235,7 @@ void __set_current_state(int state) { TRACE; }
int signal_pending(struct task_struct *p) { TRACE; return 0; }
void schedule(void) { TRACE; }
void yield(void) { TRACE; }
void cpu_relax(void) { TRACE; }
void cpu_relax(void) { TRACE; udelay(1); }
struct task_struct *current;
@ -321,7 +320,6 @@ bool device_can_wakeup(struct device *dev) { TRACE; return 0; }
********************/
int dev_set_name(struct device *dev, const char *name, ...) { TRACE; return 0; }
const char *dev_name(const struct device *dev) { TRACE; return NULL; }
int dev_to_node(struct device *dev) { TRACE; return 0; }
void set_dev_node(struct device *dev, int node) { TRACE; }
@ -523,7 +521,6 @@ void kunmap(struct page *page) { TRACE; }
** asm-generic/io.h **
**********************/
void *ioremap(resource_size_t offset, unsigned long size) { TRACE; return NULL; }
void iounmap(volatile void *addr) { TRACE; }
void native_io_delay(void) { TRACE; }
@ -780,3 +777,19 @@ void scsi_host_put(struct Scsi_Host *shost) { TRACE; }
struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost) { TRACE; return 0; }
/********************************
** linux/regulator/consumer.h **
********************************/
struct regulator;
int regulator_enable(struct regulator *r) { TRACE; return 0; }
int regulator_disable(struct regulator *r) { TRACE; return 0; }
void regulator_put(struct regulator *r) { TRACE; }
struct regulator *regulator_get(struct device *dev, const char *id) { TRACE; return 0; }
/*******************************************
** arch/arm/plat-omap/include/plat/usb.h **
*******************************************/
int omap_usbhs_enable(struct device *dev) { TRACE; return 0; }
void omap_usbhs_disable(struct device *dev) { TRACE; }

View File

@ -10,6 +10,13 @@
* the GNU General Public License version 2.
*/
/*
* Copyright (C) 2009-2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
/* Linux */
#include <linux/input.h>

View File

@ -20,6 +20,7 @@
#include <util/string.h>
/* Local includes */
#include "dma.h"
#include "routine.h"
#include "signal.h"
#include "lx_emul.h"
@ -198,15 +199,32 @@ int snprintf(char *buf, size_t size, const char *fmt, ...)
}
int scnprintf(char *buf, size_t size, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
Genode::String_console sc(buf, size);
sc.vprintf(fmt, args);
va_end(args);
return sc.len();
}
int strcmp(const char *s1, const char *s2) { return Genode::strcmp(s1, s2); }
size_t strlen(const char *s) { return Genode::strlen(s); }
size_t strlcat(char *dest, const char *src, size_t n)
{
size_t len = strlen(dest);
Genode::strncpy(dest + len, src, n);
dest[len + n] = 0;
return n;
if (len >= n)
len = n - 1;
memcpy(dest, src, len);
dest[len] = 0;
return len;
}
@ -320,10 +338,10 @@ void kmem_cache_free(struct kmem_cache *cache, void *objp)
** asm-generic/io.h **
**********************/
void *ioremap_wc(resource_size_t phys_addr, unsigned long size)
void *_ioremap(resource_size_t phys_addr, unsigned long size, int wc)
{
dde_kit_addr_t map_addr;
if (dde_kit_request_mem(phys_addr, size, 1, &map_addr)) {
if (dde_kit_request_mem(phys_addr, size, wc, &map_addr)) {
PERR("Failed to request I/O memory: [%x,%lx)", phys_addr, phys_addr + size);
return 0;
}
@ -332,6 +350,18 @@ void *ioremap_wc(resource_size_t phys_addr, unsigned long size)
}
void *ioremap_wc(resource_size_t phys_addr, unsigned long size)
{
return _ioremap(phys_addr, size, 1);
}
void *ioremap(resource_size_t offset, unsigned long size)
{
return _ioremap(offset, size, 0);
}
/********************
** linux/device.h **
********************/
@ -438,6 +468,7 @@ int dev_set_drvdata(struct device *dev, void *data)
struct device *get_device(struct device *dev) { TRACE; return dev; }
const char *dev_name(const struct device *dev) { return dev->name; }
long find_next_zero_bit_le(const void *addr,
@ -527,78 +558,9 @@ enum { JIFFIES_TICK_MS = 1000 / DDE_KIT_HZ };
unsigned long msecs_to_jiffies(const unsigned int m) { return m / JIFFIES_TICK_MS; }
long time_after_eq(long a, long b) { return (a - b) >= 0; }
long time_after(long a, long b) { return (b - a) > 0; }
long time_after(long a, long b) { return (b - a) < 0; }
/*********************
** linux/dmapool.h **
*********************/
namespace Genode {
/**
* Dma-pool manager
*/
class Dma
{
private:
enum { SIZE = 1024 * 1024 };
addr_t _base; /* virt base of pool */
addr_t _base_phys; /* phys base of pool */
Allocator_avl _range; /* range allocator for pool */
Dma() : _range(env()->heap())
{
Ram_dataspace_capability cap = env()->ram_session()->alloc(SIZE);
_base_phys = Dataspace_client(cap).phys_addr();
_base = (addr_t)env()->rm_session()->attach(cap);
dde_kit_log(DEBUG_DMA, "New DMA range [%lx-%lx)", _base, _base + SIZE);
_range.add_range(_base, SIZE);
}
public:
static Dma* pool()
{
static Dma _p;
return &_p;
}
/**
* Alloc 'size' bytes of DMA memory
*/
void *alloc(size_t size, int align = PAGE_SHIFT)
{
void *addr;
if (!_range.alloc_aligned(size, &addr, align)) {
PERR("DMA of %zu bytes allocation failed", size);
return 0;
}
return addr;
}
/**
* Free DMA memory
*/
void free(void *addr) { _range.free(addr); }
/**
* Get phys for virt address
*/
addr_t phys_addr(void *addr)
{
addr_t a = (addr_t)addr;
if (a < _base || a >= _base + SIZE) {
PERR("No DMA phys addr for %lx", a);
return 0;
}
return (a - _base) + _base_phys;
}
};
}
struct dma_pool
@ -611,7 +573,7 @@ struct dma_pool
struct dma_pool *dma_pool_create(const char *name, struct device *d, size_t size,
size_t align, size_t alloc)
{
dde_kit_log(DEBUG_DMA, "size: %zx align:%zx", size, align);
dde_kit_log(DEBUG_DMA, "size: %zx align:%zx %p", size, align, __builtin_return_address((0)));
if (align & (align - 1))
return 0;
@ -633,12 +595,13 @@ void dma_pool_destroy(struct dma_pool *d)
static void* _alloc(size_t size, int align, dma_addr_t *dma)
{
void *addr = Genode::Dma::pool()->alloc(size, align);
dde_kit_log(DEBUG_DMA, "addr: %p size %zx align: %d", addr, size, align);
if (!addr)
return 0;
*dma = (dma_addr_t)Genode::Dma::pool()->phys_addr(addr);
dde_kit_log(DEBUG_DMA, "DMA pool alloc addr: %p size %zx align: %d, pysh: %lx", addr, size, align, *dma);
memset(addr, 0, size);
return addr;
}
@ -646,6 +609,8 @@ static void* _alloc(size_t size, int align, dma_addr_t *dma)
void *dma_pool_alloc(struct dma_pool *d, gfp_t f, dma_addr_t *dma)
{
return _alloc(d->size, d->align, dma);
// return _alloc(0x1000, 12, dma);
}
@ -768,3 +733,13 @@ void *sg_virt(struct scatterlist *sg)
struct page *page = (struct page *)sg->page_link;
return (void *)((unsigned long)page->virt + sg->offset);
}
/********************
** linux/ioport.h **
********************/
resource_size_t resource_size(const struct resource *res)
{
return res->end - res->start + 1;
}

View File

@ -37,15 +37,15 @@ extern "C" {
#if VERBOSE_LX_EMUL
#define DEBUG_COMPLETION 1
#define DEBUG_COMPLETION 0
#define DEBUG_DMA 0
#define DEBUG_DRIVER 1
#define DEBUG_IRQ 1
#define DEBUG_DRIVER 0
#define DEBUG_IRQ 0
#define DEBUG_KREF 0
#define DEBUG_PCI 1
#define DEBUG_PCI 0
#define DEBUG_SLAB 0
#define DEBUG_TIMER 1
#define DEBUG_THREAD 1
#define DEBUG_TIMER 0
#define DEBUG_THREAD 0
#else
#define DEBUG_COMPLETION 0
#define DEBUG_DRIVER 0
@ -661,10 +661,14 @@ int isprint(int);
******************/
#define __init
#define __initdata
#define __devinit
#define __devinitconst
#define __devexit
#define __exit
#define __exit_p(x) x
#define subsys_initcall(fn) void subsys_##fn(void) { fn(); }
@ -679,6 +683,7 @@ int isprint(int);
#define MODULE_LICENSE(x)
#define MODULE_PARM_DESC(x, y)
//#define MODULE_ALIAS_MISCDEV(x) /* needed by agp/backend.c */
#define MODULE_ALIAS(x)
#define THIS_MODULE 0
@ -1239,7 +1244,12 @@ bool device_can_wakeup(struct device *dev);
#define dev_WARN(dev, format, arg...) dde_kit_printf("dev_WARN: " format, ## arg)
#define dev_err( dev, format, arg...) dde_kit_printf("dev_error: " format, ## arg)
#define dev_notice(dev, format, arg...) dde_kit_printf("dev_notice: " format, ## arg)
#if VERBOSE_LX_EMUL
#define dev_dbg(dev, format, arg...) dde_kit_printf("dev_dbg: " format, ## arg)
#else
#define dev_dbg( dev, format, arg...)
#endif
#define dev_printk(level, dev, format, arg...) \
dde_kit_printf("dev_printk: " format, ## arg)
@ -1284,12 +1294,16 @@ struct class
char *(*devnode)(struct device *dev, mode_t *mode);
};
/* DEVICE */
struct device {
const char *name;
struct device *parent;
struct kobject kobj;
const struct device_type *type;
struct device_driver *driver;
void *platform_data;
u64 *dma_mask; /* needed by usb/hcd.h */
u64 coherent_dma_mask; /* omap driver */
struct dev_pm_info power;
dev_t devt;
const struct attribute_group **groups;
@ -1826,12 +1840,15 @@ static inline u32 inl_p(u32 port) { u32 ret = inl(port); native_io_delay(); retu
** linux/ioport.h **
********************/
#define IORESOURCE_IO 0x00000100
#define IORESOURCE_IO 0x00000100
#define IORESOURCE_MEM 0x00000200
#define IORESOURCE_IRQ 0x00000400
struct resource
{
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
};
@ -1843,6 +1860,7 @@ struct resource *request_mem_region(resource_size_t start, resource_size_t n,
void release_region(resource_size_t start, resource_size_t n);
void release_mem_region(resource_size_t start, resource_size_t n);
resource_size_t resource_size(const struct resource *res);
/***********************
** linux/interrupt.h **
@ -2577,6 +2595,12 @@ struct scsi_driver
};
/**********************************
** Platform specific defintions **
*********************************/
#include <platform/lx_emul.h>
/**********
** misc **
**********/

View File

@ -32,13 +32,11 @@ extern "C" {
using namespace Genode;
extern "C" void subsys_usb_init();
extern "C" int subsys_usb_init();
extern "C" void subsys_input_init();
extern "C" void module_ehci_hcd_init();
extern "C" void module_evdev_init();
extern "C" void module_hid_init();
extern "C" void module_hid_init_core();
extern "C" void module_uhci_hcd_init();
extern "C" void module_usb_mouse_init();
extern "C" void module_usb_kbd_init();
extern "C" void module_usb_stor_init();
@ -74,10 +72,8 @@ static void init(bool hid, bool stor)
/*
* Host controller.
*
* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after
*/
module_ehci_hcd_init();
module_uhci_hcd_init();
platform_hcd_init();
/* storage */
if (stor)

View File

@ -22,6 +22,8 @@ extern "C" {
#include <dde_kit/memory.h>
}
#include <platform/platform.h>
static const bool verbose = false;
@ -69,11 +71,7 @@ class Routine : public Genode::List<Routine>::Element
/* XXX move to platform code */
/* switch stack and call '_func(_arg)' */
asm volatile ("movl %2, 0(%0);"
"movl %1, -0x4(%0);"
"movl %0, %%esp;"
"call *-4(%%esp);"
: : "r" (_stack + STACK_SIZE), "r" (_func), "r" (_arg));
platform_execute((void *)(_stack + STACK_SIZE), (void *)_func, _arg);
}
/* restore old state */

View File

@ -31,6 +31,8 @@ class Driver_context : public Genode::Signal_context
* Perform context operation
*/
virtual void handle() = 0;
virtual char const *debug() = 0;
};

View File

@ -43,6 +43,8 @@ class Event_context : public Driver_context
void handle() {
Routine::schedule_all(); }
char const *debug() { return "Event_context"; }
};

View File

@ -13,7 +13,7 @@
#include <signal.h>
#include <lx_emul.h>
#include <dma.h>
extern "C" {
#include <dde_kit/interrupt.h>
}
@ -93,18 +93,13 @@ class Irq_context : public Driver_context,
/* report IRQ to all clients */
for (Irq_handler *h = _handler_list.first(); h; h = h->next()) {
irqreturn_t rc;
do {
rc = h->handler(_irq, h->dev);
}
while (rc == IRQ_HANDLED);
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u", _irq, rc);
if (rc == IRQ_HANDLED) {
if ((rc = h->handler(_irq, h->dev)) == IRQ_HANDLED)
Routine::schedule_all();
return;
}
dde_kit_log(DEBUG_IRQ, "IRQ: %u ret: %u", _irq, rc);
}
}
const char *debug() { return "Irq_context"; }
/**
* Request an IRQ
*/

View File

@ -59,6 +59,7 @@ class Timer_context : public Driver_context
dde_kit_timer_schedule_absolute(_dde_timer, expires);
}
char const *debug() { return "Timer_context"; }
/**
* Return true if timer is pending
*/

View File

@ -73,6 +73,7 @@ namespace Block {
~Signal_dispatcher() { sig_rec->dissolve(this); }
void handle() { (obj.*member)(); }
char const *debug() { return "Block_context"; }
};

View File

@ -27,6 +27,13 @@
* scsi_scan_host
*/
/*
* Copyright (C) 2009-2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#include <lx_emul.h>
#include "scsi.h"

View File

@ -1,7 +1,6 @@
TARGET = usb_drv
REQUIRES = x86 32bit
LIBS = cxx env dde_kit server libc-setjmp signal
SRC_CC = main.cc lx_emul.cc pci_driver.cc irq.cc timer.cc event.cc storage.cc \
SRC_CC = main.cc lx_emul.cc irq.cc timer.cc event.cc storage.cc \
input_component.cc
SRC_C = dummies.c scsi.c evdev.c
@ -18,7 +17,7 @@ INC_DIR += $(CONTRIB_DIR)/include
INC_DIR += $(shell pwd)
CC_OPT += -U__linux__ -D__KERNEL__
CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DCONFIG_PCI -DDEBUG
CC_OPT += -DCONFIG_USB_DEVICEFS -DCONFIG_HOTPLUG -DDEBUG
CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \
-Wno-unused-function \
@ -37,8 +36,7 @@ SRC_C += $(addprefix usb/core/,$(notdir $(wildcard $(USB_DIR)/core/*.c)))
SRC_C += usb/usb-common.c
# USB host-controller driver
#SRC_C += $(addprefix usb/host/,uhci-hcd.c pci-quirks.c ehci-hcd.c ohci-hcd.c)
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c ehci-hcd.c)
SRC_C += $(addprefix usb/host/, ehci-hcd.c)
# USB hid
SRC_C += $(addprefix hid/usbhid/,hid-core.c hid-quirks.c usbmouse.c usbkbd.c)
@ -61,13 +59,48 @@ GEN_INCLUDES := $(shell grep -rh "^\#include .*\/" $(CONTRIB_DIR) |\
#
# Filter out some black-listed headers
#
NO_GEN_INCLUDES := ../../scsi/sd.h
########################
## Platform specifics ##
########################
SUPPORTED = x86_32 platform_panda
#
# x86_32
#
ifeq ($(filter-out $(SPECS),x86_32),)
INC_DIR += $(PRG_DIR)/x86_32
CC_OPT += -DCONFIG_PCI
SRC_C += $(addprefix usb/host/,pci-quirks.c uhci-hcd.c)
SRC_CC += pci_driver.cc
#
# Panda board
#
else ifeq ($(filter-out $(SPECS),platform_panda),)
CC_OPT += -DCONFIG_USB_EHCI_HCD_OMAP -DCONFIG_USB_EHCI_TT_NEWSCHED -DVERBOSE_DEBUG
INC_DIR += $(PRG_DIR)/arm
INC_DIR += $(CONTRIB_DIR)/arch/arm/plat-omap/include
SRC_C += platform_device.c
SRC_CC += platform.cc
#SRC_C += $(CONTRIB_DIR)/arch/arm/mach-omap2/usb-host.c
#SRC_C += $(DRIVERS_DIR)/mfd/omap-usb-host.c
vpath %.c $(PRG_DIR)/arm/platform
vpath %.cc $(PRG_DIR)/arm/platform
#
# Unsupported
#
else
$(error Skip USB because it requires one of the following: $(SUPPORTED))
endif
#
# Filter out original Linux headers that exist in the contrib directory
#
NO_GEN_INCLUDES := $(shell cd $(CONTRIB_DIR)/include; find -name "*.h" | sed "s/.\///")
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
#
# Make sure to create the header symlinks prior building

View File

@ -0,0 +1,18 @@
/*
* \brief Platform specific part of the Linux API emulation
* \author Sebastian Sumpf
* \date 2012-06-18
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _X86_32__PLATFORM__LX_EMUL_
#define _X86_32__PLATFORM__LX_EMUL_
#endif /* _X86_32__PLATFORM__LX_EMUL_ */

View File

@ -0,0 +1,38 @@
/**
* \brief Platform specific code
* \author Sebastian Sumpf
* \date 2012-06-10
*/
/*
* Copyright (C) 2012 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _X86_32__PLATFORM_H_
#define _X86_32__PLATFORM_H_
static inline
void platform_execute(void *sp, void *func, void *arg)
{
asm volatile ("movl %2, 0(%0);"
"movl %1, -0x4(%0);"
"movl %0, %%esp;"
"call *-4(%%esp);"
: : "r" (sp), "r" (func), "r" (arg));
}
extern "C" void module_ehci_hcd_init();
extern "C" void module_uhci_hcd_init();
static inline void platform_hcd_init(void)
{
/* ehci_hcd should always be loaded before uhci_hcd and ohci_hcd, not after */
module_ehci_hcd_init();
module_uhci_hcd_init();
}
#endif /* _X86_32__PLATFORM_H_ */

View File

@ -1,6 +1,11 @@
LIBC_GEN_ARM_DIR = $(LIBC_DIR)/libc/arm/gen
SRC_S = _setjmp.S setjmp.S
SRC_S = _setjmp.S setjmp.S
#
# Remove 'longjmperror' call
#
CC_OPT += -D_STANDALONE
include $(REP_DIR)/lib/mk/libc-common.inc