Commit 0a310d2a authored by David S. Miller's avatar David S. Miller

Merge davem@nuts.davemloft.net:/disk1/BK/sparc-2.6

into kernel.bkbits.net:/home/davem/sparc-2.6
parents 89d3f699 4ab33f9d
This diff is collapsed.
This diff is collapsed.
......@@ -14,10 +14,10 @@ Index
4. Module dependencies
5. Module loading
6. Module parameters
7. Device control through "sysfs"
7. Optional device control through "sysfs"
8. Supported devices
9. How to add support for new image sensors
10. Note for V4L2 developers
10. Notes for V4L2 application developers
11. Contact information
12. Credits
......@@ -148,8 +148,8 @@ Default: 2
-------------------------------------------------------------------------------
7. Device control through "sysfs"
=================================
7. Optional device control through "sysfs"
==========================================
It is possible to read and write both the SN9C10[12] and the image sensor
registers by using the "sysfs" filesystem interface.
......@@ -206,7 +206,7 @@ Vendor ID Product ID
0xc45 0x6029
0xc45 0x602a
0xc45 0x602c
0xc45 0x8001
0xc45 0x6030
The list above does NOT imply that all those devices work with this driver: up
until now only the ones that mount the following image sensors are supported.
......@@ -242,19 +242,27 @@ At the moment, not yet supported image sensors are: HV7131[D|E1] (VGA),
MI03 (VGA), OV7620 (VGA).
10. Note for V4L2 developers
============================
10. Notes for V4L2 application developers
=========================================
This driver follows the V4L2 API specifications. In particular, it enforces two
rules:
1) Exactly one I/O method, either "mmap" or "read", is associated with each
- exactly one I/O method, either "mmap" or "read", is associated with each
file descriptor. Once it is selected, the application must close and reopen the
device to switch to the other I/O method.
2) Previously mapped buffer memory must always be unmapped before calling any
of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. In case,
the same number of buffers as before will be allocated again to match the size
of the new video frames, so you have to map them again before any I/O attempts.
device to switch to the other I/O method;
- previously mapped buffer memory must always be unmapped before calling any
of the "VIDIOC_S_CROP", "VIDIOC_TRY_FMT" and "VIDIOC_S_FMT" ioctl's. The same
number of buffers as before will be allocated again to match the size of the
new video frames, so you have to map them again before any I/O attempts.
Consistently with the hardware limits, this driver also supports image
downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
However the V4L2 API specifications don't correctly define how the scaling
factor can be choosen arbitrarily by the "negotiation" of the "source" and
"target" rectangles. To work around this flaw, we have added the convention
that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
scaling factor is restored to 1.
11. Contact information
......
......@@ -573,12 +573,12 @@ static inline void restart_syscall(struct pt_regs *regs)
* OK, we're invoking a handler
*/
static void
handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset,
struct pt_regs * regs, int syscall)
{
struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current;
struct k_sigaction *ka = &tsk->sighand->action[sig-1];
int usig = sig;
int ret;
......@@ -633,11 +633,8 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
spin_unlock_irq(&tsk->sighand->siglock);
}
if (ret == 0) {
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
if (ret == 0)
return;
}
force_sigsegv(sig, tsk);
}
......@@ -653,6 +650,7 @@ handle_signal(unsigned long sig, siginfo_t *info, sigset_t *oldset,
*/
static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
{
struct k_sigaction ka;
siginfo_t info;
int signr;
......@@ -673,9 +671,9 @@ static int do_signal(sigset_t *oldset, struct pt_regs *regs, int syscall)
if (current->ptrace & PT_SINGLESTEP)
ptrace_cancel_bpt(current);
signr = get_signal_to_deliver(&info, regs, NULL);
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) {
handle_signal(signr, &info, oldset, regs, syscall);
handle_signal(signr, &ka, &info, oldset, regs, syscall);
if (current->ptrace & PT_SINGLESTEP)
ptrace_set_bpt(current);
return 1;
......
......@@ -41,20 +41,21 @@ obj-$(CONFIG_SCx200) += scx200.o
# Note: kbuild does not track this dependency due to usage of .incbin
$(obj)/vsyscall.o: $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so
targets += $(foreach F,int80 sysenter,vsyscall-$F.o vsyscall-$F.so)
targets += vsyscall.lds
# The DSO images are built using a special linker script.
quiet_cmd_syscall = SYSCALL $@
cmd_syscall = $(CC) -nostdlib $(SYSCFLAGS_$(@F)) \
-Wl,-T,$(filter-out FORCE,$^) -o $@
export AFLAGS_vsyscall.lds.o += -P -C -U$(ARCH)
export CPPFLAGS_vsyscall.lds += -P -C -U$(ARCH)
vsyscall-flags = -shared -s -Wl,-soname=linux-gate.so.1
SYSCFLAGS_vsyscall-sysenter.so = $(vsyscall-flags)
SYSCFLAGS_vsyscall-int80.so = $(vsyscall-flags)
$(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \
$(obj)/vsyscall-%.so: $(src)/vsyscall.lds.s $(obj)/vsyscall-%.o FORCE
$(obj)/vsyscall-%.so: $(src)/vsyscall.lds $(obj)/vsyscall-%.o FORCE
$(call if_changed,syscall)
# We also create a special relocatable object that should mirror the symbol
......@@ -65,5 +66,5 @@ $(obj)/built-in.o: $(obj)/vsyscall-syms.o
$(obj)/built-in.o: ld_flags += -R $(obj)/vsyscall-syms.o
SYSCFLAGS_vsyscall-syms.o = -r
$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds.s $(obj)/vsyscall-sysenter.o FORCE
$(obj)/vsyscall-syms.o: $(src)/vsyscall.lds $(obj)/vsyscall-sysenter.o FORCE
$(call if_changed,syscall)
......@@ -145,6 +145,9 @@ ia32_gdt_init (void)
int cpu = smp_processor_id();
ia32_shared_page[cpu] = alloc_page(GFP_KERNEL);
if (!ia32_shared_page[cpu])
panic("failed to allocate ia32_shared_page[%d]\n", cpu);
cpu_gdt_table[cpu] = page_address(ia32_shared_page[cpu]);
/* Copy from the boot cpu's GDT */
......@@ -161,6 +164,9 @@ ia32_boot_gdt_init (void)
unsigned long ldt_size;
ia32_shared_page[0] = alloc_page(GFP_KERNEL);
if (!ia32_shared_page[0])
panic("failed to allocate ia32_shared_page[0]\n");
ia32_boot_gdt = page_address(ia32_shared_page[0]);
cpu_gdt_table[0] = ia32_boot_gdt;
......
#include <linux/module.h>
#include <linux/smp.h>
#include <linux/time.h>
#include <linux/errno.h>
#include <asm/io.h>
/* IBM Summit (EXA) Cyclone counter code*/
#define CYCLONE_CBAR_ADDR 0xFEB00CD0
......
......@@ -781,8 +781,7 @@ GLOBAL_ENTRY(ia64_switch_mode_virt)
// going to virtual
// - for code addresses, set upper bits of addr to KERNEL_START
// - for stack addresses, set upper 3 bits to 0xe.... Dont change any of the
// lower bits since we want it to stay identity mapped
// - for stack addresses, copy from input argument
movl r18=KERNEL_START
dep r3=0,r3,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
dep r14=0,r14,KERNEL_TR_PAGE_SHIFT,64-KERNEL_TR_PAGE_SHIFT
......
......@@ -371,7 +371,7 @@ ia64_init_itm (void)
itc_drift = -1;
local_cpu_data->itm_delta = (itc_freq + HZ/2) / HZ;
printk(KERN_INFO "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
printk(KERN_DEBUG "CPU %d: base freq=%lu.%03luMHz, ITC ratio=%lu/%lu, "
"ITC freq=%lu.%03luMHz+/-%ldppm\n", smp_processor_id(),
platform_base_freq / 1000000, (platform_base_freq / 1000) % 1000,
itc_ratio.num, itc_ratio.den, itc_freq / 1000000, (itc_freq / 1000) % 1000,
......
......@@ -11,6 +11,7 @@
* 03/05/07 davidm Switch from PCI-DMA to generic device DMA API.
* 00/12/13 davidm Rename to swiotlb.c and add mark_clean() to avoid
* unnecessary i-cache flushing.
* 04/07/.. ak Better overflow handling. Assorted fixes.
*/
#include <linux/cache.h>
......@@ -20,6 +21,7 @@
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/ctype.h>
#include <asm/io.h>
#include <asm/pci.h>
......@@ -46,6 +48,8 @@
*/
#define IO_TLB_SHIFT 11
int swiotlb_force;
/*
* Used to do a quick range check in swiotlb_unmap_single and swiotlb_sync_single_*, to see
* if the memory was in fact allocated by this API.
......@@ -55,8 +59,16 @@ static char *io_tlb_start, *io_tlb_end;
/*
* The number of IO TLB blocks (in groups of 64) betweeen io_tlb_start and io_tlb_end.
* This is command line adjustable via setup_io_tlb_npages.
* Default to 64MB.
*/
static unsigned long io_tlb_nslabs = 32768;
/*
* When the IOMMU overflows we return a fallback buffer. This sets the size.
*/
static unsigned long io_tlb_nslabs = 1024;
static unsigned long io_tlb_overflow = 32*1024;
void *io_tlb_overflow_buffer;
/*
* This is a free list describing the number of free entries available from each index
......@@ -78,15 +90,19 @@ static spinlock_t io_tlb_lock = SPIN_LOCK_UNLOCKED;
static int __init
setup_io_tlb_npages (char *str)
{
io_tlb_nslabs = simple_strtoul(str, NULL, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
/* avoid tail segment of size < IO_TLB_SEGSIZE */
io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
if (isdigit(*str)) {
io_tlb_nslabs = simple_strtoul(str, &str, 0) << (PAGE_SHIFT - IO_TLB_SHIFT);
/* avoid tail segment of size < IO_TLB_SEGSIZE */
io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE);
}
if (*str == ',')
++str;
if (!strcmp(str, "force"))
swiotlb_force = 1;
return 1;
}
__setup("swiotlb=", setup_io_tlb_npages);
/* make io_tlb_overflow tunable too? */
/*
* Statically reserve bounce buffer space and initialize bounce buffer data structures for
......@@ -102,7 +118,7 @@ swiotlb_init (void)
*/
io_tlb_start = alloc_bootmem_low_pages(io_tlb_nslabs * (1 << IO_TLB_SHIFT));
if (!io_tlb_start)
BUG();
panic("Cannot allocate SWIOTLB buffer");
io_tlb_end = io_tlb_start + io_tlb_nslabs * (1 << IO_TLB_SHIFT);
/*
......@@ -115,11 +131,23 @@ swiotlb_init (void)
io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
io_tlb_index = 0;
io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *));
printk(KERN_INFO "Placing software IO TLB between 0x%p - 0x%p\n",
(void *) io_tlb_start, (void *) io_tlb_end);
/*
* Get the overflow emergency buffer
*/
io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
virt_to_phys(io_tlb_start), virt_to_phys(io_tlb_end));
}
static inline int address_needs_mapping(struct device *hwdev, dma_addr_t addr)
{
dma_addr_t mask = 0xffffffff;
if (hwdev && hwdev->dma_mask)
mask = *hwdev->dma_mask;
return (addr & ~mask) != 0;
}
/*
* Allocates bounce buffer and returns its kernel virtual address.
*/
......@@ -184,11 +212,8 @@ map_single (struct device *hwdev, char *buffer, size_t size, int dir)
index = 0;
} while (index != wrap);
/*
* XXX What is a suitable recovery mechanism here? We cannot
* sleep because we are called from with in interrupts!
*/
panic("map_single: could not allocate software IO TLB (%ld bytes)", size);
spin_unlock_irqrestore(&io_tlb_lock, flags);
return NULL;
}
found:
spin_unlock_irqrestore(&io_tlb_lock, flags);
......@@ -285,7 +310,7 @@ swiotlb_alloc_coherent (struct device *hwdev, size_t size, dma_addr_t *dma_handl
memset(ret, 0, size);
dev_addr = virt_to_phys(ret);
if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
if (address_needs_mapping(hwdev,dev_addr))
panic("swiotlb_alloc_consistent: allocated memory is out of range for device");
*dma_handle = dev_addr;
return ret;
......@@ -297,6 +322,28 @@ swiotlb_free_coherent (struct device *hwdev, size_t size, void *vaddr, dma_addr_
free_pages((unsigned long) vaddr, get_order(size));
}
static void swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
{
/*
* Ran out of IOMMU space for this operation. This is very bad.
* Unfortunately the drivers cannot handle this operation properly.
* unless they check for pci_dma_mapping_error (most don't)
* When the mapping is small enough return a static buffer to limit
* the damage, or panic when the transfer is too big.
*/
printk(KERN_ERR
"PCI-DMA: Out of SW-IOMMU space for %lu bytes at device %s\n",
size, dev ? dev->bus_id : "?");
if (size > io_tlb_overflow && do_panic) {
if (dir == PCI_DMA_FROMDEVICE || dir == PCI_DMA_BIDIRECTIONAL)
panic("PCI-DMA: Memory would be corrupted\n");
if (dir == PCI_DMA_TODEVICE || dir == PCI_DMA_BIDIRECTIONAL)
panic("PCI-DMA: Random memory would be DMAed\n");
}
}
/*
* Map a single buffer of the indicated size for DMA in streaming mode. The PCI address
* to use is returned.
......@@ -308,13 +355,14 @@ dma_addr_t
swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
{
unsigned long dev_addr = virt_to_phys(ptr);
void *map;
if (dir == DMA_NONE)
BUG();
/*
* Check if the PCI device can DMA to ptr... if so, just return ptr
*/
if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) == 0)
if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force)
/*
* Device is bit capable of DMA'ing to the buffer... just return the PCI
* address of ptr
......@@ -324,12 +372,18 @@ swiotlb_map_single (struct device *hwdev, void *ptr, size_t size, int dir)
/*
* get a bounce buffer:
*/
dev_addr = virt_to_phys(map_single(hwdev, ptr, size, dir));
map = map_single(hwdev, ptr, size, dir);
if (!map) {
swiotlb_full(hwdev, size, dir, 1);
map = io_tlb_overflow_buffer;
}
dev_addr = virt_to_phys(map);
/*
* Ensure that the address returned is DMA'ble:
*/
if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
if (address_needs_mapping(hwdev, dev_addr))
panic("map_single: bounce buffer is not DMA'ble");
return dev_addr;
......@@ -437,9 +491,17 @@ swiotlb_map_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int di
for (i = 0; i < nelems; i++, sg++) {
addr = SG_ENT_VIRT_ADDRESS(sg);
dev_addr = virt_to_phys(addr);
if (hwdev && hwdev->dma_mask && (dev_addr & ~*hwdev->dma_mask) != 0)
sg->dma_address = (dma_addr_t) map_single(hwdev, addr, sg->length, dir);
else
if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) {
sg->dma_address = (dma_addr_t) virt_to_phys(map_single(hwdev, addr, sg->length, dir));
if (!sg->dma_address) {
/* Don't panic here, we expect pci_map_sg users
to do proper error handling. */
swiotlb_full(hwdev, sg->length, dir, 0);
swiotlb_unmap_sg(hwdev, sg - i, i, dir);
sg[0].dma_length = 0;
return 0;
}
} else
sg->dma_address = dev_addr;
sg->dma_length = sg->length;
}
......@@ -460,7 +522,7 @@ swiotlb_unmap_sg (struct device *hwdev, struct scatterlist *sg, int nelems, int
for (i = 0; i < nelems; i++, sg++)
if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
unmap_single(hwdev, (void *) sg->dma_address, sg->dma_length, dir);
unmap_single(hwdev, (void *) phys_to_virt(sg->dma_address), sg->dma_length, dir);
else if (dir == DMA_FROM_DEVICE)
mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
}
......@@ -501,7 +563,7 @@ swiotlb_sync_sg_for_device (struct device *hwdev, struct scatterlist *sg, int ne
int
swiotlb_dma_mapping_error (dma_addr_t dma_addr)
{
return 0;
return (dma_addr == virt_to_phys(io_tlb_overflow_buffer));
}
/*
......
# arch/ia64/sn/fakeprom/Makefile
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (c) 2000-2003 Silicon Graphics, Inc. All rights reserved.
#
# Medusa fake PROM support
#
EXTRA_TARGETS := fpromasm.o main.o fw-emu.o fpmem.o klgraph_init.o \
fprom vmlinux.sym
OBJS := $(obj)/fpromasm.o $(obj)/main.o $(obj)/fw-emu.o $(obj)/fpmem.o \
$(obj)/klgraph_init.o
LDFLAGS_fprom = -static -T
.PHONY: fprom
fprom: $(obj)/fprom
$(obj)/fprom: $(src)/fprom.lds $(OBJS) arch/ia64/lib/lib.a FORCE
$(call if_changed,ld)
$(obj)/vmlinux.sym: $(src)/make_textsym System.map
$(src)/make_textsym vmlinux > vmlinux.sym
$(call cmd,cptotop)
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
*/
This directory contains the files required to build
the fake PROM image that is currently being used to
boot IA64 kernels running under the SGI Medusa kernel.
The FPROM currently provides the following functions:
- PAL emulation for all PAL calls we've made so far.
- SAL emulation for all SAL calls we've made so far.
- EFI emulation for all EFI calls we've made so far.
- builds the "ia64_bootparam" structure that is
passed to the kernel from SAL. This structure
shows the cpu & memory configurations.
- supports medusa boottime options for changing
the number of cpus present
- supports medusa boottime options for changing
the memory configuration.
At some point, this fake PROM will be replaced by the
real PROM.
To build a fake PROM, cd to this directory & type:
make
This will (or should) build a fake PROM named "fprom".
Use this fprom image when booting the Medusa simulator. The
control file used to boot Medusa should include the
following lines:
load fprom
load vmlinux
sr pc 0x100000
sr g 9 <address of kernel _start function> #(currently 0xe000000000520000)
NOTE: There is a script "runsim" in this directory that can be used to
simplify setting up an environment for running under Medusa.
The following parameters may be passed to the fake PROM to
control the PAL/SAL/EFI parameters passed to the kernel:
GR[8] = # of cpus
GR[9] = address of primary entry point into the kernel
GR[20] = memory configuration for node 0
GR[21] = memory configuration for node 1
GR[22] = memory configuration for node 2
GR[23] = memory configuration for node 3
Registers GR[20] - GR[23] contain information to specify the
amount of memory present on nodes 0-3.
- if nothing is specified (all registers are 0), the configuration
defaults to 8 MB on node 0.
- a mem config entry for node N is passed in GR[20+N]
- a mem config entry consists of 8 hex digits. Each digit gives the
amount of physical memory available on the node starting at
1GB*<dn>, where dn is the digit number. The amount of memory
is 8MB*2**<d>. (If <d> = 0, the memory size is 0).
SN1 doesn't support dimms this small but small memory systems
boot faster on Medusa.
An example helps a lot. The following specifies that node 0 has
physical memory 0 to 8MB and 1GB to 1GB+32MB, and that node 1 has
64MB starting at address 0 of the node which is 8GB.
gr[20] = 0x21 # 0 to 8MB, 1GB to 1GB+32MB
gr[21] = 0x4 # 8GB to 8GB+64MB
/*
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
/*
* FPROM EFI memory descriptor build routines
*
* - Routines to build the EFI memory descriptor map
* - Should also be usable by the SGI prom to convert
* klconfig to efi_memmap
*/
#include <linux/config.h>
#include <linux/efi.h>
#include "fpmem.h"
/*
* args points to a layout in memory like this
*
* 32 bit 32 bit
*
* numnodes numcpus
*
* 16 bit 16 bit 32 bit
* nasid0 cpuconf membankdesc0
* nasid1 cpuconf membankdesc1
* .
* .
* .
* .
* .
*/
sn_memmap_t *sn_memmap ;
sn_config_t *sn_config ;
/*
* There is a hole in the node 0 address space. Dont put it
* in the memory map
*/
#define NODE0_HOLE_SIZE (20*MB)
#define NODE0_HOLE_END (4UL*GB)
#define MB (1024*1024)
#define GB (1024*MB)
#define KERNEL_SIZE (4*MB)
#define PROMRESERVED_SIZE (1*MB)
#ifdef SGI_SN2
#define PHYS_ADDRESS(_n, _x) (((long)_n<<38) | (long)_x | 0x3000000000UL)
#define MD_BANK_SHFT 34
#endif
/*
* For SN, this may not take an arg and gets the numnodes from
* the prom variable or by traversing klcfg or promcfg
*/
int
GetNumNodes(void)
{
return sn_config->nodes;
}
int
GetNumCpus(void)
{
return sn_config->cpus;
}
/* For SN, get the index th nasid */
int
GetNasid(int index)
{
return sn_memmap[index].nasid ;
}
node_memmap_t
GetMemBankInfo(int index)
{
return sn_memmap[index].node_memmap ;
}
int
IsCpuPresent(int cnode, int cpu)
{
return sn_memmap[cnode].cpuconfig & (1UL<<cpu);
}
/*
* Made this into an explicit case statement so that
* we can assign specific properties to banks like bank0
* actually disabled etc.
*/
#ifdef SGI_SN2
int
IsBankPresent(int index, node_memmap_t nmemmap)
{
switch (index) {
case 0:return BankPresent(nmemmap.b0size);
case 1:return BankPresent(nmemmap.b1size);
case 2:return BankPresent(nmemmap.b2size);
case 3:return BankPresent(nmemmap.b3size);
default:return -1 ;
}
}
int
GetBankSize(int index, node_memmap_t nmemmap)
{
/*
* Add 2 because there are 4 dimms per bank.
*/
switch (index) {
case 0:return 2 + ((long)nmemmap.b0size + nmemmap.b0dou);
case 1:return 2 + ((long)nmemmap.b1size + nmemmap.b1dou);
case 2:return 2 + ((long)nmemmap.b2size + nmemmap.b2dou);
case 3:return 2 + ((long)nmemmap.b3size + nmemmap.b3dou);
default:return -1 ;
}
}
#endif
void
build_mem_desc(efi_memory_desc_t *md, int type, long paddr, long numbytes, long attr)
{
md->type = type;
md->phys_addr = paddr;
md->virt_addr = 0;
md->num_pages = numbytes >> 12;
md->attribute = attr;
}
int
build_efi_memmap(void *md, int mdsize)
{
int numnodes = GetNumNodes() ;
int cnode,bank ;
int nasid ;
node_memmap_t membank_info ;
int bsize;
int count = 0 ;
long paddr, hole, numbytes;
for (cnode=0;cnode<numnodes;cnode++) {
nasid = GetNasid(cnode) ;
membank_info = GetMemBankInfo(cnode) ;
for (bank=0;bank<MD_BANKS_PER_NODE;bank++) {
if (IsBankPresent(bank, membank_info)) {
bsize = GetBankSize(bank, membank_info) ;
paddr = PHYS_ADDRESS(nasid, (long)bank<<MD_BANK_SHFT);
numbytes = BankSizeBytes(bsize);
#ifdef SGI_SN2
/*
* Ignore directory.
* Shorten memory chunk by 1 page - makes a better
* testcase & is more like the real PROM.
*/
numbytes = numbytes * 31 / 32;
#endif
/*
* Only emulate the memory prom grabs
* if we have lots of memory, to allow
* us to simulate smaller memory configs than
* we can actually run on h/w. Otherwise,
* linux throws away a whole "granule".
*/
if (cnode == 0 && bank == 0 &&
numbytes > 128*1024*1024) {
numbytes -= 1000;
}
/*
* Check for the node 0 hole. Since banks cant
* span the hole, we only need to check if the end of
* the range is the end of the hole.
*/
if (paddr+numbytes == NODE0_HOLE_END)
numbytes -= NODE0_HOLE_SIZE;
/*
* UGLY hack - we must skip overr the kernel and
* PROM runtime services but we dont exactly where it is.
* So lets just reserve:
* node 0
* 0-1MB for PAL
* 1-4MB for SAL
* node 1-N
* 0-1 for SAL
*/
if (bank == 0) {
if (cnode == 0) {
hole = 2*1024*1024;
build_mem_desc(md, EFI_PAL_CODE, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
hole = 1*1024*1024;
build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, hole, EFI_MEMORY_UC);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
hole = 1*1024*1024;
build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
} else {
hole = 2*1024*1024;
build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_WB|EFI_MEMORY_WB);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
hole = 2*1024*1024;
build_mem_desc(md, EFI_RUNTIME_SERVICES_DATA, paddr, hole, EFI_MEMORY_UC);
numbytes -= hole;
paddr += hole;
count++ ;
md += mdsize;
}
}
build_mem_desc(md, EFI_CONVENTIONAL_MEMORY, paddr, numbytes, EFI_MEMORY_WB|EFI_MEMORY_WB);
md += mdsize ;
count++ ;
}
}
}
return count ;
}
void
build_init(unsigned long args)
{
sn_config = (sn_config_t *) (args);
sn_memmap = (sn_memmap_t *)(args + 8) ; /* SN equiv for this is */
/* init to klconfig start */
}
/*
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
/*
* Structure of the mem config of the node as a SN MI reg
* Medusa supports this reg config.
*
* BankSize nibble to bank size mapping
*
* 1 - 64 MB
* 2 - 128 MB
* 3 - 256 MB
* 4 - 512 MB
* 5 - 1024 MB (1GB)
*/
#define MBSHIFT 20
#ifdef SGI_SN2
typedef struct node_memmap_s
{
unsigned int b0size :3, /* 0-2 bank 0 size */
b0dou :1, /* 3 bank 0 is 2-sided */
ena0 :1, /* 4 bank 0 enabled */
r0 :3, /* 5-7 reserved */
b1size :3, /* 8-10 bank 1 size */
b1dou :1, /* 11 bank 1 is 2-sided */
ena1 :1, /* 12 bank 1 enabled */
r1 :3, /* 13-15 reserved */
b2size :3, /* 16-18 bank 2 size */
b2dou :1, /* 19 bank 1 is 2-sided */
ena2 :1, /* 20 bank 2 enabled */
r2 :3, /* 21-23 reserved */
b3size :3, /* 24-26 bank 3 size */
b3dou :1, /* 27 bank 3 is 2-sided */
ena3 :1, /* 28 bank 3 enabled */
r3 :3; /* 29-31 reserved */
} node_memmap_t ;
#define SN2_BANK_SIZE_SHIFT (MBSHIFT+6) /* 64 MB */
#define BankPresent(bsize) (bsize<6)
#define BankSizeBytes(bsize) (BankPresent(bsize) ? 1UL<<((bsize)+SN2_BANK_SIZE_SHIFT) : 0)
#define MD_BANKS_PER_NODE 4
#define MD_BANKSIZE (1UL << 34)
#endif
typedef struct sn_memmap_s
{
short nasid ;
short cpuconfig;
node_memmap_t node_memmap ;
} sn_memmap_t ;
typedef struct sn_config_s
{
int cpus;
int nodes;
sn_memmap_t memmap[1]; /* start of array */
} sn_config_t;
extern void build_init(unsigned long);
extern int build_efi_memmap(void *, int);
extern int GetNumNodes(void);
extern int GetNumCpus(void);
extern int IsCpuPresent(int, int);
extern int GetNasid(int);
/*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (c) 2002-2003 Silicon Graphics, Inc. All Rights Reserved.
*/
OUTPUT_FORMAT("elf64-ia64-little")
OUTPUT_ARCH(ia64)
ENTRY(_start)
SECTIONS
{
v = 0x0000000000000000 ; /* this symbol is here to make debugging with kdb easier... */
. = (0x000000000000000 + 0x100000) ;
_text = .;
.text : AT(ADDR(.text) - 0x0000000000000000 )
{
*(__ivt_section)
/* these are not really text pages, but the zero page needs to be in a fixed location: */
*(__special_page_section)
__start_gate_section = .;
*(__gate_section)
__stop_gate_section = .;
*(.text)
}
/* Global data */
_data = .;
.rodata : AT(ADDR(.rodata) - 0x0000000000000000 )
{ *(.rodata) *(.rodata.*) }
.opd : AT(ADDR(.opd) - 0x0000000000000000 )
{ *(.opd) }
.data : AT(ADDR(.data) - 0x0000000000000000 )
{ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
__gp = ALIGN (8) + 0x200000;
.got : AT(ADDR(.got) - 0x0000000000000000 )
{ *(.got.plt) *(.got) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata : AT(ADDR(.sdata) - 0x0000000000000000 )
{ *(.sdata) }
_edata = .;
_bss = .;
.sbss : AT(ADDR(.sbss) - 0x0000000000000000 )
{ *(.sbss) *(.scommon) }
.bss : AT(ADDR(.bss) - 0x0000000000000000 )
{ *(.bss) *(COMMON) }
. = ALIGN(64 / 8);
_end = .;
/* Sections to be discarded */
/DISCARD/ : {
*(.text.exit)
*(.data.exit)
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
/* Discard them for now since Intel SoftSDV cannot handle them.
.comment 0 : { *(.comment) }
.note 0 : { *(.note) }
*/
/DISCARD/ : { *(.comment) }
/DISCARD/ : { *(.note) }
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
#include <linux/types.h>
#include <asm/bitops.h>
extern void klgraph_init(void);
void bedrock_init(int);
void synergy_init(int, int);
void sys_fw_init (const char *args, int arglen, int bsp);
volatile int bootmaster=0; /* Used to pick bootmaster */
volatile int nasidmaster[128]={0}; /* Used to pick node/synergy masters */
int init_done=0;
extern int bsp_lid;
#define get_bit(b,p) (((*p)>>(b))&1)
int
fmain(int lid, int bsp) {
int syn, nasid, cpu;
/*
* First lets figure out who we are. This is done from the
* LID passed to us.
*/
nasid = (lid>>16)&0xfff;
cpu = (lid>>28)&3;
syn = 0;
/*
* Now pick a nasid master to initialize Bedrock registers.
*/
if (test_and_set_bit(8, &nasidmaster[nasid]) == 0) {
bedrock_init(nasid);
test_and_set_bit(9, &nasidmaster[nasid]);
} else
while (get_bit(9, &nasidmaster[nasid]) == 0);
/*
* Now pick a BSP & finish init.
*/
if (test_and_set_bit(0, &bootmaster) == 0) {
sys_fw_init(0, 0, bsp);
test_and_set_bit(1, &bootmaster);
} else
while (get_bit(1, &bootmaster) == 0);
return (lid == bsp_lid);
}
void
bedrock_init(int nasid)
{
nasid = nasid; /* to quiet gcc */
#if 0
/*
* Undef if you need fprom to generate a 1 node klgraph
* information .. only works for 1 node for nasid 0.
*/
klgraph_init();
#endif
}
void
synergy_init(int nasid, int syn)
{
long *base;
long off;
/*
* Enable all FSB flashed interrupts.
* I'd really like defines for this......
*/
base = (long*)0x80000e0000000000LL; /* base of synergy regs */
for (off = 0x2a0; off < 0x2e0; off+=8) /* offset for VEC_MASK_{0-3}_A/B */
*(base+off/8) = -1LL;
/*
* Set the NASID in the FSB_CONFIG register.
*/
base = (long*)0x80000e0000000450LL;
*base = (long)((nasid<<16)|(syn<<9));
}
/* Why isnt there a bcopy/memcpy in lib64.a */
void*
memcpy(void * dest, const void *src, size_t count)
{
char *s, *se, *d;
for(d=dest, s=(char*)src, se=s+count; s<se; s++, d++)
*d = *s;
return dest;
}
#!/bin/sh
#
# Build a textsym file for use in the Arium ITP probe.
#
#
# This file is subject to the terms and conditions of the GNU General Public
# License. See the file "COPYING" in the main directory of this archive
# for more details.
#
# Copyright (c) 2001-2003 Silicon Graphics, Inc. All rights reserved.
#
help() {
cat <<END
Build a WinDD "symtxt" file for use with the Arium ECM-30 probe.
Usage: $0 [<vmlinux file> [<output file>]]
If no input file is specified, it defaults to vmlinux.
If no output file name is specified, it defaults to "textsym".
END
exit 1
}
err () {
echo "ERROR - $*" >&2
exit 1
}
OPTS="H"
while getopts "$OPTS" c ; do
case $c in
H) help;;
\?) help;;
esac
done
shift `expr $OPTIND - 1`
#OBJDUMP=/usr/bin/ia64-linux-objdump
LINUX=${1:-vmlinux}
TEXTSYM=${2:-${LINUX}.sym}
TMPSYM=${2:-${LINUX}.sym.tmp}
trap "/bin/rm -f $TMPSYM" 0
[ -f $VMLINUX ] || help
$OBJDUMP -t $LINUX | egrep -v '__ks' | sort > $TMPSYM
SN1=`egrep "dig_setup|Synergy_da_indr" $TMPSYM|wc -l`
# Dataprefix and textprefix correspond to the VGLOBAL_BASE and VPERNODE_BASE.
# Eventually, these values should be:
# dataprefix ffffffff
# textprefix fffffffe
# but right now they're still changing, so make them dynamic.
dataprefix=`awk ' / \.data / { print substr($1, 0, 8) ; exit ; }' $TMPSYM`
textprefix=`awk ' / \.text / { print substr($1, 0, 8) ; exit ; }' $TMPSYM`
# pipe everything thru sort
echo "TEXTSYM V1.0"
(cat <<END
GLOBAL | ${textprefix}00000000 | CODE | VEC_VHPT_Translation_0000
GLOBAL | ${textprefix}00000400 | CODE | VEC_ITLB_0400
GLOBAL | ${textprefix}00000800 | CODE | VEC_DTLB_0800
GLOBAL | ${textprefix}00000c00 | CODE | VEC_Alt_ITLB_0c00
GLOBAL | ${textprefix}00001000 | CODE | VEC_Alt_DTLB_1000
GLOBAL | ${textprefix}00001400 | CODE | VEC_Data_nested_TLB_1400
GLOBAL | ${textprefix}00001800 | CODE | VEC_Instruction_Key_Miss_1800
GLOBAL | ${textprefix}00001c00 | CODE | VEC_Data_Key_Miss_1c00
GLOBAL | ${textprefix}00002000 | CODE | VEC_Dirty-bit_2000
GLOBAL | ${textprefix}00002400 | CODE | VEC_Instruction_Access-bit_2400
GLOBAL | ${textprefix}00002800 | CODE | VEC_Data_Access-bit_2800
GLOBAL | ${textprefix}00002c00 | CODE | VEC_Break_instruction_2c00
GLOBAL | ${textprefix}00003000 | CODE | VEC_External_Interrupt_3000
GLOBAL | ${textprefix}00003400 | CODE | VEC_Reserved_3400
GLOBAL | ${textprefix}00003800 | CODE | VEC_Reserved_3800
GLOBAL | ${textprefix}00003c00 | CODE | VEC_Reserved_3c00
GLOBAL | ${textprefix}00004000 | CODE | VEC_Reserved_4000
GLOBAL | ${textprefix}00004400 | CODE | VEC_Reserved_4400
GLOBAL | ${textprefix}00004800 | CODE | VEC_Reserved_4800
GLOBAL | ${textprefix}00004c00 | CODE | VEC_Reserved_4c00
GLOBAL | ${textprefix}00005000 | CODE | VEC_Page_Not_Present_5000
GLOBAL | ${textprefix}00005100 | CODE | VEC_Key_Permission_5100
GLOBAL | ${textprefix}00005200 | CODE | VEC_Instruction_Access_Rights_5200
GLOBAL | ${textprefix}00005300 | CODE | VEC_Data_Access_Rights_5300
GLOBAL | ${textprefix}00005400 | CODE | VEC_General_Exception_5400
GLOBAL | ${textprefix}00005500 | CODE | VEC_Disabled_FP-Register_5500
GLOBAL | ${textprefix}00005600 | CODE | VEC_Nat_Consumption_5600
GLOBAL | ${textprefix}00005700 | CODE | VEC_Speculation_5700
GLOBAL | ${textprefix}00005800 | CODE | VEC_Reserved_5800
GLOBAL | ${textprefix}00005900 | CODE | VEC_Debug_5900
GLOBAL | ${textprefix}00005a00 | CODE | VEC_Unaligned_Reference_5a00
GLOBAL | ${textprefix}00005b00 | CODE | VEC_Unsupported_Data_Reference_5b00
GLOBAL | ${textprefix}00005c00 | CODE | VEC_Floating-Point_Fault_5c00
GLOBAL | ${textprefix}00005d00 | CODE | VEC_Floating_Point_Trap_5d00
GLOBAL | ${textprefix}00005e00 | CODE | VEC_Lower_Privilege_Tranfer_Trap_5e00
GLOBAL | ${textprefix}00005f00 | CODE | VEC_Taken_Branch_Trap_5f00
GLOBAL | ${textprefix}00006000 | CODE | VEC_Single_Step_Trap_6000
GLOBAL | ${textprefix}00006100 | CODE | VEC_Reserved_6100
GLOBAL | ${textprefix}00006200 | CODE | VEC_Reserved_6200
GLOBAL | ${textprefix}00006300 | CODE | VEC_Reserved_6300
GLOBAL | ${textprefix}00006400 | CODE | VEC_Reserved_6400
GLOBAL | ${textprefix}00006500 | CODE | VEC_Reserved_6500
GLOBAL | ${textprefix}00006600 | CODE | VEC_Reserved_6600
GLOBAL | ${textprefix}00006700 | CODE | VEC_Reserved_6700
GLOBAL | ${textprefix}00006800 | CODE | VEC_Reserved_6800
GLOBAL | ${textprefix}00006900 | CODE | VEC_IA-32_Exeception_6900
GLOBAL | ${textprefix}00006a00 | CODE | VEC_IA-32_Intercept_6a00
GLOBAL | ${textprefix}00006b00 | CODE | VEC_IA-32_Interrupt_6b00
GLOBAL | ${textprefix}00006c00 | CODE | VEC_Reserved_6c00
GLOBAL | ${textprefix}00006d00 | CODE | VEC_Reserved_6d00
GLOBAL | ${textprefix}00006e00 | CODE | VEC_Reserved_6e00
GLOBAL | ${textprefix}00006f00 | CODE | VEC_Reserved_6f00
GLOBAL | ${textprefix}00007000 | CODE | VEC_Reserved_7000
GLOBAL | ${textprefix}00007100 | CODE | VEC_Reserved_7100
GLOBAL | ${textprefix}00007200 | CODE | VEC_Reserved_7200
GLOBAL | ${textprefix}00007300 | CODE | VEC_Reserved_7300
GLOBAL | ${textprefix}00007400 | CODE | VEC_Reserved_7400
GLOBAL | ${textprefix}00007500 | CODE | VEC_Reserved_7500
GLOBAL | ${textprefix}00007600 | CODE | VEC_Reserved_7600
GLOBAL | ${textprefix}00007700 | CODE | VEC_Reserved_7700
GLOBAL | ${textprefix}00007800 | CODE | VEC_Reserved_7800
GLOBAL | ${textprefix}00007900 | CODE | VEC_Reserved_7900
GLOBAL | ${textprefix}00007a00 | CODE | VEC_Reserved_7a00
GLOBAL | ${textprefix}00007b00 | CODE | VEC_Reserved_7b00
GLOBAL | ${textprefix}00007c00 | CODE | VEC_Reserved_7c00
GLOBAL | ${textprefix}00007d00 | CODE | VEC_Reserved_7d00
GLOBAL | ${textprefix}00007e00 | CODE | VEC_Reserved_7e00
GLOBAL | ${textprefix}00007f00 | CODE | VEC_Reserved_7f00
END
awk '
/ _start$/ {start=1}
/ start_ap$/ {start=1}
/__start_gate_section/ {start=1}
/^'${dataprefix}\|${textprefix}'/ {
if ($4 == ".kdb")
next
if (start && substr($NF,1,1) != "0") {
type = substr($0,26,5)
if (type == ".text")
printf "GLOBAL | %s | CODE | %s\n", $1, $NF
else {
n = 0
s = $(NF-1)
while (length(s) > 0) {
n = n*16 + (index("0123456789abcdef", substr(s,1,1)) - 1)
s = substr(s,2)
}
printf "GLOBAL | %s | DATA | %s | %d\n", $1, $NF, n
}
}
if($NF == "_end")
exit
}
' $TMPSYM ) | egrep -v " __device| __vendor" | awk -v sn1="$SN1" '
/GLOBAL/ {
print $0
if (sn1 != 0) {
/* 32 bits of sn1 physical addrs, */
print substr($0,1,9) "04" substr($0,20,16) "Phy_" substr($0,36)
} else {
/* 38 bits of sn2 physical addrs, need addr space bits */
print substr($0,1,9) "3004" substr($0,20,16) "Phy_" substr($0,36)
}
} ' | sort -k3
N=`wc -l $TEXTSYM|awk '{print $1}'`
echo "Generated TEXTSYM file" >&2
echo " $LINUX --> $TEXTSYM" >&2
echo " Found $N symbols" >&2
This diff is collapsed.
......@@ -290,6 +290,7 @@ sn_pci_fixup_slot(struct pci_dev *dev)
addr |= __IA64_UNCACHED_OFFSET;
dev->resource[idx].start = addr;
dev->resource[idx].end = addr + size;
dev->resource[idx].parent = &ioport_resource;
}
if (dev->resource[idx].flags & IORESOURCE_IO)
......@@ -322,6 +323,7 @@ sn_pci_fixup_slot(struct pci_dev *dev)
addr |= __IA64_UNCACHED_OFFSET;
dev->resource[idx].start = addr;
dev->resource[idx].end = addr + size;
dev->resource[idx].parent = &iomem_resource;
}
if (dev->resource[idx].flags & IORESOURCE_MEM)
......@@ -351,6 +353,7 @@ sn_pci_fixup_slot(struct pci_dev *dev)
addr |= __IA64_UNCACHED_OFFSET;
dev->resource[PCI_ROM_RESOURCE].start = addr;
dev->resource[PCI_ROM_RESOURCE].end = addr + size;
dev->resource[idx].parent = &iomem_resource;
if (dev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_MEM)
cmd |= PCI_COMMAND_MEMORY;
}
......
......@@ -421,9 +421,10 @@ bte_init_node(nodepda_t * mynodepda, cnodeid_t cnode)
mynodepda->bte_recovery_timer.data = (unsigned long) mynodepda;
for (i = 0; i < BTES_PER_NODE; i++) {
(u64) mynodepda->bte_if[i].bte_base_addr =
REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode),
(i == 0 ? IIO_IBLS0 : IIO_IBLS1));
/* Which link status register should we use? */
unsigned long link_status = (i == 0 ? IIO_IBLS0 : IIO_IBLS1);
mynodepda->bte_if[i].bte_base_addr = (u64 *)
REMOTE_HUB_ADDR(cnodeid_to_nasid(cnode), link_status);
/*
* Initialize the notification and spinlock
......
......@@ -3,7 +3,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
* Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved.
*/
#include <linux/config.h>
#include <asm/uaccess.h>
......@@ -118,11 +118,33 @@ register_sn_force_interrupt(void) {
}
}
static int coherence_id_read_proc(char *page, char **start, off_t off,
int count, int *eof, void *data) {
return sprintf(page, "%d\n", cpuid_to_coherence_id(smp_processor_id()));
}
void
register_sn_coherence_id(void) {
struct proc_dir_entry *entry;
if (!sgi_proc_dir) {
sgi_proc_dir = proc_mkdir("sgi_sn", 0);
}
entry = create_proc_entry("coherence_id", 0444, sgi_proc_dir);
if (entry) {
entry->nlink = 1;
entry->data = 0;
entry->read_proc = coherence_id_read_proc;
entry->write_proc = NULL;
}
}
void
register_sn_procfs(void) {
register_sn_partition_id();
register_sn_serial_numbers();
register_sn_force_interrupt();
register_sn_coherence_id();
}
#endif /* CONFIG_PROC_FS */
......@@ -107,6 +107,8 @@ struct ub_dev;
* A second ought to be enough for a 32K transfer (UB_MAX_SECTORS)
* even if a webcam hogs the bus (famous last words).
* Some CDs need a second to spin up though.
* ZIP drive rejects commands when it's not spinning,
* so it does not need long timeouts either.
*/
#define UB_URB_TIMEOUT (HZ*2)
#define UB_CTRL_TIMEOUT (HZ/2) /* 500ms ought to be enough to clear a stall */
......@@ -287,6 +289,7 @@ struct ub_dev {
struct ub_completion work_done;
struct urb work_urb;
struct timer_list work_timer;
int last_pipe; /* What might need clearing */
struct bulk_cb_wrap work_bcb;
struct bulk_cs_wrap work_bcs;
......@@ -776,16 +779,20 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->send_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe,
bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT;
sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
/* Fill what we shouldn't be filling, because usb-storage did so. */
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */
printk("ub: cmd #%d start failed (%d)\n", cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done);
return rc;
}
......@@ -795,6 +802,19 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
return 0;
}
/*
* Timeout handler.
*/
static void ub_urb_timeout(unsigned long arg)
{
struct ub_dev *sc = (struct ub_dev *) arg;
unsigned long flags;
spin_lock_irqsave(&sc->lock, flags);
usb_unlink_urb(&sc->work_urb);
spin_unlock_irqrestore(&sc->lock, flags);
}
/*
* Completion routine for the work URB.
*
......@@ -943,14 +963,18 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe,
cmd->data, cmd->len, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT;
sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */
printk("ub: data #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc);
return;
......@@ -1034,16 +1058,20 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
usb_fill_bulk_urb(&sc->work_urb, sc->dev,
sc->recv_bulk_pipe, &sc->work_bcs,
US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT;
sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC);
if (rc != 0) {
/* XXX Clear stalls */
printk("%s: CSW #%d submit failed (%d)\n",
sc->name, cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc);
return;
......@@ -1153,14 +1181,18 @@ static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
sc->last_pipe = sc->recv_bulk_pipe;
usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe,
&sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc);
sc->work_urb.timeout = UB_URB_TIMEOUT;
sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_URB_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
/* XXX Clear stalls */
printk("ub: CSW #%d submit failed (%d)\n", cmd->tag, rc); /* P3 */
del_timer(&sc->work_timer);
ub_complete(&sc->work_done);
ub_state_done(sc, cmd, rc);
return;
......@@ -1233,14 +1265,17 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
UB_INIT_COMPLETION(sc->work_done);
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
(unsigned char*) cr, NULL, 0,
ub_urb_complete, sc);
sc->work_urb.timeout = UB_CTRL_TIMEOUT;
(unsigned char*) cr, NULL, 0, ub_urb_complete, sc);
sc->work_urb.transfer_flags = URB_ASYNC_UNLINK;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT;
add_timer(&sc->work_timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
del_timer(&sc->work_timer);
ub_complete(&sc->work_done);
return rc;
}
......@@ -1653,6 +1688,12 @@ static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt)
complete(cop);
}
static void ub_probe_timeout(unsigned long arg)
{
struct completion *cop = (struct completion *) arg;
complete(cop);
}
/*
* Clear initial stalls.
*/
......@@ -1661,6 +1702,7 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
int endp;
struct usb_ctrlrequest *cr;
struct completion compl;
struct timer_list timer;
int rc;
init_completion(&compl);
......@@ -1677,21 +1719,35 @@ static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe)
cr->wLength = cpu_to_le16(0);
usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe,
(unsigned char*) cr, NULL, 0,
ub_probe_urb_complete, &compl);
sc->work_urb.timeout = UB_CTRL_TIMEOUT;
(unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl);
sc->work_urb.transfer_flags = 0;
sc->work_urb.actual_length = 0;
sc->work_urb.error_count = 0;
sc->work_urb.status = 0;
init_timer(&timer);
timer.function = ub_probe_timeout;
timer.data = (unsigned long) &compl;
timer.expires = jiffies + UB_CTRL_TIMEOUT;
add_timer(&timer);
if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
printk(KERN_WARNING
"%s: Unable to submit a probe clear (%d)\n", sc->name, rc);
del_timer_sync(&timer);
return rc;
}
wait_for_completion(&compl);
del_timer_sync(&timer);
/*
* Most of the time, URB was done and dev set to NULL, and so
* the unlink bounces out with ENODEV. We do not call usb_kill_urb
* because we still think about a backport to 2.4.
*/
usb_unlink_urb(&sc->work_urb);
/* reset the endpoint toggle */
usb_settoggle(sc->dev, endp, usb_pipeout(sc->last_pipe), 0);
......@@ -1767,6 +1823,10 @@ static int ub_probe(struct usb_interface *intf,
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0);
init_timer(&sc->work_timer);
sc->work_timer.data = (unsigned long) sc;
sc->work_timer.function = ub_urb_timeout;
ub_init_completion(&sc->work_done);
sc->work_done.done = 1; /* A little yuk, but oh well... */
......
......@@ -299,4 +299,16 @@ config SENSORS_RTC8564
This driver can also be built as a module. If so, the module
will be called i2c-rtc8564.
config ISP1301_OMAP
tristate "Philips ISP1301 with OMAP OTG"
depends on I2C && ARCH_OMAP_OTG
help
If you say yes here you get support for the Philips ISP1301
USB-On-The-Go transceiver working with the OMAP OTG controller.
The ISP1301 is used in products including H2 and H3 development
boards for Texas Instruments OMAP processors.
This driver can also be built as a module. If so, the module
will be called isp1301_omap.
endmenu
......@@ -29,7 +29,9 @@ obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_VIA686A) += via686a.o
obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o
obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
EXTRA_CFLAGS += -DDEBUG
endif
This diff is collapsed.
......@@ -268,7 +268,6 @@ static void irda_usb_change_speed_xbofs(struct irda_usb_cb *self)
speed_bulk_callback, self);
urb->transfer_buffer_length = USB_IRDA_HEADER;
urb->transfer_flags = URB_ASYNC_UNLINK;
urb->timeout = msecs_to_jiffies(100);
/* Irq disabled -> GFP_ATOMIC */
if ((ret = usb_submit_urb(urb, GFP_ATOMIC))) {
......@@ -411,8 +410,6 @@ static int irda_usb_hard_xmit(struct sk_buff *skb, struct net_device *netdev)
* after each of our packets that is exact multiple of the frame size.
* This is how the dongle will detect the end of packet - Jean II */
urb->transfer_flags |= URB_ZERO_PACKET;
/* Timeout need to be shorter than NET watchdog timer */
urb->timeout = msecs_to_jiffies(200);
/* Generate min turn time. FIXME: can we do better than this? */
/* Trying to a turnaround time at this level is trying to measure
......
......@@ -367,7 +367,7 @@ static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned c
acm->writeurb->dev = acm->dev;
acm->ready_for_write = 0;
stat = usb_submit_urb(acm->writeurb, GFP_NOIO);
stat = usb_submit_urb(acm->writeurb, from_user ? GFP_KERNEL : GFP_ATOMIC);
if (stat < 0) {
dbg("usb_submit_urb(write bulk) failed");
acm->ready_for_write = 1;
......
......@@ -71,3 +71,29 @@ config USB_SUSPEND
may not yet work as expected.
If you are unsure about this, say N here.
config USB_OTG
bool
depends on USB && EXPERIMENTAL
select USB_SUSPEND
default n
config USB_OTG_WHITELIST
bool "Rely on OTG Targeted Peripherals List"
depends on USB_OTG
default y
help
If you say Y here, the "otg_whitelist.h" file will be used as a
product whitelist, so USB peripherals not listed there will be
rejected during enumeration. This behavior is required by the
USB OTG specification for all devices not on your product's
"Targeted Peripherals List".
Otherwise, peripherals not listed there will only generate a
warning and enumeration will continue. That's more like what
normal Linux-USB hosts do (other than the warning), and is
convenient for many stages of product development.
......@@ -790,6 +790,8 @@ int usb_register_root_hub (struct usb_device *usb_dev, struct device *parent_dev
usb_dev->epmaxpacketin[0] = usb_dev->epmaxpacketout[0] = 64;
retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
if (retval != sizeof usb_dev->descriptor) {
usb_dev->bus->root_hub = NULL;
up (&usb_bus_list_lock);
dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
usb_dev->dev.bus_id, retval);
return (retval < 0) ? retval : -EMSGSIZE;
......@@ -1404,6 +1406,45 @@ static int hcd_hub_resume (struct usb_bus *bus)
/*-------------------------------------------------------------------------*/
#ifdef CONFIG_USB_OTG
/**
* usb_bus_start_enum - start immediate enumeration (for OTG)
* @bus: the bus (must use hcd framework)
* @port: 1-based number of port; usually bus->otg_port
* Context: in_interrupt()
*
* Starts enumeration, with an immediate reset followed later by
* khubd identifying and possibly configuring the device.
* This is needed by OTG controller drivers, where it helps meet
* HNP protocol timing requirements for starting a port reset.
*/
int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num)
{
struct usb_hcd *hcd;
int status = -EOPNOTSUPP;
/* NOTE: since HNP can't start by grabbing the bus's address0_sem,
* boards with root hubs hooked up to internal devices (instead of
* just the OTG port) may need more attention to resetting...
*/
hcd = container_of (bus, struct usb_hcd, self);
if (port_num && hcd->driver->start_port_reset)
status = hcd->driver->start_port_reset(hcd, port_num);
/* run khubd shortly after (first) root port reset finishes;
* it may issue others, until at least 50 msecs have passed.
*/
if (status == 0)
mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(10));
return status;
}
EXPORT_SYMBOL (usb_bus_start_enum);
#endif
/*-------------------------------------------------------------------------*/
/* called by khubd, rmmod, apmd, or other thread for hcd-private cleanup.
* we're guaranteed that the device is fully quiesced. also, that each
* endpoint has been hcd_endpoint_disabled.
......
......@@ -212,6 +212,7 @@ struct hc_driver {
char *buf, u16 wLength);
int (*hub_suspend)(struct usb_hcd *);
int (*hub_resume)(struct usb_hcd *);
int (*start_port_reset)(struct usb_hcd *, unsigned port_num);
};
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
......
......@@ -1095,6 +1095,10 @@ static inline void show_string(struct usb_device *udev, char *id, int index)
{}
#endif
#ifdef CONFIG_USB_OTG
#include "otg_whitelist.h"
#endif
/**
* usb_new_device - perform initial device setup (usbcore-internal)
* @udev: newly addressed device (in ADDRESS state)
......@@ -1144,6 +1148,79 @@ int usb_new_device(struct usb_device *udev)
show_string(udev, "SerialNumber",
udev->descriptor.iSerialNumber);
#ifdef CONFIG_USB_OTG
/*
* OTG-aware devices on OTG-capable root hubs may be able to use SRP,
* to wake us after we've powered off VBUS; and HNP, switching roles
* "host" to "peripheral". The OTG descriptor helps figure this out.
*/
if (!udev->bus->is_b_host
&& udev->config
&& udev->parent == udev->bus->root_hub) {
struct usb_otg_descriptor *desc = 0;
struct usb_bus *bus = udev->bus;
/* descriptor may appear anywhere in config */
if (__usb_get_extra_descriptor (udev->rawdescriptors[0],
udev->config[0].desc.wTotalLength,
USB_DT_OTG, (void **) &desc) == 0) {
if (desc->bmAttributes & USB_OTG_HNP) {
unsigned port;
struct usb_device *root = udev->parent;
for (port = 0; port < root->maxchild; port++) {
if (root->children[port] == udev)
break;
}
port++;
dev_info(&udev->dev,
"Dual-Role OTG device on %sHNP port\n",
(port == bus->otg_port)
? "" : "non-");
/* enable HNP before suspend, it's simpler */
if (port == bus->otg_port)
bus->b_hnp_enable = 1;
err = usb_control_msg(udev,
usb_sndctrlpipe(udev, 0),
USB_REQ_SET_FEATURE, 0,
bus->b_hnp_enable
? USB_DEVICE_B_HNP_ENABLE
: USB_DEVICE_A_ALT_HNP_SUPPORT,
0, NULL, 0, HZ * USB_CTRL_SET_TIMEOUT);
if (err < 0) {
/* OTG MESSAGE: report errors here,
* customize to match your product.
*/
dev_info(&udev->dev,
"can't set HNP mode; %d\n",
err);
bus->b_hnp_enable = 0;
}
}
}
}
if (!is_targeted(udev)) {
/* Maybe it can talk to us, though we can't talk to it.
* (Includes HNP test device.)
*/
if (udev->bus->b_hnp_enable || udev->bus->is_b_host) {
static int __usb_suspend_device (struct usb_device *,
int port, u32 state);
err = __usb_suspend_device(udev,
udev->bus->otg_port - 1,
PM_SUSPEND_MEM);
if (err < 0)
dev_dbg(&udev->dev, "HNP fail, %d\n", err);
}
err = -ENODEV;
goto fail;
}
#endif
/* put device-specific files into sysfs */
err = device_add (&udev->dev);
if (err) {
......@@ -1934,6 +2011,10 @@ hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port)
hdev->bus->b_hnp_enable = 0;
}
retval = clear_port_feature(hdev, port, USB_PORT_FEAT_SUSPEND);
if (retval < 0 && retval != -EPIPE)
dev_dbg(&udev->dev, "can't clear suspend; %d\n", retval);
/* Some low speed devices have problems with the quick delay, so */
/* be a bit pessimistic with those devices. RHbug #23670 */
if (oldspeed == USB_SPEED_LOW)
......@@ -2160,6 +2241,12 @@ static void hub_port_connect_change(struct usb_hub *hub, int port,
usb_disconnect(&hdev->children[port]);
clear_bit(port, hub->change_bits);
#ifdef CONFIG_USB_OTG
/* during HNP, don't repeat the debounce */
if (hdev->bus->is_b_host)
portchange &= ~USB_PORT_STAT_C_CONNECTION;
#endif
if (portchange & USB_PORT_STAT_C_CONNECTION) {
status = hub_port_debounce(hdev, port);
if (status < 0) {
......
......@@ -190,8 +190,8 @@ struct usb_hub {
struct usb_device *hdev;
struct urb *urb; /* for interrupt polling pipe */
/* buffer for urb ... 1 bit each for hub and children, rounded up */
char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
/* buffer for urb ... with extra space in case of babble */
char (*buffer)[8];
dma_addr_t buffer_dma; /* DMA address for buffer */
union {
struct usb_hub_status hub;
......
......@@ -248,7 +248,7 @@ static void sg_complete (struct urb *urb, struct pt_regs *regs)
* unlink pending urbs so they won't rx/tx bad data.
*/
for (i = 0, found = 0; i < io->entries; i++) {
if (!io->urbs [i])
if (!io->urbs [i] || !io->urbs [i]->dev)
continue;
if (found) {
status = usb_unlink_urb (io->urbs [i]);
......@@ -337,7 +337,7 @@ int usb_sg_init (
if (io->entries <= 0)
return io->entries;
io->count = 0;
io->count = io->entries;
io->urbs = kmalloc (io->entries * sizeof *io->urbs, mem_flags);
if (!io->urbs)
goto nomem;
......@@ -347,7 +347,7 @@ int usb_sg_init (
if (usb_pipein (pipe))
urb_flags |= URB_SHORT_NOT_OK;
for (i = 0; i < io->entries; i++, io->count = i) {
for (i = 0; i < io->entries; i++) {
unsigned len;
io->urbs [i] = usb_alloc_urb (0, mem_flags);
......@@ -477,24 +477,19 @@ void usb_sg_wait (struct usb_sg_request *io)
/* fail any uncompleted urbs */
default:
spin_lock_irq (&io->lock);
io->count -= entries - i;
if (io->status == -EINPROGRESS)
io->status = retval;
if (io->count == 0)
complete (&io->complete);
spin_unlock_irq (&io->lock);
io->urbs[i]->dev = NULL;
io->urbs [i]->dev = NULL;
io->urbs [i]->status = retval;
dev_dbg (&io->dev->dev, "%s, submit --> %d\n",
__FUNCTION__, retval);
usb_sg_cancel (io);
}
spin_lock_irq (&io->lock);
if (retval && io->status == -ECONNRESET)
if (retval && (io->status == 0 || io->status == -ECONNRESET))
io->status = retval;
}
io->count -= entries - i;
if (io->count == 0)
complete (&io->complete);
spin_unlock_irq (&io->lock);
/* OK, yes, this could be packaged as non-blocking.
......
/*
* drivers/usb/core/otg_whitelist.h
*
* Copyright (C) 2004 Texas Instruments
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
/*
* This OTG Whitelist is the OTG "Targeted Peripheral List". It should
* mostly use of USB_DEVICE() or USB_DEVICE_VER() entries..
*
* YOU _SHOULD_ CHANGE THIS LIST TO MATCH YOUR PRODUCT AND ITS TESTING!
*/
static struct usb_device_id whitelist_table [] = {
/* hubs are optional in OTG, but very handy ... */
{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 0), },
{ USB_DEVICE_INFO(USB_CLASS_HUB, 0, 1), },
#ifdef CONFIG_USB_PRINTER /* ignoring nonstatic linkage! */
/* FIXME actually, printers are NOT supposed to use device classes;
* they're supposed to use interface classes...
*/
{ USB_DEVICE_INFO(7, 1, 1) },
{ USB_DEVICE_INFO(7, 1, 2) },
{ USB_DEVICE_INFO(7, 1, 3) },
#endif
#ifdef CONFIG_USB_CDCETHER
/* Linux-USB CDC Ethernet gadget */
{ USB_DEVICE(0x0525, 0xa4a1), },
/* Linux-USB CDC Ethernet + RNDIS gadget */
{ USB_DEVICE(0x0525, 0xa4a2), },
#endif
#if defined(CONFIG_USB_TEST) || defined(CONFIG_USB_TEST_MODULE)
/* gadget zero, for testing */
{ USB_DEVICE(0x0525, 0xa4a0), },
#endif
{ } /* Terminating entry */
};
static int is_targeted(struct usb_device *dev)
{
struct usb_device_id *id = whitelist_table;
/* possible in developer configs only! */
if (!dev->bus->otg_port)
return 1;
/* HNP test device is _never_ targeted (see OTG spec 6.6.6) */
if (dev->descriptor.idVendor == 0x1a0a
&& dev->descriptor.idProduct == 0xbadd)
return 0;
/* NOTE: can't use usb_match_id() since interface caches
* aren't set up yet. this is cut/paste from that code.
*/
for (id = whitelist_table; id->match_flags; id++) {
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
id->idVendor != dev->descriptor.idVendor)
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
id->idProduct != dev->descriptor.idProduct)
continue;
/* No need to test id->bcdDevice_lo != 0, since 0 is never
greater than any unsigned number. */
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
(id->bcdDevice_lo > dev->descriptor.bcdDevice))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
(id->bcdDevice_hi < dev->descriptor.bcdDevice))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
(id->bDeviceClass != dev->descriptor.bDeviceClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
(id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
continue;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
continue;
return 1;
}
/* add other match criteria here ... */
/* OTG MESSAGE: report errors here, customize to match your product */
dev_err(&dev->dev, "device v%04x p%04x is not supported\n",
dev->descriptor.idVendor,
dev->descriptor.idProduct);
#ifdef CONFIG_USB_OTG_WHITELIST
return 0;
#else
return 1;
#endif
}
......@@ -135,6 +135,18 @@ config USB_SA1100
depends on USB_GADGET_SA1100
default USB_GADGET
config USB_GADGET_LH7A40X
boolean "LH7A40X"
depends on ARCH_LH7A40X
help
This driver provides USB Device Controller driver for LH7A40x
config USB_LH7A40X
tristate
depends on USB_GADGET_LH7A40X
default USB_GADGET
config USB_GADGET_DUMMY_HCD
boolean "Dummy HCD (DEVELOPMENT)"
depends on USB && EXPERIMENTAL
......@@ -163,6 +175,41 @@ config USB_DUMMY_HCD
depends on USB_GADGET_DUMMY_HCD
default USB_GADGET
config USB_GADGET_OMAP
boolean "OMAP USB Device Controller"
depends on ARCH_OMAP
select ISP1301_OMAP if MACH_OMAP_H2
help
Many Texas Instruments OMAP processors have flexible full
speed USB device controllers, with support for up to 30
endpoints (plus endpoint zero). This driver supports the
controller in the OMAP 1611, and should work with controllers
in other OMAP processors too, given minor tweaks.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "omap_udc" and force all
gadget drivers to also be dynamically linked.
config USB_OMAP
tristate
depends on USB_GADGET_OMAP
default USB_GADGET
config USB_OTG
boolean "OTG Support"
depends on USB_GADGET_OMAP && ARCH_OMAP_OTG && USB_OHCI_HCD
help
The most notable feature of USB OTG is support for a
"Dual-Role" device, which can act as either a device
or a host. The initial role choice can be changed
later, when two dual-role devices talk to each other.
Select this only if your OMAP board has a Mini-AB connector.
config USB_OMAP_PROC
boolean "/proc/driver/udc file"
depends on USB_GADGET_OMAP
endchoice
config USB_GADGET_DUALSPEED
......
......@@ -5,6 +5,8 @@ obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2280) += net2280.o
obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o
obj-$(CONFIG_USB_LH7A40X) += lh7a40x_udc.o
#
# USB gadget drivers
......
......@@ -63,6 +63,7 @@
/*
* Ethernet gadget driver -- with CDC and non-CDC options
* Builds on hardware support for a full duplex link.
*
* CDC Ethernet is the standard USB solution for sending Ethernet frames
* using USB. Real hardware tends to use the same framing protocol but look
......@@ -242,6 +243,10 @@ MODULE_PARM_DESC(host_addr, "Host Ethernet Address");
#define DEV_CONFIG_SUBSET
#endif
#ifdef CONFIG_USB_GADGET_LH7A40X
#define DEV_CONFIG_CDC
#endif
#ifdef CONFIG_USB_GADGET_SA1100
/* use non-CDC for backwards compatibility */
#define DEV_CONFIG_SUBSET
......@@ -855,7 +860,7 @@ static char product_desc [40] = DRIVER_DESC;
static char ethaddr [2 * ETH_ALEN + 1];
#endif
/* static strings, in iso 8859/1 */
/* static strings, in UTF-8 */
static struct usb_string strings [] = {
{ STRING_MANUFACTURER, manufacturer, },
{ STRING_PRODUCT, product_desc, },
......@@ -897,9 +902,9 @@ config_buf (enum usb_device_speed speed,
if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs;
#define which_fn(t) (hs ? & hs_ ## t ## _function : & fs_ ## t ## _function)
#define which_fn(t) (hs ? hs_ ## t ## _function : fs_ ## t ## _function)
#else
#define which_fn(t) (& fs_ ## t ## _function)
#define which_fn(t) (fs_ ## t ## _function)
#endif
if (index >= device_desc.bNumConfigurations)
......@@ -911,14 +916,12 @@ config_buf (enum usb_device_speed speed,
*/
if (device_desc.bNumConfigurations == 2 && index == 0) {
config = &rndis_config;
function = (const struct usb_descriptor_header **)
which_fn (rndis);
function = which_fn (rndis);
} else
#endif
{
config = &eth_config;
function = (const struct usb_descriptor_header **)
which_fn (eth);
function = which_fn (eth);
}
/* for now, don't advertise srp-only devices */
......@@ -2329,6 +2332,8 @@ eth_bind (struct usb_gadget *gadget)
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
} else if (gadget_is_omap (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
} else if (gadget_is_lh7a40x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
} else {
/* can't assume CDC works. don't want to default to
* anything less functional on CDC-capable hardware,
......
......@@ -3713,6 +3713,8 @@ static int __init check_parameters(struct fsg_dev *fsg)
mod_data.release = __constant_cpu_to_le16(0x0307);
else if (gadget_is_omap(fsg->gadget))
mod_data.release = __constant_cpu_to_le16(0x0308);
else if (gadget_is_lh7a40x(gadget))
mod_data.release = __constant_cpu_to_le16 (0x0309);
else {
WARN(fsg, "controller '%s' not recognized\n",
fsg->gadget->name);
......
......@@ -44,6 +44,12 @@
#define gadget_is_sa1100(g) 0
#endif
#ifdef CONFIG_USB_GADGET_LH7A40X
#define gadget_is_lh7a40x(g) !strcmp("lh7a40x_udc", (g)->name)
#else
#define gadget_is_lh7a40x(g) 0
#endif
#ifdef CONFIG_USB_GADGET_MQ11XX
#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name)
#else
......
/*
* inode.c -- user mode filesystem api for usb gadget controllers
*
* Copyright (C) 2003 David Brownell
* Copyright (C) 2003-2004 David Brownell
* Copyright (C) 2003 Agilent Technologies
*
* This program is free software; you can redistribute it and/or modify
......@@ -71,7 +71,7 @@
*/
#define DRIVER_DESC "USB Gadget filesystem"
#define DRIVER_VERSION "18 Nov 2003"
#define DRIVER_VERSION "24 Aug 2004"
static const char driver_desc [] = DRIVER_DESC;
static const char shortname [] = "gadgetfs";
......@@ -229,37 +229,12 @@ static void put_ep (struct ep_data *data)
/*----------------------------------------------------------------------*/
/* most "how to use the hardware" policy choices are in userspace:
* mapping endpoint roles the driver needs to the capabilities that
* the usb controller exposes.
* mapping endpoint roles (which the driver needs) to the capabilities
* which the usb controller has. most of those capabilities are exposed
* implicitly, starting with the driver name and then endpoint names.
*/
#ifdef CONFIG_USB_GADGET_DUMMY_HCD
/* act (mostly) like a net2280 */
#define CONFIG_USB_GADGET_NET2280
#endif
#ifdef CONFIG_USB_GADGET_NET2280
#define CHIP "net2280"
#define HIGHSPEED
#endif
#ifdef CONFIG_USB_GADGET_PXA2XX
#define CHIP "pxa2xx_udc"
/* earlier hardware doesn't have UDCCFR, races set_{config,interface} */
#warning works best with pxa255 or newer
#endif
#ifdef CONFIG_USB_GADGET_GOKU
#define CHIP "goku_udc"
#endif
#ifdef CONFIG_USB_GADGET_OMAP
#define CHIP "omap_udc"
#endif
#ifdef CONFIG_USB_GADGET_SA1100
#define CHIP "sa1100"
#endif
static const char *CHIP;
/*----------------------------------------------------------------------*/
......@@ -558,7 +533,7 @@ struct kiocb_priv {
static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
{
struct kiocb_priv *priv = (void *) &iocb->private;
struct kiocb_priv *priv = iocb->private;
struct ep_data *epdata;
int value;
......@@ -579,7 +554,7 @@ static int ep_aio_cancel(struct kiocb *iocb, struct io_event *e)
static ssize_t ep_aio_read_retry(struct kiocb *iocb)
{
struct kiocb_priv *priv = (void *) &iocb->private;
struct kiocb_priv *priv = iocb->private;
ssize_t status = priv->actual;
/* we "retry" to get the right mm context for this: */
......@@ -589,6 +564,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
else
status = priv->actual;
kfree(priv->buf);
kfree(priv);
aio_put_req(iocb);
return status;
}
......@@ -596,7 +572,7 @@ static ssize_t ep_aio_read_retry(struct kiocb *iocb)
static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
{
struct kiocb *iocb = req->context;
struct kiocb_priv *priv = (void *) &iocb->private;
struct kiocb_priv *priv = iocb->private;
struct ep_data *epdata = priv->epdata;
/* lock against disconnect (and ideally, cancel) */
......@@ -607,6 +583,8 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
|| unlikely(0 == req->actual)
|| unlikely(kiocbIsCancelled(iocb))) {
kfree(req->buf);
kfree(priv);
iocb->private = 0;
/* aio_complete() reports bytes-transferred _and_ faults */
if (unlikely(kiocbIsCancelled(iocb)))
aio_put_req(iocb);
......@@ -631,17 +609,33 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req)
}
static ssize_t
ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
ep_aio_rwtail(
struct kiocb *iocb,
char *buf,
size_t len,
struct ep_data *epdata,
char __user *ubuf
)
{
struct kiocb_priv *priv = (void *) &iocb->private;
struct usb_request *req;
ssize_t value;
value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
if (unlikely(value < 0)) {
priv = kmalloc(sizeof *priv, GFP_KERNEL);
if (!priv) {
value = -ENOMEM;
fail:
kfree(buf);
return value;
}
iocb->private = priv;
priv->ubuf = ubuf;
value = get_ready_ep(iocb->ki_filp->f_flags, epdata);
if (unlikely(value < 0)) {
kfree(priv);
goto fail;
}
iocb->ki_cancel = ep_aio_cancel;
get_ep(epdata);
......@@ -671,9 +665,10 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
up(&epdata->lock);
if (unlikely(value))
if (unlikely(value)) {
kfree(priv);
put_ep(epdata);
else
} else
value = -EIOCBQUEUED;
return value;
}
......@@ -681,7 +676,6 @@ ep_aio_rwtail(struct kiocb *iocb, char *buf, size_t len, struct ep_data *epdata)
static ssize_t
ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
{
struct kiocb_priv *priv = (void *) &iocb->private;
struct ep_data *epdata = iocb->ki_filp->private_data;
char *buf;
......@@ -691,8 +685,7 @@ ep_aio_read(struct kiocb *iocb, char __user *ubuf, size_t len, loff_t o)
if (unlikely(!buf))
return -ENOMEM;
iocb->ki_retry = ep_aio_read_retry;
priv->ubuf = ubuf;
return ep_aio_rwtail(iocb, buf, len, epdata);
return ep_aio_rwtail(iocb, buf, len, epdata, ubuf);
}
static ssize_t
......@@ -710,7 +703,7 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
kfree(buf);
return -EFAULT;
}
return ep_aio_rwtail(iocb, buf, len, epdata);
return ep_aio_rwtail(iocb, buf, len, epdata, 0);
}
/*----------------------------------------------------------------------*/
......@@ -718,6 +711,8 @@ ep_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t len, loff_t o)
/* used after endpoint configuration */
static struct file_operations ep_io_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = ep_read,
.write = ep_write,
.ioctl = ep_ioctl,
......@@ -874,6 +869,8 @@ ep_open (struct inode *inode, struct file *fd)
/* used before endpoint configuration */
static struct file_operations ep_config_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.open = ep_open,
.write = ep_config,
.release = ep_release,
......@@ -980,6 +977,18 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
retval = usb_ep_queue (ep, req, GFP_ATOMIC);
dev->state = STATE_CONNECTED;
/* assume that was SET_CONFIGURATION */
if (dev->current_config) {
unsigned power;
#ifdef HIGHSPEED
if (dev->gadget->speed == USB_SPEED_HIGH)
power = dev->hs_config->bMaxPower;
else
#endif
power = dev->config->bMaxPower;
usb_gadget_vbus_draw(dev->gadget, 2 * power);
}
} else { /* collect OUT data */
if ((fd->f_flags & O_NONBLOCK) != 0
&& !dev->setup_out_ready) {
......@@ -1230,6 +1239,8 @@ static int dev_ioctl (struct inode *inode, struct file *fd,
/* used after device configuration */
static struct file_operations ep0_io_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = ep0_read,
.write = ep0_write,
.fasync = ep0_fasync,
......@@ -1406,19 +1417,25 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (0 == (u8) ctrl->wValue) {
value = 0;
dev->current_config = 0;
usb_gadget_vbus_draw(gadget, 8 /* mA */ );
// user mode expected to disable endpoints
} else {
u8 config;
u8 config, power;
#ifdef HIGHSPEED
if (gadget->speed == USB_SPEED_HIGH)
if (gadget->speed == USB_SPEED_HIGH) {
config = dev->hs_config->bConfigurationValue;
else
power = dev->hs_config->bMaxPower;
} else
#endif
{
config = dev->config->bConfigurationValue;
power = dev->config->bMaxPower;
}
if (config == (u8) ctrl->wValue) {
value = 0;
dev->current_config = config;
usb_gadget_vbus_draw(gadget, 2 * power);
}
}
......@@ -1636,8 +1653,8 @@ gadgetfs_bind (struct usb_gadget *gadget)
if (!dev)
return -ESRCH;
if (0 != strcmp (CHIP, gadget->name)) {
printk (KERN_ERR "%s expected " CHIP " controller not %s\n",
shortname, gadget->name);
printk (KERN_ERR "%s expected %s controller not %s\n",
shortname, CHIP, gadget->name);
return -ENODEV;
}
......@@ -1727,6 +1744,26 @@ static struct usb_gadget_driver gadgetfs_driver = {
/*----------------------------------------------------------------------*/
static void gadgetfs_nop(struct usb_gadget *arg) { }
static int gadgetfs_probe (struct usb_gadget *gadget)
{
CHIP = gadget->name;
return -EISNAM;
}
static struct usb_gadget_driver probe_driver = {
.speed = USB_SPEED_HIGH,
.bind = gadgetfs_probe,
.unbind = gadgetfs_nop,
.setup = (void *)gadgetfs_nop,
.disconnect = gadgetfs_nop,
.driver = {
.name = "nop",
},
};
/* DEVICE INITIALIZATION
*
* fd = open ("/dev/gadget/$CHIP", O_RDWR)
......@@ -1763,6 +1800,7 @@ static int is_valid_config (struct usb_config_descriptor *config)
&& config->bConfigurationValue != 0
&& (config->bmAttributes & USB_CONFIG_ATT_ONE) != 0
&& (config->bmAttributes & USB_CONFIG_ATT_WAKEUP) == 0;
/* FIXME if gadget->is_otg, _must_ include an otg descriptor */
/* FIXME check lengths: walk to end */
}
......@@ -1881,6 +1919,8 @@ dev_open (struct inode *inode, struct file *fd)
static struct file_operations dev_init_operations = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.open = dev_open,
.write = dev_config,
.fasync = ep0_fasync,
......@@ -1976,6 +2016,11 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent)
if (the_device)
return -ESRCH;
/* fake probe to determine $CHIP */
(void) usb_gadget_register_driver (&probe_driver);
if (!CHIP)
return -ENODEV;
/* superblock */
sb->s_blocksize = PAGE_CACHE_SIZE;
sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
......
This diff is collapsed.
This diff is collapsed.
......@@ -307,7 +307,6 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
| (1 << SET_NAK_OUT_PACKETS)
| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
| (1 << CLEAR_INTERRUPT_MODE)
| (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
| (1 << CLEAR_ENDPOINT_TOGGLE)
| (1 << CLEAR_ENDPOINT_HALT)
, &ep->regs->ep_rsp);
......@@ -2511,15 +2510,23 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
{
struct net2280_ep *ep;
u32 tmp, num, scratch;
u32 tmp, num, mask, scratch;
/* after disconnect there's nothing else to do! */
tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
/* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
* Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
* both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT
* only indicates a change in the reset state).
*/
if (stat & tmp) {
writel (tmp, &dev->regs->irqstat1);
if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0
|| (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0
) && dev->gadget.speed != USB_SPEED_UNKNOWN) {
if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) &&
((readl (&dev->usb->usbstat) & mask) == 0))
|| ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0)
) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
DEBUG (dev, "disconnect %s\n",
dev->driver->driver.name);
stop_activity (dev, dev->driver);
......
This diff is collapsed.
This diff is collapsed.
......@@ -1299,6 +1299,9 @@ static int gs_bind(struct usb_gadget *gadget)
} else if (gadget_is_omap(gadget)) {
gs_device_desc.bcdDevice =
__constant_cpu_to_le16(GS_VERSION_NUM|0x0007);
} else if (gadget_is_lh7a40x(gadget)) {
gs_device_desc.bcdDevice =
__constant_cpu_to_le16(GS_VERSION_NUM|0x0008);
} else {
printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n",
gadget->name);
......
......@@ -399,7 +399,7 @@ static const struct usb_descriptor_header *hs_loopback_function [] = {
static char manufacturer [40];
static char serial [40];
/* static strings, in iso 8859/1 */
/* static strings, in UTF-8 */
static struct usb_string strings [] = {
{ STRING_MANUFACTURER, manufacturer, },
{ STRING_PRODUCT, longname, },
......@@ -960,7 +960,8 @@ zero_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_DT_STRING:
/* wIndex == language code.
* this driver only handles one language, you can
* add others even if they don't use iso8859/1
* add string tables for other languages, using
* any UTF-8 characters
*/
value = usb_gadget_get_string (&stringtab,
ctrl->wValue & 0xff, req->buf);
......@@ -1185,6 +1186,8 @@ zero_bind (struct usb_gadget *gadget)
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0207);
} else if (gadget_is_omap (gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0208);
} else if (gadget_is_lh7a40x(gadget)) {
device_desc.bcdDevice = __constant_cpu_to_le16 (0x0209);
} else {
/* gadget zero is so simple (for now, no altsettings) that
* it SHOULD NOT have problems with bulk-capable hardware.
......@@ -1236,6 +1239,12 @@ zero_bind (struct usb_gadget *gadget)
loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
if (gadget->is_otg) {
otg_descriptor.bmAttributes |= USB_OTG_HNP,
source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
}
usb_gadget_set_selfpowered (gadget);
init_timer (&dev->resume);
......
......@@ -52,6 +52,7 @@ config USB_EHCI_ROOT_HUB_TT
config USB_OHCI_HCD
tristate "OHCI HCD support"
depends on USB
select ISP1301_OMAP if MACH_OMAP_H2
---help---
The Open Host Controller Interface (OHCI) is a standard for accessing
USB 1.1 host controller hardware. It does more in hardware than Intel's
......
......@@ -97,6 +97,7 @@
#include <linux/list.h>
#include <linux/interrupt.h> /* for in_interrupt () */
#include <linux/usb.h>
#include <linux/usb_otg.h>
#include "../core/hcd.h"
#include <linux/dma-mapping.h>
#include <linux/dmapool.h> /* needed by ohci-mem.c when no PCI */
......@@ -693,7 +694,7 @@ static void ohci_stop (struct usb_hcd *hcd)
/* must not be called from interrupt context */
#ifdef CONFIG_PM
#if defined(CONFIG_USB_SUSPEND) || defined(CONFIG_PM)
static void mark_children_gone (struct usb_device *dev)
{
......
This diff is collapsed.
This diff is collapsed.
/*
* linux/drivers/usb/host/ohci-omap.h
*
* OMAP OHCI USB controller specific defines
*/
/* OMAP USB OHCI common defines */
#define OMAP_OHCI_NAME "omap-ohci"
#define OMAP_OHCI_BASE 0xfffba000
#define OMAP_OHCI_SIZE 4096
#define HMC_CLEAR (0x3f << 1)
#define APLL_NDPLL_SWITCH 0x0001
#define DPLL_PLL_ENABLE 0x0010
#define DPLL_LOCK 0x0001
#define SOFT_REQ_REG_REQ 0x0001
#define USB_MCLK_EN 0x0010
#define USB_HOST_HHC_UHOST_EN 0x00000200
#define SOFT_USB_OTG_REQ (1 << 8)
#define SOFT_USB_REQ (1 << 3)
#define STATUS_REQ_REG 0xfffe0840
#define USB_HOST_DPLL_REQ (1 << 8)
#define SOFT_DPLL_REQ (1 << 0)
/* OMAP-1510 USB OHCI defines */
#define OMAP1510_LB_MEMSIZE 32 /* Should be same as SDRAM size */
#define OMAP1510_LB_CLOCK_DIV 0xfffec10c
#define OMAP1510_LB_MMU_CTL 0xfffec208
#define OMAP1510_LB_MMU_LCK 0xfffec224
#define OMAP1510_LB_MMU_LD_TLB 0xfffec228
#define OMAP1510_LB_MMU_CAM_H 0xfffec22c
#define OMAP1510_LB_MMU_CAM_L 0xfffec230
#define OMAP1510_LB_MMU_RAM_H 0xfffec234
#define OMAP1510_LB_MMU_RAM_L 0xfffec238
/* OMAP-1610 USB OHCI defines */
#define USB_TRANSCEIVER_CTRL 0xfffe1064
#define OTG_REV 0xfffb0400
#define OTG_SYSCON_1 0xfffb0404
#define OTG_IDLE_EN (1 << 15)
#define DEV_IDLE_EN (1 << 13)
#define OTG_SYSCON_2 0xfffb0408
#define OTG_CTRL 0xfffb040c
#define OTG_IRQ_EN 0xfffb0410
#define OTG_IRQ_SRC 0xfffb0414
#define OTG_EN (1 << 31)
#define USBX_SYNCHRO (1 << 30)
#define SRP_VBUS (1 << 12)
#define OTG_PADEN (1 << 10)
#define HMC_PADEN (1 << 9)
#define UHOST_EN (1 << 8)
/* Hardware specific defines */
#define OMAP1510_FPGA_HOST_CTRL 0xe800020c
......@@ -242,6 +242,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
.hub_suspend = ohci_hub_suspend,
.hub_resume = ohci_hub_resume,
#endif
.start_port_reset = ohci_start_port_reset,
};
/*-------------------------------------------------------------------------*/
......@@ -276,7 +277,7 @@ static int __init ohci_hcd_pci_init (void)
if (usb_disabled())
return -ENODEV;
printk (KERN_DEBUG "%s: block sizes: ed %Zd td %Zd\n", hcd_name,
pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
sizeof (struct ed), sizeof (struct td));
return pci_module_init (&ohci_pci_driver);
}
......
......@@ -900,9 +900,6 @@ static struct td *dl_reverse_done_list (struct ohci_hcd *ohci)
/*-------------------------------------------------------------------------*/
/* wrap-aware logic stolen from <linux/jiffies.h> */
#define tick_before(t1,t2) ((((s16)(t1))-((s16)(t2))) < 0)
/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */
static void
finish_unlinks (struct ohci_hcd *ohci, u16 tick, struct pt_regs *regs)
......
......@@ -359,6 +359,13 @@ struct ohci_hcd {
struct ed *ed_controltail; /* last in ctrl list */
struct ed *periodic [NUM_INTS]; /* shadow int_table */
/*
* OTG controllers and transceivers need software interaction;
* other external transceivers should be software-transparent
*/
struct otg_transceiver *transceiver;
unsigned power_budget;
/*
* memory management for queue data structures
*/
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -704,7 +704,6 @@ static int stv680_start_stream (struct usb_stv *stv680)
usb_rcvbulkpipe (stv680->udev, stv680->bulk_in_endpointAddr),
stv680->sbuf[i].data, stv680->rawbufsize,
stv680_video_irq, stv680);
urb->timeout = PENCAM_TIMEOUT * 2;
stv680->urb[i] = urb;
err = usb_submit_urb (stv680->urb[i], GFP_KERNEL);
if (err)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -114,3 +114,5 @@ otg_start_srp(struct otg_transceiver *otg)
}
/* for OTG controller drivers (and maybe other stuff) */
extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num);
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment