usb: Arndale EHCI controller support
This commit is contained in:
parent
79949bb338
commit
e901bca416
|
@ -31,7 +31,8 @@ CONTENT += include/linux/usbdevice_fs.h include/asm-generic/ioctl.h
|
||||||
|
|
||||||
# USB host-controller driver
|
# USB host-controller driver
|
||||||
CONTENT_USB_HOST := ehci.h ehci-hcd.c ehci-hub.c ehci-dbg.c ehci-mem.c \
|
CONTENT_USB_HOST := ehci.h ehci-hcd.c ehci-hub.c ehci-dbg.c ehci-mem.c \
|
||||||
ehci-omap.c ehci-q.c ehci-pci.c ehci-sched.c ehci-sysfs.c
|
ehci-omap.c ehci-q.c ehci-pci.c ehci-s5p.c ehci-sched.c \
|
||||||
|
ehci-sysfs.c
|
||||||
CONTENT_USB_HOST += ohci.h ohci-hcd.c ohci-hub.c ohci-dbg.c ohci-mem.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
|
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 \
|
CONTENT_USB_HOST += uhci-hcd.h uhci-hcd.c uhci-debug.c uhci-q.c uhci-hub.c \
|
||||||
|
@ -61,6 +62,10 @@ CONTENT_NET = usbnet.c smsc95xx.c smsc95xx.h
|
||||||
CONTENT += $(addprefix drivers/net/usb/,$(CONTENT_NET))
|
CONTENT += $(addprefix drivers/net/usb/,$(CONTENT_NET))
|
||||||
CONTENT += include/linux/usb/usbnet.h
|
CONTENT += include/linux/usb/usbnet.h
|
||||||
|
|
||||||
|
# Arndale
|
||||||
|
CONTENT_ARNDALE = ehci.h usb-phy.h
|
||||||
|
CONTENT += $(addprefix arch/arm/plat-samsung/include/plat/,$(CONTENT_ARNDALE))
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Utility to check if a tool is installed
|
# Utility to check if a tool is installed
|
||||||
|
|
|
@ -84,7 +84,10 @@ struct platform_driver {
|
||||||
const struct platform_device_id *id_table;
|
const struct platform_device_id *id_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct resource *platform_get_resource(struct platform_device *, unsigned, unsigned);
|
||||||
struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *);
|
struct resource *platform_get_resource_byname(struct platform_device *, unsigned int, const char *);
|
||||||
|
|
||||||
|
int platform_get_irq(struct platform_device *, unsigned int);
|
||||||
int platform_get_irq_byname(struct platform_device *, const char *);
|
int platform_get_irq_byname(struct platform_device *, const char *);
|
||||||
|
|
||||||
int platform_driver_register(struct platform_driver *);
|
int platform_driver_register(struct platform_driver *);
|
||||||
|
@ -134,4 +137,24 @@ struct regulator *regulator_get(struct device *dev, const char *id);
|
||||||
int omap_usbhs_enable(struct device *dev);
|
int omap_usbhs_enable(struct device *dev);
|
||||||
void omap_usbhs_disable(struct device *dev);
|
void omap_usbhs_disable(struct device *dev);
|
||||||
|
|
||||||
|
|
||||||
|
/****************
|
||||||
|
** linux/pm.h **
|
||||||
|
****************/
|
||||||
|
|
||||||
|
struct dev_pm_ops {
|
||||||
|
int (*suspend)(struct device *dev);
|
||||||
|
int (*resume)(struct device *dev);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
** linux/clk.h **
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
struct clk *clk_get(struct device *, const char *);
|
||||||
|
int clk_enable(struct clk *);
|
||||||
|
void clk_disable(struct clk *);
|
||||||
|
void clk_put(struct clk *);
|
||||||
|
|
||||||
#endif /* _ARM__PLATFORM__LX_EMUL_H_ */
|
#endif /* _ARM__PLATFORM__LX_EMUL_H_ */
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
/*
|
||||||
|
* \brief EHCI for Arndale initializaion code
|
||||||
|
* \author Sebastian Sumpf
|
||||||
|
* \date 2013-02-20
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode */
|
||||||
|
#include <io_mem_session/connection.h>
|
||||||
|
#include <util/mmio.h>
|
||||||
|
|
||||||
|
/* Emulation */
|
||||||
|
#include <platform/platform.h>
|
||||||
|
#include <lx_emul.h>
|
||||||
|
|
||||||
|
/* Linux */
|
||||||
|
#include <plat/ehci.h>
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
EHCI_BASE = 0x12110000,
|
||||||
|
GPIO_BASE = 0x11400000,
|
||||||
|
EHCI_IRQ = 103,
|
||||||
|
};
|
||||||
|
|
||||||
|
static resource _ehci[] =
|
||||||
|
{
|
||||||
|
{ EHCI_BASE, EHCI_BASE + 0xfff, "ehci", IORESOURCE_MEM },
|
||||||
|
{ EHCI_IRQ, EHCI_IRQ, "ehci-irq", IORESOURCE_IRQ },
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct s5p_ehci_platdata _ehci_data;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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()
|
||||||
|
{
|
||||||
|
enum Gpio_offset { D1 = 0x180, X3 = 0xc60 };
|
||||||
|
|
||||||
|
/* reset hub via GPIO */
|
||||||
|
Io_mem_connection io_gpio(GPIO_BASE, 0x1000);
|
||||||
|
addr_t gpio_base = (addr_t)env()->rm_session()->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_session()->detach(gpio_base);
|
||||||
|
|
||||||
|
/* reset ehci controller */
|
||||||
|
Io_mem_connection io_ehci(EHCI_BASE, 0x1000);
|
||||||
|
addr_t ehci_base = (addr_t)env()->rm_session()->attach(io_ehci.dataspace());
|
||||||
|
|
||||||
|
Ehci ehci(ehci_base);
|
||||||
|
env()->rm_session()->detach(ehci_base);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void module_ehci_hcd_init();
|
||||||
|
|
||||||
|
void platform_hcd_init(Services *services)
|
||||||
|
{
|
||||||
|
/* register EHCI controller */
|
||||||
|
module_ehci_hcd_init();
|
||||||
|
|
||||||
|
/* setup controller */
|
||||||
|
arndale_ehci_init();
|
||||||
|
|
||||||
|
/* setup EHCI-controller platform device */
|
||||||
|
platform_device *pdev = (platform_device *)kzalloc(sizeof(platform_device), 0);
|
||||||
|
pdev->name = "s5p-ehci";
|
||||||
|
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 = ~(u64)0;
|
||||||
|
pdev->dev.dma_mask = &dma_mask;
|
||||||
|
pdev->dev.coherent_dma_mask = ~0;
|
||||||
|
|
||||||
|
platform_device_register(pdev);
|
||||||
|
}
|
|
@ -52,6 +52,20 @@ int platform_driver_register(struct platform_driver *drv)
|
||||||
return driver_register(&drv->driver);
|
return driver_register(&drv->driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct resource *platform_get_resource(struct platform_device *dev,
|
||||||
|
unsigned int type, unsigned int num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < dev->num_resources; i++) {
|
||||||
|
struct resource *r = &dev->resource[i];
|
||||||
|
|
||||||
|
if ((type & r->flags) && num-- == 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
struct resource *platform_get_resource_byname(struct platform_device *dev,
|
struct resource *platform_get_resource_byname(struct platform_device *dev,
|
||||||
unsigned int type,
|
unsigned int type,
|
||||||
|
@ -77,6 +91,12 @@ int platform_get_irq_byname(struct platform_device *dev, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int platform_get_irq(struct platform_device *dev, unsigned int num)
|
||||||
|
{
|
||||||
|
struct resource *r = platform_get_resource(dev, IORESOURCE_IRQ, 0);
|
||||||
|
return r ? r->start : -1;
|
||||||
|
}
|
||||||
|
|
||||||
int platform_device_register(struct platform_device *pdev)
|
int platform_device_register(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
pdev->dev.bus = &platform_bus_type;
|
pdev->dev.bus = &platform_bus_type;
|
||||||
|
|
|
@ -383,6 +383,7 @@ void class_destroy(struct class *cls) { TRACE; }
|
||||||
*****************************/
|
*****************************/
|
||||||
|
|
||||||
void *platform_get_drvdata(const struct platform_device *pdev) { TRACE; return NULL; }
|
void *platform_get_drvdata(const struct platform_device *pdev) { TRACE; return NULL; }
|
||||||
|
void platform_set_drvdata(struct platform_device *pdev, void *data) { TRACE; }
|
||||||
|
|
||||||
|
|
||||||
/********************
|
/********************
|
||||||
|
@ -878,3 +879,19 @@ __wsum csum_partial(const void *buff, int len, __wsum wsum) { TRACE; return 0; }
|
||||||
__sum16 csum_fold(__wsum sum) { TRACE; return 0; }
|
__sum16 csum_fold(__wsum sum) { TRACE; return 0; }
|
||||||
|
|
||||||
|
|
||||||
|
/*****************
|
||||||
|
** linux/clk.h **
|
||||||
|
*****************/
|
||||||
|
|
||||||
|
struct clk { };
|
||||||
|
|
||||||
|
struct clk *clk_get(struct device *dev, const char *id)
|
||||||
|
{
|
||||||
|
static struct clk _c;
|
||||||
|
TRACE;
|
||||||
|
return &_c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int clk_enable(struct clk *clk) { TRACE; return 0; }
|
||||||
|
void clk_disable(struct clk *clk) { TRACE; }
|
||||||
|
void clk_put(struct clk *clk) { TRACE; }
|
||||||
|
|
|
@ -39,8 +39,8 @@ extern "C" {
|
||||||
#if VERBOSE_LX_EMUL
|
#if VERBOSE_LX_EMUL
|
||||||
#define DEBUG_COMPLETION 0
|
#define DEBUG_COMPLETION 0
|
||||||
#define DEBUG_DMA 0
|
#define DEBUG_DMA 0
|
||||||
#define DEBUG_DRIVER 0
|
#define DEBUG_DRIVER 1
|
||||||
#define DEBUG_IRQ 0
|
#define DEBUG_IRQ 1
|
||||||
#define DEBUG_KREF 0
|
#define DEBUG_KREF 0
|
||||||
#define DEBUG_PCI 0
|
#define DEBUG_PCI 0
|
||||||
#define DEBUG_SKB 0
|
#define DEBUG_SKB 0
|
||||||
|
@ -675,6 +675,7 @@ int isprint(int);
|
||||||
#define __devinit
|
#define __devinit
|
||||||
#define __devinitconst
|
#define __devinitconst
|
||||||
#define __devexit
|
#define __devexit
|
||||||
|
#define __devexit_p(x) x
|
||||||
#define __exit
|
#define __exit
|
||||||
|
|
||||||
#define __exit_p(x) x
|
#define __exit_p(x) x
|
||||||
|
@ -1292,6 +1293,8 @@ struct device_driver {
|
||||||
const char *mod_name;
|
const char *mod_name;
|
||||||
int (*probe) (struct device *dev);
|
int (*probe) (struct device *dev);
|
||||||
int (*remove) (struct device *dev);
|
int (*remove) (struct device *dev);
|
||||||
|
|
||||||
|
const struct dev_pm_ops *pm;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct kobj_uevent_env;
|
struct kobj_uevent_env;
|
||||||
|
@ -1434,6 +1437,7 @@ void class_destroy(struct class *cls);
|
||||||
|
|
||||||
struct platform_device;
|
struct platform_device;
|
||||||
void *platform_get_drvdata(const struct platform_device *pdev);
|
void *platform_get_drvdata(const struct platform_device *pdev);
|
||||||
|
void platform_set_drvdata(struct platform_device *pdev, void *data);
|
||||||
|
|
||||||
|
|
||||||
/*********************
|
/*********************
|
||||||
|
|
|
@ -81,13 +81,22 @@ SRC_CC += pci_driver.cc
|
||||||
else ifeq ($(filter-out $(SPECS),platform_panda),)
|
else ifeq ($(filter-out $(SPECS),platform_panda),)
|
||||||
CC_OPT += -DCONFIG_USB_EHCI_HCD_OMAP -DCONFIG_USB_EHCI_TT_NEWSCHED -DVERBOSE_DEBUG
|
CC_OPT += -DCONFIG_USB_EHCI_HCD_OMAP -DCONFIG_USB_EHCI_TT_NEWSCHED -DVERBOSE_DEBUG
|
||||||
INC_DIR += $(PRG_DIR)/arm
|
INC_DIR += $(PRG_DIR)/arm
|
||||||
INC_DIR += $(CONTRIB_DIR)/arch/arm/plat-omap/include
|
|
||||||
SRC_C += platform_device.c usbnet.c smsc95xx.c
|
SRC_C += platform_device.c usbnet.c smsc95xx.c
|
||||||
SRC_CC += platform.cc mem.cc
|
SRC_CC += platform.cc mem.cc
|
||||||
vpath %.c $(PRG_DIR)/arm/platform
|
vpath %.c $(PRG_DIR)/arm/platform
|
||||||
vpath %.cc $(PRG_DIR)/arm/platform
|
vpath %.cc $(PRG_DIR)/arm/platform
|
||||||
|
vpath %.cc $(PRG_DIR)/arm/platform/platform_panda
|
||||||
vpath %.c $(CONTRIB_DIR)/drivers/net/usb
|
vpath %.c $(CONTRIB_DIR)/drivers/net/usb
|
||||||
|
|
||||||
|
else ifeq ($(filter-out $(SPECS),platform_arndale),)
|
||||||
|
CC_OPT += -DCONFIG_USB_EHCI_S5P -DCONFIG_USB_EHCI_TT_NEWSCHED
|
||||||
|
INC_DIR += $(PRG_DIR)/arm
|
||||||
|
INC_DIR += $(CONTRIB_DIR)/arch/arm/plat-samsung/include
|
||||||
|
SRC_C += platform_device.c
|
||||||
|
SRC_CC += platform.cc
|
||||||
|
vpath %.c $(PRG_DIR)/arm/platform
|
||||||
|
vpath %.cc $(PRG_DIR)/arm/platform/platform_arndale
|
||||||
|
|
||||||
#
|
#
|
||||||
# Unsupported
|
# Unsupported
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in New Issue
Block a user