[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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.