Merge master.kernel.org:/home/rmk/linux-2.6-arm
This commit is contained in:
commit
435d444a53
93
Documentation/arm/Samsung-S3C24XX/USB-Host.txt
Normal file
93
Documentation/arm/Samsung-S3C24XX/USB-Host.txt
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
S3C24XX USB Host support
|
||||||
|
========================
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
------------
|
||||||
|
|
||||||
|
This document details the S3C2410/S3C2440 in-built OHCI USB host support.
|
||||||
|
|
||||||
|
Configuration
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Enable at least the following kernel options:
|
||||||
|
|
||||||
|
menuconfig:
|
||||||
|
|
||||||
|
Device Drivers --->
|
||||||
|
USB support --->
|
||||||
|
<*> Support for Host-side USB
|
||||||
|
<*> OHCI HCD support
|
||||||
|
|
||||||
|
|
||||||
|
.config:
|
||||||
|
CONFIG_USB
|
||||||
|
CONFIG_USB_OHCI_HCD
|
||||||
|
|
||||||
|
|
||||||
|
Once these options are configured, the standard set of USB device
|
||||||
|
drivers can be configured and used.
|
||||||
|
|
||||||
|
|
||||||
|
Board Support
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The driver attaches to a platform device, which will need to be
|
||||||
|
added by the board specific support file in linux/arch/arm/mach-s3c2410,
|
||||||
|
such as mach-bast.c or mach-smdk2410.c
|
||||||
|
|
||||||
|
The platform device's platform_data field is only needed if the
|
||||||
|
board implements extra power control or over-current monitoring.
|
||||||
|
|
||||||
|
The OHCI driver does not ensure the state of the S3C2410's MISCCTRL
|
||||||
|
register, so if both ports are to be used for the host, then it is
|
||||||
|
the board support file's responsibility to ensure that the second
|
||||||
|
port is configured to be connected to the OHCI core.
|
||||||
|
|
||||||
|
|
||||||
|
Platform Data
|
||||||
|
-------------
|
||||||
|
|
||||||
|
See linux/include/asm-arm/arch-s3c2410/usb-control.h for the
|
||||||
|
descriptions of the platform device data. An implementation
|
||||||
|
can be found in linux/arch/arm/mach-s3c2410/usb-simtec.c .
|
||||||
|
|
||||||
|
The `struct s3c2410_hcd_info` contains a pair of functions
|
||||||
|
that get called to enable over-current detection, and to
|
||||||
|
control the port power status.
|
||||||
|
|
||||||
|
The ports are numbered 0 and 1.
|
||||||
|
|
||||||
|
power_control:
|
||||||
|
|
||||||
|
Called to enable or disable the power on the port.
|
||||||
|
|
||||||
|
enable_oc:
|
||||||
|
|
||||||
|
Called to enable or disable the over-current monitoring.
|
||||||
|
This should claim or release the resources being used to
|
||||||
|
check the power condition on the port, such as an IRQ.
|
||||||
|
|
||||||
|
report_oc:
|
||||||
|
|
||||||
|
The OHCI driver fills this field in for the over-current code
|
||||||
|
to call when there is a change to the over-current state on
|
||||||
|
an port. The ports argument is a bitmask of 1 bit per port,
|
||||||
|
with bit X being 1 for an over-current on port X.
|
||||||
|
|
||||||
|
The function s3c2410_usb_report_oc() has been provided to
|
||||||
|
ensure this is called correctly.
|
||||||
|
|
||||||
|
port[x]:
|
||||||
|
|
||||||
|
This is struct describes each port, 0 or 1. The platform driver
|
||||||
|
should set the flags field of each port to S3C_HCDFLG_USED if
|
||||||
|
the port is enabled.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Document Author
|
||||||
|
---------------
|
||||||
|
|
||||||
|
Ben Dooks, (c) 2005 Simtec Electronics
|
@ -1,6 +1,6 @@
|
|||||||
/* linux/arch/arm/mach-s3c2410/usb-simtec.c
|
/* linux/arch/arm/mach-s3c2410/usb-simtec.c
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004 Simtec Electronics
|
* Copyright (c) 2004,2005 Simtec Electronics
|
||||||
* Ben Dooks <ben@simtec.co.uk>
|
* Ben Dooks <ben@simtec.co.uk>
|
||||||
*
|
*
|
||||||
* http://www.simtec.co.uk/products/EB2410ITX/
|
* http://www.simtec.co.uk/products/EB2410ITX/
|
||||||
@ -14,6 +14,8 @@
|
|||||||
* Modifications:
|
* Modifications:
|
||||||
* 14-Sep-2004 BJD Created
|
* 14-Sep-2004 BJD Created
|
||||||
* 18-Oct-2004 BJD Cleanups, and added code to report OC cleared
|
* 18-Oct-2004 BJD Cleanups, and added code to report OC cleared
|
||||||
|
* 09-Aug-2005 BJD Renamed s3c2410_report_oc to s3c2410_usb_report_oc
|
||||||
|
* 09-Aug-2005 BJD Ports powered only if both are enabled
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define DEBUG
|
#define DEBUG
|
||||||
@ -47,13 +49,19 @@
|
|||||||
* designed boards.
|
* designed boards.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static unsigned int power_state[2];
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usb_simtec_powercontrol(int port, int to)
|
usb_simtec_powercontrol(int port, int to)
|
||||||
{
|
{
|
||||||
pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
|
pr_debug("usb_simtec_powercontrol(%d,%d)\n", port, to);
|
||||||
|
|
||||||
if (port == 1)
|
power_state[port] = to;
|
||||||
s3c2410_gpio_setpin(S3C2410_GPB4, to ? 0:1);
|
|
||||||
|
if (power_state[0] && power_state[1])
|
||||||
|
s3c2410_gpio_setpin(S3C2410_GPB4, 0);
|
||||||
|
else
|
||||||
|
s3c2410_gpio_setpin(S3C2410_GPB4, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t
|
static irqreturn_t
|
||||||
@ -63,10 +71,10 @@ usb_simtec_ocirq(int irq, void *pw, struct pt_regs *regs)
|
|||||||
|
|
||||||
if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
|
if (s3c2410_gpio_getpin(S3C2410_GPG10) == 0) {
|
||||||
pr_debug("usb_simtec: over-current irq (oc detected)\n");
|
pr_debug("usb_simtec: over-current irq (oc detected)\n");
|
||||||
s3c2410_report_oc(info, 3);
|
s3c2410_usb_report_oc(info, 3);
|
||||||
} else {
|
} else {
|
||||||
pr_debug("usb_simtec: over-current irq (oc cleared)\n");
|
pr_debug("usb_simtec: over-current irq (oc cleared)\n");
|
||||||
s3c2410_report_oc(info, 0);
|
s3c2410_usb_report_oc(info, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
|
@ -383,6 +383,7 @@ static void __init build_mem_type_table(void)
|
|||||||
{
|
{
|
||||||
struct cachepolicy *cp;
|
struct cachepolicy *cp;
|
||||||
unsigned int cr = get_cr();
|
unsigned int cr = get_cr();
|
||||||
|
unsigned int user_pgprot;
|
||||||
int cpu_arch = cpu_architecture();
|
int cpu_arch = cpu_architecture();
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -408,6 +409,9 @@ static void __init build_mem_type_table(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cp = &cache_policies[cachepolicy];
|
||||||
|
user_pgprot = cp->pte;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ARMv6 and above have extended page tables.
|
* ARMv6 and above have extended page tables.
|
||||||
*/
|
*/
|
||||||
@ -426,11 +430,18 @@ static void __init build_mem_type_table(void)
|
|||||||
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||||
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark the device area as "shared device"
|
||||||
|
*/
|
||||||
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
|
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
|
||||||
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
|
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
|
||||||
}
|
|
||||||
|
|
||||||
cp = &cache_policies[cachepolicy];
|
/*
|
||||||
|
* User pages need to be mapped with the ASID
|
||||||
|
* (iow, non-global)
|
||||||
|
*/
|
||||||
|
user_pgprot |= L_PTE_ASID;
|
||||||
|
}
|
||||||
|
|
||||||
if (cpu_arch >= CPU_ARCH_ARMv5) {
|
if (cpu_arch >= CPU_ARCH_ARMv5) {
|
||||||
mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
|
mem_types[MT_LOW_VECTORS].prot_pte |= cp->pte & PTE_CACHEABLE;
|
||||||
@ -448,7 +459,7 @@ static void __init build_mem_type_table(void)
|
|||||||
|
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
unsigned long v = pgprot_val(protection_map[i]);
|
unsigned long v = pgprot_val(protection_map[i]);
|
||||||
v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | cp->pte;
|
v &= (~(PTE_BUFFERABLE|PTE_CACHEABLE)) | user_pgprot;
|
||||||
protection_map[i] = __pgprot(v);
|
protection_map[i] = __pgprot(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,12 +111,6 @@ ENTRY(cpu_v6_switch_mm)
|
|||||||
mcr p15, 0, r1, c13, c0, 1 @ set context ID
|
mcr p15, 0, r1, c13, c0, 1 @ set context ID
|
||||||
mov pc, lr
|
mov pc, lr
|
||||||
|
|
||||||
#define nG (1 << 11)
|
|
||||||
#define APX (1 << 9)
|
|
||||||
#define AP1 (1 << 5)
|
|
||||||
#define AP0 (1 << 4)
|
|
||||||
#define XN (1 << 0)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* cpu_v6_set_pte(ptep, pte)
|
* cpu_v6_set_pte(ptep, pte)
|
||||||
*
|
*
|
||||||
@ -139,24 +133,24 @@ ENTRY(cpu_v6_switch_mm)
|
|||||||
ENTRY(cpu_v6_set_pte)
|
ENTRY(cpu_v6_set_pte)
|
||||||
str r1, [r0], #-2048 @ linux version
|
str r1, [r0], #-2048 @ linux version
|
||||||
|
|
||||||
bic r2, r1, #0x00000ff0
|
bic r2, r1, #0x000007f0
|
||||||
bic r2, r2, #0x00000003
|
bic r2, r2, #0x00000003
|
||||||
orr r2, r2, #AP0 | 2
|
orr r2, r2, #PTE_EXT_AP0 | 2
|
||||||
|
|
||||||
tst r1, #L_PTE_WRITE
|
tst r1, #L_PTE_WRITE
|
||||||
tstne r1, #L_PTE_DIRTY
|
tstne r1, #L_PTE_DIRTY
|
||||||
orreq r2, r2, #APX
|
orreq r2, r2, #PTE_EXT_APX
|
||||||
|
|
||||||
tst r1, #L_PTE_USER
|
tst r1, #L_PTE_USER
|
||||||
orrne r2, r2, #AP1 | nG
|
orrne r2, r2, #PTE_EXT_AP1
|
||||||
tstne r2, #APX
|
tstne r2, #PTE_EXT_APX
|
||||||
bicne r2, r2, #APX | AP0
|
bicne r2, r2, #PTE_EXT_APX | PTE_EXT_AP0
|
||||||
|
|
||||||
tst r1, #L_PTE_YOUNG
|
tst r1, #L_PTE_YOUNG
|
||||||
biceq r2, r2, #APX | AP1 | AP0
|
biceq r2, r2, #PTE_EXT_APX | PTE_EXT_AP_MASK
|
||||||
|
|
||||||
@ tst r1, #L_PTE_EXEC
|
@ tst r1, #L_PTE_EXEC
|
||||||
@ orreq r2, r2, #XN
|
@ orreq r2, r2, #PTE_EXT_XN
|
||||||
|
|
||||||
tst r1, #L_PTE_PRESENT
|
tst r1, #L_PTE_PRESENT
|
||||||
moveq r2, #0
|
moveq r2, #0
|
||||||
|
@ -717,6 +717,9 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
|
|||||||
DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
|
DPRINTK("reg_lccr2 0x%08x\n", (unsigned int) fbi->reg_lccr2);
|
||||||
DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
|
DPRINTK("reg_lccr3 0x%08x\n", (unsigned int) fbi->reg_lccr3);
|
||||||
|
|
||||||
|
/* enable LCD controller clock */
|
||||||
|
pxa_set_cken(CKEN16_LCD, 1);
|
||||||
|
|
||||||
/* Sequence from 11.7.10 */
|
/* Sequence from 11.7.10 */
|
||||||
LCCR3 = fbi->reg_lccr3;
|
LCCR3 = fbi->reg_lccr3;
|
||||||
LCCR2 = fbi->reg_lccr2;
|
LCCR2 = fbi->reg_lccr2;
|
||||||
@ -750,6 +753,9 @@ static void pxafb_disable_controller(struct pxafb_info *fbi)
|
|||||||
|
|
||||||
schedule_timeout(20 * HZ / 1000);
|
schedule_timeout(20 * HZ / 1000);
|
||||||
remove_wait_queue(&fbi->ctrlr_wait, &wait);
|
remove_wait_queue(&fbi->ctrlr_wait, &wait);
|
||||||
|
|
||||||
|
/* disable LCD controller clock */
|
||||||
|
pxa_set_cken(CKEN16_LCD, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1299,8 +1305,6 @@ int __init pxafb_probe(struct device *dev)
|
|||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
/* enable LCD controller clock */
|
|
||||||
pxa_set_cken(CKEN16_LCD, 1);
|
|
||||||
|
|
||||||
ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi);
|
ret = request_irq(IRQ_LCD, pxafb_handle_irq, SA_INTERRUPT, "LCD", fbi);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
* Changelog:
|
* Changelog:
|
||||||
* 11-Sep-2004 BJD Created file
|
* 11-Sep-2004 BJD Created file
|
||||||
* 21-Sep-2004 BJD Updated port info
|
* 21-Sep-2004 BJD Updated port info
|
||||||
|
* 09-Aug-2005 BJD Renamed s3c2410_report_oc s3c2410_usb_report_oc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ASM_ARCH_USBCONTROL_H
|
#ifndef __ASM_ARCH_USBCONTROL_H
|
||||||
@ -35,7 +36,7 @@ struct s3c2410_hcd_info {
|
|||||||
void (*report_oc)(struct s3c2410_hcd_info *, int ports);
|
void (*report_oc)(struct s3c2410_hcd_info *, int ports);
|
||||||
};
|
};
|
||||||
|
|
||||||
static void inline s3c2410_report_oc(struct s3c2410_hcd_info *info, int ports)
|
static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
|
||||||
{
|
{
|
||||||
if (info->report_oc != NULL) {
|
if (info->report_oc != NULL) {
|
||||||
(info->report_oc)(info, ports);
|
(info->report_oc)(info, ports);
|
||||||
|
@ -188,12 +188,18 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
|
|||||||
/*
|
/*
|
||||||
* - extended small page/tiny page
|
* - extended small page/tiny page
|
||||||
*/
|
*/
|
||||||
|
#define PTE_EXT_XN (1 << 0) /* v6 */
|
||||||
#define PTE_EXT_AP_MASK (3 << 4)
|
#define PTE_EXT_AP_MASK (3 << 4)
|
||||||
|
#define PTE_EXT_AP0 (1 << 4)
|
||||||
|
#define PTE_EXT_AP1 (2 << 4)
|
||||||
#define PTE_EXT_AP_UNO_SRO (0 << 4)
|
#define PTE_EXT_AP_UNO_SRO (0 << 4)
|
||||||
#define PTE_EXT_AP_UNO_SRW (1 << 4)
|
#define PTE_EXT_AP_UNO_SRW (PTE_EXT_AP0)
|
||||||
#define PTE_EXT_AP_URO_SRW (2 << 4)
|
#define PTE_EXT_AP_URO_SRW (PTE_EXT_AP1)
|
||||||
#define PTE_EXT_AP_URW_SRW (3 << 4)
|
#define PTE_EXT_AP_URW_SRW (PTE_EXT_AP1|PTE_EXT_AP0)
|
||||||
#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
|
#define PTE_EXT_TEX(x) ((x) << 6) /* v5 */
|
||||||
|
#define PTE_EXT_APX (1 << 9) /* v6 */
|
||||||
|
#define PTE_EXT_SHARED (1 << 10) /* v6 */
|
||||||
|
#define PTE_EXT_NG (1 << 11) /* v6 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* - small page
|
* - small page
|
||||||
@ -224,6 +230,8 @@ extern void __pgd_error(const char *file, int line, unsigned long val);
|
|||||||
#define L_PTE_WRITE (1 << 5)
|
#define L_PTE_WRITE (1 << 5)
|
||||||
#define L_PTE_EXEC (1 << 6)
|
#define L_PTE_EXEC (1 << 6)
|
||||||
#define L_PTE_DIRTY (1 << 7)
|
#define L_PTE_DIRTY (1 << 7)
|
||||||
|
#define L_PTE_SHARED (1 << 10) /* shared between CPUs (v6) */
|
||||||
|
#define L_PTE_ASID (1 << 11) /* non-global (use ASID, v6) */
|
||||||
|
|
||||||
#ifndef __ASSEMBLY__
|
#ifndef __ASSEMBLY__
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user