diff mbox

[05/31] usb: usbssp: Added first part of initialization sequence.

Message ID 1531374448-26532-6-git-send-email-pawell@cadence.com (mailing list archive)
State New, archived
Headers show

Commit Message

Pawel Laszczak July 12, 2018, 5:47 a.m. UTC
Patch adds some initialization function. The initialization sequence
is quite complicated and this patch implements it only partially.
Initialization will be completed in next few patches.

Patch introduce three new files:
1. gadget-dbg.c - file contains functions used for debugging purpose.
2. gadget-ext-caps.h - holds macro definition related to
		       Extended Capabilities
3. gadget-if - file implements stuff related to upper layer
	(e.g usb_ep_ops, usb_gadget_ops interface).

Signed-off-by: Pawel Laszczak <pawell@cadence.com>
---
 drivers/usb/usbssp/Makefile          |   3 +-
 drivers/usb/usbssp/gadget-dbg.c      |  30 ++++
 drivers/usb/usbssp/gadget-ext-caps.h |  53 ++++++
 drivers/usb/usbssp/gadget-if.c       |  24 +++
 drivers/usb/usbssp/gadget.c          | 248 +++++++++++++++++++++++++++
 drivers/usb/usbssp/gadget.h          |  14 ++
 6 files changed, 371 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/usbssp/gadget-dbg.c
 create mode 100644 drivers/usb/usbssp/gadget-ext-caps.h
 create mode 100644 drivers/usb/usbssp/gadget-if.c

Comments

Greg KH July 12, 2018, 6:27 a.m. UTC | #1
On Thu, Jul 12, 2018 at 06:47:02AM +0100, Pawel Laszczak wrote:
> +/* USB 2.0 hardware LMP capability*/
> +#define USBSSP_HLC			(1 << 19)
> +#define USBSSP_BLC			(1 << 20)

Again, BIT() please.

> +int usbssp_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
> +{
> +	u32	result;

Some places you use tabs for the variable declarations, and some you do
not.  Pick a single style and stick to it please.

> +
> +	do {
> +		result = readl(ptr);
> +		if (result == ~(u32)0)	/* card removed */
> +			return -ENODEV;
> +		result &= mask;
> +		if (result == done)
> +			return 0;
> +		udelay(1);
> +		usec--;
> +	} while (usec > 0);
> +	return -ETIMEDOUT;

We don't have a built-in kernel function to do this type of thing
already?  That's sad.  Oh well...

> +int usbssp_init(struct usbssp_udc *usbssp_data)
> +{
> +	int retval = 0;
> +
> +	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init, "usbssp_init");
> +
> +	spin_lock_init(&usbssp_data->lock);
> +	spin_lock_init(&usbssp_data->irq_thread_lock);
> +
> +	//TODO: memory initialization
> +	//retval = usbssp_mem_init(usbssp_data, GFP_KERNEL);
> +
> +	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init,
> +			"Finished usbssp_init");

When your trace functions do nothing but say "entered a function", and
"exited a function", why even have them?  ftrace can provide that for
you already, no need to overload that on the tracing framework, right?

> +/*
> + * gadget-if.c file is part of gadget.c file and implements interface
> + * for gadget driver
> + */
> +#include "gadget-if.c"

Ugh, I know USB hcd drivers love to include .c files in the middle of
them, but do we have to continue that crazy practice in newer drivers?
Is it really necessary?

> +	/*
> +	 * Check the compiler generated sizes of structures that must be laid
> +	 * out in specific ways for hardware access.
> +	 */
> +	BUILD_BUG_ON(sizeof(struct usbssp_doorbell_array) != 2*32/8);
> +	BUILD_BUG_ON(sizeof(struct usbssp_slot_ctx) != 8*32/8);
> +	BUILD_BUG_ON(sizeof(struct usbssp_ep_ctx) != 8*32/8);
> +	/* usbssp_device has eight fields, and also
> +	 * embeds one usbssp_slot_ctx and 31 usbssp_ep_ctx
> +	 */
> +	BUILD_BUG_ON(sizeof(struct usbssp_stream_ctx) != 4*32/8);
> +	BUILD_BUG_ON(sizeof(union usbssp_trb) != 4*32/8);
> +	BUILD_BUG_ON(sizeof(struct usbssp_erst_entry) != 4*32/8);
> +	BUILD_BUG_ON(sizeof(struct usbssp_cap_regs) != 8*32/8);
> +	BUILD_BUG_ON(sizeof(struct usbssp_intr_reg) != 8*32/8);
> +	/* usbssp_run_regs has eight fields and embeds 128 usbssp_intr_regs */
> +	BUILD_BUG_ON(sizeof(struct usbssp_run_regs) != (8+8*128)*32/8);

I love hard-coded numbers as much as the next person, but really?  Is
this necessary now that you have the code up and working properly?


I've stopped reviewing this series here.

