[patch 4/4] Gadget support for Cypress c67x00
Peter Korsgaard <[email protected]>
| Newsgroups | gmane.linux.usb.devel |
|---|---|
| Message-ID | <[email protected]> |
usb-c67x00-udc.patch
(text/plain, 10.4 KB)
Gadget driver for the Cypress c67x00. Work in progress.
Only posted to show how it will fit together with rest.
---
drivers/usb/c67x00/Kconfig | 2
drivers/usb/c67x00/Makefile | 1
drivers/usb/c67x00/c67x00-drv.c | 16 +++
drivers/usb/c67x00/c67x00-udc.c | 168 ++++++++++++++++++++++++++++++++++++++++
drivers/usb/c67x00/c67x00-udc.h | 59 ++++++++++++++
drivers/usb/gadget/Kconfig | 7 +
include/linux/usb/c67x00.h | 3
7 files changed, 256 insertions(+)
Index: linux/drivers/usb/c67x00/c67x00-udc.c
===================================================================
--- /dev/null
+++ linux/drivers/usb/c67x00/c67x00-udc.c
@@ -0,0 +1,168 @@
+/*
+ * c67x00-udc.c: Cypress C67X00 USB device controller
+ *
+ * Copyright (C) 2006-2007 Barco N.V.
+ * Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ * based on multiple device controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/usb.h>
+#include <linux/usb/c67x00.h>
+#include <linux/usb_gadget.h>
+
+#include "c67x00-drv.h"
+#include "c67x00-udc.h"
+#include "c67x00-ll-hpi.h"
+
+#define MAX_NB_PERIPHERALS 2
+
+struct c67x00_udc {
+ spinlock_t lock;
+ struct c67x00_sie *sie;
+ struct usb_gadget_driver *driver;
+};
+#define udc_dev(udc) (sie_dev((udc)->sie))
+
+/*
+ * the sie and gadget_driver get probed/registered from 2 totally independant
+ * places, this datastructure binds them together
+ */
+static struct c67x00_udc controller[MAX_NB_PERIPHERALS];
+
+/* -------------------------------------------------------------------------- */
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+ int i;
+ struct c67x00_udc *udc = NULL;
+
+ /* Find a free controller attached to an sie */
+ for (i = 0; !udc && (i < MAX_NB_PERIPHERALS); i++) {
+ udc = &controller[i];
+ spin_lock(&udc->lock);
+ if (!udc->sie || udc->driver) {
+ spin_unlock(&udc->lock);
+ udc = NULL;
+ }
+ }
+ if (!udc)
+ return -EBUSY;
+
+ udc->driver = driver;
+ /* TODO do something with driver->driver? */
+ dev_dbg(udc_dev(udc), "Binding %s\n", driver->function);
+
+ dev_warn(udc_dev(udc), "This is not implemented yet!\n");
+
+ /* TODO bind */
+ spin_unlock(&udc->lock);
+ return 0;
+}
+
+EXPORT_SYMBOL(usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+ int i;
+ struct c67x00_udc *udc = NULL;
+
+ for (i = 0; !udc && (i < MAX_NB_PERIPHERALS); i++) {
+ udc = &controller[i];
+ spin_lock(&udc->lock);
+ if (udc->driver != driver) {
+ spin_unlock(&udc->lock);
+ udc = NULL;
+ }
+ }
+ if (!udc)
+ return -EINVAL;
+
+ /* TODO unbind */
+ udc->driver = NULL;
+
+ spin_unlock(&udc->lock);
+ return 0;
+}
+
+EXPORT_SYMBOL(usb_gadget_unregister_driver);
+
+/* -------------------------------------------------------------------------- */
+
+int c67x00_udc_probe(struct c67x00_sie *sie)
+{
+ int i;
+ struct c67x00_udc *udc = NULL;
+
+ /* Find an unused controller */
+ for (i = 0; !udc && (i < MAX_NB_PERIPHERALS); i++) {
+ udc = &controller[i];
+ spin_lock(&udc->lock);
+ if (udc->sie) {
+ spin_unlock(&udc->lock);
+ udc = NULL;
+ }
+ }
+ if (!udc) {
+ dev_warn(sie_dev(sie), "Could not find unused controller\n");
+ return -EBUSY;
+ }
+
+ /* udc lock is held here */
+ sie->private_data = udc;
+ udc->sie = sie;
+
+ spin_unlock(&udc->lock);
+ return 0;
+}
+
+void c67x00_udc_remove(struct c67x00_sie *sie)
+{
+ struct c67x00_udc *udc = sie->private_data;
+ if (!udc) {
+ dev_err(sie_dev(sie), "No udc found!\n");
+ return;
+ }
+
+ spin_lock(&udc->lock);
+ /* TODO check if driver is register -> unbind? */
+ sie->private_data = NULL;
+ udc->sie = NULL;
+ spin_unlock(&udc->lock);
+}
+
+/* -------------------------------------------------------------------------- */
+/* Module initialization/cleanup */
+
+int c67x00_udc_init(void)
+{
+ int i;
+ struct c67x00_udc *udc;
+ for (i = 0; i < MAX_NB_PERIPHERALS; i++) {
+ udc = &controller[i];
+ spin_lock_init(&udc->lock);
+ udc->sie = NULL; /* Mark unused */
+ }
+ return 0;
+}
+
+void c67x00_udc_cleanup(void)
+{
+
+}
Index: linux/drivers/usb/c67x00/c67x00-udc.h
===================================================================
--- /dev/null
+++ linux/drivers/usb/c67x00/c67x00-udc.h
@@ -0,0 +1,59 @@
+/*
+ * c67x00-udc.h: Cypress C67X00 USB device controller
+ *
+ * Copyright (C) 2006-2007 Barco N.V.
+ * Derived from the Cypress cy7c67200/300 ezusb linux driver and
+ * based on multiple device controller drivers inside the linux kernel.
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA.
+ */
+
+#ifndef _USB_C67X00_UDC_H
+#define _USB_C67X00_UDC_H
+
+#include <linux/kernel.h>
+
+#ifdef CONFIG_USB_C67X00_PERIPHERAL
+/* Functions used by drv */
+int c67x00_udc_probe(struct c67x00_sie *sie);
+void c67x00_udc_remove(struct c67x00_sie *sie);
+
+int c67x00_udc_init(void);
+void c67x00_udc_cleanup(void);
+
+#else
+static inline int c67x00_udc_probe(struct c67x00_sie *sie)
+{
+ printk(KERN_ERR "udc requested but CONFIG_USB_C67X00_PERIPHERAL "
+ "not enabled!\n");
+ return -ENODEV;
+}
+
+static inline void c67x00_udc_remove(struct c67x00_sie *sie)
+{
+}
+
+static inline int c67x00_udc_init(void)
+{
+ return 0;
+}
+
+static inline void c67x00_udc_cleanup(void)
+{
+}
+#endif /* CONFIG_USB_C67X00_PERIPHERAL */
+
+#endif /* _USB_C67X00_UDC_H */
Index: linux/drivers/usb/gadget/Kconfig
===================================================================
--- linux.orig/drivers/usb/gadget/Kconfig
+++ linux/drivers/usb/gadget/Kconfig
@@ -205,6 +205,13 @@
depends on USB_GADGET_AT91
default USB_GADGET
+config USB_C67X00_PERIPHERAL
+ bool "Cypress C67X00 Gadget support"
+ depends on USB_C67X00_DRV
+ select USB_GADGET_SELECTED
+ help
+ This enables the gadget functionality of the Cypress C67X00.
+
config USB_GADGET_DUMMY_HCD
boolean "Dummy HCD (DEVELOPMENT)"
depends on (USB=y || (USB=m && USB_GADGET=m)) && EXPERIMENTAL
Index: linux/drivers/usb/c67x00/Kconfig
===================================================================
--- linux.orig/drivers/usb/c67x00/Kconfig
+++ linux/drivers/usb/c67x00/Kconfig
@@ -3,6 +3,8 @@
#
config USB_C67X00_DRV
tristate "Cypress C67x00 support"
+ # only allowed to be =y if both USB!=m and USB_GADGET!=m
+ depends (!USB && USB_GADGET) || (!USB_GADGET && USB) || (USB && USB_GADGET)
default n
help
The Cypress C67x00 (EZ-Host/EZ-OTG) chips are dual-role
Index: linux/drivers/usb/c67x00/c67x00-drv.c
===================================================================
--- linux.orig/drivers/usb/c67x00/c67x00-drv.c
+++ linux/drivers/usb/c67x00/c67x00-drv.c
@@ -44,6 +44,7 @@
#include "c67x00-drv.h"
#include "c67x00-ll-hpi.h"
#include "c67x00-hcd.h"
+#include "c67x00-udc.h"
static struct platform_driver c67x00_driver;
@@ -80,6 +81,10 @@
usb_hcd_c67x00_probe(sie);
break;
+ case C67X00_SIE_PERIPHERAL:
+ c67x00_udc_probe(sie);
+ break;
+
case C67X00_SIE_UNUSED:
dev_info(sie_dev(sie),
"Not using SIE %d as requested\n", sie->sie_num);
@@ -101,6 +106,10 @@
usb_hcd_c67x00_remove(sie);
break;
+ case C67X00_SIE_PERIPHERAL:
+ c67x00_udc_remove(sie);
+ break;
+
default:
break;
}
@@ -257,14 +266,21 @@
static int __init c67x00_init(void)
{
+ int ret;
+
if (usb_disabled())
return -ENODEV;
+ ret = c67x00_udc_init();
+ if (ret)
+ return ret;
+
return platform_driver_register(&c67x00_driver);
}
static void __exit c67x00_exit(void)
{
+ c67x00_udc_cleanup();
platform_driver_unregister(&c67x00_driver);
}
Index: linux/include/linux/usb/c67x00.h
===================================================================
--- linux.orig/include/linux/usb/c67x00.h
+++ linux/include/linux/usb/c67x00.h
@@ -25,14 +25,17 @@
/* SIE configuration */
#define C67X00_SIE_UNUSED 0
#define C67X00_SIE_HOST 1
+#define C67X00_SIE_PERIPHERAL 2
#define c67x00_sie_config(config, n) (((config)>>(4*(n)))&0x3)
#define C67X00_SIE1_UNUSED (C67X00_SIE_UNUSED << 0)
#define C67X00_SIE1_HOST (C67X00_SIE_HOST << 0)
+#define C67X00_SIE1_PERIPHERAL (C67X00_SIE_PERIPHERAL << 0)
#define C67X00_SIE2_UNUSED (C67X00_SIE_UNUSED << 4)
#define C67X00_SIE2_HOST (C67X00_SIE_HOST << 4)
+#define C67X00_SIE2_PERIPHERAL (C67X00_SIE_PERIPHERAL << 4)
struct c67x00_platform_data {
int sie_config; /* SIEs config (C67X00_SIEx_*) */
Index: linux/drivers/usb/c67x00/Makefile
===================================================================
--- linux.orig/drivers/usb/c67x00/Makefile
+++ linux/drivers/usb/c67x00/Makefile
@@ -12,3 +12,4 @@
c67x00-y += c67x00-ll-hpi.o
c67x00-$(CONFIG_USB_C67X00_HCD) += c67x00-hcd.o c67x00-sched.o
+c67x00-$(CONFIG_USB_C67X00_PERIPHERAL) += c67x00-udc.o
--
Bye, Peter Korsgaard
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel