// SPDX-License-Identifier: GPL-2.0+
/*
* MAX3420 Device Controller driver for USB.
*
* Author: Jaswinder Singh Brar <jaswinder.singh@linaro.org>
* (C) Copyright 2019-2020 Linaro Ltd
*
* Based on:
* o MAX3420E datasheet
* https://datasheets.maximintegrated.com/en/ds/MAX3420E.pdf
* o MAX342{0,1}E Programming Guides
* https://pdfserv.maximintegrated.com/en/an/AN3598.pdf
* https://pdfserv.maximintegrated.com/en/an/AN3785.pdf
*/
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/bitfield.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/prefetch.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/spi/spi.h>
#include <linux/gpio/consumer.h>
#define MAX3420_MAX_EPS 4
#define MAX3420_EP_MAX_PACKET 64 /* Same for all Endpoints */
#define MAX3420_EPNAME_SIZE 16 /* Buffer size for endpoint name */
#define MAX3420_ACKSTAT BIT(0)
#define MAX3420_SPI_DIR_RD 0 /* read register from MAX3420 */
#define MAX3420_SPI_DIR_WR 1 /* write register to MAX3420 */
/* SPI commands: */
#define MAX3420_SPI_DIR_SHIFT 1
#define MAX3420_SPI_REG_SHIFT 3
#define MAX3420_REG_EP0FIFO 0
#define MAX3420_REG_EP1FIFO 1
#define MAX3420_REG_EP2FIFO 2
#define MAX3420_REG_EP3FIFO 3
#define MAX3420_REG_SUDFIFO 4
#define MAX3420_REG_EP0BC 5
#define MAX3420_REG_EP1BC 6
#define MAX3420_REG_EP2BC 7
#define MAX3420_REG_EP3BC 8
#define MAX3420_REG_EPSTALLS 9
#define ACKSTAT BIT(6)
#define STLSTAT BIT(5)
#define STLEP3IN BIT(4)
#define STLEP2IN BIT(3)
#define STLEP1OUT BIT(2)
#define STLEP0OUT BIT(1)
#define STLEP0IN BIT(0)
#define MAX3420_REG_CLRTOGS 10
#define EP3DISAB BIT(7)
#define EP2DISAB BIT(6)
#define EP1DISAB BIT(5)
#define CTGEP3IN BIT(4)
#define CTGEP2IN BIT(3)
#define CTGEP1OUT BIT(2)
#define MAX3420_REG_EPIRQ 11
#define MAX3420_REG_EPIEN 12
#define SUDAVIRQ BIT(5)
#define IN3BAVIRQ BIT(4)
#define IN2BAVIRQ BIT(3)
#define OUT1DAVIRQ BIT(2)
#define OUT0DAVIRQ BIT(1)
#define IN0BAVIRQ BIT(0)
#define MAX3420_REG_USBIRQ 13
#define MAX3420_REG_USBIEN 14
#define OSCOKIRQ BIT(0)
#define RWUDNIRQ BIT(1)
#define BUSACTIRQ BIT(2)
#define URESIRQ BIT(3)
#define SUSPIRQ BIT(4)
#define NOVBUSIRQ BIT(5)
#define VBUSIRQ BIT(6)
#define URESDNIRQ BIT(7)
#define MAX3420_REG_USBCTL 15
#define HOSCSTEN BIT(7)
#define VBGATE BIT(6)
#define CHIPRES BIT(5)
#define PWRDOWN BIT(4)
#define CONNECT BIT(3)
#define SIGRWU BIT(2)
#define MAX3420_REG_CPUCTL 16
#define IE BIT(0)
#define MAX3420_REG_PINCTL 17
#define EP3INAK BIT(7)
#define EP2INAK BIT(6)
#define EP0INAK BIT(5)
#define FDUPSPI BIT(4)
#define INTLEVEL BIT(3)
#define POSINT BIT(2)
#define GPXB BIT(1)
#define GPXA BIT(0)
#define MAX3420_REG_REVISION 18
#define MAX3420_REG_FNADDR 19
#define FNADDR_MASK 0x7f
#define MAX3420_REG_IOPINS 20
#define MAX3420_REG_IOPINS2 21
#define MAX3420_REG_GPINIRQ 22
#define MAX3420_REG_GPINIEN 23
#define MAX3420_REG_GPINPOL 24
#define MAX3420_REG_HIRQ 25
#define MAX3420_REG_HIEN 26
#define MAX3420_REG_MODE 27
#define MAX3420_REG_PERADDR 28
#define MAX3420_REG_HCTL 29
#define MAX3420_REG_HXFR 30
#define MAX3420_REG_HRSL 31
#define ENABLE_IRQ BIT(0)
#define IOPIN_UPDATE BIT(1)
#define REMOTE_WAKEUP BIT(2)
#define CONNECT_HOST GENMASK(4, 3)
#define HCONNECT (1 << 3)
#define HDISCONNECT (3 << 3)
#define UDC_START GENMASK(6, 5)
#define START (1 << 5)
#define STOP (3 << 5)
#define ENABLE_EP GENMASK(8, 7)
#define ENABLE (1 << 7)
#define DISABLE (3 << 7)
#define STALL_EP GENMASK(10, 9)
#define STALL (1 << 9)
#define UNSTALL (3 << 9)
#define MAX3420_CMD(c) FIELD_PREP(GENMASK(7, 3), c)
#define MAX3420_SPI_CMD_RD(c) (MAX3420_CMD(c) | (0 << 1))
#define MAX3420_SPI_CMD_WR(c) (MAX3420_CMD(c) | (1 << 1))
struct max3420_req {
struct usb_request usb_req;
struct list_head queue;
struct max3420_ep *ep;
};
struct max3420_ep {
struct usb_ep ep_usb;
struct max3420_udc *udc;
struct list_head queue;
char name[MAX3420_EPNAME_SIZE];
unsigned int maxpacket;
spinlock_t lock;
int halted;
u32 todo;
int id;
};
struct max3420_udc {
struct usb_gadget gadget;
struct max3420_ep ep[MAX3420_MAX_EPS];
struct usb_gadget_driver *driver;
struct task_struct *thread_task;
int remote_wkp, is_selfpowered;
bool vbus_active, softconnect;
struct usb_ctrlrequest setup