thanks,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pawel Laszczak July 12, 2018, 9:03 a.m. UTC | #2
PiA+ICsvKiBVU0IgMi4wIGhhcmR3YXJlIExNUCBjYXBhYmlsaXR5Ki8NCj4gPiArI2RlZmluZSBV
U0JTU1BfSExDCQkJKDEgPDwgMTkpDQo+ID4gKyNkZWZpbmUgVVNCU1NQX0JMQwkJCSgxIDw8IDIw
KQ0KPiANCj4gQWdhaW4sIEJJVCgpIHBsZWFzZS4NCj4gDQo+ID4gK2ludCB1c2Jzc3BfaGFuZHNo
YWtlKHZvaWQgX19pb21lbSAqcHRyLCB1MzIgbWFzaywgdTMyIGRvbmUsIGludCB1c2VjKQ0KPiA+
ICt7DQo+ID4gKwl1MzIJcmVzdWx0Ow0KPiANCj4gU29tZSBwbGFjZXMgeW91IHVzZSB0YWJzIGZv
ciB0aGUgdmFyaWFibGUgZGVjbGFyYXRpb25zLCBhbmQgc29tZSB5b3UgZG8NCj4gbm90LiAgUGlj
ayBhIHNpbmdsZSBzdHlsZSBhbmQgc3RpY2sgdG8gaXQgcGxlYXNlLg0KPiANCj4gPiArDQo+ID4g
KwlkbyB7DQo+ID4gKwkJcmVzdWx0ID0gcmVhZGwocHRyKTsNCj4gPiArCQlpZiAocmVzdWx0ID09
IH4odTMyKTApCS8qIGNhcmQgcmVtb3ZlZCAqLw0KPiA+ICsJCQlyZXR1cm4gLUVOT0RFVjsNCj4g
PiArCQlyZXN1bHQgJj0gbWFzazsNCj4gPiArCQlpZiAocmVzdWx0ID09IGRvbmUpDQo+ID4gKwkJ
CXJldHVybiAwOw0KPiA+ICsJCXVkZWxheSgxKTsNCj4gPiArCQl1c2VjLS07DQo+ID4gKwl9IHdo
aWxlICh1c2VjID4gMCk7DQo+ID4gKwlyZXR1cm4gLUVUSU1FRE9VVDsNCj4gDQo+IFdlIGRvbid0
IGhhdmUgYSBidWlsdC1pbiBrZXJuZWwgZnVuY3Rpb24gdG8gZG8gdGhpcyB0eXBlIG9mIHRoaW5n
IGFscmVhZHk/DQo+IFRoYXQncyBzYWQuICBPaCB3ZWxsLi4uDQo+IA0KPiA+ICtpbnQgdXNic3Nw
X2luaXQoc3RydWN0IHVzYnNzcF91ZGMgKnVzYnNzcF9kYXRhKSB7DQo+ID4gKwlpbnQgcmV0dmFs
ID0gMDsNCj4gPiArDQo+ID4gKwl1c2Jzc3BfZGJnX3RyYWNlKHVzYnNzcF9kYXRhLCB0cmFjZV91
c2Jzc3BfZGJnX2luaXQsDQo+ICJ1c2Jzc3BfaW5pdCIpOw0KPiA+ICsNCj4gPiArCXNwaW5fbG9j
a19pbml0KCZ1c2Jzc3BfZGF0YS0+bG9jayk7DQo+ID4gKwlzcGluX2xvY2tfaW5pdCgmdXNic3Nw
X2RhdGEtPmlycV90aHJlYWRfbG9jayk7DQo+ID4gKw0KPiA+ICsJLy9UT0RPOiBtZW1vcnkgaW5p
dGlhbGl6YXRpb24NCj4gPiArCS8vcmV0dmFsID0gdXNic3NwX21lbV9pbml0KHVzYnNzcF9kYXRh
LCBHRlBfS0VSTkVMKTsNCj4gPiArDQo+ID4gKwl1c2Jzc3BfZGJnX3RyYWNlKHVzYnNzcF9kYXRh
LCB0cmFjZV91c2Jzc3BfZGJnX2luaXQsDQo+ID4gKwkJCSJGaW5pc2hlZCB1c2Jzc3BfaW5pdCIp
Ow0KPiANCj4gV2hlbiB5b3VyIHRyYWNlIGZ1bmN0aW9ucyBkbyBub3RoaW5nIGJ1dCBzYXkgImVu
dGVyZWQgYSBmdW5jdGlvbiIsIGFuZA0KPiAiZXhpdGVkIGEgZnVuY3Rpb24iLCB3aHkgZXZlbiBo
YXZlIHRoZW0/ICBmdHJhY2UgY2FuIHByb3ZpZGUgdGhhdCBmb3IgeW91DQo+IGFscmVhZHksIG5v
IG5lZWQgdG8gb3ZlcmxvYWQgdGhhdCBvbiB0aGUgdHJhY2luZyBmcmFtZXdvcmssIHJpZ2h0Pw0K
DQpEbyB5b3Ugc3VnZ2VzdCB0byB1c2Ugb25seTogDQoJdHJhY2VfdXNic3NwX2RiZ19pbml0KCJG
aW5pc2hlZCB1c2Jzc3BfaW5pdCIpOyANCmluc3RlYWQ6IA0KCXVzYnNzcF9kYmcodXNic3NwX2Rh
dGEsICIlcFZcbiIsICJGaW5pc2hlZCB1c2Jzc3BfaW5pdCIpOw0KCXRyYWNlX3VzYnNzcF9kYmdf
aW5pdCgiRmluaXNoZWQgdXNic3NwX2luaXQiKTsNCj8NCg0KSSdtIHNpbXBsZSByZS11c2VkIHRo
ZSBjb2RlIGZyb20gWEhDSSBkcml2ZXIuIEl0J3MgcmVhbGx5IHJlZHVuZGFudCwgDQpidXQgSSBk
b24ndCBrbm93IHRoZSBpbnRlbnRpb24gb2YgYXV0aG9yIPCfmIouICANCiANCj4gPiArLyoNCj4g
PiArICogZ2FkZ2V0LWlmLmMgZmlsZSBpcyBwYXJ0IG9mIGdhZGdldC5jIGZpbGUgYW5kIGltcGxl
bWVudHMgaW50ZXJmYWNlDQo+ID4gKyAqIGZvciBnYWRnZXQgZHJpdmVyDQo+ID4gKyAqLw0KPiA+
ICsjaW5jbHVkZSAiZ2FkZ2V0LWlmLmMiDQo+IA0KPiBVZ2gsIEkga25vdyBVU0IgaGNkIGRyaXZl
cnMgbG92ZSB0byBpbmNsdWRlIC5jIGZpbGVzIGluIHRoZSBtaWRkbGUgb2YgdGhlbSwgYnV0DQo+
IGRvIHdlIGhhdmUgdG8gY29udGludWUgdGhhdCBjcmF6eSBwcmFjdGljZSBpbiBuZXdlciBkcml2
ZXJzPw0KPiBJcyBpdCByZWFsbHkgbmVjZXNzYXJ5Pw0KDQpJdCdzIG5vdCBuZWNlc3NhcnkgSSB3
YW50ZWQgdG8gbGVhdmUgdGhpcyBhcyB0d28gc2VwYXJhdGUgZmlsZSwgYmVjYXVzZSBnYWRnZXQu
YyANCklzIGJhc2VkIG9uIHhoY2kuYyBhbmQgZ2FkZ2V0LWlmLmMgZGVmaW5lIGludGVyZmFjZSBi
ZXR3ZWVuIGdhZGdldC5jIGFuZCANClVTQiBnYWRnZXQgY29yZSBkcml2ZXIuIEkgZGlkbid0IHdh
bnQgdG8gY29tYmluZSB0aGVzZSB0d28gZmlsZXMuIA0KDQpJIHdpbGwgYWRkIHNvbWUgYWRkaXRp
b25hbCBmdW5jdGlvbiBkZWNsYXJhdGlvbiB0byBnYWRnZXQuaCBhbmQgcmVtb3ZlIGl0IA0KZnJv
bSBnYWRnZXQuYyBmaWxlLiANCg0KIA0KPiA+ICsJLyoNCj4gPiArCSAqIENoZWNrIHRoZSBjb21w
aWxlciBnZW5lcmF0ZWQgc2l6ZXMgb2Ygc3RydWN0dXJlcyB0aGF0IG11c3QgYmUgbGFpZA0KPiA+
ICsJICogb3V0IGluIHNwZWNpZmljIHdheXMgZm9yIGhhcmR3YXJlIGFjY2Vzcy4NCj4gPiArCSAq
Lw0KPiA+ICsJQlVJTERfQlVHX09OKHNpemVvZihzdHJ1Y3QgdXNic3NwX2Rvb3JiZWxsX2FycmF5
KSAhPSAyKjMyLzgpOw0KPiA+ICsJQlVJTERfQlVHX09OKHNpemVvZihzdHJ1Y3QgdXNic3NwX3Ns
b3RfY3R4KSAhPSA4KjMyLzgpOw0KPiA+ICsJQlVJTERfQlVHX09OKHNpemVvZihzdHJ1Y3QgdXNi
c3NwX2VwX2N0eCkgIT0gOCozMi84KTsNCj4gPiArCS8qIHVzYnNzcF9kZXZpY2UgaGFzIGVpZ2h0
IGZpZWxkcywgYW5kIGFsc28NCj4gPiArCSAqIGVtYmVkcyBvbmUgdXNic3NwX3Nsb3RfY3R4IGFu
ZCAzMSB1c2Jzc3BfZXBfY3R4DQo+ID4gKwkgKi8NCj4gPiArCUJVSUxEX0JVR19PTihzaXplb2Yo
c3RydWN0IHVzYnNzcF9zdHJlYW1fY3R4KSAhPSA0KjMyLzgpOw0KPiA+ICsJQlVJTERfQlVHX09O
KHNpemVvZih1bmlvbiB1c2Jzc3BfdHJiKSAhPSA0KjMyLzgpOw0KPiA+ICsJQlVJTERfQlVHX09O
KHNpemVvZihzdHJ1Y3QgdXNic3NwX2Vyc3RfZW50cnkpICE9IDQqMzIvOCk7DQo+ID4gKwlCVUlM
RF9CVUdfT04oc2l6ZW9mKHN0cnVjdCB1c2Jzc3BfY2FwX3JlZ3MpICE9IDgqMzIvOCk7DQo+ID4g
KwlCVUlMRF9CVUdfT04oc2l6ZW9mKHN0cnVjdCB1c2Jzc3BfaW50cl9yZWcpICE9IDgqMzIvOCk7
DQo+ID4gKwkvKiB1c2Jzc3BfcnVuX3JlZ3MgaGFzIGVpZ2h0IGZpZWxkcyBhbmQgZW1iZWRzIDEy
OA0KPiB1c2Jzc3BfaW50cl9yZWdzICovDQo+ID4gKwlCVUlMRF9CVUdfT04oc2l6ZW9mKHN0cnVj
dCB1c2Jzc3BfcnVuX3JlZ3MpICE9ICg4KzgqMTI4KSozMi84KTsNCj4gDQo+IEkgbG92ZSBoYXJk
LWNvZGVkIG51bWJlcnMgYXMgbXVjaCBhcyB0aGUgbmV4dCBwZXJzb24sIGJ1dCByZWFsbHk/ICBJ
cyB0aGlzDQo+IG5lY2Vzc2FyeSBub3cgdGhhdCB5b3UgaGF2ZSB0aGUgY29kZSB1cCBhbmQgd29y
a2luZyBwcm9wZXJseT8NCg0KQ29kZSBpcyBzdGlsbCBiZWluZyBkZXZlbG9wZWQsICBhbmQgaXMg
c3RpbGwgdGVzdGVkLiBJdCdzIGJldHRlciB0byBsZWF2ZSB0aGlzIGNvZGUgYXQgDQp0aGlzIG1v
bWVudC4gIEkgd2lsbCByZW1vdmUgaXQgaW4gdGhlIGZlYXR1cmUuIA0KDQp0aGFua3MsDQpQYXdl
bCBMYXN6Y3phaw0K
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Greg KH July 12, 2018, 9:09 a.m. UTC | #3
On Thu, Jul 12, 2018 at 09:03:30AM +0000, Pawel Laszczak wrote:
> > > +/* USB 2.0 hardware LMP capability*/
> > > +#define USBSSP_HLC			(1 << 19)
> > > +#define USBSSP_BLC			(1 << 20)
> > 
> > Again, BIT() please.
> > 
> > > +int usbssp_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
> > > +{
> > > +	u32	result;
> > 
> > Some places you use tabs for the variable declarations, and some you do
> > not.  Pick a single style and stick to it please.
> > 
> > > +
> > > +	do {
> > > +		result = readl(ptr);
> > > +		if (result == ~(u32)0)	/* card removed */
> > > +			return -ENODEV;
> > > +		result &= mask;
> > > +		if (result == done)
> > > +			return 0;
> > > +		udelay(1);
> > > +		usec--;
> > > +	} while (usec > 0);
> > > +	return -ETIMEDOUT;
> > 
> > We don't have a built-in kernel function to do this type of thing already?
> > That's sad.  Oh well...
> > 
> > > +int usbssp_init(struct usbssp_udc *usbssp_data) {
> > > +	int retval = 0;
> > > +
> > > +	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init,
> > "usbssp_init");
> > > +
> > > +	spin_lock_init(&usbssp_data->lock);
> > > +	spin_lock_init(&usbssp_data->irq_thread_lock);
> > > +
> > > +	//TODO: memory initialization
> > > +	//retval = usbssp_mem_init(usbssp_data, GFP_KERNEL);
> > > +
> > > +	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init,
> > > +			"Finished usbssp_init");
> > 
> > When your trace functions do nothing but say "entered a function", and
> > "exited a function", why even have them?  ftrace can provide that for you
> > already, no need to overload that on the tracing framework, right?
> 
> Do you suggest to use only: 
> 	trace_usbssp_dbg_init("Finished usbssp_init"); 
> instead: 
> 	usbssp_dbg(usbssp_data, "%pV\n", "Finished usbssp_init");
> 	trace_usbssp_dbg_init("Finished usbssp_init");
> ?
> 
> I'm simple re-used the code from XHCI driver. It's really redundant, 
> but I don't know the intention of author 
Pawel Laszczak July 12, 2018, 9:47 a.m. UTC | #4
> > > > +/* USB 2.0 hardware LMP capability*/

