diff options
author | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
commit | 709c4d66e0b107ca606941b988bad717c0b45d9b (patch) | |
tree | 37ee08b1eb308f3b2b6426d5793545c38396b838 /packages/cfu1 | |
parent | fa6cd5a3b993f16c27de4ff82b42684516d433ba (diff) |
rename packages/ to recipes/ per earlier agreement
See links below for more details:
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816
Signed-off-by: Denys Dmytriyenko <denis@denix.org>
Acked-by: Mike Westerhof <mwester@dls.net>
Acked-by: Philip Balister <philip@balister.org>
Acked-by: Khem Raj <raj.khem@gmail.com>
Acked-by: Marcin Juszkiewicz <hrw@openembedded.org>
Acked-by: Koen Kooi <koen@openembedded.org>
Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'packages/cfu1')
-rw-r--r-- | packages/cfu1/cfu1-modules_2.6.bb | 30 | ||||
-rw-r--r-- | packages/cfu1/files/Makefile | 2 | ||||
-rw-r--r-- | packages/cfu1/files/hcd.h | 487 | ||||
-rw-r--r-- | packages/cfu1/files/hub.h | 227 | ||||
-rw-r--r-- | packages/cfu1/files/rex-cfu1.conf | 6 | ||||
-rw-r--r-- | packages/cfu1/files/sl811.h | 266 | ||||
-rw-r--r-- | packages/cfu1/files/sl811_cs.c | 518 | ||||
-rw-r--r-- | packages/cfu1/files/sl811_hcd.c | 1932 |
8 files changed, 0 insertions, 3468 deletions
diff --git a/packages/cfu1/cfu1-modules_2.6.bb b/packages/cfu1/cfu1-modules_2.6.bb deleted file mode 100644 index b6446c689b..0000000000 --- a/packages/cfu1/cfu1-modules_2.6.bb +++ /dev/null @@ -1,30 +0,0 @@ -DESCRIPTION = "PCMCIA driver for the RATOC REX-CFU1 USB host controller CF card." -SECTION = "kernel/modules" -PRIORITY = "optional" -DEPENDS = "virtual/kernel" -LICENSE = "GPL" -RDEPENDS = "kernel-module-usbcore" -PR = "r2" - -SRC_URI = "file://rex-cfu1.conf \ - file://Makefile \ - file://sl811_cs.c \ - file://sl811_hcd.c \ - file://sl811.h \ - file://hcd.h \ - file://hub.h" - -S = "${WORKDIR}" - -inherit module - -EXTRA_OEMAKE = 'EXTRA_CFLAGS="-DCONFIG_USB_SL811_CS -DCONFIG_USB_DEBUG" -C ${STAGING_KERNEL_DIR} SUBDIRS=${WORKDIR}' - -do_install() { - install -d ${D}/lib/modules/${KERNEL_VERSION}/pcmcia/ - install -m 0644 sl811_cs.ko ${D}/lib/modules/${KERNEL_VERSION}/pcmcia/ - install -m 0644 sl811_hcd.ko ${D}/lib/modules/${KERNEL_VERSION}/pcmcia/ - - install -d ${D}/${sysconfdir}/pcmcia/ - install -m 0644 ${WORKDIR}/rex-cfu1.conf ${D}/${sysconfdir}/pcmcia/ -} diff --git a/packages/cfu1/files/Makefile b/packages/cfu1/files/Makefile deleted file mode 100644 index dbfb40d18a..0000000000 --- a/packages/cfu1/files/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += sl811_cs.o -obj-m += sl811_hcd.o diff --git a/packages/cfu1/files/hcd.h b/packages/cfu1/files/hcd.h deleted file mode 100644 index a9bb99053b..0000000000 --- a/packages/cfu1/files/hcd.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * 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 program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#ifdef __KERNEL__ - -/* This file contains declarations of usbcore internals that are mostly - * used or exposed by Host Controller Drivers. - */ - -/* - * USB Packet IDs (PIDs) - */ -#define USB_PID_UNDEF_0 0xf0 -#define USB_PID_OUT 0xe1 -#define USB_PID_ACK 0xd2 -#define USB_PID_DATA0 0xc3 -#define USB_PID_PING 0xb4 /* USB 2.0 */ -#define USB_PID_SOF 0xa5 -#define USB_PID_NYET 0x96 /* USB 2.0 */ -#define USB_PID_DATA2 0x87 /* USB 2.0 */ -#define USB_PID_SPLIT 0x78 /* USB 2.0 */ -#define USB_PID_IN 0x69 -#define USB_PID_NAK 0x5a -#define USB_PID_DATA1 0x4b -#define USB_PID_PREAMBLE 0x3c /* Token mode */ -#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ -#define USB_PID_SETUP 0x2d -#define USB_PID_STALL 0x1e -#define USB_PID_MDATA 0x0f /* USB 2.0 */ - -/*-------------------------------------------------------------------------*/ - -/* - * USB Host Controller Driver (usb_hcd) framework - * - * Since "struct usb_bus" is so thin, you can't share much code in it. - * This framework is a layer over that, and should be more sharable. - */ - -/*-------------------------------------------------------------------------*/ - -struct usb_hcd { /* usb_bus.hcpriv points to this */ - - /* - * housekeeping - */ - struct usb_bus self; /* hcd is-a bus */ - - const char *product_desc; /* product/vendor string */ - char irq_descr[24]; /* driver + bus # */ - - struct timer_list rh_timer; /* drives root-hub polling */ - struct urb *status_urb; /* the current status urb */ - - /* - * hardware info/state - */ - const struct hc_driver *driver; /* hw-specific hooks */ - unsigned saw_irq : 1; - unsigned can_wakeup:1; /* hw supports wakeup? */ - unsigned remote_wakeup:1;/* sw should use wakeup? */ - unsigned rh_registered:1;/* is root hub registered? */ - - /* The next flag is a stopgap, to be removed when all the HCDs - * support the new root-hub polling mechanism. */ - unsigned uses_new_polling:1; - unsigned poll_rh:1; /* poll for rh status? */ - unsigned poll_pending:1; /* status has changed? */ - - int irq; /* irq allocated */ - void __iomem *regs; /* device memory/io */ - u64 rsrc_start; /* memory/io resource start */ - u64 rsrc_len; /* memory/io resource length */ - unsigned power_budget; /* in mA, 0 = no limit */ - -#define HCD_BUFFER_POOLS 4 - struct dma_pool *pool [HCD_BUFFER_POOLS]; - - int state; -# define __ACTIVE 0x01 -# define __SUSPEND 0x04 -# define __TRANSIENT 0x80 - -# define HC_STATE_HALT 0 -# define HC_STATE_RUNNING (__ACTIVE) -# define HC_STATE_QUIESCING (__SUSPEND|__TRANSIENT|__ACTIVE) -# define HC_STATE_RESUMING (__SUSPEND|__TRANSIENT) -# define HC_STATE_SUSPENDED (__SUSPEND) - -#define HC_IS_RUNNING(state) ((state) & __ACTIVE) -#define HC_IS_SUSPENDED(state) ((state) & __SUSPEND) - - /* more shared queuing code would be good; it should support - * smarter scheduling, handle transaction translators, etc; - * input size of periodic table to an interrupt scheduler. - * (ohci 32, uhci 1024, ehci 256/512/1024). - */ - - /* The HC driver's private data is stored at the end of - * this structure. - */ - unsigned long hcd_priv[0] - __attribute__ ((aligned (sizeof(unsigned long)))); -}; - -/* 2.4 does this a bit differently ... */ -static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd) -{ - return &hcd->self; -} - - -// urb.hcpriv is really hardware-specific - -struct hcd_timeout { /* timeouts we allocate */ - struct list_head timeout_list; - struct timer_list timer; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * FIXME usb_operations should vanish or become hc_driver, - * when usb_bus and usb_hcd become the same thing. - */ - -struct usb_operations { - int (*get_frame_number) (struct usb_device *usb_dev); - int (*submit_urb) (struct urb *urb, int mem_flags); - int (*unlink_urb) (struct urb *urb, int status); - - /* allocate dma-consistent buffer for URB_DMA_NOMAPPING */ - void *(*buffer_alloc)(struct usb_bus *bus, size_t size, - int mem_flags, - dma_addr_t *dma); - void (*buffer_free)(struct usb_bus *bus, size_t size, - void *addr, dma_addr_t dma); - - void (*disable)(struct usb_device *udev, - struct usb_host_endpoint *ep); - - /* global suspend/resume of bus */ - int (*hub_suspend)(struct usb_bus *); - int (*hub_resume)(struct usb_bus *); -}; - -/* each driver provides one of these, and hardware init support */ - -struct pt_regs; - -struct hc_driver { - const char *description; /* "ehci-hcd" etc */ - const char *product_desc; /* product/vendor string */ - size_t hcd_priv_size; /* size of private data */ - - /* irq handler */ - irqreturn_t (*irq) (struct usb_hcd *hcd, struct pt_regs *regs); - - int flags; -#define HCD_MEMORY 0x0001 /* HC regs use memory (else I/O) */ -#define HCD_USB11 0x0010 /* USB 1.1 */ -#define HCD_USB2 0x0020 /* USB 2.0 */ - - /* called to init HCD and root hub */ - int (*reset) (struct usb_hcd *hcd); - int (*start) (struct usb_hcd *hcd); - - /* NOTE: these suspend/resume calls relate to the HC as - * a whole, not just the root hub; they're for bus glue. - */ - /* called after all devices were suspended */ - int (*suspend) (struct usb_hcd *hcd, pm_message_t message); - - /* called before any devices get resumed */ - int (*resume) (struct usb_hcd *hcd); - - /* cleanly make HCD stop writing memory and doing I/O */ - void (*stop) (struct usb_hcd *hcd); - - /* return current frame number */ - int (*get_frame_number) (struct usb_hcd *hcd); - - /* manage i/o requests, device state */ - int (*urb_enqueue) (struct usb_hcd *hcd, - struct usb_host_endpoint *ep, - struct urb *urb, - int mem_flags); - int (*urb_dequeue) (struct usb_hcd *hcd, struct urb *urb); - - /* hw synch, freeing endpoint resources that urb_dequeue can't */ - void (*endpoint_disable)(struct usb_hcd *hcd, - struct usb_host_endpoint *ep); - - /* root hub support */ - int (*hub_status_data) (struct usb_hcd *hcd, char *buf); - int (*hub_control) (struct usb_hcd *hcd, - u16 typeReq, u16 wValue, u16 wIndex, - 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); - void (*hub_irq_enable)(struct usb_hcd *); - /* Needed only if port-change IRQs are level-triggered */ -}; - -extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs); - -extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver, - struct device *dev, char *bus_name); -extern void usb_put_hcd (struct usb_hcd *hcd); -extern int usb_add_hcd(struct usb_hcd *hcd, - unsigned int irqnum, unsigned long irqflags); -extern void usb_remove_hcd(struct usb_hcd *hcd); - -#ifdef CONFIG_PCI -struct pci_dev; -struct pci_device_id; -extern int usb_hcd_pci_probe (struct pci_dev *dev, - const struct pci_device_id *id); -extern void usb_hcd_pci_remove (struct pci_dev *dev); - -#ifdef CONFIG_PM -extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state); -extern int usb_hcd_pci_resume (struct pci_dev *dev); -#endif /* CONFIG_PM */ - -#endif /* CONFIG_PCI */ - -/* pci-ish (pdev null is ok) buffer alloc/mapping support */ -int hcd_buffer_create (struct usb_hcd *hcd); -void hcd_buffer_destroy (struct usb_hcd *hcd); - -void *hcd_buffer_alloc (struct usb_bus *bus, size_t size, - int mem_flags, dma_addr_t *dma); -void hcd_buffer_free (struct usb_bus *bus, size_t size, - void *addr, dma_addr_t dma); - -/* generic bus glue, needed for host controllers that don't use PCI */ -extern irqreturn_t usb_hcd_irq (int irq, void *__hcd, struct pt_regs *r); - -extern void usb_hc_died (struct usb_hcd *hcd); -extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); - -/* -------------------------------------------------------------------------- */ - -/* Enumeration is only for the hub driver, or HCD virtual root hubs */ -extern struct usb_device *usb_alloc_dev(struct usb_device *parent, - struct usb_bus *, unsigned port); -extern int usb_new_device(struct usb_device *dev); -extern void usb_disconnect(struct usb_device **); - -extern int usb_get_configuration(struct usb_device *dev); -extern void usb_destroy_configuration(struct usb_device *dev); - -/*-------------------------------------------------------------------------*/ - -/* - * HCD Root Hub support - */ - -#include "hub.h" - -/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ -#define DeviceRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) -#define DeviceOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_DEVICE)<<8) - -#define InterfaceRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) - -#define EndpointRequest \ - ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) -#define EndpointOutRequest \ - ((USB_DIR_OUT|USB_TYPE_STANDARD|USB_RECIP_INTERFACE)<<8) - -/* class requests from the USB 2.0 hub spec, table 11-15 */ -/* GetBusState and SetHubDescriptor are optional, omitted */ -#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) -#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) -#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) -#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) -#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) -#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) -#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) - - -/*-------------------------------------------------------------------------*/ - -/* - * Generic bandwidth allocation constants/support - */ -#define FRAME_TIME_USECS 1000L -#define BitTime(bytecount) (7 * 8 * bytecount / 6) /* with integer truncation */ - /* Trying not to use worst-case bit-stuffing - of (7/6 * 8 * bytecount) = 9.33 * bytecount */ - /* bytecount = data payload byte count */ - -#define NS_TO_US(ns) ((ns + 500L) / 1000L) - /* convert & round nanoseconds to microseconds */ - -extern void usb_claim_bandwidth (struct usb_device *dev, struct urb *urb, - int bustime, int isoc); -extern void usb_release_bandwidth (struct usb_device *dev, struct urb *urb, - int isoc); - -/* - * Full/low speed bandwidth allocation constants/support. - */ -#define BW_HOST_DELAY 1000L /* nanoseconds */ -#define BW_HUB_LS_SETUP 333L /* nanoseconds */ - /* 4 full-speed bit times (est.) */ - -#define FRAME_TIME_BITS 12000L /* frame = 1 millisecond */ -#define FRAME_TIME_MAX_BITS_ALLOC (90L * FRAME_TIME_BITS / 100L) -#define FRAME_TIME_MAX_USECS_ALLOC (90L * FRAME_TIME_USECS / 100L) - -extern int usb_check_bandwidth (struct usb_device *dev, struct urb *urb); - -/* - * Ceiling microseconds (typical) for that many bytes at high speed - * ISO is a bit less, no ACK ... from USB 2.0 spec, 5.11.3 (and needed - * to preallocate bandwidth) - */ -#define USB2_HOST_DELAY 5 /* nsec, guess */ -#define HS_USECS(bytes) NS_TO_US ( ((55 * 8 * 2083)/1000) \ - + ((2083UL * (3167 + BitTime (bytes)))/1000) \ - + USB2_HOST_DELAY) -#define HS_USECS_ISO(bytes) NS_TO_US ( ((38 * 8 * 2083)/1000) \ - + ((2083UL * (3167 + BitTime (bytes)))/1000) \ - + USB2_HOST_DELAY) - -extern long usb_calc_bus_time (int speed, int is_input, - int isoc, int bytecount); - -/*-------------------------------------------------------------------------*/ - -extern struct usb_bus *usb_alloc_bus (struct usb_operations *); - -extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd); - -extern void usb_set_device_state(struct usb_device *udev, - enum usb_device_state new_state); - -/*-------------------------------------------------------------------------*/ - -/* exported only within usbcore */ - -extern struct list_head usb_bus_list; -extern struct semaphore usb_bus_list_lock; -extern wait_queue_head_t usb_kill_urb_queue; - -extern struct usb_bus *usb_bus_get (struct usb_bus *bus); -extern void usb_bus_put (struct usb_bus *bus); - -extern void usb_enable_root_hub_irq (struct usb_bus *bus); - -extern int usb_find_interface_driver (struct usb_device *dev, - struct usb_interface *interface); - -#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN)) - -/* - * USB device fs stuff - */ - -#ifdef CONFIG_USB_DEVICEFS - -/* - * these are expected to be called from the USB core/hub thread - * with the kernel lock held - */ -extern void usbfs_add_bus(struct usb_bus *bus); -extern void usbfs_remove_bus(struct usb_bus *bus); -extern void usbfs_add_device(struct usb_device *dev); -extern void usbfs_remove_device(struct usb_device *dev); -extern void usbfs_update_special (void); - -extern int usbfs_init(void); -extern void usbfs_cleanup(void); - -#else /* CONFIG_USB_DEVICEFS */ - -static inline void usbfs_add_bus(struct usb_bus *bus) {} -static inline void usbfs_remove_bus(struct usb_bus *bus) {} -static inline void usbfs_add_device(struct usb_device *dev) {} -static inline void usbfs_remove_device(struct usb_device *dev) {} -static inline void usbfs_update_special (void) {} - -static inline int usbfs_init(void) { return 0; } -static inline void usbfs_cleanup(void) { } - -#endif /* CONFIG_USB_DEVICEFS */ - -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_USB_MON) || defined(CONFIG_USB_MON_MODULE) - -struct usb_mon_operations { - void (*urb_submit)(struct usb_bus *bus, struct urb *urb); - void (*urb_submit_error)(struct usb_bus *bus, struct urb *urb, int err); - void (*urb_complete)(struct usb_bus *bus, struct urb *urb); - /* void (*urb_unlink)(struct usb_bus *bus, struct urb *urb); */ - void (*bus_add)(struct usb_bus *bus); - void (*bus_remove)(struct usb_bus *bus); -}; - -extern struct usb_mon_operations *mon_ops; - -static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) -{ - if (bus->monitored) - (*mon_ops->urb_submit)(bus, urb); -} - -static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, - int error) -{ - if (bus->monitored) - (*mon_ops->urb_submit_error)(bus, urb, error); -} - -static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) -{ - if (bus->monitored) - (*mon_ops->urb_complete)(bus, urb); -} - -static inline void usbmon_notify_bus_add(struct usb_bus *bus) -{ - if (mon_ops) - (*mon_ops->bus_add)(bus); -} - -static inline void usbmon_notify_bus_remove(struct usb_bus *bus) -{ - if (mon_ops) - (*mon_ops->bus_remove)(bus); -} - -int usb_mon_register(struct usb_mon_operations *ops); -void usb_mon_deregister(void); - -#else - -static inline void usbmon_urb_submit(struct usb_bus *bus, struct urb *urb) {} -static inline void usbmon_urb_submit_error(struct usb_bus *bus, struct urb *urb, - int error) {} -static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb) {} -static inline void usbmon_notify_bus_add(struct usb_bus *bus) {} -static inline void usbmon_notify_bus_remove(struct usb_bus *bus) {} - -#endif /* CONFIG_USB_MON */ - -/*-------------------------------------------------------------------------*/ - -/* hub.h ... DeviceRemovable in 2.4.2-ac11, gone in 2.4.10 */ -// bleech -- resurfaced in 2.4.11 or 2.4.12 -#define bitmap DeviceRemovable - - -/*-------------------------------------------------------------------------*/ - -/* random stuff */ - -#define RUN_CONTEXT (in_irq () ? "in_irq" \ - : (in_interrupt () ? "in_interrupt" : "can sleep")) - - -#endif /* __KERNEL__ */ - diff --git a/packages/cfu1/files/hub.h b/packages/cfu1/files/hub.h deleted file mode 100644 index 53bf564962..0000000000 --- a/packages/cfu1/files/hub.h +++ /dev/null @@ -1,227 +0,0 @@ -#ifndef __LINUX_HUB_H -#define __LINUX_HUB_H - -/* - * Hub protocol and driver data structures. - * - * Some of these are known to the "virtual root hub" code - * in host controller drivers. - */ - -#include <linux/list.h> -#include <linux/workqueue.h> -#include <linux/compiler.h> /* likely()/unlikely() */ - -/* - * Hub request types - */ - -#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) -#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) - -/* - * Hub class requests - * See USB 2.0 spec Table 11-16 - */ -#define HUB_CLEAR_TT_BUFFER 8 -#define HUB_RESET_TT 9 -#define HUB_GET_TT_STATE 10 -#define HUB_STOP_TT 11 - -/* - * Hub Class feature numbers - * See USB 2.0 spec Table 11-17 - */ -#define C_HUB_LOCAL_POWER 0 -#define C_HUB_OVER_CURRENT 1 - -/* - * Port feature numbers - * See USB 2.0 spec Table 11-17 - */ -#define USB_PORT_FEAT_CONNECTION 0 -#define USB_PORT_FEAT_ENABLE 1 -#define USB_PORT_FEAT_SUSPEND 2 -#define USB_PORT_FEAT_OVER_CURRENT 3 -#define USB_PORT_FEAT_RESET 4 -#define USB_PORT_FEAT_POWER 8 -#define USB_PORT_FEAT_LOWSPEED 9 -#define USB_PORT_FEAT_HIGHSPEED 10 -#define USB_PORT_FEAT_C_CONNECTION 16 -#define USB_PORT_FEAT_C_ENABLE 17 -#define USB_PORT_FEAT_C_SUSPEND 18 -#define USB_PORT_FEAT_C_OVER_CURRENT 19 -#define USB_PORT_FEAT_C_RESET 20 -#define USB_PORT_FEAT_TEST 21 -#define USB_PORT_FEAT_INDICATOR 22 - -/* - * Hub Status and Hub Change results - * See USB 2.0 spec Table 11-19 and Table 11-20 - */ -struct usb_port_status { - __le16 wPortStatus; - __le16 wPortChange; -} __attribute__ ((packed)); - -/* - * wPortStatus bit field - * See USB 2.0 spec Table 11-21 - */ -#define USB_PORT_STAT_CONNECTION 0x0001 -#define USB_PORT_STAT_ENABLE 0x0002 -#define USB_PORT_STAT_SUSPEND 0x0004 -#define USB_PORT_STAT_OVERCURRENT 0x0008 -#define USB_PORT_STAT_RESET 0x0010 -/* bits 5 to 7 are reserved */ -#define USB_PORT_STAT_POWER 0x0100 -#define USB_PORT_STAT_LOW_SPEED 0x0200 -#define USB_PORT_STAT_HIGH_SPEED 0x0400 -#define USB_PORT_STAT_TEST 0x0800 -#define USB_PORT_STAT_INDICATOR 0x1000 -/* bits 13 to 15 are reserved */ - -/* - * wPortChange bit field - * See USB 2.0 spec Table 11-22 - * Bits 0 to 4 shown, bits 5 to 15 are reserved - */ -#define USB_PORT_STAT_C_CONNECTION 0x0001 -#define USB_PORT_STAT_C_ENABLE 0x0002 -#define USB_PORT_STAT_C_SUSPEND 0x0004 -#define USB_PORT_STAT_C_OVERCURRENT 0x0008 -#define USB_PORT_STAT_C_RESET 0x0010 - -/* - * wHubCharacteristics (masks) - * See USB 2.0 spec Table 11-13, offset 3 - */ -#define HUB_CHAR_LPSM 0x0003 /* D1 .. D0 */ -#define HUB_CHAR_COMPOUND 0x0004 /* D2 */ -#define HUB_CHAR_OCPM 0x0018 /* D4 .. D3 */ -#define HUB_CHAR_TTTT 0x0060 /* D6 .. D5 */ -#define HUB_CHAR_PORTIND 0x0080 /* D7 */ - -struct usb_hub_status { - __le16 wHubStatus; - __le16 wHubChange; -} __attribute__ ((packed)); - -/* - * Hub Status & Hub Change bit masks - * See USB 2.0 spec Table 11-19 and Table 11-20 - * Bits 0 and 1 for wHubStatus and wHubChange - * Bits 2 to 15 are reserved for both - */ -#define HUB_STATUS_LOCAL_POWER 0x0001 -#define HUB_STATUS_OVERCURRENT 0x0002 -#define HUB_CHANGE_LOCAL_POWER 0x0001 -#define HUB_CHANGE_OVERCURRENT 0x0002 - - -/* - * Hub descriptor - * See USB 2.0 spec Table 11-13 - */ - -#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) -#define USB_DT_HUB_NONVAR_SIZE 7 - -struct usb_hub_descriptor { - __u8 bDescLength; - __u8 bDescriptorType; - __u8 bNbrPorts; - __u16 wHubCharacteristics; - __u8 bPwrOn2PwrGood; - __u8 bHubContrCurrent; - /* add 1 bit for hub status change; round to bytes */ - __u8 DeviceRemovable[(USB_MAXCHILDREN + 1 + 7) / 8]; - __u8 PortPwrCtrlMask[(USB_MAXCHILDREN + 1 + 7) / 8]; -} __attribute__ ((packed)); - - -/* port indicator status selectors, tables 11-7 and 11-25 */ -#define HUB_LED_AUTO 0 -#define HUB_LED_AMBER 1 -#define HUB_LED_GREEN 2 -#define HUB_LED_OFF 3 - -enum hub_led_mode { - INDICATOR_AUTO = 0, - INDICATOR_CYCLE, - /* software blinks for attention: software, hardware, reserved */ - INDICATOR_GREEN_BLINK, INDICATOR_GREEN_BLINK_OFF, - INDICATOR_AMBER_BLINK, INDICATOR_AMBER_BLINK_OFF, - INDICATOR_ALT_BLINK, INDICATOR_ALT_BLINK_OFF -} __attribute__ ((packed)); - -struct usb_device; - -/* - * As of USB 2.0, full/low speed devices are segregated into trees. - * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). - * The other type grows from high speed hubs when they connect to - * full/low speed devices using "Transaction Translators" (TTs). - * - * TTs should only be known to the hub driver, and high speed bus - * drivers (only EHCI for now). They affect periodic scheduling and - * sometimes control/bulk error recovery. - */ -struct usb_tt { - struct usb_device *hub; /* upstream highspeed hub */ - int multi; /* true means one TT per port */ - - /* for control/bulk error recovery (CLEAR_TT_BUFFER) */ - spinlock_t lock; - struct list_head clear_list; /* of usb_tt_clear */ - struct work_struct kevent; -}; - -struct usb_tt_clear { - struct list_head clear_list; - unsigned tt; - u16 devinfo; -}; - -extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe); - -struct usb_hub { - struct device *intfdev; /* the "interface" device */ - struct usb_device *hdev; - struct urb *urb; /* for interrupt polling pipe */ - - /* 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; - struct usb_port_status port; - } *status; /* buffer for status reports */ - - int error; /* last reported error */ - int nerrors; /* track consecutive errors */ - - struct list_head event_list; /* hubs w/data or errs ready */ - unsigned long event_bits[1]; /* status change bitmask */ - unsigned long change_bits[1]; /* ports with logical connect - status change */ - unsigned long busy_bits[1]; /* ports being reset */ -#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */ -#error event_bits[] is too short! -#endif - - struct usb_hub_descriptor *descriptor; /* class descriptor */ - struct usb_tt tt; /* Transaction Translator */ - - u8 power_budget; /* in 2mA units; or zero */ - - unsigned quiescing:1; - unsigned activating:1; - unsigned resume_root_hub:1; - - unsigned has_indicators:1; - enum hub_led_mode indicator[USB_MAXCHILDREN]; - struct work_struct leds; -}; - -#endif /* __LINUX_HUB_H */ diff --git a/packages/cfu1/files/rex-cfu1.conf b/packages/cfu1/files/rex-cfu1.conf deleted file mode 100644 index fd06c621df..0000000000 --- a/packages/cfu1/files/rex-cfu1.conf +++ /dev/null @@ -1,6 +0,0 @@ -device "sl811_cs" - class "usb" module "sl811_hcd", "sl811_cs" - -card "RATOC USB HOST CF+ Card" - manfid 0xc015, 0x0001 - bind "sl811_cs" diff --git a/packages/cfu1/files/sl811.h b/packages/cfu1/files/sl811.h deleted file mode 100644 index 7690d98e42..0000000000 --- a/packages/cfu1/files/sl811.h +++ /dev/null @@ -1,266 +0,0 @@ -/* - * SL811HS register declarations and HCD data structures - * - * Copyright (C) 2004 Psion Teklogix - * Copyright (C) 2004 David Brownell - * Copyright (C) 2001 Cypress Semiconductor Inc. - */ - -/* - * SL811HS has transfer registers, and control registers. In host/master - * mode one set of registers is used; in peripheral/slave mode, another. - * - SL11H only has some "A" transfer registers from 0x00-0x04 - * - SL811HS also has "B" registers from 0x08-0x0c - * - SL811S (or HS in slave mode) has four A+B sets, at 00, 10, 20, 30 - */ - -#define SL811_EP_A(base) ((base) + 0) -#define SL811_EP_B(base) ((base) + 8) - -#define SL811_HOST_BUF 0x00 -#define SL811_PERIPH_EP0 0x00 -#define SL811_PERIPH_EP1 0x10 -#define SL811_PERIPH_EP2 0x20 -#define SL811_PERIPH_EP3 0x30 - - -/* TRANSFER REGISTERS: host and peripheral sides are similar - * except for the control models (master vs slave). - */ -#define SL11H_HOSTCTLREG 0 -# define SL11H_HCTLMASK_ARM 0x01 -# define SL11H_HCTLMASK_ENABLE 0x02 -# define SL11H_HCTLMASK_IN 0x00 -# define SL11H_HCTLMASK_OUT 0x04 -# define SL11H_HCTLMASK_ISOCH 0x10 -# define SL11H_HCTLMASK_AFTERSOF 0x20 -# define SL11H_HCTLMASK_TOGGLE 0x40 -# define SL11H_HCTLMASK_PREAMBLE 0x80 -#define SL11H_BUFADDRREG 1 -#define SL11H_BUFLNTHREG 2 -#define SL11H_PKTSTATREG 3 /* read */ -# define SL11H_STATMASK_ACK 0x01 -# define SL11H_STATMASK_ERROR 0x02 -# define SL11H_STATMASK_TMOUT 0x04 -# define SL11H_STATMASK_SEQ 0x08 -# define SL11H_STATMASK_SETUP 0x10 -# define SL11H_STATMASK_OVF 0x20 -# define SL11H_STATMASK_NAK 0x40 -# define SL11H_STATMASK_STALL 0x80 -#define SL11H_PIDEPREG 3 /* write */ -# define SL_SETUP 0xd0 -# define SL_IN 0x90 -# define SL_OUT 0x10 -# define SL_SOF 0x50 -# define SL_PREAMBLE 0xc0 -# define SL_NAK 0xa0 -# define SL_STALL 0xe0 -# define SL_DATA0 0x30 -# define SL_DATA1 0xb0 -#define SL11H_XFERCNTREG 4 /* read */ -#define SL11H_DEVADDRREG 4 /* write */ - - -/* CONTROL REGISTERS: host and peripheral are very different. - */ -#define SL11H_CTLREG1 5 -# define SL11H_CTL1MASK_SOF_ENA 0x01 -# define SL11H_CTL1MASK_FORCE 0x18 -# define SL11H_CTL1MASK_NORMAL 0x00 -# define SL11H_CTL1MASK_SE0 0x08 /* reset */ -# define SL11H_CTL1MASK_J 0x10 -# define SL11H_CTL1MASK_K 0x18 /* resume */ -# define SL11H_CTL1MASK_LSPD 0x20 -# define SL11H_CTL1MASK_SUSPEND 0x40 -#define SL11H_IRQ_ENABLE 6 -# define SL11H_INTMASK_DONE_A 0x01 -# define SL11H_INTMASK_DONE_B 0x02 -# define SL11H_INTMASK_SOFINTR 0x10 -# define SL11H_INTMASK_INSRMV 0x20 /* to/from SE0 */ -# define SL11H_INTMASK_RD 0x40 -# define SL11H_INTMASK_DP 0x80 /* only in INTSTATREG */ -#define SL11S_ADDRESS 7 - -/* 0x08-0x0c are for the B buffer (not in SL11) */ - -#define SL11H_IRQ_STATUS 0x0D /* write to ack */ -#define SL11H_HWREVREG 0x0E /* read */ -# define SL11H_HWRMASK_HWREV 0xF0 -#define SL11H_SOFLOWREG 0x0E /* write */ -#define SL11H_SOFTMRREG 0x0F /* read */ - -/* a write to this register enables SL811HS features. - * HOST flag presumably overrides the chip input signal? - */ -#define SL811HS_CTLREG2 0x0F -# define SL811HS_CTL2MASK_SOF_MASK 0x3F -# define SL811HS_CTL2MASK_DSWAP 0x40 -# define SL811HS_CTL2MASK_HOST 0x80 - -#define SL811HS_CTL2_INIT (SL811HS_CTL2MASK_HOST | 0x2e) - - -/* DATA BUFFERS: registers from 0x10..0xff are for data buffers; - * that's 240 bytes, which we'll split evenly between A and B sides. - * Only ISO can use more than 64 bytes per packet. - * (The SL11S has 0x40..0xff for buffers.) - */ -#define H_MAXPACKET 120 /* bytes in A or B fifos */ - -#define SL11H_DATA_START 0x10 -#define SL811HS_PACKET_BUF(is_a) ((is_a) \ - ? SL11H_DATA_START \ - : (SL11H_DATA_START + H_MAXPACKET)) - -/*-------------------------------------------------------------------------*/ - -#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */ -#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE) - -struct sl811 { - spinlock_t lock; - void __iomem *addr_reg; - void __iomem *data_reg; - struct sl811_platform_data *board; - struct proc_dir_entry *pde; - - unsigned long stat_insrmv; - unsigned long stat_wake; - unsigned long stat_sof; - unsigned long stat_a; - unsigned long stat_b; - unsigned long stat_lost; - unsigned long stat_overrun; - - /* sw model */ - struct timer_list timer; - struct sl811h_ep *next_periodic; - struct sl811h_ep *next_async; - - struct sl811h_ep *active_a; - unsigned long jiffies_a; - struct sl811h_ep *active_b; - unsigned long jiffies_b; - - u32 port1; - u8 ctrl1, ctrl2, irq_enable; - u16 frame; - - /* async schedule: control, bulk */ - struct list_head async; - - /* periodic schedule: interrupt, iso */ - u16 load[PERIODIC_SIZE]; - struct sl811h_ep *periodic[PERIODIC_SIZE]; - unsigned periodic_count; -}; - -static inline struct sl811 *hcd_to_sl811(struct usb_hcd *hcd) -{ - return (struct sl811 *) (hcd->hcd_priv); -} - -static inline struct usb_hcd *sl811_to_hcd(struct sl811 *sl811) -{ - return container_of((void *) sl811, struct usb_hcd, hcd_priv); -} - -struct sl811h_ep { - struct usb_host_endpoint *hep; - struct usb_device *udev; - - u8 defctrl; - u8 maxpacket; - u8 epnum; - u8 nextpid; - - u16 error_count; - u16 nak_count; - u16 length; /* of current packet */ - - /* periodic schedule */ - u16 period; - u16 branch; - u16 load; - struct sl811h_ep *next; - - /* async schedule */ - struct list_head schedule; -}; - -/*-------------------------------------------------------------------------*/ - -/* These register utilities should work for the SL811S register API too - * NOTE: caller must hold sl811->lock. - */ - -static inline u8 sl811_read(struct sl811 *sl811, int reg) -{ - writeb(reg, sl811->addr_reg); - return readb(sl811->data_reg); -} - -static inline void sl811_write(struct sl811 *sl811, int reg, u8 val) -{ - writeb(reg, sl811->addr_reg); - writeb(val, sl811->data_reg); -} - -static inline void -sl811_write_buf(struct sl811 *sl811, int addr, const void *buf, size_t count) -{ - const u8 *data; - void __iomem *data_reg; - - if (!count) - return; - writeb(addr, sl811->addr_reg); - - data = buf; - data_reg = sl811->data_reg; - do { - writeb(*data++, data_reg); - } while (--count); -} - -static inline void -sl811_read_buf(struct sl811 *sl811, int addr, void *buf, size_t count) -{ - u8 *data; - void __iomem *data_reg; - - if (!count) - return; - writeb(addr, sl811->addr_reg); - - data = buf; - data_reg = sl811->data_reg; - do { - *data++ = readb(data_reg); - } while (--count); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG -#define DBG(stuff...) printk(KERN_DEBUG "sl811: " stuff) -#else -#define DBG(stuff...) do{}while(0) -#endif - -#ifdef VERBOSE -# define VDBG DBG -#else -# define VDBG(stuff...) do{}while(0) -#endif - -#ifdef PACKET_TRACE -# define PACKET VDBG -#else -# define PACKET(stuff...) do{}while(0) -#endif - -#define ERR(stuff...) printk(KERN_ERR "sl811: " stuff) -#define WARN(stuff...) printk(KERN_WARNING "sl811: " stuff) -#define INFO(stuff...) printk(KERN_INFO "sl811: " stuff) - diff --git a/packages/cfu1/files/sl811_cs.c b/packages/cfu1/files/sl811_cs.c deleted file mode 100644 index e223b647b3..0000000000 --- a/packages/cfu1/files/sl811_cs.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - A SL811 CLIENT DRIVER for linux 2.4.x - Filename: sl811_cs.c - Version: 0.0.2 - Author: Yukio Yamamoto - - Port to sl811-hcd and 2.6.x by - Botond Botyanszki <boti()rocketmail.com> - Simon Pickering - - Last update: 2005-05-05 -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/sched.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/string.h> -#include <linux/timer.h> -#include <linux/ioport.h> -#include <linux/version.h> -#include <asm/io.h> -#include <asm/system.h> - -#include <pcmcia/version.h> -#include <pcmcia/cs_types.h> -#include <pcmcia/cs.h> -#include <pcmcia/cistpl.h> -#include <pcmcia/cisreg.h> -#include <pcmcia/ds.h> - -#include <linux/usb_sl811.h> - -MODULE_AUTHOR("Botond Botyanszki"); -MODULE_DESCRIPTION("REX-CFU1 PCMCIA driver for 2.6"); -MODULE_LICENSE("GPL"); - - -/*====================================================================*/ -/* MACROS */ -/*====================================================================*/ - -#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) -#define DBG(n, args...) printk(KERN_DEBUG "sl811_cs: " args) -#else -#define DBG(n, args...) do{}while(0) -#endif - -#define INFO(args...) printk(KERN_INFO "sl811_cs: " args) - -/*static char *version = "sl811_cs.c 0.04 2005/04/27 00:00:00 (OpenZaurus Team)";*/ - -#define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") - -#define CS_CHECK(fn, ret) \ - do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -/*====================================================================*/ -/* VARIABLES */ -/*====================================================================*/ - -static dev_info_t dev_info = "sl811_cs"; -static dev_link_t *dev_list = NULL; - -static ioaddr_t base_addr = 0x00000000; -static int irq = -1; - -static int irq_list[4] = { -1 }; -MODULE_PARM(irq_list, "1-4i"); -INT_MODULE_PARM(free_ports, 0); -INT_MODULE_PARM(irq_mask, 0xdeb8); - -/*====================================================================*/ -/* PROTO TYPES */ -/*====================================================================*/ - -static dev_link_t* sl811_cs_attach(void); -static void sl811_cs_detach(dev_link_t *); -static void sl811_cs_config(dev_link_t *link); -static void sl811_cs_release(dev_link_t *arg); -static int sl811_cs_event(event_t event, int priority, - event_callback_args_t *args); - -/*====================================================================*/ -/* PROTO TYPES */ -/*====================================================================*/ - -typedef struct local_info_t { - dev_link_t link; - dev_node_t node; -} local_info_t; - -static struct pcmcia_driver sl811_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "sl811_cs", - }, - .attach = sl811_cs_attach, - .detach = sl811_cs_detach, -}; -extern struct device_driver sl811h_driver; - -static struct sl811_platform_data platform_data; -static struct res { - struct resource irq_res; - struct resource addr_res; - struct resource data_res; -} resources; -static struct platform_device platform_dev = { - .name = "sl811_cs", - .id = 0, - .num_resources = 0, - .dev.dma_mask = 0, - .dev.platform_data = &platform_data, - .dev.bus_id = "sl811-hcd", - .dev.driver = &sl811h_driver -}; - -/*====================================================================*/ -/* EXTERNAL FUNCTIONS */ -/*====================================================================*/ -int sl811h_probe(void *dev); - -/*====================================================================*/ - - -/*====================================================================*/ -static void release_platform_dev(struct device * dev) { - DBG(0, "sl811_cs platform_dev release\n"); -} - -/*====================================================================*/ -static dev_link_t *sl811_cs_attach(void) -{ - local_info_t *local; - dev_link_t *link; - client_reg_t client_reg; - int ret, i; - - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); - if (!local) return NULL; - memset(local, 0, sizeof(local_info_t)); - link = &local->link; link->priv = local; - - /* Initialize */ - link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; - link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID; - if (irq_list[0] == -1) - link->irq.IRQInfo2 = irq_mask; - else - for (i = 0; i < 4; i++) - link->irq.IRQInfo2 |= 1 << irq_list[i]; - link->irq.Handler = NULL; - - link->conf.Attributes = 0; - link->conf.Vcc = 33; - link->conf.IntType = INT_MEMORY_AND_IO; - - /* Register with Card Services */ - link->next = dev_list; - dev_list = link; - client_reg.dev_info = &dev_info; - client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; - client_reg.EventMask = - CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | - CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | - CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; - client_reg.event_handler = &sl811_cs_event; - client_reg.Version = 0x0210; - client_reg.event_callback_args.client_data = link; - ret = pcmcia_register_client(&link->handle, &client_reg); - if (ret != CS_SUCCESS) { - cs_error(link->handle, RegisterClient, ret); - sl811_cs_detach(link); - return NULL; - } - - return link; -} /* sl811_cs_attach */ - -/*====================================================================*/ -static void sl811_cs_detach(dev_link_t *link) -{ - dev_link_t **linkp; - - DBG(0, "sl811_cs_detach(0x%p)\n", link); - - /* Locate device structure */ - for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) - if (*linkp == link) break; - if (*linkp == NULL) - return; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - if (link->state & DEV_CONFIG) { -#ifdef PCMCIA_DEBUG - printk(KERN_DEBUG "sl811_cs: detach postponed, '%s' " - "still locked\n", link->dev->dev_name); -#endif - link->state |= DEV_STALE_LINK; - return; - } -#endif - - /* Break the link with Card Services */ - if (link->handle) - pcmcia_deregister_client(link->handle); - - /* Unlink device structure, and free it */ - *linkp = link->next; - /* This points to the parent local_info_t struct */ - kfree(link->priv); - -} /* sl811_cs_detach */ - - -/*====================================================================*/ -static int sl811_hc_init(void) -{ - /* set up the device structure */ - resources.irq_res.flags = IORESOURCE_IRQ; - resources.irq_res.start = irq; - - resources.addr_res.flags = IORESOURCE_MEM; - resources.addr_res.start = base_addr; - resources.addr_res.end = base_addr + 1; - - resources.data_res.flags = IORESOURCE_MEM; - resources.data_res.start = base_addr + 1; - resources.data_res.end = base_addr + 4; - - platform_dev.dev.release = release_platform_dev; - platform_device_register(&platform_dev); - /* FIXME: we register the platform device with 0 resources - otherwise the unregister call won't work*/ - - platform_dev.num_resources = 3; - platform_dev.resource = (struct resource *) &resources; - - /* try to initialize the host controller */ - if (sl811h_probe(&platform_dev.dev) != 0) { - DBG(0, "sl811h_probe() didn't return 0\n"); - return 0; - } - return 1; -} - - -/*====================================================================*/ -static void sl811_cs_config(dev_link_t *link) -{ - client_handle_t handle = link->handle; - local_info_t *dev = link->priv; - tuple_t tuple; - cisparse_t parse; - int last_fn, last_ret; - u_char buf[64]; - config_info_t conf; - cistpl_cftable_entry_t dflt = { 0 }; - - DBG(0, "sl811_cs_config(0x%p)\n", link); - - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple)); - CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse)); - link->conf.ConfigBase = parse.config.base; - link->conf.Present = parse.config.rmask[0]; - - /* Configure card */ - link->state |= DEV_CONFIG; - - /* Look up the current Vcc */ - CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(handle, &conf)); - link->conf.Vcc = conf.Vcc; - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple)); - while (1) { - cistpl_cftable_entry_t *cfg = &(parse.cftable_entry); - if (pcmcia_get_tuple_data(handle, &tuple) != 0 || - pcmcia_parse_tuple(handle, &tuple, &parse) != 0) - goto next_entry; - - if (cfg->flags & CISTPL_CFTABLE_DEFAULT) { - dflt = *cfg; - } - - if (cfg->index == 0) goto next_entry; - - link->conf.ConfigIndex = cfg->index; - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - link->conf.Attributes |= CONF_ENABLE_SPKR; - link->conf.Status = CCSR_AUDIO_ENA; - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != cfg->vcc.param[CISTPL_POWER_VNOM]/10000) { - goto next_entry; - } - } else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) { - if (conf.Vcc != dflt.vcc.param[CISTPL_POWER_VNOM]/10000) { - goto next_entry; - } - } - - if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM)) - link->conf.Vpp1 = link->conf.Vpp2 = - dflt.vpp1.param[CISTPL_POWER_VNOM]/10000; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) - link->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - link->io.NumPorts1 = link->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; - - link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - link->io.BasePort1 = io->win[0].base; - link->io.NumPorts1 = io->win[0].len; - - if (pcmcia_request_io(link->handle, &link->io) != 0) - goto next_entry; - } - break; - - next_entry: - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - last_ret = pcmcia_get_next_tuple(handle, &tuple); - } - - if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq)); - - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf)); - - if (free_ports) { - if (link->io.BasePort1) - release_region(link->io.BasePort1, link->io.NumPorts1); - } - - sprintf(dev->node.dev_name, "cf_usb0"); - dev->node.major = dev->node.minor = 0; - link->dev = &dev->node; - - printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", - dev->node.dev_name, link->conf.ConfigIndex, - link->conf.Vcc/10, link->conf.Vcc%10); - if (link->conf.Vpp1) - printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); - if (link->conf.Attributes & CONF_ENABLE_IRQ) { - printk(", irq %d", link->irq.AssignedIRQ); - irq = link->irq.AssignedIRQ; - } - - if (link->io.NumPorts1) { - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - base_addr = link->io.BasePort1; - } - - printk("\n"); - - link->state &= ~DEV_CONFIG_PENDING; - - /* Release resources claimed by PCMCIA for the sl811h driver */ - release_region(link->io.BasePort1, link->io.NumPorts1); - - if (sl811_hc_init() == 0) goto cs_failed; - - return; - - cs_failed: - printk("sl811_cs_config failed\n"); - cs_error(link->handle, last_fn, last_ret); - sl811_cs_release(link); - link->state &= ~DEV_CONFIG_PENDING; - -} /* sl811_cs_config */ - -/*====================================================================*/ -static void sl811_cs_release(dev_link_t * link) -{ - - DBG(0, "sl811_cs_release(0x%p)\n", link); - - if (link->open) { - DBG(1, "sl811_cs: release postponed, '%s' still open\n", - link->dev->dev_name); - link->state |= DEV_STALE_CONFIG; - return; - } - - /* request IO, because PCMCIA thinks it has claimed it */ - request_region(link->io.BasePort1, link->io.NumPorts1, "sl811_cs"); - - /* Unlink the device chain */ - link->dev = NULL; - - pcmcia_release_configuration(link->handle); - if (link->io.NumPorts1) - pcmcia_release_io(link->handle, &link->io); - if (link->irq.AssignedIRQ) - pcmcia_release_irq(link->handle, &link->irq); - link->state &= ~DEV_CONFIG; - - if (link->state & DEV_STALE_LINK) - sl811_cs_detach(link); - - /* FIXME: if the unregister call frees up the resources, it oopses - so we pretend to have 0 resources */ - platform_dev.num_resources = 0; - platform_dev.resource = NULL; - - platform_device_unregister(&platform_dev); - -} /* sl811_cs_release */ - -/*====================================================================*/ -static int sl811_cs_event(event_t event, int priority, event_callback_args_t *args) -{ - dev_link_t *link = args->client_data; - - DBG(1, "sl811_cs_event(0x%06x)\n", event); - - switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) { - sl811_cs_release(link); - } - break; - - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - sl811_cs_config(link); - break; - - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - - INFO("FIXME: card reset\n"); - - break; - } - return 0; -} /* sl811_cs_event */ - -/*====================================================================*/ -static int __init init_sl811_cs(void) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - servinfo_t serv; - DBG(0, "%s\n", version); - CardServices(GetCardServicesInfo, &serv); - if (serv.Revision != CS_RELEASE_CODE) { - printk(KERN_NOTICE "sl811_cs: Card Services release " - "does not match!\n"); - return -EINVAL; - } - register_pccard_driver(&dev_info, &sl811_cs_attach, &sl811_cs_detach); - return 0; -#else - return pcmcia_register_driver(&sl811_driver); -#endif - -} - -/*====================================================================*/ -static void __exit exit_sl811_cs(void) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - DBG(0, "sl811_cs: unloading\n"); - unregister_pccard_driver(&dev_info); - while (dev_list != NULL) { - del_timer(&dev_list->release); - if (dev_list->state & DEV_CONFIG) - sl811_cs_release(dev_list); - sl811_cs_detach(dev_list); - } -#else - pcmcia_unregister_driver(&sl811_driver); -#endif - -} - -/*====================================================================*/ - -module_init(init_sl811_cs); -module_exit(exit_sl811_cs); diff --git a/packages/cfu1/files/sl811_hcd.c b/packages/cfu1/files/sl811_hcd.c deleted file mode 100644 index 90e5f869b9..0000000000 --- a/packages/cfu1/files/sl811_hcd.c +++ /dev/null @@ -1,1932 +0,0 @@ -/* - * SL811HS HCD (Host Controller Driver) for USB. - * - * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) - * Copyright (C) 2004 David Brownell - * - * Periodic scheduling is based on Roman's OHCI code - * Copyright (C) 1999 Roman Weissgaerber - * - * The SL811HS controller handles host side USB (like the SL11H, but with - * another register set and SOF generation) as well as peripheral side USB - * (like the SL811S). This driver version doesn't implement the Gadget API - * for the peripheral role; or OTG (that'd need much external circuitry). - * - * For documentation, see the SL811HS spec and the "SL811HS Embedded Host" - * document (providing significant pieces missing from that spec); plus - * the SL811S spec if you want peripheral side info. - */ - -/* - * Status: Passed basic stress testing, works with hubs, mice, keyboards, - * and usb-storage. - * - * TODO: - * - usb suspend/resume triggered by sl811 (with USB_SUSPEND) - * - various issues noted in the code - * - performance work; use both register banks; ... - * - use urb->iso_frame_desc[] with ISO transfers - */ - -#undef VERBOSE -#undef PACKET_TRACE - -#include <linux/config.h> - -#ifdef CONFIG_USB_DEBUG -# define DEBUG -#else -# undef DEBUG -#endif - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/smp_lock.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/timer.h> -#include <linux/list.h> -#include <linux/interrupt.h> -#include <linux/usb.h> -#include <linux/usb_sl811.h> - -#include <asm/io.h> -#include <asm/irq.h> -#include <asm/system.h> -#include <asm/byteorder.h> - -#include "hcd.h" -#include "sl811.h" - - -MODULE_DESCRIPTION("SL811HS USB Host Controller Driver"); -MODULE_LICENSE("GPL"); - -#define DRIVER_VERSION "15 Dec 2004" - - -#ifndef DEBUG -# define STUB_DEBUG_FILE -#endif - -/* for now, use only one transfer register bank */ -#undef USE_B - -/* this doesn't understand urb->iso_frame_desc[], but if you had a driver - * that just queued one ISO frame per URB then iso transfers "should" work - * using the normal urb status fields. - */ -#define DISABLE_ISO - -#define QUIRK2 -//#define QUIRK3 - -static const char hcd_name[] = "sl811-hcd"; - -/*-------------------------------------------------------------------------*/ - - -static void port_power(struct sl811 *sl811, int is_on) -{ - struct usb_hcd *hcd = sl811_to_hcd(sl811); - - /* hub is inactive unless the port is powered */ - if (is_on) { - if (sl811->port1 & (1 << USB_PORT_FEAT_POWER)) - return; - - sl811->port1 = (1 << USB_PORT_FEAT_POWER); - sl811->irq_enable = SL11H_INTMASK_INSRMV; - hcd->self.controller->power.power_state = PMSG_ON; - } else { - sl811->port1 = 0; - sl811->irq_enable = 0; - hcd->state = HC_STATE_HALT; - hcd->self.controller->power.power_state = PMSG_SUSPEND; - } - sl811->ctrl1 = 0; - sl811_write(sl811, SL11H_IRQ_ENABLE, 0); - sl811_write(sl811, SL11H_IRQ_STATUS, ~0); - - if (sl811->board && sl811->board->port_power) { - /* switch VBUS, at 500mA unless hub power budget gets set */ - DBG("power %s\n", is_on ? "on" : "off"); - sl811->board->port_power(hcd->self.controller, is_on); - } - - /* reset as thoroughly as we can */ - if (sl811->board && sl811->board->reset) - sl811->board->reset(hcd->self.controller); - - sl811_write(sl811, SL11H_IRQ_ENABLE, 0); - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - sl811_write(sl811, SL811HS_CTLREG2, SL811HS_CTL2_INIT); - sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); - - // if !is_on, put into lowpower mode now -} - -/*-------------------------------------------------------------------------*/ - -/* This is a PIO-only HCD. Queueing appends URBs to the endpoint's queue, - * and may start I/O. Endpoint queues are scanned during completion irq - * handlers (one per packet: ACK, NAK, faults, etc) and urb cancelation. - * - * Using an external DMA engine to copy a packet at a time could work, - * though setup/teardown costs may be too big to make it worthwhile. - */ - -/* SETUP starts a new control request. Devices are not allowed to - * STALL or NAK these; they must cancel any pending control requests. - */ -static void setup_packet( - struct sl811 *sl811, - struct sl811h_ep *ep, - struct urb *urb, - u8 bank, - u8 control -) -{ - u8 addr; - u8 len; - void __iomem *data_reg; - - addr = SL811HS_PACKET_BUF(bank == 0); - len = sizeof(struct usb_ctrlrequest); - data_reg = sl811->data_reg; - sl811_write_buf(sl811, addr, urb->setup_packet, len); - - /* autoincrementing */ - sl811_write(sl811, bank + SL11H_BUFADDRREG, addr); - writeb(len, data_reg); - writeb(SL_SETUP /* | ep->epnum */, data_reg); - writeb(usb_pipedevice(urb->pipe), data_reg); - - /* always OUT/data0 */ ; - sl811_write(sl811, bank + SL11H_HOSTCTLREG, - control | SL11H_HCTLMASK_OUT); - ep->length = 0; - PACKET("SETUP qh%p\n", ep); -} - -/* STATUS finishes control requests, often after IN or OUT data packets */ -static void status_packet( - struct sl811 *sl811, - struct sl811h_ep *ep, - struct urb *urb, - u8 bank, - u8 control -) -{ - int do_out; - void __iomem *data_reg; - - do_out = urb->transfer_buffer_length && usb_pipein(urb->pipe); - data_reg = sl811->data_reg; - - /* autoincrementing */ - sl811_write(sl811, bank + SL11H_BUFADDRREG, 0); - writeb(0, data_reg); - writeb((do_out ? SL_OUT : SL_IN) /* | ep->epnum */, data_reg); - writeb(usb_pipedevice(urb->pipe), data_reg); - - /* always data1; sometimes IN */ - control |= SL11H_HCTLMASK_TOGGLE; - if (do_out) - control |= SL11H_HCTLMASK_OUT; - sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); - ep->length = 0; - PACKET("STATUS%s/%s qh%p\n", ep->nak_count ? "/retry" : "", - do_out ? "out" : "in", ep); -} - -/* IN packets can be used with any type of endpoint. here we just - * start the transfer, data from the peripheral may arrive later. - * urb->iso_frame_desc is currently ignored here... - */ -static void in_packet( - struct sl811 *sl811, - struct sl811h_ep *ep, - struct urb *urb, - u8 bank, - u8 control -) -{ - u8 addr; - u8 len; - void __iomem *data_reg; - - /* avoid losing data on overflow */ - len = ep->maxpacket; - addr = SL811HS_PACKET_BUF(bank == 0); - if (!(control & SL11H_HCTLMASK_ISOCH) - && usb_gettoggle(urb->dev, ep->epnum, 0)) - control |= SL11H_HCTLMASK_TOGGLE; - data_reg = sl811->data_reg; - - /* autoincrementing */ - sl811_write(sl811, bank + SL11H_BUFADDRREG, addr); - writeb(len, data_reg); - writeb(SL_IN | ep->epnum, data_reg); - writeb(usb_pipedevice(urb->pipe), data_reg); - - sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); - ep->length = min((int)len, - urb->transfer_buffer_length - urb->actual_length); - PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", - !!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len); -} - -/* OUT packets can be used with any type of endpoint. - * urb->iso_frame_desc is currently ignored here... - */ -static void out_packet( - struct sl811 *sl811, - struct sl811h_ep *ep, - struct urb *urb, - u8 bank, - u8 control -) -{ - void *buf; - u8 addr; - u8 len; - void __iomem *data_reg; - - buf = urb->transfer_buffer + urb->actual_length; - prefetch(buf); - - len = min((int)ep->maxpacket, - urb->transfer_buffer_length - urb->actual_length); - - if (!(control & SL11H_HCTLMASK_ISOCH) - && usb_gettoggle(urb->dev, ep->epnum, 1)) - control |= SL11H_HCTLMASK_TOGGLE; - addr = SL811HS_PACKET_BUF(bank == 0); - data_reg = sl811->data_reg; - - sl811_write_buf(sl811, addr, buf, len); - - /* autoincrementing */ - sl811_write(sl811, bank + SL11H_BUFADDRREG, addr); - writeb(len, data_reg); - writeb(SL_OUT | ep->epnum, data_reg); - writeb(usb_pipedevice(urb->pipe), data_reg); - - sl811_write(sl811, bank + SL11H_HOSTCTLREG, - control | SL11H_HCTLMASK_OUT); - ep->length = len; - PACKET("OUT%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", - !!usb_gettoggle(urb->dev, ep->epnum, 1), ep, len); -} - -/*-------------------------------------------------------------------------*/ - -/* caller updates on-chip enables later */ - -static inline void sofirq_on(struct sl811 *sl811) -{ - if (sl811->irq_enable & SL11H_INTMASK_SOFINTR) - return; - VDBG("sof irq on\n"); - sl811->irq_enable |= SL11H_INTMASK_SOFINTR; -} - -static inline void sofirq_off(struct sl811 *sl811) -{ - if (!(sl811->irq_enable & SL11H_INTMASK_SOFINTR)) - return; - VDBG("sof irq off\n"); - sl811->irq_enable &= ~SL11H_INTMASK_SOFINTR; -} - -/*-------------------------------------------------------------------------*/ - -/* pick the next endpoint for a transaction, and issue it. - * frames start with periodic transfers (after whatever is pending - * from the previous frame), and the rest of the time is async - * transfers, scheduled round-robin. - */ -static struct sl811h_ep *start(struct sl811 *sl811, u8 bank) -{ - struct sl811h_ep *ep; - struct urb *urb; - int fclock; - u8 control; - - /* use endpoint at schedule head */ - if (sl811->next_periodic) { - ep = sl811->next_periodic; - sl811->next_periodic = ep->next; - } else { - if (sl811->next_async) - ep = sl811->next_async; - else if (!list_empty(&sl811->async)) - ep = container_of(sl811->async.next, - struct sl811h_ep, schedule); - else { - /* could set up the first fullspeed periodic - * transfer for the next frame ... - */ - return NULL; - } - -#ifdef USE_B - if ((bank && sl811->active_b == ep) || sl811->active_a == ep) - return NULL; -#endif - - if (ep->schedule.next == &sl811->async) - sl811->next_async = NULL; - else - sl811->next_async = container_of(ep->schedule.next, - struct sl811h_ep, schedule); - } - - if (unlikely(list_empty(&ep->hep->urb_list))) { - DBG("empty %p queue?\n", ep); - return NULL; - } - - urb = container_of(ep->hep->urb_list.next, struct urb, urb_list); - control = ep->defctrl; - - /* if this frame doesn't have enough time left to transfer this - * packet, wait till the next frame. too-simple algorithm... - */ - fclock = sl811_read(sl811, SL11H_SOFTMRREG) << 6; - fclock -= 100; /* setup takes not much time */ - if (urb->dev->speed == USB_SPEED_LOW) { - if (control & SL11H_HCTLMASK_PREAMBLE) { - /* also note erratum 1: some hubs won't work */ - fclock -= 800; - } - fclock -= ep->maxpacket << 8; - - /* erratum 2: AFTERSOF only works for fullspeed */ - if (fclock < 0) { - if (ep->period) - sl811->stat_overrun++; - sofirq_on(sl811); - return NULL; - } - } else { - fclock -= 12000 / 19; /* 19 64byte packets/msec */ - if (fclock < 0) { - if (ep->period) - sl811->stat_overrun++; - control |= SL11H_HCTLMASK_AFTERSOF; - - /* throttle bulk/control irq noise */ - } else if (ep->nak_count) - control |= SL11H_HCTLMASK_AFTERSOF; - } - - - switch (ep->nextpid) { - case USB_PID_IN: - in_packet(sl811, ep, urb, bank, control); - break; - case USB_PID_OUT: - out_packet(sl811, ep, urb, bank, control); - break; - case USB_PID_SETUP: - setup_packet(sl811, ep, urb, bank, control); - break; - case USB_PID_ACK: /* for control status */ - status_packet(sl811, ep, urb, bank, control); - break; - default: - DBG("bad ep%p pid %02x\n", ep, ep->nextpid); - ep = NULL; - } - return ep; -} - -#define MIN_JIFFIES ((msecs_to_jiffies(2) > 1) ? msecs_to_jiffies(2) : 2) - -static inline void start_transfer(struct sl811 *sl811) -{ - if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) - return; - if (sl811->active_a == NULL) { - sl811->active_a = start(sl811, SL811_EP_A(SL811_HOST_BUF)); - if (sl811->active_a != NULL) - sl811->jiffies_a = jiffies + MIN_JIFFIES; - } -#ifdef USE_B - if (sl811->active_b == NULL) { - sl811->active_b = start(sl811, SL811_EP_B(SL811_HOST_BUF)); - if (sl811->active_b != NULL) - sl811->jiffies_b = jiffies + MIN_JIFFIES; - } -#endif -} - -static void finish_request( - struct sl811 *sl811, - struct sl811h_ep *ep, - struct urb *urb, - struct pt_regs *regs, - int status -) __releases(sl811->lock) __acquires(sl811->lock) -{ - unsigned i; - - if (usb_pipecontrol(urb->pipe)) - ep->nextpid = USB_PID_SETUP; - - spin_lock(&urb->lock); - if (urb->status == -EINPROGRESS) - urb->status = status; - spin_unlock(&urb->lock); - - spin_unlock(&sl811->lock); - usb_hcd_giveback_urb(sl811_to_hcd(sl811), urb, regs); - spin_lock(&sl811->lock); - - /* leave active endpoints in the schedule */ - if (!list_empty(&ep->hep->urb_list)) - return; - - /* async deschedule? */ - if (!list_empty(&ep->schedule)) { - list_del_init(&ep->schedule); - if (ep == sl811->next_async) - sl811->next_async = NULL; - return; - } - - /* periodic deschedule */ - DBG("deschedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); - for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { - struct sl811h_ep *temp; - struct sl811h_ep **prev = &sl811->periodic[i]; - - while (*prev && ((temp = *prev) != ep)) - prev = &temp->next; - if (*prev) - *prev = ep->next; - sl811->load[i] -= ep->load; - } - ep->branch = PERIODIC_SIZE; - sl811->periodic_count--; - sl811_to_hcd(sl811)->self.bandwidth_allocated - -= ep->load / ep->period; - if (ep == sl811->next_periodic) - sl811->next_periodic = ep->next; - - /* we might turn SOFs back on again for the async schedule */ - if (sl811->periodic_count == 0) - sofirq_off(sl811); -} - -static void -done(struct sl811 *sl811, struct sl811h_ep *ep, u8 bank, struct pt_regs *regs) -{ - u8 status; - struct urb *urb; - int urbstat = -EINPROGRESS; - - if (unlikely(!ep)) - return; - - status = sl811_read(sl811, bank + SL11H_PKTSTATREG); - - urb = container_of(ep->hep->urb_list.next, struct urb, urb_list); - - /* we can safely ignore NAKs */ - if (status & SL11H_STATMASK_NAK) { - // PACKET("...NAK_%02x qh%p\n", bank, ep); - if (!ep->period) - ep->nak_count++; - ep->error_count = 0; - - /* ACK advances transfer, toggle, and maybe queue */ - } else if (status & SL11H_STATMASK_ACK) { - struct usb_device *udev = urb->dev; - int len; - unsigned char *buf; - - /* urb->iso_frame_desc is currently ignored here... */ - - ep->nak_count = ep->error_count = 0; - switch (ep->nextpid) { - case USB_PID_OUT: - // PACKET("...ACK/out_%02x qh%p\n", bank, ep); - urb->actual_length += ep->length; - usb_dotoggle(udev, ep->epnum, 1); - if (urb->actual_length - == urb->transfer_buffer_length) { - if (usb_pipecontrol(urb->pipe)) - ep->nextpid = USB_PID_ACK; - - /* some bulk protocols terminate OUT transfers - * by a short packet, using ZLPs not padding. - */ - else if (ep->length < ep->maxpacket - || !(urb->transfer_flags - & URB_ZERO_PACKET)) - urbstat = 0; - } - break; - case USB_PID_IN: - // PACKET("...ACK/in_%02x qh%p\n", bank, ep); - buf = urb->transfer_buffer + urb->actual_length; - prefetchw(buf); - len = ep->maxpacket - sl811_read(sl811, - bank + SL11H_XFERCNTREG); - if (len > ep->length) { - len = ep->length; - urb->status = -EOVERFLOW; - } - urb->actual_length += len; - sl811_read_buf(sl811, SL811HS_PACKET_BUF(bank == 0), - buf, len); - usb_dotoggle(udev, ep->epnum, 0); - if (urb->actual_length == urb->transfer_buffer_length) - urbstat = 0; - else if (len < ep->maxpacket) { - if (urb->transfer_flags & URB_SHORT_NOT_OK) - urbstat = -EREMOTEIO; - else - urbstat = 0; - } - if (usb_pipecontrol(urb->pipe) - && (urbstat == -EREMOTEIO - || urbstat == 0)) { - - /* NOTE if the status stage STALLs (why?), - * this reports the wrong urb status. - */ - spin_lock(&urb->lock); - if (urb->status == -EINPROGRESS) - urb->status = urbstat; - spin_unlock(&urb->lock); - - urb = NULL; - ep->nextpid = USB_PID_ACK; - } - break; - case USB_PID_SETUP: - // PACKET("...ACK/setup_%02x qh%p\n", bank, ep); - if (urb->transfer_buffer_length == urb->actual_length) - ep->nextpid = USB_PID_ACK; - else if (usb_pipeout(urb->pipe)) { - usb_settoggle(udev, 0, 1, 1); - ep->nextpid = USB_PID_OUT; - } else { - usb_settoggle(udev, 0, 0, 1); - ep->nextpid = USB_PID_IN; - } - break; - case USB_PID_ACK: - // PACKET("...ACK/status_%02x qh%p\n", bank, ep); - urbstat = 0; - break; - } - - /* STALL stops all transfers */ - } else if (status & SL11H_STATMASK_STALL) { - PACKET("...STALL_%02x qh%p\n", bank, ep); - ep->nak_count = ep->error_count = 0; - urbstat = -EPIPE; - - /* error? retry, until "3 strikes" */ - } else if (++ep->error_count >= 3) { - if (status & SL11H_STATMASK_TMOUT) - urbstat = -ETIMEDOUT; - else if (status & SL11H_STATMASK_OVF) - urbstat = -EOVERFLOW; - else - urbstat = -EPROTO; - ep->error_count = 0; - PACKET("...3STRIKES_%02x %02x qh%p stat %d\n", - bank, status, ep, urbstat); - } - - if (urb && (urbstat != -EINPROGRESS || urb->status != -EINPROGRESS)) - finish_request(sl811, ep, urb, regs, urbstat); -} - -static inline u8 checkdone(struct sl811 *sl811) -{ - u8 ctl; - u8 irqstat = 0; - - if (sl811->active_a && time_before_eq(sl811->jiffies_a, jiffies)) { - ctl = sl811_read(sl811, SL811_EP_A(SL11H_HOSTCTLREG)); - if (ctl & SL11H_HCTLMASK_ARM) - sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0); - DBG("%s DONE_A: ctrl %02x sts %02x\n", - (ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost", - ctl, - sl811_read(sl811, SL811_EP_A(SL11H_PKTSTATREG))); - irqstat |= SL11H_INTMASK_DONE_A; - } -#ifdef USE_B - if (sl811->active_b && time_before_eq(sl811->jiffies_b, jiffies)) { - ctl = sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG)); - if (ctl & SL11H_HCTLMASK_ARM) - sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0); - DBG("%s DONE_B: ctrl %02x sts %02x\n", - (ctl & SL11H_HCTLMASK_ARM) ? "timeout" : "lost", - ctl, - sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG))); - irqstat |= SL11H_INTMASK_DONE_A; - } -#endif - return irqstat; -} - -static irqreturn_t sl811h_irq(struct usb_hcd *hcd, struct pt_regs *regs) -{ - struct sl811 *sl811 = hcd_to_sl811(hcd); - u8 irqstat; - irqreturn_t ret = IRQ_NONE; - unsigned retries = 5; - - spin_lock(&sl811->lock); - -retry: - irqstat = sl811_read(sl811, SL11H_IRQ_STATUS) & ~SL11H_INTMASK_DP; - if (irqstat) { - sl811_write(sl811, SL11H_IRQ_STATUS, irqstat); - irqstat &= sl811->irq_enable; - } - -#ifdef QUIRK2 - /* this may no longer be necessary ... */ - if (irqstat == 0 && ret == IRQ_NONE) { - irqstat = checkdone(sl811); - if (irqstat /* && irq != ~0 */ ) - sl811->stat_lost++; - } -#endif - - /* USB packets, not necessarily handled in the order they're - * issued ... that's fine if they're different endpoints. - */ - if (irqstat & SL11H_INTMASK_DONE_A) { - done(sl811, sl811->active_a, SL811_EP_A(SL811_HOST_BUF), regs); - sl811->active_a = NULL; - sl811->stat_a++; - } -#ifdef USE_B - if (irqstat & SL11H_INTMASK_DONE_B) { - done(sl811, sl811->active_b, SL811_EP_B(SL811_HOST_BUF), regs); - sl811->active_b = NULL; - sl811->stat_b++; - } -#endif - if (irqstat & SL11H_INTMASK_SOFINTR) { - unsigned index; - - index = sl811->frame++ % (PERIODIC_SIZE - 1); - sl811->stat_sof++; - - /* be graceful about almost-inevitable periodic schedule - * overruns: continue the previous frame's transfers iff - * this one has nothing scheduled. - */ - if (sl811->next_periodic) { - // ERR("overrun to slot %d\n", index); - sl811->stat_overrun++; - } - if (sl811->periodic[index]) - sl811->next_periodic = sl811->periodic[index]; - } - - /* khubd manages debouncing and wakeup */ - if (irqstat & SL11H_INTMASK_INSRMV) { - sl811->stat_insrmv++; - - /* most stats are reset for each VBUS session */ - sl811->stat_wake = 0; - sl811->stat_sof = 0; - sl811->stat_a = 0; - sl811->stat_b = 0; - sl811->stat_lost = 0; - - sl811->ctrl1 = 0; - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - - sl811->irq_enable = SL11H_INTMASK_INSRMV; - sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); - - /* usbcore nukes other pending transactions on disconnect */ - if (sl811->active_a) { - sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0); - finish_request(sl811, sl811->active_a, - container_of(sl811->active_a->hep->urb_list.next, - struct urb, urb_list), - NULL, -ESHUTDOWN); - sl811->active_a = NULL; - } -#ifdef USE_B - if (sl811->active_b) { - sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0); - finish_request(sl811, sl811->active_b, - container_of(sl811->active_b->hep->urb_list.next, - struct urb, urb_list), - NULL, -ESHUTDOWN); - sl811->active_b = NULL; - } -#endif - - /* port status seems wierd until after reset, so - * force the reset and make khubd clean up later. - */ - sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION) - | (1 << USB_PORT_FEAT_CONNECTION); - - } else if (irqstat & SL11H_INTMASK_RD) { - if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) { - DBG("wakeup\n"); - sl811->port1 |= 1 << USB_PORT_FEAT_C_SUSPEND; - sl811->stat_wake++; - } else - irqstat &= ~SL11H_INTMASK_RD; - } - - if (irqstat) { - if (sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)) - start_transfer(sl811); - ret = IRQ_HANDLED; - if (retries--) - goto retry; - } - - if (sl811->periodic_count == 0 && list_empty(&sl811->async)) - sofirq_off(sl811); - sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); - - spin_unlock(&sl811->lock); - - return ret; -} - -/*-------------------------------------------------------------------------*/ - -/* usb 1.1 says max 90% of a frame is available for periodic transfers. - * this driver doesn't promise that much since it's got to handle an - * IRQ per packet; irq handling latencies also use up that time. - */ -#define MAX_PERIODIC_LOAD 500 /* out of 1000 usec */ - -static int balance(struct sl811 *sl811, u16 period, u16 load) -{ - int i, branch = -ENOSPC; - - /* search for the least loaded schedule branch of that period - * which has enough bandwidth left unreserved. - */ - for (i = 0; i < period ; i++) { - if (branch < 0 || sl811->load[branch] > sl811->load[i]) { - int j; - - for (j = i; j < PERIODIC_SIZE; j += period) { - if ((sl811->load[j] + load) - > MAX_PERIODIC_LOAD) - break; - } - if (j < PERIODIC_SIZE) - continue; - branch = i; - } - } - return branch; -} - -/*-------------------------------------------------------------------------*/ - -static int sl811h_urb_enqueue( - struct usb_hcd *hcd, - struct usb_host_endpoint *hep, - struct urb *urb, - int mem_flags -) { - struct sl811 *sl811 = hcd_to_sl811(hcd); - struct usb_device *udev = urb->dev; - unsigned int pipe = urb->pipe; - int is_out = !usb_pipein(pipe); - int type = usb_pipetype(pipe); - int epnum = usb_pipeendpoint(pipe); - struct sl811h_ep *ep = NULL; - unsigned long flags; - int i; - int retval = 0; - -#ifdef DISABLE_ISO - if (type == PIPE_ISOCHRONOUS) - return -ENOSPC; -#endif - - /* avoid all allocations within spinlocks */ - if (!hep->hcpriv) { - ep = kcalloc(1, sizeof *ep, mem_flags); - /* set hep, otherwise sl811h_ep *start(struct sl811 *sl811, u8 bank) crashes */ - ep->hep = hep; - } - - spin_lock_irqsave(&sl811->lock, flags); - - /* don't submit to a dead or disabled port */ - if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE)) - || !HC_IS_RUNNING(hcd->state)) { - retval = -ENODEV; - goto fail; - } - - if (hep->hcpriv) { - kfree(ep); - ep = hep->hcpriv; - } else if (!ep) { - retval = -ENOMEM; - goto fail; - - } else { - INIT_LIST_HEAD(&ep->schedule); - ep->udev = usb_get_dev(udev); - ep->epnum = epnum; - ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); - ep->defctrl = SL11H_HCTLMASK_ARM | SL11H_HCTLMASK_ENABLE; - usb_settoggle(udev, epnum, is_out, 0); - - if (type == PIPE_CONTROL) - ep->nextpid = USB_PID_SETUP; - else if (is_out) - ep->nextpid = USB_PID_OUT; - else - ep->nextpid = USB_PID_IN; - - if (ep->maxpacket > H_MAXPACKET) { - /* iso packets up to 240 bytes could work... */ - DBG("dev %d ep%d maxpacket %d\n", - udev->devnum, epnum, ep->maxpacket); - retval = -EINVAL; - goto fail; - } - - if (udev->speed == USB_SPEED_LOW) { - /* send preamble for external hub? */ - if (!(sl811->ctrl1 & SL11H_CTL1MASK_LSPD)) - ep->defctrl |= SL11H_HCTLMASK_PREAMBLE; - } - switch (type) { - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - if (urb->interval > PERIODIC_SIZE) - urb->interval = PERIODIC_SIZE; - ep->period = urb->interval; - ep->branch = PERIODIC_SIZE; - if (type == PIPE_ISOCHRONOUS) - ep->defctrl |= SL11H_HCTLMASK_ISOCH; - ep->load = usb_calc_bus_time(udev->speed, !is_out, - (type == PIPE_ISOCHRONOUS), - usb_maxpacket(udev, pipe, is_out)) - / 1000; - break; - } - - hep->hcpriv = ep; - } - - /* maybe put endpoint into schedule */ - switch (type) { - case PIPE_CONTROL: - case PIPE_BULK: - if (list_empty(&ep->schedule)) - list_add_tail(&ep->schedule, &sl811->async); - break; - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - urb->interval = ep->period; - if (ep->branch < PERIODIC_SIZE) - break; - - retval = balance(sl811, ep->period, ep->load); - if (retval < 0) - goto fail; - ep->branch = retval; - retval = 0; - urb->start_frame = (sl811->frame & (PERIODIC_SIZE - 1)) - + ep->branch; - - /* sort each schedule branch by period (slow before fast) - * to share the faster parts of the tree without needing - * dummy/placeholder nodes - */ - DBG("schedule qh%d/%p branch %d\n", ep->period, ep, ep->branch); - for (i = ep->branch; i < PERIODIC_SIZE; i += ep->period) { - struct sl811h_ep **prev = &sl811->periodic[i]; - struct sl811h_ep *here = *prev; - - while (here && ep != here) { - if (ep->period > here->period) - break; - prev = &here->next; - here = *prev; - } - if (ep != here) { - ep->next = here; - *prev = ep; - } - sl811->load[i] += ep->load; - } - sl811->periodic_count++; - hcd->self.bandwidth_allocated += ep->load / ep->period; - sofirq_on(sl811); - } - - /* in case of unlink-during-submit */ - spin_lock(&urb->lock); - if (urb->status != -EINPROGRESS) { - spin_unlock(&urb->lock); - finish_request(sl811, ep, urb, NULL, 0); - retval = 0; - goto fail; - } - - /* when uncommented, causes this error on mouse open: - drivers/usb/input/usbmouse.c: can't resubmit intr, sl811-hcd-1/input0, status -22 - urb->hcpriv = hep; */ - - spin_unlock(&urb->lock); - - start_transfer(sl811); - sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); -fail: - spin_unlock_irqrestore(&sl811->lock, flags); - return retval; -} - -static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -{ - struct sl811 *sl811 = hcd_to_sl811(hcd); - struct usb_host_endpoint *hep = urb->hcpriv; - unsigned long flags; - struct sl811h_ep *ep; - int retval = 0; - - if (!hep) - return -EINVAL; - - spin_lock_irqsave(&sl811->lock, flags); - ep = hep->hcpriv; - if (ep) { - /* finish right away if this urb can't be active ... - * note that some drivers wrongly expect delays - */ - if (ep->hep->urb_list.next != &urb->urb_list) { - /* not front of queue? never active */ - - /* for active transfers, we expect an IRQ */ - } else if (sl811->active_a == ep) { - if (time_before_eq(sl811->jiffies_a, jiffies)) { - /* happens a lot with lowspeed?? */ - DBG("giveup on DONE_A: ctrl %02x sts %02x\n", - sl811_read(sl811, - SL811_EP_A(SL11H_HOSTCTLREG)), - sl811_read(sl811, - SL811_EP_A(SL11H_PKTSTATREG))); - sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), - 0); - sl811->active_a = NULL; - } else - urb = NULL; -#ifdef USE_B - } else if (sl811->active_b == ep) { - if (time_before_eq(sl811->jiffies_a, jiffies)) { - /* happens a lot with lowspeed?? */ - DBG("giveup on DONE_B: ctrl %02x sts %02x\n", - sl811_read(sl811, - SL811_EP_B(SL11H_HOSTCTLREG)), - sl811_read(sl811, - SL811_EP_B(SL11H_PKTSTATREG))); - sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), - 0); - sl811->active_b = NULL; - } else - urb = NULL; -#endif - } else { - /* front of queue for inactive endpoint */ - } - - if (urb) - finish_request(sl811, ep, urb, NULL, 0); - else - VDBG("dequeue, urb %p active %s; wait4irq\n", urb, - (sl811->active_a == ep) ? "A" : "B"); - } else - retval = -EINVAL; - spin_unlock_irqrestore(&sl811->lock, flags); - return retval; -} - -static void -sl811h_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) -{ - struct sl811h_ep *ep = hep->hcpriv; - - if (!ep) - return; - - /* assume we'd just wait for the irq */ - if (!list_empty(&hep->urb_list)) - msleep(3); - if (!list_empty(&hep->urb_list)) - WARN("ep %p not empty?\n", ep); - - usb_put_dev(ep->udev); - kfree(ep); - hep->hcpriv = NULL; -} - -static int -sl811h_get_frame(struct usb_hcd *hcd) -{ - struct sl811 *sl811 = hcd_to_sl811(hcd); - - /* wrong except while periodic transfers are scheduled; - * never matches the on-the-wire frame; - * subject to overruns. - */ - return sl811->frame; -} - - -/*-------------------------------------------------------------------------*/ - -/* the virtual root hub timer IRQ checks for hub status */ -static int -sl811h_hub_status_data(struct usb_hcd *hcd, char *buf) -{ - struct sl811 *sl811 = hcd_to_sl811(hcd); -#ifdef QUIRK3 - unsigned long flags; - - /* non-SMP HACK: use root hub timer as i/o watchdog - * this seems essential when SOF IRQs aren't in use... - */ - local_irq_save(flags); - if (!timer_pending(&sl811->timer)) { - if (sl811h_irq( /* ~0, */ hcd, NULL) != IRQ_NONE) - sl811->stat_lost++; - } - local_irq_restore(flags); -#endif - - if (!(sl811->port1 & (0xffff << 16))) - return 0; - - /* tell khubd port 1 changed */ - *buf = (1 << 1); - return 1; -} - -static void -sl811h_hub_descriptor ( - struct sl811 *sl811, - struct usb_hub_descriptor *desc -) { - u16 temp = 0; - - desc->bDescriptorType = 0x29; - desc->bHubContrCurrent = 0; - - desc->bNbrPorts = 1; - desc->bDescLength = 9; - - /* per-port power switching (gang of one!), or none */ - desc->bPwrOn2PwrGood = 0; - if (sl811->board && sl811->board->port_power) { - desc->bPwrOn2PwrGood = sl811->board->potpg; - if (!desc->bPwrOn2PwrGood) - desc->bPwrOn2PwrGood = 10; - temp = 0x0001; - } else - temp = 0x0002; - - /* no overcurrent errors detection/handling */ - temp |= 0x0010; - - desc->wHubCharacteristics = (__force __u16)cpu_to_le16(temp); - - /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ - desc->bitmap[0] = 1 << 1; - desc->bitmap[1] = ~0; -} - -static void -sl811h_timer(unsigned long _sl811) -{ - struct sl811 *sl811 = (void *) _sl811; - unsigned long flags; - u8 irqstat; - u8 signaling = sl811->ctrl1 & SL11H_CTL1MASK_FORCE; - const u32 mask = (1 << USB_PORT_FEAT_CONNECTION) - | (1 << USB_PORT_FEAT_ENABLE) - | (1 << USB_PORT_FEAT_LOWSPEED); - - spin_lock_irqsave(&sl811->lock, flags); - - /* stop special signaling */ - sl811->ctrl1 &= ~SL11H_CTL1MASK_FORCE; - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - udelay(3); - - irqstat = sl811_read(sl811, SL11H_IRQ_STATUS); - - switch (signaling) { - case SL11H_CTL1MASK_SE0: - DBG("end reset\n"); - sl811->port1 = (1 << USB_PORT_FEAT_C_RESET) - | (1 << USB_PORT_FEAT_POWER); - sl811->ctrl1 = 0; - /* don't wrongly ack RD */ - if (irqstat & SL11H_INTMASK_INSRMV) - irqstat &= ~SL11H_INTMASK_RD; - break; - case SL11H_CTL1MASK_K: - DBG("end resume\n"); - sl811->port1 &= ~(1 << USB_PORT_FEAT_SUSPEND); - break; - default: - DBG("odd timer signaling: %02x\n", signaling); - break; - } - sl811_write(sl811, SL11H_IRQ_STATUS, irqstat); - - if (irqstat & SL11H_INTMASK_RD) { - /* usbcore nukes all pending transactions on disconnect */ - if (sl811->port1 & (1 << USB_PORT_FEAT_CONNECTION)) - sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION) - | (1 << USB_PORT_FEAT_C_ENABLE); - sl811->port1 &= ~mask; - sl811->irq_enable = SL11H_INTMASK_INSRMV; - } else { - sl811->port1 |= mask; - if (irqstat & SL11H_INTMASK_DP) - sl811->port1 &= ~(1 << USB_PORT_FEAT_LOWSPEED); - sl811->irq_enable = SL11H_INTMASK_INSRMV | SL11H_INTMASK_RD; - } - - if (sl811->port1 & (1 << USB_PORT_FEAT_CONNECTION)) { - u8 ctrl2 = SL811HS_CTL2_INIT; - - sl811->irq_enable |= SL11H_INTMASK_DONE_A; -#ifdef USE_B - sl811->irq_enable |= SL11H_INTMASK_DONE_B; -#endif - if (sl811->port1 & (1 << USB_PORT_FEAT_LOWSPEED)) { - sl811->ctrl1 |= SL11H_CTL1MASK_LSPD; - ctrl2 |= SL811HS_CTL2MASK_DSWAP; - } - - /* start SOFs flowing, kickstarting with A registers */ - sl811->ctrl1 |= SL11H_CTL1MASK_SOF_ENA; - sl811_write(sl811, SL11H_SOFLOWREG, 0xe0); - sl811_write(sl811, SL811HS_CTLREG2, ctrl2); - - /* autoincrementing */ - sl811_write(sl811, SL811_EP_A(SL11H_BUFLNTHREG), 0); - writeb(SL_SOF, sl811->data_reg); - writeb(0, sl811->data_reg); - sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), - SL11H_HCTLMASK_ARM); - - /* khubd provides debounce delay */ - } else { - sl811->ctrl1 = 0; - } - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - - /* reenable irqs */ - sl811_write(sl811, SL11H_IRQ_ENABLE, sl811->irq_enable); - spin_unlock_irqrestore(&sl811->lock, flags); -} - -static int -sl811h_hub_control( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -) { - struct sl811 *sl811 = hcd_to_sl811(hcd); - int retval = 0; - unsigned long flags; - - spin_lock_irqsave(&sl811->lock, flags); - - switch (typeReq) { - case ClearHubFeature: - case SetHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: - case C_HUB_LOCAL_POWER: - break; - default: - goto error; - } - break; - case ClearPortFeature: - if (wIndex != 1 || wLength != 0) - goto error; - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - sl811->port1 &= (1 << USB_PORT_FEAT_POWER); - sl811->ctrl1 = 0; - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - sl811->irq_enable = SL11H_INTMASK_INSRMV; - sl811_write(sl811, SL11H_IRQ_ENABLE, - sl811->irq_enable); - break; - case USB_PORT_FEAT_SUSPEND: - if (!(sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND))) - break; - - /* 20 msec of resume/K signaling, other irqs blocked */ - DBG("start resume...\n"); - sl811->irq_enable = 0; - sl811_write(sl811, SL11H_IRQ_ENABLE, - sl811->irq_enable); - sl811->ctrl1 |= SL11H_CTL1MASK_K; - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - - mod_timer(&sl811->timer, jiffies - + msecs_to_jiffies(20)); - break; - case USB_PORT_FEAT_POWER: - port_power(sl811, 0); - break; - case USB_PORT_FEAT_C_ENABLE: - case USB_PORT_FEAT_C_SUSPEND: - case USB_PORT_FEAT_C_CONNECTION: - case USB_PORT_FEAT_C_OVER_CURRENT: - case USB_PORT_FEAT_C_RESET: - break; - default: - goto error; - } - sl811->port1 &= ~(1 << wValue); - break; - case GetHubDescriptor: - sl811h_hub_descriptor(sl811, (struct usb_hub_descriptor *) buf); - break; - case GetHubStatus: - *(__le32 *) buf = cpu_to_le32(0); - break; - case GetPortStatus: - if (wIndex != 1) - goto error; - *(__le32 *) buf = cpu_to_le32(sl811->port1); - -#ifndef VERBOSE - if (*(u16*)(buf+2)) /* only if wPortChange is interesting */ -#endif - DBG("GetPortStatus %08x\n", sl811->port1); - break; - case SetPortFeature: - if (wIndex != 1 || wLength != 0) - goto error; - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if (sl811->port1 & (1 << USB_PORT_FEAT_RESET)) - goto error; - if (!(sl811->port1 & (1 << USB_PORT_FEAT_ENABLE))) - goto error; - - DBG("suspend...\n"); - sl811->ctrl1 &= ~SL11H_CTL1MASK_SOF_ENA; - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - break; - case USB_PORT_FEAT_POWER: - port_power(sl811, 1); - break; - case USB_PORT_FEAT_RESET: - if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) - goto error; - if (!(sl811->port1 & (1 << USB_PORT_FEAT_POWER))) - break; - - /* 50 msec of reset/SE0 signaling, irqs blocked */ - sl811->irq_enable = 0; - sl811_write(sl811, SL11H_IRQ_ENABLE, - sl811->irq_enable); - sl811->ctrl1 = SL11H_CTL1MASK_SE0; - sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1); - sl811->port1 |= (1 << USB_PORT_FEAT_RESET); - mod_timer(&sl811->timer, jiffies - + msecs_to_jiffies(50)); - break; - default: - goto error; - } - sl811->port1 |= 1 << wValue; - break; - - default: -error: - /* "protocol stall" on error */ - retval = -EPIPE; - } - - spin_unlock_irqrestore(&sl811->lock, flags); - return retval; -} - -#ifdef CONFIG_PM - -static int -sl811h_hub_suspend(struct usb_hcd *hcd) -{ - // SOFs off - DBG("%s\n", __FUNCTION__); - return 0; -} - -static int -sl811h_hub_resume(struct usb_hcd *hcd) -{ - // SOFs on - DBG("%s\n", __FUNCTION__); - return 0; -} - -#else - -#define sl811h_hub_suspend NULL -#define sl811h_hub_resume NULL - -#endif - - -/*-------------------------------------------------------------------------*/ - -#ifdef STUB_DEBUG_FILE - -static inline void create_debug_file(struct sl811 *sl811) { } -static inline void remove_debug_file(struct sl811 *sl811) { } - -#else - -#include <linux/proc_fs.h> -#include <linux/seq_file.h> - -static void dump_irq(struct seq_file *s, char *label, u8 mask) -{ - seq_printf(s, "%s %02x%s%s%s%s%s%s\n", label, mask, - (mask & SL11H_INTMASK_DONE_A) ? " done_a" : "", - (mask & SL11H_INTMASK_DONE_B) ? " done_b" : "", - (mask & SL11H_INTMASK_SOFINTR) ? " sof" : "", - (mask & SL11H_INTMASK_INSRMV) ? " ins/rmv" : "", - (mask & SL11H_INTMASK_RD) ? " rd" : "", - (mask & SL11H_INTMASK_DP) ? " dp" : ""); -} - -static int proc_sl811h_show(struct seq_file *s, void *unused) -{ - struct sl811 *sl811 = s->private; - struct sl811h_ep *ep; - unsigned i; - - seq_printf(s, "%s\n%s version %s\nportstatus[1] = %08x\n", - sl811_to_hcd(sl811)->product_desc, - hcd_name, DRIVER_VERSION, - sl811->port1); - - seq_printf(s, "insert/remove: %ld\n", sl811->stat_insrmv); - seq_printf(s, "current session: done_a %ld done_b %ld " - "wake %ld sof %ld overrun %ld lost %ld\n\n", - sl811->stat_a, sl811->stat_b, - sl811->stat_wake, sl811->stat_sof, - sl811->stat_overrun, sl811->stat_lost); - - spin_lock_irq(&sl811->lock); - - if (sl811->ctrl1 & SL11H_CTL1MASK_SUSPEND) - seq_printf(s, "(suspended)\n\n"); - else { - u8 t = sl811_read(sl811, SL11H_CTLREG1); - - seq_printf(s, "ctrl1 %02x%s%s%s%s\n", t, - (t & SL11H_CTL1MASK_SOF_ENA) ? " sofgen" : "", - ({char *s; switch (t & SL11H_CTL1MASK_FORCE) { - case SL11H_CTL1MASK_NORMAL: s = ""; break; - case SL11H_CTL1MASK_SE0: s = " se0/reset"; break; - case SL11H_CTL1MASK_K: s = " k/resume"; break; - default: s = "j"; break; - }; s; }), - (t & SL11H_CTL1MASK_LSPD) ? " lowspeed" : "", - (t & SL11H_CTL1MASK_SUSPEND) ? " suspend" : ""); - - dump_irq(s, "irq_enable", - sl811_read(sl811, SL11H_IRQ_ENABLE)); - dump_irq(s, "irq_status", - sl811_read(sl811, SL11H_IRQ_STATUS)); - seq_printf(s, "frame clocks remaining: %d\n", - sl811_read(sl811, SL11H_SOFTMRREG) << 6); - } - - seq_printf(s, "A: qh%p ctl %02x sts %02x\n", sl811->active_a, - sl811_read(sl811, SL811_EP_A(SL11H_HOSTCTLREG)), - sl811_read(sl811, SL811_EP_A(SL11H_PKTSTATREG))); - seq_printf(s, "B: qh%p ctl %02x sts %02x\n", sl811->active_b, - sl811_read(sl811, SL811_EP_B(SL11H_HOSTCTLREG)), - sl811_read(sl811, SL811_EP_B(SL11H_PKTSTATREG))); - seq_printf(s, "\n"); - list_for_each_entry (ep, &sl811->async, schedule) { - struct urb *urb; - - seq_printf(s, "%s%sqh%p, ep%d%s, maxpacket %d" - " nak %d err %d\n", - (ep == sl811->active_a) ? "(A) " : "", - (ep == sl811->active_b) ? "(B) " : "", - ep, ep->epnum, - ({ char *s; switch (ep->nextpid) { - case USB_PID_IN: s = "in"; break; - case USB_PID_OUT: s = "out"; break; - case USB_PID_SETUP: s = "setup"; break; - case USB_PID_ACK: s = "status"; break; - default: s = "?"; break; - }; s;}), - ep->maxpacket, - ep->nak_count, ep->error_count); - list_for_each_entry (urb, &ep->hep->urb_list, urb_list) { - seq_printf(s, " urb%p, %d/%d\n", urb, - urb->actual_length, - urb->transfer_buffer_length); - } - } - if (!list_empty(&sl811->async)) - seq_printf(s, "\n"); - - seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE); - - for (i = 0; i < PERIODIC_SIZE; i++) { - ep = sl811->periodic[i]; - if (!ep) - continue; - seq_printf(s, "%2d [%3d]:\n", i, sl811->load[i]); - - /* DUMB: prints shared entries multiple times */ - do { - seq_printf(s, - " %s%sqh%d/%p (%sdev%d ep%d%s max %d) " - "err %d\n", - (ep == sl811->active_a) ? "(A) " : "", - (ep == sl811->active_b) ? "(B) " : "", - ep->period, ep, - (ep->udev->speed == USB_SPEED_FULL) - ? "" : "ls ", - ep->udev->devnum, ep->epnum, - (ep->epnum == 0) ? "" - : ((ep->nextpid == USB_PID_IN) - ? "in" - : "out"), - ep->maxpacket, ep->error_count); - ep = ep->next; - } while (ep); - } - - spin_unlock_irq(&sl811->lock); - seq_printf(s, "\n"); - - return 0; -} - -static int proc_sl811h_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_sl811h_show, PDE(inode)->data); -} - -static struct file_operations proc_ops = { - .open = proc_sl811h_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* expect just one sl811 per system */ -static const char proc_filename[] = "driver/sl811h"; - -static void create_debug_file(struct sl811 *sl811) -{ - struct proc_dir_entry *pde; - - pde = create_proc_entry(proc_filename, 0, NULL); - if (pde == NULL) - return; - - pde->proc_fops = &proc_ops; - pde->data = sl811; - sl811->pde = pde; -} - -static void remove_debug_file(struct sl811 *sl811) -{ - if (sl811->pde) - remove_proc_entry(proc_filename, NULL); -} - -#endif - -/*-------------------------------------------------------------------------*/ - -static void -sl811h_stop(struct usb_hcd *hcd) -{ - struct sl811 *sl811 = hcd_to_sl811(hcd); - unsigned long flags; - - del_timer_sync(&hcd->rh_timer); - - spin_lock_irqsave(&sl811->lock, flags); - port_power(sl811, 0); - spin_unlock_irqrestore(&sl811->lock, flags); -} - -static int -sl811h_start(struct usb_hcd *hcd) -{ - struct sl811 *sl811 = hcd_to_sl811(hcd); - - /* chip has been reset, VBUS power is off */ - hcd->state = HC_STATE_RUNNING; - - if (sl811->board) { - hcd->can_wakeup = sl811->board->can_wakeup; - hcd->power_budget = sl811->board->power * 2; - } - - // enable power and interupts - port_power(sl811, 1); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static struct hc_driver sl811h_hc_driver = { - .description = hcd_name, - .hcd_priv_size = sizeof(struct sl811), - - /* - * generic hardware linkage - */ - .irq = sl811h_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* Basic lifecycle operations */ - .start = sl811h_start, - .stop = sl811h_stop, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = sl811h_urb_enqueue, - .urb_dequeue = sl811h_urb_dequeue, - .endpoint_disable = sl811h_endpoint_disable, - - /* - * periodic schedule support - */ - .get_frame_number = sl811h_get_frame, - - /* - * root hub support - */ - .hub_status_data = sl811h_hub_status_data, - .hub_control = sl811h_hub_control, - .hub_suspend = sl811h_hub_suspend, - .hub_resume = sl811h_hub_resume, -}; - -/*-------------------------------------------------------------------------*/ - -static int __init_or_module -sl811h_remove(struct device *dev) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct sl811 *sl811 = hcd_to_sl811(hcd); - struct platform_device *pdev; - struct resource *res; - - DBG("sl811h_remove\n"); - pdev = container_of(dev, struct platform_device, dev); - - remove_debug_file(sl811); - usb_remove_hcd(hcd); - -#ifndef CONFIG_USB_SL811_CS - iounmap(sl811->data_reg); -#endif - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (res != NULL) release_mem_region(res->start, 1); - else DBG("res: %d\n", res); -#ifndef CONFIG_USB_SL811_CS - iounmap(sl811->addr_reg); -#endif - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res != NULL) release_mem_region(res->start, 1); - else DBG("res: %d\n", res); - - usb_put_hcd(hcd); - return 0; -} - -#define resource_len(r) (((r)->end - (r)->start) + 1) - -/*************************************************************************** - * This routine tests the Read/Write functionality of SL811HS registers - * - * 1) Store original register value into a buffer - * 2) Write to registers with a RAMP pattern. (10, 11, 12, ..., 255) - * 3) Read from register - * 4) Compare the written value with the read value and make sure they are - * equivalent - * 5) Restore the original register value - * - * Input: hci = data structure for the host controller - * - * Return: 1 = passed; 0 = failed - **************************************************************************/ -static int test_registers(struct sl811 * sl811) -{ - int i, result = 1; - u8 buf[256], data; - - for (i = 0x10; i < 256; i++) { - /* save the original buffer */ - buf[i] = sl811_read(sl811, i); - - /* Write the new data to the buffer */ - sl811_write(sl811, i, i); - } - - /* compare the written data */ - for (i = 0x10; i < 256; i++) { - data = sl811_read(sl811, i); - if (data != i) { - DBG("Pattern test failed!! value = 0x%x, s/b 0x%x\n", - data, i); - result = 0; - break; - } - } - - /* restore the data */ - for (i = 0x10; i < 256; i++) { - sl811_write(sl811, i, buf[i]); - } - - return result; -} - - -int sl811h_probe(struct device *dev) -{ - struct usb_hcd *hcd; - struct sl811 *sl811; - struct platform_device *pdev; - struct resource *addr, *data; - int irq; - void __iomem *addr_reg; - void __iomem *data_reg; - int retval; - u8 tmp; - - /* basic sanity checks first. board-specific init logic should - * have initialized these three resources and probably board - * specific platform_data. we don't probe for IRQs, and do only - * minimal sanity checking. - */ - pdev = container_of(dev, struct platform_device, dev); - if (pdev->num_resources < 3) - return -ENODEV; - - addr = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq = platform_get_irq(pdev, 0); - if (!addr || !data || irq < 0) - return -ENODEV; - - /* refuse to confuse usbcore */ - if (dev->dma_mask) { - DBG("no we won't dma\n"); - return -EINVAL; - } - - if (!request_mem_region(addr->start, 1, hcd_name)) { - retval = -EBUSY; - goto err1; - } -#ifdef CONFIG_USB_SL811_CS - addr_reg = (void *) addr->start; -#else - addr_reg = ioremap(addr->start, resource_len(addr)); -#endif - if (addr_reg == NULL) { - retval = -ENOMEM; - goto err2; - } - - if (!request_mem_region(data->start, 1, hcd_name)) { - retval = -EBUSY; - goto err3; - } - -#ifdef CONFIG_USB_SL811_CS - data_reg = (void *) data->start; -#else - data_reg = ioremap(data->start, resource_len(data)); -#endif - if (data_reg == NULL) { - retval = -ENOMEM; - goto err4; - } - - DBG("SL811_HCD: addr_reg: 0x%04x, data_reg: 0x%04x\n", - (int) addr_reg, (int) data_reg); - - /* allocate and initialize hcd */ - hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id); - if (!hcd) { - retval = -ENOMEM; - goto err5; - } - hcd->rsrc_start = addr->start; - - sl811 = hcd_to_sl811(hcd); - - spin_lock_init(&sl811->lock); - INIT_LIST_HEAD(&sl811->async); - sl811->board = dev->platform_data; - init_timer(&sl811->timer); - sl811->timer.function = sl811h_timer; - sl811->timer.data = (unsigned long) sl811; - sl811->addr_reg = addr_reg; - sl811->data_reg = data_reg; - - if (test_registers(sl811) == 0) { - DBG("ERROR: register test failed!\n"); - goto err5; - } - else DBG("sl811 register test passed.\n"); - - - spin_lock_irq(&sl811->lock); - port_power(sl811, 0); - spin_unlock_irq(&sl811->lock); - msleep(200); - - tmp = sl811_read(sl811, SL11H_HWREVREG); - switch (tmp >> 4) { - case 1: - hcd->product_desc = "SL811HS v1.2"; - break; - case 2: - hcd->product_desc = "SL811HS v1.5"; - break; - default: - /* reject case 0, SL11S is less functional */ - DBG("chiprev %02x\n", tmp); - retval = -ENXIO; - goto err6; - } - /* sl811s would need a different handler for this irq */ - -#if !defined(CONFIG_USB_SL811_CS) && defined(CONFIG_ARM) - /* Cypress docs say the IRQ is IRQT_HIGH ... */ - set_irq_type(irq, IRQT_RISING); - -#endif - retval = usb_add_hcd(hcd, irq, SA_INTERRUPT); - if (retval != 0) - goto err6; - - INFO("%s, irq %d\n", hcd->product_desc, irq); - - create_debug_file(sl811); - DBG("sl811_hcd initialized\n"); - return retval; - - err6: - usb_put_hcd(hcd); - err5: - -#ifndef CONFIG_USB_SL811_CS - iounmap(data_reg); -#endif - err4: - release_mem_region(data->start, 1); - err3: -#ifndef CONFIG_USB_SL811_CS - iounmap(addr_reg); -#endif - err2: - release_mem_region(addr->start, 1); - err1: - - DBG("init error, %d\n", retval); - return retval; -} -EXPORT_SYMBOL (sl811h_probe); - -#ifdef CONFIG_PM - -/* for this device there's no useful distinction between the controller - * and its root hub, except that the root hub only gets direct PM calls - * when CONFIG_USB_SUSPEND is enabled. - */ - -static int -sl811h_suspend(struct device *dev, pm_message_t state, u32 phase) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct sl811 *sl811 = hcd_to_sl811(hcd); - int retval = 0; - - if (phase != SUSPEND_POWER_DOWN) - return retval; - - if (state <= PM_SUSPEND_MEM) - retval = sl811h_hub_suspend(hcd); - else - port_power(sl811, 0); - if (retval == 0) - dev->power.power_state = state; - return retval; -} - -static int -sl811h_resume(struct device *dev, u32 phase) -{ - struct usb_hcd *hcd = dev_get_drvdata(dev); - struct sl811 *sl811 = hcd_to_sl811(hcd); - - if (phase != RESUME_POWER_ON) - return 0; - - /* with no "check to see if VBUS is still powered" board hook, - * let's assume it'd only be powered to enable remote wakeup. - */ - if (dev->power.power_state > PM_SUSPEND_MEM - || !hcd->can_wakeup) { - sl811->port1 = 0; - port_power(sl811, 1); - return 0; - } - - dev->power.power_state = PMSG_ON; - return sl811h_hub_resume(hcd); -} - -#else - -#define sl811h_suspend NULL -#define sl811h_resume NULL - -#endif - - -struct device_driver sl811h_driver = { - .name = (char *) hcd_name, - .bus = &platform_bus_type, - - .probe = sl811h_probe, - .remove = sl811h_remove, - - .suspend = sl811h_suspend, - .resume = sl811h_resume, -}; -EXPORT_SYMBOL(sl811h_driver); - -/*-------------------------------------------------------------------------*/ - -static int __init sl811h_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - INFO("driver %s, %s\n", hcd_name, DRIVER_VERSION); - return driver_register(&sl811h_driver); -} -module_init(sl811h_init); - -static void __exit sl811h_cleanup(void) -{ - driver_unregister(&sl811h_driver); -} -module_exit(sl811h_cleanup); |