162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Driver for the NXP ISP1761 device controller
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2021 Linaro, Rui Miguel Silva
662306a36Sopenharmony_ci * Copyright 2014 Ideas on Board Oy
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Contacts:
962306a36Sopenharmony_ci *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
1062306a36Sopenharmony_ci *	Rui Miguel Silva <rui.silva@linaro.org>
1162306a36Sopenharmony_ci */
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#ifndef _ISP1760_UDC_H_
1462306a36Sopenharmony_ci#define _ISP1760_UDC_H_
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include <linux/ioport.h>
1762306a36Sopenharmony_ci#include <linux/list.h>
1862306a36Sopenharmony_ci#include <linux/spinlock.h>
1962306a36Sopenharmony_ci#include <linux/timer.h>
2062306a36Sopenharmony_ci#include <linux/usb/gadget.h>
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#include "isp1760-regs.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_cistruct isp1760_device;
2562306a36Sopenharmony_cistruct isp1760_udc;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cienum isp1760_ctrl_state {
2862306a36Sopenharmony_ci	ISP1760_CTRL_SETUP,		/* Waiting for a SETUP transaction */
2962306a36Sopenharmony_ci	ISP1760_CTRL_DATA_IN,		/* Setup received, data IN stage */
3062306a36Sopenharmony_ci	ISP1760_CTRL_DATA_OUT,		/* Setup received, data OUT stage */
3162306a36Sopenharmony_ci	ISP1760_CTRL_STATUS,		/* 0-length request in status stage */
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistruct isp1760_ep {
3562306a36Sopenharmony_ci	struct isp1760_udc *udc;
3662306a36Sopenharmony_ci	struct usb_ep ep;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	struct list_head queue;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	unsigned int addr;
4162306a36Sopenharmony_ci	unsigned int maxpacket;
4262306a36Sopenharmony_ci	char name[7];
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	const struct usb_endpoint_descriptor *desc;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	bool rx_pending;
4762306a36Sopenharmony_ci	bool halted;
4862306a36Sopenharmony_ci	bool wedged;
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/**
5262306a36Sopenharmony_ci * struct isp1760_udc - UDC state information
5362306a36Sopenharmony_ci * irq: IRQ number
5462306a36Sopenharmony_ci * irqname: IRQ name (as passed to request_irq)
5562306a36Sopenharmony_ci * regs: regmap for UDC registers
5662306a36Sopenharmony_ci * driver: Gadget driver
5762306a36Sopenharmony_ci * gadget: Gadget device
5862306a36Sopenharmony_ci * lock: Protects driver, vbus_timer, ep, ep0_*, DC_EPINDEX register
5962306a36Sopenharmony_ci * ep: Array of endpoints
6062306a36Sopenharmony_ci * ep0_state: Control request state for endpoint 0
6162306a36Sopenharmony_ci * ep0_dir: Direction of the current control request
6262306a36Sopenharmony_ci * ep0_length: Length of the current control request
6362306a36Sopenharmony_ci * connected: Tracks gadget driver bus connection state
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_cistruct isp1760_udc {
6662306a36Sopenharmony_ci	struct isp1760_device *isp;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	int irq;
6962306a36Sopenharmony_ci	char *irqname;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	struct regmap *regs;
7262306a36Sopenharmony_ci	struct regmap_field *fields[DC_FIELD_MAX];
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	struct usb_gadget_driver *driver;
7562306a36Sopenharmony_ci	struct usb_gadget gadget;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	spinlock_t lock;
7862306a36Sopenharmony_ci	struct timer_list vbus_timer;
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_ci	struct isp1760_ep ep[15];
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	enum isp1760_ctrl_state ep0_state;
8362306a36Sopenharmony_ci	u8 ep0_dir;
8462306a36Sopenharmony_ci	u16 ep0_length;
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	bool connected;
8762306a36Sopenharmony_ci	bool is_isp1763;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	unsigned int devstatus;
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#ifdef CONFIG_USB_ISP1761_UDC
9362306a36Sopenharmony_ciint isp1760_udc_register(struct isp1760_device *isp, int irq,
9462306a36Sopenharmony_ci			 unsigned long irqflags);
9562306a36Sopenharmony_civoid isp1760_udc_unregister(struct isp1760_device *isp);
9662306a36Sopenharmony_ci#else
9762306a36Sopenharmony_cistatic inline int isp1760_udc_register(struct isp1760_device *isp, int irq,
9862306a36Sopenharmony_ci				       unsigned long irqflags)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	return 0;
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic inline void isp1760_udc_unregister(struct isp1760_device *isp)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci#endif
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#endif
109