> > > > +#define USBSSP_HLC			(1 << 19)

> > > > +#define USBSSP_BLC			(1 << 20)

> > >

> > > Again, BIT() please.

> > >

> > > > +int usbssp_handshake(void __iomem *ptr, u32 mask, u32 done, int

> > > > +usec) {

> > > > +	u32	result;

> > >

> > > Some places you use tabs for the variable declarations, and some you

> > > do not.  Pick a single style and stick to it please.

> > >

> > > > +

> > > > +	do {

> > > > +		result = readl(ptr);

> > > > +		if (result == ~(u32)0)	/* card removed */

> > > > +			return -ENODEV;

> > > > +		result &= mask;

> > > > +		if (result == done)

> > > > +			return 0;

> > > > +		udelay(1);

> > > > +		usec--;

> > > > +	} while (usec > 0);

> > > > +	return -ETIMEDOUT;

> > >

> > > We don't have a built-in kernel function to do this type of thing already?

> > > That's sad.  Oh well...

> > >

> > > > +int usbssp_init(struct usbssp_udc *usbssp_data) {

> > > > +	int retval = 0;

> > > > +

> > > > +	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init,

> > > "usbssp_init");

> > > > +

> > > > +	spin_lock_init(&usbssp_data->lock);

> > > > +	spin_lock_init(&usbssp_data->irq_thread_lock);

> > > > +

> > > > +	//TODO: memory initialization

> > > > +	//retval = usbssp_mem_init(usbssp_data, GFP_KERNEL);

> > > > +

> > > > +	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init,

> > > > +			"Finished usbssp_init");

