/* linux/drivers/usb/gadget/s3c-hsudc.c
*
* Copyright (c) 2010 Samsung Electronics Co., Ltd.
* http://www.samsung.com/
*
* S3C24XX USB 2.0 High-speed USB controller gadget driver
*
* The S3C24XX USB 2.0 high-speed USB controller supports upto 9 endpoints.
* Each endpoint can be configured as either in or out endpoint. Endpoints
* can be configured for Bulk or Interrupt transfer mode.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/usb/ch9.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
#include <linux/prefetch.h>
#include <linux/platform_data/s3c-hsudc.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <mach/regs-s3c2443-clock.h>
#define S3C_HSUDC_REG(x) (x)
/* Non-Indexed Registers */
#define S3C_IR S3C_HSUDC_REG(0x00) /* Index Register */
#define S3C_EIR S3C_HSUDC_REG(0x04) /* EP Intr Status */
#define S3C_EIR_EP0 (1<<0)
#define S3C_EIER S3C_HSUDC_REG(0x08) /* EP Intr Enable */
#define S3C_FAR S3C_HSUDC_REG(0x0c) /* Gadget Address */
#define S3C_FNR S3C_HSUDC_REG(0x10) /* Frame Number */
#define S3C_EDR S3C_HSUDC_REG(0x14) /* EP Direction */
#define S3C_TR S3C_HSUDC_REG(0x18) /* Test Register */
#define S3C_SSR S3C_HSUDC_REG(0x1c) /* System Status */
#define S3C_SSR_DTZIEN_EN (0xff8f)
#define S3C_SSR_ERR (0xff80)
#define S3C_SSR_VBUSON (1 << 8)
#define S3C_SSR_HSP (1 << 4)
#define S3C_SSR_SDE (1 << 3)
#define S3C_SSR_RESUME (1 << 2)
#define S3C_SSR_SUSPEND (1 << 1)
#define S3C_SSR_RESET (1 << 0)
#define S3C_SCR S3C_HSUDC_REG(0x20) /* System Control */
#define S3C_SCR_DTZIEN_EN (1 << 14)
#define S3C_SCR_RRD_EN (1 << 5)
#define S3C_SCR_SUS_EN (1 << 1)
#define S3C_SCR_RST_EN (1 << 0)
#define S3C_EP0SR S3C_HSUDC_REG(0x24) /* EP0 Status */
#define S3C_EP0SR_EP0_LWO (1 << 6)
#define S3C_EP0SR_STALL (1 << 4)
#define S3C_EP0SR_TX_SUCCESS (1 << 1)
#define S3C_EP0SR_RX_SUCCESS (1 << 0)
#define S3C_EP0CR S3C_HSUDC_REG(0x28) /* EP0 Control */
#define S3C_BR(_x) S3C_HSUDC_REG(0x60 + (_x * 4))
/* Indexed Registers */
#define S3C_ESR S3C_HSUDC_REG(0x2c) /* EPn Status */
#define S3C_ESR_FLUSH (1 << 6)
#define S3C_ESR_STALL (1 << 5)
#define S3C_ESR_LWO (1 << 4)
#define S3C_ESR_PSIF_ONE (1 << 2)
#define S3C_ESR_PSIF_TWO (2 << 2)
#define S3C_ESR_TX_SUCCESS (1 << 1)
#define S3C_ESR_RX_SUCCESS (1 << 0)
#define S3C_ECR S3C_HSUDC_REG(0x30) /* EPn Control */
#define S3C_ECR_DUEN (1 << 7)
#define S3C_ECR_FLUSH (1 << 6)
#define S3C_ECR_STALL (1 << 1)
#define S3C_ECR_IEMS (1 << 0)
#define S3C_BRCR S3C_HSUDC_REG(0x34) /* Read Count */
#define S3C_BWCR S3C_HSUDC_REG(0x38) /* Write Count */
#define S3C_MPR S3C_HSUDC_REG(0x3c) /* Max Pkt Size */
#define WAIT_FOR_SETUP (0)
#define DATA_STATE_XMIT (1)
#define DATA_STATE_RECV (2)
static const char * const s3c_hsudc_supply_names[] = {
"vdda", /* analog phy supply, 3.3V */
"vddi", /* digital phy supply, 1.2V */
"vddosc", /* oscillator supply, 1.8V - 3.3V */
};
/**
* struct s3c_hsudc_ep - Endpoint representation used by driver.
* @ep: USB gadget layer representation of device endpoint.
* @name: Endpoint name (as required by ep autoconfiguration).
* @dev: Reference to the device controller to which this EP belongs.
* @desc: Endpoint descriptor obtained from the gadget driver.
* @queue: Transfer request queue for the endpoint.
* @stopped: Maintains state of endpoint, set if EP is halted.
* @bEndpointAddress: EP address (including direction bit).
* @fifo: Base address of EP FIFO.
*/
struct s3c_hsudc_ep {
struct usb_ep ep;
char name[20];
struct s3c_hsudc