> > >

> > > When your trace functions do nothing but say "entered a function",

> > > and "exited a function", why even have them?  ftrace can provide

> > > that for you already, no need to overload that on the tracing framework,

> right?

> >

> > Do you suggest to use only:

> > 	trace_usbssp_dbg_init("Finished usbssp_init");

> > instead:

> > 	usbssp_dbg(usbssp_data, "%pV\n", "Finished usbssp_init");

> > 	trace_usbssp_dbg_init("Finished usbssp_init"); ?

> >

> > I'm simple re-used the code from XHCI driver. It's really redundant,

> > but I don't know the intention of author 
diff mbox

Patch

diff --git a/drivers/usb/usbssp/Makefile b/drivers/usb/usbssp/Makefile
index 1b6261068fd9..ccc7c5646a6b 100644
--- a/drivers/usb/usbssp/Makefile
+++ b/drivers/usb/usbssp/Makefile
@@ -4,7 +4,8 @@  CFLAGS_gadget-trace.o := -I$(src)
 
 obj-$(CONFIG_USB_USBSSP_GADGET) += usbssp.o
 usbssp-y 			:=  usbssp-plat.o gadget-ring.o \
-				    gadget.o
+				    gadget.o \
+				    gadget-dbg.o
 
 ifneq ($(CONFIG_TRACING),)
 	usbssp-y		+= gadget-trace.o
diff --git a/drivers/usb/usbssp/gadget-dbg.c b/drivers/usb/usbssp/gadget-dbg.c
new file mode 100644
index 000000000000..88e4e8d38e4b
--- /dev/null
+++ b/drivers/usb/usbssp/gadget-dbg.c
@@ -0,0 +1,30 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USBSSP device controller driver
+ *
+ * Copyright (C) 2018 Cadence.
+ *
+ * Author: Pawel Laszczak
+ *
+ * A lot of code based on Linux XHCI driver.
+ * Origin: Copyright (C) 2008 Intel Corp
+ */
+
+#include "gadget.h"
+
+void usbssp_dbg_trace(struct usbssp_udc *usbssp_data,
+		      void (*trace)(struct va_format *),
+		      const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.fmt = fmt;
+	vaf.va = &args;
+	usbssp_dbg(usbssp_data, "%pV\n", &vaf);
+	trace(&vaf);
+	va_end(args);
+}
+EXPORT_SYMBOL_GPL(usbssp_dbg_trace);
+
diff --git a/drivers/usb/usbssp/gadget-ext-caps.h b/drivers/usb/usbssp/gadget-ext-caps.h
new file mode 100644
index 000000000000..0107bc18ad7d
--- /dev/null
+++ b/drivers/usb/usbssp/gadget-ext-caps.h
@@ -0,0 +1,53 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USBSSP device controller driver
+ *
+ * Copyright (C) 2018 Cadence.
+ *
+ * Author: Pawel Laszczak
+ *
+ * A lot of code based on Linux XHCI driver.
+ * Origin: Copyright (C) 2008 Intel Corp
+ */
+
+/* Up to 16 ms to halt an DC */
+#define USBSSP_MAX_HALT_USEC		(16*1000)
+
+/* DC not running - set to 1 when run/stop bit is cleared. */
+#define USBSSP_STS_HALT			(1<<0)
+
+/* HCCPARAMS offset from PCI base address */
+#define USBSSP_HCC_PARAMS_OFFSET	0x10
+/* HCCPARAMS contains the first extended capability pointer */
+#define USBSSP_HCC_EXT_CAPS(p)	(((p)>>16)&0xffff)
+
+/* Command and Status registers offset from the Operational Registers address */
+#define USBSSP_CMD_OFFSET		0x00
+#define USBSSP_STS_OFFSET		0x04
+
+/* Capability Register */
+/* bits 7:0 - how long is the Capabilities register */
+#define USBSSP_HC_LENGTH(p)		(((p)>>00)&0x00ff)
+
+/* Extended capability register fields */
+#define USBSSP_EXT_CAPS_ID(p)		(((p)>>0)&0xff)
+#define USBSSP_EXT_CAPS_NEXT(p)		(((p)>>8)&0xff)
+#define	v_EXT_CAPS_VAL(p)		((p)>>16)
+/* Extended capability IDs - ID 0 reserved */
+#define USBSSP_EXT_CAPS_PROTOCOL		2
+
+/* USB 2.0 hardware LMP capability*/
+#define USBSSP_HLC			(1 << 19)
+#define USBSSP_BLC			(1 << 20)
+
+/* command register values to disable interrupts and halt the DC */
+/* start/stop DC execution - do not write unless DC is halted*/
+#define USBSSP_CMD_RUN			(1 << 0)
+/* Event Interrupt Enable - get irq when EINT bit is set in USBSTS register */
+#define USBSSP_CMD_EIE			(1 << 2)
+/* Host System Error Interrupt Enable - get irq when HSEIE bit set in USBSTS */
+#define USBSSP_CMD_HSEIE		(1 << 3)
+/* Enable Wrap Event - '1' means DC generates an event when MFINDEX wraps. */
+#define USBSSP_CMD_EWE			(1 << 10)
+
+#define USBSSP_IRQS	(USBSSP_CMD_EIE | USBSSP_CMD_HSEIE | USBSSP_CMD_EWE)
diff --git a/drivers/usb/usbssp/gadget-if.c b/drivers/usb/usbssp/gadget-if.c
new file mode 100644
index 000000000000..d53e0fb65299
--- /dev/null
+++ b/drivers/usb/usbssp/gadget-if.c
@@ -0,0 +1,24 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * USBSSP device controller driver
+ *
+ * Copyright (C) 2018 Cadence.
+ *
+ * Author: Pawel Laszczak
+ *
+ */
+
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+#include "gadget.h"
+
+int usbssp_gadget_init_endpoint(struct usbssp_udc *usbssp_data)
+{
+	/*TODO: it has to be implemented*/
+	return 0;
+}
+
+void usbssp_gadget_free_endpoint(struct usbssp_udc *usbssp_data)
+{
+	/*TODO: it has to be implemented*/
+}
diff --git a/drivers/usb/usbssp/gadget.c b/drivers/usb/usbssp/gadget.c
index 2f60d7dd1fe4..75272dd2447a 100644
--- a/drivers/usb/usbssp/gadget.c
+++ b/drivers/usb/usbssp/gadget.c
@@ -23,6 +23,111 @@ 
 #include "gadget-trace.h"
 #include "gadget.h"
 
+
+/*
+ * usbssp_handshake - spin reading dc until handshake completes or fails
+ * @ptr: address of dc register to be read
+ * @mask: bits to look at in result of read
+ * @done: value of those bits when handshake succeeds
+ * @usec: timeout in microseconds
+ *
+ * Returns negative errno, or zero on success
+ *
+ * Success happens when the "mask" bits have the specified value (hardware
+ * handshake done). There are two failure modes: "usec" have passed (major
+ * hardware flakeout), or the register reads as all-ones (hardware removed).
+ */
+int usbssp_handshake(void __iomem *ptr, u32 mask, u32 done, int usec)
+{
+	u32	result;
+
+	do {
+		result = readl(ptr);
+		if (result == ~(u32)0)	/* card removed */
+			return -ENODEV;
+		result &= mask;
+		if (result == done)
+			return 0;
+		udelay(1);
+		usec--;
+	} while (usec > 0);
+	return -ETIMEDOUT;
+}
+
+/*
+ * Disable interrupts and begin the DC halting process.
+ */
+void usbssp_quiesce(struct usbssp_udc *usbssp_data)
+{
+	u32 halted;
+	u32 cmd;
+	u32 mask;
+
+	mask = ~(USBSSP_IRQS);
+
+	halted = readl(&usbssp_data->op_regs->status) & STS_HALT;
+	if (!halted)
+		mask &= ~CMD_RUN;
+
+	cmd = readl(&usbssp_data->op_regs->command);
+	cmd &= mask;
+	writel(cmd, &usbssp_data->op_regs->command);
+}
+
+/*
+ * Force DC into halt state.
+ *
+ * Disable any IRQs and clear the run/stop bit.
+ * USBSSP will complete any current and actively pipelined transactions, and
+ * should halt within 16 ms of the run/stop bit being cleared.
+ * Read DC Halted bit in the status register to see when the DC is finished.
+ */
+int usbssp_halt(struct usbssp_udc *usbssp_data)
+{
+	int ret;
+
+	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init,
+			 "// Halt the USBSSP");
+	usbssp_quiesce(usbssp_data);
+
+	ret = usbssp_handshake(&usbssp_data->op_regs->status,
+		STS_HALT, STS_HALT, USBSSP_MAX_HALT_USEC);
+
+	if (!ret) {
+		usbssp_warn(usbssp_data, "Device halt failed, %d\n", ret);
+		return ret;
+	}
+
+	usbssp_data->usbssp_state |= USBSSP_STATE_HALTED;
+	usbssp_data->cmd_ring_state = CMD_RING_STATE_STOPPED;
+	return ret;
+}
+
+
+/*
+ * Initialize memory for gadget driver and USBSSP (one-time init).
+ *
+ * Program the PAGESIZE register, initialize the device context array, create
+ * device contexts, set up a command ring segment (or two?), create event
+ * ring (one for now).
+ */
+int usbssp_init(struct usbssp_udc *usbssp_data)
+{
+	int retval = 0;
+
+	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init, "usbssp_init");
+
+	spin_lock_init(&usbssp_data->lock);
+	spin_lock_init(&usbssp_data->irq_thread_lock);
+
+	//TODO: memory initialization
+	//retval = usbssp_mem_init(usbssp_data, GFP_KERNEL);
+
+	usbssp_dbg_trace(usbssp_data, trace_usbssp_dbg_init,
+			"Finished usbssp_init");
+	return retval;
+}
+
 #ifdef CONFIG_PM
 /*
  * Stop DC (not bus-specific)
@@ -50,9 +155,148 @@  int usbssp_resume(struct usbssp_udc *usbssp_data, bool hibernated)
 
 #endif	/* CONFIG_PM */
 
+int usbssp_gen_setup(struct usbssp_udc *usbssp_data)
+{
+	int	retval;
+
+	mutex_init(&usbssp_data->mutex);
+
+	usbssp_data->cap_regs = usbssp_data->regs;
+	usbssp_data->op_regs = usbssp_data->regs +
+		HC_LENGTH(readl(&usbssp_data->cap_regs->hc_capbase));
+
+	usbssp_data->run_regs = usbssp_data->regs +
+		(readl(&usbssp_data->cap_regs->run_regs_off) & RTSOFF_MASK);
+	/* Cache read-only capability registers */
+	usbssp_data->hcs_params1 = readl(&usbssp_data->cap_regs->hcs_params1);
+	usbssp_data->hcs_params2 = readl(&usbssp_data->cap_regs->hcs_params2);
+	usbssp_data->hcs_params3 = readl(&usbssp_data->cap_regs->hcs_params3);
+	usbssp_data->hcc_params = readl(&usbssp_data->cap_regs->hc_capbase);
+	usbssp_data->hci_version = HC_VERSION(usbssp_data->hcc_params);
+	usbssp_data->hcc_params = readl(&usbssp_data->cap_regs->hcc_params);
+	usbssp_data->hcc_params2 = readl(&usbssp_data->cap_regs->hcc_params2);
+
+	/* Make sure the Device Controller is halted. */
+	retval = usbssp_halt(usbssp_data);
+	if (retval)
+		return retval;
+
+	usbssp_dbg(usbssp_data, "Resetting Device Controller\n");
+	/* Reset the internal DC memory state and registers. */
+	/*TODO: add implementation of usbssp_reset function*/
+	//retval = usbssp_reset(usbssp_data);
+	if (retval)
+		return retval;
+	usbssp_dbg(usbssp_data, "Reset complete\n");
+
+	/* Set dma_mask and coherent_dma_mask to 64-bits,
+	 * if USBSSP supports 64-bit addressing
+	 */
+	if (HCC_64BIT_ADDR(usbssp_data->hcc_params) &&
+	    !dma_set_mask(usbssp_data->dev, DMA_BIT_MASK(64))) {
+		usbssp_dbg(usbssp_data, "Enabling 64-bit DMA addresses.\n");
+		dma_set_coherent_mask(usbssp_data->dev, DMA_BIT_MASK(64));
+	} else {
+		/*
+		 * This is to avoid error in cases where a 32-bit USB
+		 * controller is used on a 64-bit capable system.
+		 */
+		retval = dma_set_mask(usbssp_data->dev, DMA_BIT_MASK(32));
+		if (retval)
+			return retval;
+		usbssp_dbg(usbssp_data, "Enabling 32-bit DMA addresses.\n");
+		dma_set_coherent_mask(usbssp_data->dev, DMA_BIT_MASK(32));
+	}
+
+	usbssp_dbg(usbssp_data, "Calling USBSSP init\n");
+	/* Initialize USBSSP controller data structures. */
+	retval = usbssp_init(usbssp_data);
+	if (retval)
+		return retval;
+	usbssp_dbg(usbssp_data, "Called USBSSPinit\n");
+
+	usbssp_info(usbssp_data, "USBSSP params 0x%08x USBSSP version 0x%x\n",
+		usbssp_data->hcc_params, usbssp_data->hci_version);
+
+	return 0;
+}
+
+/*
+ * gadget-if.c file is part of gadget.c file and implements interface
+ * for gadget driver
+ */
+#include "gadget-if.c"
+
 int usbssp_gadget_init(struct usbssp_udc *usbssp_data)
 {
 	int ret;
+
+	/*
+	 * Check the compiler generated sizes of structures that must be laid
+	 * out in specific ways for hardware access.
+	 */
+	BUILD_BUG_ON(sizeof(struct usbssp_doorbell_array) != 2*32/8);
+	BUILD_BUG_ON(sizeof(struct usbssp_slot_ctx) != 8*32/8);
+	BUILD_BUG_ON(sizeof(struct usbssp_ep_ctx) != 8*32/8);
+	/* usbssp_device has eight fields, and also
+	 * embeds one usbssp_slot_ctx and 31 usbssp_ep_ctx
+	 */
+	BUILD_BUG_ON(sizeof(struct usbssp_stream_ctx) != 4*32/8);
+	BUILD_BUG_ON(sizeof(union usbssp_trb) != 4*32/8);
+	BUILD_BUG_ON(sizeof(struct usbssp_erst_entry) != 4*32/8);
+	BUILD_BUG_ON(sizeof(struct usbssp_cap_regs) != 8*32/8);
+	BUILD_BUG_ON(sizeof(struct usbssp_intr_reg) != 8*32/8);
+	/* usbssp_run_regs has eight fields and embeds 128 usbssp_intr_regs */
+	BUILD_BUG_ON(sizeof(struct usbssp_run_regs) != (8+8*128)*32/8);
+
+	/* fill gadget fields */
+	/*TODO: implements usbssp_gadget_ops object*/
+	//usbssp_data->gadget.ops = &usbssp_gadget_ops;
+	usbssp_data->gadget.name = "usbssp-gadget";
+	usbssp_data->gadget.max_speed = USB_SPEED_SUPER_PLUS;
+	usbssp_data->gadget.speed = USB_SPEED_UNKNOWN;
+	usbssp_data->gadget.sg_supported = true;
+	usbssp_data->gadget.lpm_capable = 1;
+
+	usbssp_data->setup_buf = kzalloc(USBSSP_EP0_SETUP_SIZE, GFP_KERNEL);
+	if (!usbssp_data->setup_buf)
+		return -ENOMEM;
+
+	/*USBSSP support not aligned buffer but this option
+	 * improve performance of this controller.
+	 */
+	usbssp_data->gadget.quirk_ep_out_aligned_size = true;
+	ret = usbssp_gen_setup(usbssp_data);
+	if (ret < 0) {
+		usbssp_err(usbssp_data,
+				"Generic initialization failed with error code%d\n",
+				ret);
+		goto err3;
+	}
+
+	ret = usbssp_gadget_init_endpoint(usbssp_data);
+	if (ret < 0) {
+		usbssp_err(usbssp_data, "failed to initialize endpoints\n");
+		goto err1;
+	}
+
+	ret = usb_add_gadget_udc(usbssp_data->dev, &usbssp_data->gadget);
+
+	if (ret) {
+		usbssp_err(usbssp_data, "failed to register udc\n");
+		goto err2;
+	}
+
+	return ret;
+err2:
+	usbssp_gadget_free_endpoint(usbssp_data);
+err1:
+	usbssp_halt(usbssp_data);
+	/*TODO add implementation of usbssp_reset function*/
+	//usbssp_reset(usbssp_data);
+	//TODO freeing memory
+	//usbssp_mem_cleanup(usbssp_data);
+err3:
 	return ret;
 }
 
@@ -60,5 +304,9 @@  int usbssp_gadget_exit(struct usbssp_udc *usbssp_data)
 {
 	int ret = 0;
 
+	usb_del_gadget_udc(&usbssp_data->gadget);
+	usbssp_gadget_free_endpoint(usbssp_data);
+	/*TODO: add usbssp_stop implementation*/
+	//usbssp_stop(usbssp_data);
 	return ret;
 }
diff --git a/drivers/usb/usbssp/gadget.h b/drivers/usb/usbssp/gadget.h
index 2f9ee3543911..ce0ac6883efc 100644
--- a/drivers/usb/usbssp/gadget.h
+++ b/drivers/usb/usbssp/gadget.h
@@ -17,6 +17,7 @@ 
 #include <linux/kernel.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
 #include <linux/usb/gadget.h>
+#include "gadget-ext-caps.h"
 
 /* Max number slots - only 1 is allowed */
 #define DEV_MAX_SLOTS 1
@@ -1671,7 +1672,18 @@  static inline void usbssp_write_64(struct usbssp_udc *usbssp_data,
 	lo_hi_writeq(val, regs);
 }
 
+/* USBSSP memory management */
+void usbssp_dbg_trace(struct usbssp_udc *usbssp_data,
+		void (*trace)(struct va_format *),
+		const char *fmt, ...);
 /* USBSSP Device controller glue */
+void usbssp_bottom_irq(struct work_struct *work);
+int usbssp_init(struct usbssp_udc *usbssp_data);
+void usbssp_stop(struct usbssp_udc *usbssp_data);
+int usbssp_handshake(void __iomem *ptr, u32 mask, u32 done, int usec);
+void usbssp_quiesce(struct usbssp_udc *usbssp_data);
+extern int usbssp_reset(struct usbssp_udc *usbssp_data);
+
 int usbssp_suspend(struct usbssp_udc *usbssp_data, bool do_wakeup);
 int usbssp_resume(struct usbssp_udc *usbssp_data, bool hibernated);
 
@@ -1684,6 +1696,8 @@  dma_addr_t usbssp_trb_virt_to_dma(struct usbssp_segment *seg,
 /* USBSSP gadget interface*/
 int usbssp_gadget_init(struct usbssp_udc *usbssp_data);
 int  usbssp_gadget_exit(struct usbssp_udc *usbssp_data);
+void usbssp_gadget_free_endpoint(struct usbssp_udc *usbssp_data);
+int usbssp_gadget_init_endpoint(struct usbssp_udc *usbssp_data);
 
 static inline char *usbssp_slot_state_string(u32 state)
 {