You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
usb: Add MediaTek USB3 DRD driver
This patch adds support for the MediaTek USB3 controller integrated into MT8173. It currently supports High-Speed Peripheral Only mode. Super-Speed Peripheral, Dual-Role Device and Host Only (xHCI) modes will be added in the next patchs. Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
065d48cf40
commit
df2069acb0
@@ -95,6 +95,8 @@ source "drivers/usb/usbip/Kconfig"
|
||||
|
||||
endif
|
||||
|
||||
source "drivers/usb/mtu3/Kconfig"
|
||||
|
||||
source "drivers/usb/musb/Kconfig"
|
||||
|
||||
source "drivers/usb/dwc3/Kconfig"
|
||||
|
||||
@@ -12,6 +12,7 @@ obj-$(CONFIG_USB_DWC2) += dwc2/
|
||||
obj-$(CONFIG_USB_ISP1760) += isp1760/
|
||||
|
||||
obj-$(CONFIG_USB_MON) += mon/
|
||||
obj-$(CONFIG_USB_MTU3) += mtu3/
|
||||
|
||||
obj-$(CONFIG_PCI) += host/
|
||||
obj-$(CONFIG_USB_EHCI_HCD) += host/
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# For MTK USB3.0 IP
|
||||
|
||||
config USB_MTU3
|
||||
tristate "MediaTek USB3 Dual Role controller"
|
||||
depends on (USB || USB_GADGET) && HAS_DMA
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
help
|
||||
Say Y or M here if your system runs on MediaTek SoCs with
|
||||
Dual Role SuperSpeed USB controller. You can select usb
|
||||
mode as peripheral role or host role, or both.
|
||||
|
||||
If you don't know what this is, please say N.
|
||||
|
||||
Choose M here to compile this driver as a module, and it
|
||||
will be called mtu3.ko.
|
||||
|
||||
|
||||
if USB_MTU3
|
||||
choice
|
||||
bool "MTU3 Mode Selection"
|
||||
default USB_MTU3_GADGET if (!USB && USB_GADGET)
|
||||
|
||||
config USB_MTU3_GADGET
|
||||
bool "Gadget only mode"
|
||||
depends on USB_GADGET=y || USB_GADGET=USB_MTU3
|
||||
help
|
||||
Select this when you want to use MTU3 in gadget mode only,
|
||||
thereby the host feature will be regressed.
|
||||
|
||||
endchoice
|
||||
|
||||
endif
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_USB_MTU3) += mtu3.o
|
||||
mtu3-y := mtu3_plat.o mtu3_core.o mtu3_gadget_ep0.o mtu3_gadget.o mtu3_qmu.o
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* mtu3.h - MediaTek USB3 DRD header
|
||||
*
|
||||
* Copyright (C) 2016 MediaTek Inc.
|
||||
*
|
||||
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MTU3_H__
|
||||
#define __MTU3_H__
|
||||
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmapool.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/otg.h>
|
||||
|
||||
struct mtu3;
|
||||
struct mtu3_ep;
|
||||
struct mtu3_request;
|
||||
|
||||
#include "mtu3_hw_regs.h"
|
||||
#include "mtu3_qmu.h"
|
||||
|
||||
#define MU3D_EP_TXCR0(epnum) (U3D_TX1CSR0 + (((epnum) - 1) * 0x10))
|
||||
#define MU3D_EP_TXCR1(epnum) (U3D_TX1CSR1 + (((epnum) - 1) * 0x10))
|
||||
#define MU3D_EP_TXCR2(epnum) (U3D_TX1CSR2 + (((epnum) - 1) * 0x10))
|
||||
|
||||
#define MU3D_EP_RXCR0(epnum) (U3D_RX1CSR0 + (((epnum) - 1) * 0x10))
|
||||
#define MU3D_EP_RXCR1(epnum) (U3D_RX1CSR1 + (((epnum) - 1) * 0x10))
|
||||
#define MU3D_EP_RXCR2(epnum) (U3D_RX1CSR2 + (((epnum) - 1) * 0x10))
|
||||
|
||||
#define USB_QMU_RQCSR(epnum) (U3D_RXQCSR1 + (((epnum) - 1) * 0x10))
|
||||
#define USB_QMU_RQSAR(epnum) (U3D_RXQSAR1 + (((epnum) - 1) * 0x10))
|
||||
#define USB_QMU_RQCPR(epnum) (U3D_RXQCPR1 + (((epnum) - 1) * 0x10))
|
||||
|
||||
#define USB_QMU_TQCSR(epnum) (U3D_TXQCSR1 + (((epnum) - 1) * 0x10))
|
||||
#define USB_QMU_TQSAR(epnum) (U3D_TXQSAR1 + (((epnum) - 1) * 0x10))
|
||||
#define USB_QMU_TQCPR(epnum) (U3D_TXQCPR1 + (((epnum) - 1) * 0x10))
|
||||
|
||||
#define SSUSB_U2_CTRL(p) (U3D_SSUSB_U2_CTRL_0P + ((p) * 0x08))
|
||||
|
||||
#define MTU3_DRIVER_NAME "mtu3"
|
||||
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
|
||||
|
||||
#define MTU3_EP_ENABLED BIT(0)
|
||||
#define MTU3_EP_STALL BIT(1)
|
||||
#define MTU3_EP_WEDGE BIT(2)
|
||||
#define MTU3_EP_BUSY BIT(3)
|
||||
|
||||
#define MTU3_U2_IP_SLOT_DEFAULT 1
|
||||
|
||||
/**
|
||||
* Normally the device works on HS or SS, to simplify fifo management,
|
||||
* devide fifo into some 512B parts, use bitmap to manage it; And
|
||||
* 128 bits size of bitmap is large enough, that means it can manage
|
||||
* up to 64KB fifo size.
|
||||
* NOTE: MTU3_EP_FIFO_UNIT should be power of two
|
||||
*/
|
||||
#define MTU3_EP_FIFO_UNIT (1 << 9)
|
||||
#define MTU3_FIFO_BIT_SIZE 128
|
||||
#define MTU3_U2_IP_EP0_FIFO_SIZE 64
|
||||
|
||||
/**
|
||||
* Maximum size of ep0 response buffer for ch9 requests,
|
||||
* the SET_SEL request uses 6 so far, and GET_STATUS is 2
|
||||
*/
|
||||
#define EP0_RESPONSE_BUF 6
|
||||
|
||||
/* device operated link and speed got from DEVICE_CONF register */
|
||||
enum mtu3_speed {
|
||||
MTU3_SPEED_INACTIVE = 0,
|
||||
MTU3_SPEED_FULL = 1,
|
||||
MTU3_SPEED_HIGH = 3,
|
||||
};
|
||||
|
||||
/**
|
||||
* @MU3D_EP0_STATE_SETUP: waits for SETUP or received a SETUP
|
||||
* without data stage.
|
||||
* @MU3D_EP0_STATE_TX: IN data stage
|
||||
* @MU3D_EP0_STATE_RX: OUT data stage
|
||||
* @MU3D_EP0_STATE_TX_END: the last IN data is transferred, and
|
||||
* waits for its completion interrupt
|
||||
* @MU3D_EP0_STATE_STALL: ep0 is in stall status, will be auto-cleared
|
||||
* after receives a SETUP.
|
||||
*/
|
||||
enum mtu3_g_ep0_state {
|
||||
MU3D_EP0_STATE_SETUP = 1,
|
||||
MU3D_EP0_STATE_TX,
|
||||
MU3D_EP0_STATE_RX,
|
||||
MU3D_EP0_STATE_TX_END,
|
||||
MU3D_EP0_STATE_STALL,
|
||||
};
|
||||
|
||||
/**
|
||||
* @base: the base address of fifo
|
||||
* @limit: the bitmap size in bits
|
||||
* @bitmap: fifo bitmap in unit of @MTU3_EP_FIFO_UNIT
|
||||
*/
|
||||
struct mtu3_fifo_info {
|
||||
u32 base;
|
||||
u32 limit;
|
||||
DECLARE_BITMAP(bitmap, MTU3_FIFO_BIT_SIZE);
|
||||
};
|
||||
|
||||
/**
|
||||
* General Purpose Descriptor (GPD):
|
||||
* The format of TX GPD is a little different from RX one.
|
||||
* And the size of GPD is 16 bytes.
|
||||
*
|
||||
* @flag:
|
||||
* bit0: Hardware Own (HWO)
|
||||
* bit1: Buffer Descriptor Present (BDP), always 0, BD is not supported
|
||||
* bit2: Bypass (BPS), 1: HW skips this GPD if HWO = 1
|
||||
* bit7: Interrupt On Completion (IOC)
|
||||
* @chksum: This is used to validate the contents of this GPD;
|
||||
* If TXQ_CS_EN / RXQ_CS_EN bit is set, an interrupt is issued
|
||||
* when checksum validation fails;
|
||||
* Checksum value is calculated over the 16 bytes of the GPD by default;
|
||||
* @data_buf_len (RX ONLY): This value indicates the length of
|
||||
* the assigned data buffer
|
||||
* @next_gpd: Physical address of the next GPD
|
||||
* @buffer: Physical address of the data buffer
|
||||
* @buf_len:
|
||||
* (TX): This value indicates the length of the assigned data buffer
|
||||
* (RX): The total length of data received
|
||||
* @ext_len: reserved
|
||||
* @ext_flag:
|
||||
* bit5 (TX ONLY): Zero Length Packet (ZLP),
|
||||
*/
|
||||
struct qmu_gpd {
|
||||
__u8 flag;
|
||||
__u8 chksum;
|
||||
__le16 data_buf_len;
|
||||
__le32 next_gpd;
|
||||
__le32 buffer;
|
||||
__le16 buf_len;
|
||||
__u8 ext_len;
|
||||
__u8 ext_flag;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* dma: physical base address of GPD segment
|
||||
* start: virtual base address of GPD segment
|
||||
* end: the last GPD element
|
||||
* enqueue: the first empty GPD to use
|
||||
* dequeue: the first completed GPD serviced by ISR
|
||||
* NOTE: the size of GPD ring should be >= 2
|
||||
*/
|
||||
struct mtu3_gpd_ring {
|
||||
dma_addr_t dma;
|
||||
struct qmu_gpd *start;
|
||||
struct qmu_gpd *end;
|
||||
struct qmu_gpd *enqueue;
|
||||
struct qmu_gpd *dequeue;
|
||||
};
|
||||
|
||||
/**
|
||||
* @fifo_size: it is (@slot + 1) * @fifo_seg_size
|
||||
* @fifo_seg_size: it is roundup_pow_of_two(@maxp)
|
||||
*/
|
||||
struct mtu3_ep {
|
||||
struct usb_ep ep;
|
||||
char name[12];
|
||||
struct mtu3 *mtu;
|
||||
u8 epnum;
|
||||
u8 type;
|
||||
u8 is_in;
|
||||
u16 maxp;
|
||||
int slot;
|
||||
u32 fifo_size;
|
||||
u32 fifo_addr;
|
||||
u32 fifo_seg_size;
|
||||
struct mtu3_fifo_info *fifo;
|
||||
|
||||
struct list_head req_list;
|
||||
struct mtu3_gpd_ring gpd_ring;
|
||||
const struct usb_endpoint_descriptor *desc;
|
||||
|
||||
int flags;
|
||||
u8 wedged;
|
||||
u8 busy;
|
||||
};
|
||||
|
||||
struct mtu3_request {
|
||||
struct usb_request request;
|
||||
struct list_head list;
|
||||
struct mtu3_ep *mep;
|
||||
struct mtu3 *mtu;
|
||||
struct qmu_gpd *gpd;
|
||||
int epnum;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mtu3 - device driver instance data.
|
||||
* @slot: MTU3_U2_IP_SLOT_DEFAULT for U2 IP
|
||||
* @may_wakeup: means device's remote wakeup is enabled
|
||||
* @is_self_powered: is reported in device status and the config descriptor
|
||||
* @ep0_req: dummy request used while handling standard USB requests
|
||||
* for GET_STATUS and SET_SEL
|
||||
* @setup_buf: ep0 response buffer for GET_STATUS and SET_SEL requests
|
||||
*/
|
||||
struct mtu3 {
|
||||
spinlock_t lock;
|
||||
struct device *dev;
|
||||
void __iomem *mac_base;
|
||||
void __iomem *ippc_base;
|
||||
struct phy *phy;
|
||||
struct regulator *vusb33;
|
||||
struct clk *sys_clk;
|
||||
int irq;
|
||||
|
||||
struct mtu3_fifo_info tx_fifo;
|
||||
struct mtu3_fifo_info rx_fifo;
|
||||
|
||||
struct mtu3_ep *ep_array;
|
||||
struct mtu3_ep *in_eps;
|
||||
struct mtu3_ep *out_eps;
|
||||
struct mtu3_ep *ep0;
|
||||
int num_eps;
|
||||
int slot;
|
||||
int active_ep;
|
||||
|
||||
struct dma_pool *qmu_gpd_pool;
|
||||
enum mtu3_g_ep0_state ep0_state;
|
||||
struct usb_gadget g; /* the gadget */
|
||||
struct usb_gadget_driver *gadget_driver;
|
||||
struct mtu3_request ep0_req;
|
||||
u8 setup_buf[EP0_RESPONSE_BUF];
|
||||
|
||||
unsigned is_active:1;
|
||||
unsigned may_wakeup:1;
|
||||
unsigned is_self_powered:1;
|
||||
unsigned test_mode:1;
|
||||
unsigned softconnect:1;
|
||||
|
||||
u8 address;
|
||||
u8 test_mode_nr;
|
||||
u32 hw_version;
|
||||
};
|
||||
|
||||
static inline struct mtu3 *gadget_to_mtu3(struct usb_gadget *g)
|
||||
{
|
||||
return container_of(g, struct mtu3, g);
|
||||
}
|
||||
|
||||
static inline int is_first_entry(const struct list_head *list,
|
||||
const struct list_head *head)
|
||||
{
|
||||
return list_is_last(head, list);
|
||||
}
|
||||
|
||||
static inline struct mtu3_request *to_mtu3_request(struct usb_request *req)
|
||||
{
|
||||
return req ? container_of(req, struct mtu3_request, request) : NULL;
|
||||
}
|
||||
|
||||
static inline struct mtu3_ep *to_mtu3_ep(struct usb_ep *ep)
|
||||
{
|
||||
return ep ? container_of(ep, struct mtu3_ep, ep) : NULL;
|
||||
}
|
||||
|
||||
static inline struct mtu3_request *next_request(struct mtu3_ep *mep)
|
||||
{
|
||||
struct list_head *queue = &mep->req_list;
|
||||
|
||||
if (list_empty(queue))
|
||||
return NULL;
|
||||
|
||||
return list_first_entry(queue, struct mtu3_request, list);
|
||||
}
|
||||
|
||||
static inline void mtu3_writel(void __iomem *base, u32 offset, u32 data)
|
||||
{
|
||||
writel(data, base + offset);
|
||||
}
|
||||
|
||||
static inline u32 mtu3_readl(void __iomem *base, u32 offset)
|
||||
{
|
||||
return readl(base + offset);
|
||||
}
|
||||
|
||||
static inline void mtu3_setbits(void __iomem *base, u32 offset, u32 bits)
|
||||
{
|
||||
void __iomem *addr = base + offset;
|
||||
u32 tmp = readl(addr);
|
||||
|
||||
writel((tmp | (bits)), addr);
|
||||
}
|
||||
|
||||
static inline void mtu3_clrbits(void __iomem *base, u32 offset, u32 bits)
|
||||
{
|
||||
void __iomem *addr = base + offset;
|
||||
u32 tmp = readl(addr);
|
||||
|
||||
writel((tmp & ~(bits)), addr);
|
||||
}
|
||||
|
||||
int ssusb_check_clocks(struct mtu3 *mtu, u32 ex_clks);
|
||||
struct usb_request *mtu3_alloc_request(struct usb_ep *ep, gfp_t gfp_flags);
|
||||
void mtu3_free_request(struct usb_ep *ep, struct usb_request *req);
|
||||
void mtu3_req_complete(struct mtu3_ep *mep,
|
||||
struct usb_request *req, int status);
|
||||
|
||||
int mtu3_config_ep(struct mtu3 *mtu, struct mtu3_ep *mep,
|
||||
int interval, int burst, int mult);
|
||||
void mtu3_deconfig_ep(struct mtu3 *mtu, struct mtu3_ep *mep);
|
||||
void mtu3_ep_stall_set(struct mtu3_ep *mep, bool set);
|
||||
void mtu3_ep0_setup(struct mtu3 *mtu);
|
||||
void mtu3_start(struct mtu3 *mtu);
|
||||
void mtu3_stop(struct mtu3 *mtu);
|
||||
void mtu3_hs_softconn_set(struct mtu3 *mtu, bool enable);
|
||||
|
||||
int mtu3_gadget_setup(struct mtu3 *mtu);
|
||||
void mtu3_gadget_cleanup(struct mtu3 *mtu);
|
||||
void mtu3_gadget_reset(struct mtu3 *mtu);
|
||||
void mtu3_gadget_suspend(struct mtu3 *mtu);
|
||||
void mtu3_gadget_resume(struct mtu3 *mtu);
|
||||
void mtu3_gadget_disconnect(struct mtu3 *mtu);
|
||||
int ssusb_gadget_init(struct mtu3 *mtu);
|
||||
void ssusb_gadget_exit(struct mtu3 *mtu);
|
||||
|
||||
irqreturn_t mtu3_ep0_isr(struct mtu3 *mtu);
|
||||
extern const struct usb_ep_ops mtu3_ep0_ops;
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* mtu3_hw_regs.h - MediaTek USB3 DRD register and field definitions
|
||||
*
|
||||
* Copyright (C) 2016 MediaTek Inc.
|
||||
*
|
||||
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SSUSB_HW_REGS_H_
|
||||
#define _SSUSB_HW_REGS_H_
|
||||
|
||||
/* segment offset of MAC register */
|
||||
#define SSUSB_DEV_BASE 0x0000
|
||||
#define SSUSB_EPCTL_CSR_BASE 0x0800
|
||||
#define SSUSB_USB3_MAC_CSR_BASE 0x1400
|
||||
#define SSUSB_USB3_SYS_CSR_BASE 0x1400
|
||||
#define SSUSB_USB2_CSR_BASE 0x2400
|
||||
|
||||
/* IPPC register in Infra */
|
||||
#define SSUSB_SIFSLV_IPPC_BASE 0x0000
|
||||
|
||||
/* --------------- SSUSB_DEV REGISTER DEFINITION --------------- */
|
||||
|
||||
#define U3D_LV1ISR (SSUSB_DEV_BASE + 0x0000)
|
||||
#define U3D_LV1IER (SSUSB_DEV_BASE + 0x0004)
|
||||
#define U3D_LV1IESR (SSUSB_DEV_BASE + 0x0008)
|
||||
#define U3D_LV1IECR (SSUSB_DEV_BASE + 0x000C)
|
||||
|
||||
#define U3D_EPISR (SSUSB_DEV_BASE + 0x0080)
|
||||
#define U3D_EPIER (SSUSB_DEV_BASE + 0x0084)
|
||||
#define U3D_EPIESR (SSUSB_DEV_BASE + 0x0088)
|
||||
#define U3D_EPIECR (SSUSB_DEV_BASE + 0x008C)
|
||||
|
||||
#define U3D_EP0CSR (SSUSB_DEV_BASE + 0x0100)
|
||||
#define U3D_RXCOUNT0 (SSUSB_DEV_BASE + 0x0108)
|
||||
#define U3D_RESERVED (SSUSB_DEV_BASE + 0x010C)
|
||||
#define U3D_TX1CSR0 (SSUSB_DEV_BASE + 0x0110)
|
||||
#define U3D_TX1CSR1 (SSUSB_DEV_BASE + 0x0114)
|
||||
#define U3D_TX1CSR2 (SSUSB_DEV_BASE + 0x0118)
|
||||
|
||||
#define U3D_RX1CSR0 (SSUSB_DEV_BASE + 0x0210)
|
||||
#define U3D_RX1CSR1 (SSUSB_DEV_BASE + 0x0214)
|
||||
#define U3D_RX1CSR2 (SSUSB_DEV_BASE + 0x0218)
|
||||
|
||||
#define U3D_FIFO0 (SSUSB_DEV_BASE + 0x0300)
|
||||
|
||||
#define U3D_QCR0 (SSUSB_DEV_BASE + 0x0400)
|
||||
#define U3D_QCR1 (SSUSB_DEV_BASE + 0x0404)
|
||||
#define U3D_QCR2 (SSUSB_DEV_BASE + 0x0408)
|
||||
#define U3D_QCR3 (SSUSB_DEV_BASE + 0x040C)
|
||||
|
||||
#define U3D_TXQCSR1 (SSUSB_DEV_BASE + 0x0510)
|
||||
#define U3D_TXQSAR1 (SSUSB_DEV_BASE + 0x0514)
|
||||
#define U3D_TXQCPR1 (SSUSB_DEV_BASE + 0x0518)
|
||||
|
||||
#define U3D_RXQCSR1 (SSUSB_DEV_BASE + 0x0610)
|
||||
#define U3D_RXQSAR1 (SSUSB_DEV_BASE + 0x0614)
|
||||
#define U3D_RXQCPR1 (SSUSB_DEV_BASE + 0x0618)
|
||||
#define U3D_RXQLDPR1 (SSUSB_DEV_BASE + 0x061C)
|
||||
|
||||
#define U3D_QISAR0 (SSUSB_DEV_BASE + 0x0700)
|
||||
#define U3D_QIER0 (SSUSB_DEV_BASE + 0x0704)
|
||||
#define U3D_QIESR0 (SSUSB_DEV_BASE + 0x0708)
|
||||
#define U3D_QIECR0 (SSUSB_DEV_BASE + 0x070C)
|
||||
#define U3D_QISAR1 (SSUSB_DEV_BASE + 0x0710)
|
||||
#define U3D_QIER1 (SSUSB_DEV_BASE + 0x0714)
|
||||
#define U3D_QIESR1 (SSUSB_DEV_BASE + 0x0718)
|
||||
#define U3D_QIECR1 (SSUSB_DEV_BASE + 0x071C)
|
||||
|
||||
#define U3D_TQERRIR0 (SSUSB_DEV_BASE + 0x0780)
|
||||
#define U3D_TQERRIER0 (SSUSB_DEV_BASE + 0x0784)
|
||||
#define U3D_TQERRIESR0 (SSUSB_DEV_BASE + 0x0788)
|
||||
#define U3D_TQERRIECR0 (SSUSB_DEV_BASE + 0x078C)
|
||||
#define U3D_RQERRIR0 (SSUSB_DEV_BASE + 0x07C0)
|
||||
#define U3D_RQERRIER0 (SSUSB_DEV_BASE + 0x07C4)
|
||||
#define U3D_RQERRIESR0 (SSUSB_DEV_BASE + 0x07C8)
|
||||
#define U3D_RQERRIECR0 (SSUSB_DEV_BASE + 0x07CC)
|
||||
#define U3D_RQERRIR1 (SSUSB_DEV_BASE + 0x07D0)
|
||||
#define U3D_RQERRIER1 (SSUSB_DEV_BASE + 0x07D4)
|
||||
#define U3D_RQERRIESR1 (SSUSB_DEV_BASE + 0x07D8)
|
||||
#define U3D_RQERRIECR1 (SSUSB_DEV_BASE + 0x07DC)
|
||||
|
||||
#define U3D_CAP_EP0FFSZ (SSUSB_DEV_BASE + 0x0C04)
|
||||
#define U3D_CAP_EPNTXFFSZ (SSUSB_DEV_BASE + 0x0C08)
|
||||
#define U3D_CAP_EPNRXFFSZ (SSUSB_DEV_BASE + 0x0C0C)
|
||||
#define U3D_CAP_EPINFO (SSUSB_DEV_BASE + 0x0C10)
|
||||
#define U3D_MISC_CTRL (SSUSB_DEV_BASE + 0x0C84)
|
||||
|
||||
/*---------------- SSUSB_DEV FIELD DEFINITION ---------------*/
|
||||
|
||||
/* U3D_LV1ISR */
|
||||
#define EP_CTRL_INTR BIT(5)
|
||||
#define MAC2_INTR BIT(4)
|
||||
#define DMA_INTR BIT(3)
|
||||
#define MAC3_INTR BIT(2)
|
||||
#define QMU_INTR BIT(1)
|
||||
#define BMU_INTR BIT(0)
|
||||
|
||||
/* U3D_LV1IECR */
|
||||
#define LV1IECR_MSK GENMASK(31, 0)
|
||||
|
||||
/* U3D_EPISR */
|
||||
#define EPRISR(x) (BIT(16) << (x))
|
||||
#define EPTISR(x) (BIT(0) << (x))
|
||||
#define EP0ISR BIT(0)
|
||||
|
||||
/* U3D_EP0CSR */
|
||||
#define EP0_SENDSTALL BIT(25)
|
||||
#define EP0_FIFOFULL BIT(23)
|
||||
#define EP0_SENTSTALL BIT(22)
|
||||
#define EP0_DPHTX BIT(20)
|
||||
#define EP0_DATAEND BIT(19)
|
||||
#define EP0_TXPKTRDY BIT(18)
|
||||
#define EP0_SETUPPKTRDY BIT(17)
|
||||
#define EP0_RXPKTRDY BIT(16)
|
||||
#define EP0_MAXPKTSZ_MSK GENMASK(9, 0)
|
||||
#define EP0_MAXPKTSZ(x) ((x) & EP0_MAXPKTSZ_MSK)
|
||||
#define EP0_W1C_BITS (~(EP0_RXPKTRDY | EP0_SETUPPKTRDY | EP0_SENTSTALL))
|
||||
|
||||
/* U3D_TX1CSR0 */
|
||||
#define TX_DMAREQEN BIT(29)
|
||||
#define TX_FIFOFULL BIT(25)
|
||||
#define TX_FIFOEMPTY BIT(24)
|
||||
#define TX_SENTSTALL BIT(22)
|
||||
#define TX_SENDSTALL BIT(21)
|
||||
#define TX_TXPKTRDY BIT(16)
|
||||
#define TX_TXMAXPKTSZ_MSK GENMASK(10, 0)
|
||||
#define TX_TXMAXPKTSZ(x) ((x) & TX_TXMAXPKTSZ_MSK)
|
||||
#define TX_W1C_BITS (~(TX_SENTSTALL))
|
||||
|
||||
/* U3D_TX1CSR1 */
|
||||
#define TX_MULT(x) (((x) & 0x3) << 22)
|
||||
#define TX_MAX_PKT(x) (((x) & 0x3f) << 16)
|
||||
#define TX_SLOT(x) (((x) & 0x3f) << 8)
|
||||
#define TX_TYPE(x) (((x) & 0x3) << 4)
|
||||
#define TX_SS_BURST(x) (((x) & 0xf) << 0)
|
||||
|
||||
/* for TX_TYPE & RX_TYPE */
|
||||
#define TYPE_BULK (0x0)
|
||||
#define TYPE_INT (0x1)
|
||||
#define TYPE_ISO (0x2)
|
||||
#define TYPE_MASK (0x3)
|
||||
|
||||
/* U3D_TX1CSR2 */
|
||||
#define TX_BINTERVAL(x) (((x) & 0xff) << 24)
|
||||
#define TX_FIFOSEGSIZE(x) (((x) & 0xf) << 16)
|
||||
#define TX_FIFOADDR(x) (((x) & 0x1fff) << 0)
|
||||
|
||||
/* U3D_RX1CSR0 */
|
||||
#define RX_DMAREQEN BIT(29)
|
||||
#define RX_SENTSTALL BIT(22)
|
||||
#define RX_SENDSTALL BIT(21)
|
||||
#define RX_RXPKTRDY BIT(16)
|
||||
#define RX_RXMAXPKTSZ_MSK GENMASK(10, 0)
|
||||
#define RX_RXMAXPKTSZ(x) ((x) & RX_RXMAXPKTSZ_MSK)
|
||||
#define RX_W1C_BITS (~(RX_SENTSTALL | RX_RXPKTRDY))
|
||||
|
||||
/* U3D_RX1CSR1 */
|
||||
#define RX_MULT(x) (((x) & 0x3) << 22)
|
||||
#define RX_MAX_PKT(x) (((x) & 0x3f) << 16)
|
||||
#define RX_SLOT(x) (((x) & 0x3f) << 8)
|
||||
#define RX_TYPE(x) (((x) & 0x3) << 4)
|
||||
#define RX_SS_BURST(x) (((x) & 0xf) << 0)
|
||||
|
||||
/* U3D_RX1CSR2 */
|
||||
#define RX_BINTERVAL(x) (((x) & 0xff) << 24)
|
||||
#define RX_FIFOSEGSIZE(x) (((x) & 0xf) << 16)
|
||||
#define RX_FIFOADDR(x) (((x) & 0x1fff) << 0)
|
||||
|
||||
/* U3D_QCR0 */
|
||||
#define QMU_RX_CS_EN(x) (BIT(16) << (x))
|
||||
#define QMU_TX_CS_EN(x) (BIT(0) << (x))
|
||||
#define QMU_CS16B_EN BIT(0)
|
||||
|
||||
/* U3D_QCR1 */
|
||||
#define QMU_TX_ZLP(x) (BIT(0) << (x))
|
||||
|
||||
/* U3D_QCR3 */
|
||||
#define QMU_RX_COZ(x) (BIT(16) << (x))
|
||||
#define QMU_RX_ZLP(x) (BIT(0) << (x))
|
||||
|
||||
/* U3D_TXQCSR1 */
|
||||
/* U3D_RXQCSR1 */
|
||||
#define QMU_Q_ACTIVE BIT(15)
|
||||
#define QMU_Q_STOP BIT(2)
|
||||
#define QMU_Q_RESUME BIT(1)
|
||||
#define QMU_Q_START BIT(0)
|
||||
|
||||
/* U3D_QISAR0, U3D_QIER0, U3D_QIESR0, U3D_QIECR0 */
|
||||
#define QMU_RX_DONE_INT(x) (BIT(16) << (x))
|
||||
#define QMU_TX_DONE_INT(x) (BIT(0) << (x))
|
||||
|
||||
/* U3D_QISAR1, U3D_QIER1, U3D_QIESR1, U3D_QIECR1 */
|
||||
#define RXQ_ZLPERR_INT BIT(20)
|
||||
#define RXQ_LENERR_INT BIT(18)
|
||||
#define RXQ_CSERR_INT BIT(17)
|
||||
#define RXQ_EMPTY_INT BIT(16)
|
||||
#define TXQ_LENERR_INT BIT(2)
|
||||
#define TXQ_CSERR_INT BIT(1)
|
||||
#define TXQ_EMPTY_INT BIT(0)
|
||||
|
||||
/* U3D_TQERRIR0, U3D_TQERRIER0, U3D_TQERRIESR0, U3D_TQERRIECR0 */
|
||||
#define QMU_TX_LEN_ERR(x) (BIT(16) << (x))
|
||||
#define QMU_TX_CS_ERR(x) (BIT(0) << (x))
|
||||
|
||||
/* U3D_RQERRIR0, U3D_RQERRIER0, U3D_RQERRIESR0, U3D_RQERRIECR0 */
|
||||
#define QMU_RX_LEN_ERR(x) (BIT(16) << (x))
|
||||
#define QMU_RX_CS_ERR(x) (BIT(0) << (x))
|
||||
|
||||
/* U3D_RQERRIR1, U3D_RQERRIER1, U3D_RQERRIESR1, U3D_RQERRIECR1 */
|
||||
#define QMU_RX_ZLP_ERR(n) (BIT(16) << (n))
|
||||
|
||||
/* U3D_CAP_EPINFO */
|
||||
#define CAP_RX_EP_NUM(x) (((x) >> 8) & 0x1f)
|
||||
#define CAP_TX_EP_NUM(x) ((x) & 0x1f)
|
||||
|
||||
/* U3D_MISC_CTRL */
|
||||
#define VBUS_ON BIT(1)
|
||||
#define VBUS_FRC_EN BIT(0)
|
||||
|
||||
|
||||
/*---------------- SSUSB_EPCTL_CSR REGISTER DEFINITION ----------------*/
|
||||
|
||||
#define U3D_DEVICE_CONF (SSUSB_EPCTL_CSR_BASE + 0x0000)
|
||||
#define U3D_EP_RST (SSUSB_EPCTL_CSR_BASE + 0x0004)
|
||||
|
||||
#define U3D_DEV_LINK_INTR_ENABLE (SSUSB_EPCTL_CSR_BASE + 0x0050)
|
||||
#define U3D_DEV_LINK_INTR (SSUSB_EPCTL_CSR_BASE + 0x0054)
|
||||
|
||||
/*---------------- SSUSB_EPCTL_CSR FIELD DEFINITION ----------------*/
|
||||
|
||||
/* U3D_DEVICE_CONF */
|
||||
#define DEV_ADDR_MSK GENMASK(30, 24)
|
||||
#define DEV_ADDR(x) ((0x7f & (x)) << 24)
|
||||
#define HW_USB2_3_SEL BIT(18)
|
||||
#define SW_USB2_3_SEL_EN BIT(17)
|
||||
#define SW_USB2_3_SEL BIT(16)
|
||||
#define SSUSB_DEV_SPEED(x) ((x) & 0x7)
|
||||
|
||||
/* U3D_EP_RST */
|
||||
#define EP1_IN_RST BIT(17)
|
||||
#define EP1_OUT_RST BIT(1)
|
||||
#define EP_RST(is_in, epnum) (((is_in) ? BIT(16) : BIT(0)) << (epnum))
|
||||
#define EP0_RST BIT(0)
|
||||
|
||||
/* U3D_DEV_LINK_INTR_ENABLE */
|
||||
/* U3D_DEV_LINK_INTR */
|
||||
#define SSUSB_DEV_SPEED_CHG_INTR BIT(0)
|
||||
|
||||
|
||||
/*---------------- SSUSB_USB3_MAC_CSR REGISTER DEFINITION ----------------*/
|
||||
|
||||
#define U3D_USB3_CONFIG (SSUSB_USB3_MAC_CSR_BASE + 0x001C)
|
||||
|
||||
/*---------------- SSUSB_USB3_MAC_CSR FIELD DEFINITION ----------------*/
|
||||
|
||||
/* U3D_USB3_CONFIG */
|
||||
#define USB3_EN BIT(0)
|
||||
|
||||
/*---------------- SSUSB_USB3_SYS_CSR REGISTER DEFINITION ----------------*/
|
||||
|
||||
#define U3D_LINK_UX_INACT_TIMER (SSUSB_USB3_SYS_CSR_BASE + 0x020C)
|
||||
#define U3D_LINK_POWER_CONTROL (SSUSB_USB3_SYS_CSR_BASE + 0x0210)
|
||||
#define U3D_LINK_ERR_COUNT (SSUSB_USB3_SYS_CSR_BASE + 0x0214)
|
||||
|
||||
/*---------------- SSUSB_USB3_SYS_CSR FIELD DEFINITION ----------------*/
|
||||
|
||||
/* U3D_LINK_UX_INACT_TIMER */
|
||||
#define DEV_U2_INACT_TIMEOUT_MSK GENMASK(23, 16)
|
||||
#define DEV_U2_INACT_TIMEOUT_VALUE(x) (((x) & 0xff) << 16)
|
||||
#define U2_INACT_TIMEOUT_MSK GENMASK(15, 8)
|
||||
#define U1_INACT_TIMEOUT_MSK GENMASK(7, 0)
|
||||
#define U1_INACT_TIMEOUT_VALUE(x) ((x) & 0xff)
|
||||
|
||||
/* U3D_LINK_POWER_CONTROL */
|
||||
#define SW_U2_ACCEPT_ENABLE BIT(9)
|
||||
#define SW_U1_ACCEPT_ENABLE BIT(8)
|
||||
#define UX_EXIT BIT(5)
|
||||
#define LGO_U3 BIT(4)
|
||||
#define LGO_U2 BIT(3)
|
||||
#define LGO_U1 BIT(2)
|
||||
#define SW_U2_REQUEST_ENABLE BIT(1)
|
||||
#define SW_U1_REQUEST_ENABLE BIT(0)
|
||||
|
||||
/* U3D_LINK_ERR_COUNT */
|
||||
#define CLR_LINK_ERR_CNT BIT(16)
|
||||
#define LINK_ERROR_COUNT GENMASK(15, 0)
|
||||
|
||||
/*---------------- SSUSB_USB2_CSR REGISTER DEFINITION ----------------*/
|
||||
|
||||
#define U3D_POWER_MANAGEMENT (SSUSB_USB2_CSR_BASE + 0x0004)
|
||||
#define U3D_DEVICE_CONTROL (SSUSB_USB2_CSR_BASE + 0x000C)
|
||||
#define U3D_USB2_TEST_MODE (SSUSB_USB2_CSR_BASE + 0x0014)
|
||||
#define U3D_COMMON_USB_INTR_ENABLE (SSUSB_USB2_CSR_BASE + 0x0018)
|
||||
#define U3D_COMMON_USB_INTR (SSUSB_USB2_CSR_BASE + 0x001C)
|
||||
#define U3D_LINK_RESET_INFO (SSUSB_USB2_CSR_BASE + 0x0024)
|
||||
#define U3D_USB20_FRAME_NUM (SSUSB_USB2_CSR_BASE + 0x003C)
|
||||
#define U3D_USB20_LPM_PARAMETER (SSUSB_USB2_CSR_BASE + 0x0044)
|
||||
#define U3D_USB20_MISC_CONTROL (SSUSB_USB2_CSR_BASE + 0x004C)
|
||||
|
||||
/*---------------- SSUSB_USB2_CSR FIELD DEFINITION ----------------*/
|
||||
|
||||
/* U3D_POWER_MANAGEMENT */
|
||||
#define LPM_BESL_STALL BIT(14)
|
||||
#define LPM_BESLD_STALL BIT(13)
|
||||
#define LPM_RWP BIT(11)
|
||||
#define LPM_HRWE BIT(10)
|
||||
#define LPM_MODE(x) (((x) & 0x3) << 8)
|
||||
#define ISO_UPDATE BIT(7)
|
||||
#define SOFT_CONN BIT(6)
|
||||
#define HS_ENABLE BIT(5)
|
||||
#define RESUME BIT(2)
|
||||
#define SUSPENDM_ENABLE BIT(0)
|
||||
|
||||
/* U3D_DEVICE_CONTROL */
|
||||
#define DC_HOSTREQ BIT(1)
|
||||
#define DC_SESSION BIT(0)
|
||||
|
||||
/* U3D_USB2_TEST_MODE */
|
||||
#define U2U3_AUTO_SWITCH BIT(10)
|
||||
#define LPM_FORCE_STALL BIT(8)
|
||||
#define FIFO_ACCESS BIT(6)
|
||||
#define FORCE_FS BIT(5)
|
||||
#define FORCE_HS BIT(4)
|
||||
#define TEST_PACKET_MODE BIT(3)
|
||||
#define TEST_K_MODE BIT(2)
|
||||
#define TEST_J_MODE BIT(1)
|
||||
#define TEST_SE0_NAK_MODE BIT(0)
|
||||
|
||||
/* U3D_COMMON_USB_INTR_ENABLE */
|
||||
/* U3D_COMMON_USB_INTR */
|
||||
#define LPM_RESUME_INTR BIT(9)
|
||||
#define LPM_INTR BIT(8)
|
||||
#define DISCONN_INTR BIT(5)
|
||||
#define CONN_INTR BIT(4)
|
||||
#define SOF_INTR BIT(3)
|
||||
#define RESET_INTR BIT(2)
|
||||
#define RESUME_INTR BIT(1)
|
||||
#define SUSPEND_INTR BIT(0)
|
||||
|
||||
/* U3D_LINK_RESET_INFO */
|
||||
#define WTCHRP_MSK GENMASK(19, 16)
|
||||
|
||||
/* U3D_USB20_LPM_PARAMETER */
|
||||
#define LPM_BESLCK_U3(x) (((x) & 0xf) << 12)
|
||||
#define LPM_BESLCK(x) (((x) & 0xf) << 8)
|
||||
#define LPM_BESLDCK(x) (((x) & 0xf) << 4)
|
||||
#define LPM_BESL GENMASK(3, 0)
|
||||
|
||||
/* U3D_USB20_MISC_CONTROL */
|
||||
#define LPM_U3_ACK_EN BIT(0)
|
||||
|
||||
/*---------------- SSUSB_SIFSLV_IPPC REGISTER DEFINITION ----------------*/
|
||||
|
||||
#define U3D_SSUSB_IP_PW_CTRL0 (SSUSB_SIFSLV_IPPC_BASE + 0x0000)
|
||||
#define U3D_SSUSB_IP_PW_CTRL1 (SSUSB_SIFSLV_IPPC_BASE + 0x0004)
|
||||
#define U3D_SSUSB_IP_PW_CTRL2 (SSUSB_SIFSLV_IPPC_BASE + 0x0008)
|
||||
#define U3D_SSUSB_IP_PW_CTRL3 (SSUSB_SIFSLV_IPPC_BASE + 0x000C)
|
||||
#define U3D_SSUSB_IP_PW_STS1 (SSUSB_SIFSLV_IPPC_BASE + 0x0010)
|
||||
#define U3D_SSUSB_IP_PW_STS2 (SSUSB_SIFSLV_IPPC_BASE + 0x0014)
|
||||
#define U3D_SSUSB_OTG_STS (SSUSB_SIFSLV_IPPC_BASE + 0x0018)
|
||||
#define U3D_SSUSB_OTG_STS_CLR (SSUSB_SIFSLV_IPPC_BASE + 0x001C)
|
||||
#define U3D_SSUSB_IP_XHCI_CAP (SSUSB_SIFSLV_IPPC_BASE + 0x0024)
|
||||
#define U3D_SSUSB_IP_DEV_CAP (SSUSB_SIFSLV_IPPC_BASE + 0x0028)
|
||||
#define U3D_SSUSB_OTG_INT_EN (SSUSB_SIFSLV_IPPC_BASE + 0x002C)
|
||||
#define U3D_SSUSB_U3_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE + 0x0030)
|
||||
#define U3D_SSUSB_U2_CTRL_0P (SSUSB_SIFSLV_IPPC_BASE + 0x0050)
|
||||
#define U3D_SSUSB_REF_CK_CTRL (SSUSB_SIFSLV_IPPC_BASE + 0x008C)
|
||||
#define U3D_SSUSB_DEV_RST_CTRL (SSUSB_SIFSLV_IPPC_BASE + 0x0098)
|
||||
#define U3D_SSUSB_HW_ID (SSUSB_SIFSLV_IPPC_BASE + 0x00A0)
|
||||
#define U3D_SSUSB_HW_SUB_ID (SSUSB_SIFSLV_IPPC_BASE + 0x00A4)
|
||||
#define U3D_SSUSB_IP_SPARE0 (SSUSB_SIFSLV_IPPC_BASE + 0x00C8)
|
||||
|
||||
/*---------------- SSUSB_SIFSLV_IPPC FIELD DEFINITION ----------------*/
|
||||
|
||||
/* U3D_SSUSB_IP_PW_CTRL0 */
|
||||
#define SSUSB_IP_SW_RST BIT(0)
|
||||
|
||||
/* U3D_SSUSB_IP_PW_CTRL1 */
|
||||
#define SSUSB_IP_HOST_PDN BIT(0)
|
||||
|
||||
/* U3D_SSUSB_IP_PW_CTRL2 */
|
||||
#define SSUSB_IP_DEV_PDN BIT(0)
|
||||
|
||||
/* U3D_SSUSB_IP_PW_CTRL3 */
|
||||
#define SSUSB_IP_PCIE_PDN BIT(0)
|
||||
|
||||
/* U3D_SSUSB_IP_PW_STS1 */
|
||||
#define SSUSB_IP_SLEEP_STS BIT(30)
|
||||
#define SSUSB_U3_MAC_RST_B_STS BIT(16)
|
||||
#define SSUSB_XHCI_RST_B_STS BIT(11)
|
||||
#define SSUSB_SYS125_RST_B_STS BIT(10)
|
||||
#define SSUSB_REF_RST_B_STS BIT(8)
|
||||
#define SSUSB_SYSPLL_STABLE BIT(0)
|
||||
|
||||
/* U3D_SSUSB_IP_PW_STS2 */
|
||||
#define SSUSB_U2_MAC_SYS_RST_B_STS BIT(0)
|
||||
|
||||
/* U3D_SSUSB_OTG_STS */
|
||||
#define SSUSB_VBUS_VALID BIT(9)
|
||||
|
||||
/* U3D_SSUSB_OTG_STS_CLR */
|
||||
#define SSUSB_VBUS_INTR_CLR BIT(6)
|
||||
|
||||
/* U3D_SSUSB_IP_XHCI_CAP */
|
||||
#define SSUSB_IP_XHCI_U2_PORT_NUM(x) (((x) >> 8) & 0xff)
|
||||
#define SSUSB_IP_XHCI_U3_PORT_NUM(x) ((x) & 0xff)
|
||||
|
||||
/* U3D_SSUSB_IP_DEV_CAP */
|
||||
#define SSUSB_IP_DEV_U3_PORT_NUM(x) ((x) & 0xff)
|
||||
|
||||
/* U3D_SSUSB_OTG_INT_EN */
|
||||
#define SSUSB_VBUS_CHG_INT_A_EN BIT(7)
|
||||
#define SSUSB_VBUS_CHG_INT_B_EN BIT(6)
|
||||
|
||||
/* U3D_SSUSB_U3_CTRL_0P */
|
||||
#define SSUSB_U3_PORT_HOST_SEL BIT(2)
|
||||
#define SSUSB_U3_PORT_PDN BIT(1)
|
||||
#define SSUSB_U3_PORT_DIS BIT(0)
|
||||
|
||||
/* U3D_SSUSB_U2_CTRL_0P */
|
||||
#define SSUSB_U2_PORT_OTG_SEL BIT(7)
|
||||
#define SSUSB_U2_PORT_HOST_SEL BIT(2)
|
||||
#define SSUSB_U2_PORT_PDN BIT(1)
|
||||
#define SSUSB_U2_PORT_DIS BIT(0)
|
||||
|
||||
/* U3D_SSUSB_DEV_RST_CTRL */
|
||||
#define SSUSB_DEV_SW_RST BIT(0)
|
||||
|
||||
#endif /* _SSUSB_HW_REGS_H_ */
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright (C) 2016 MediaTek Inc.
|
||||
*
|
||||
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include "mtu3.h"
|
||||
|
||||
/* u2-port0 should be powered on and enabled; */
|
||||
int ssusb_check_clocks(struct mtu3 *mtu, u32 ex_clks)
|
||||
{
|
||||
void __iomem *ibase = mtu->ippc_base;
|
||||
u32 value, check_val;
|
||||
int ret;
|
||||
|
||||
check_val = ex_clks | SSUSB_SYS125_RST_B_STS | SSUSB_SYSPLL_STABLE |
|
||||
SSUSB_REF_RST_B_STS;
|
||||
|
||||
ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS1, value,
|
||||
(check_val == (value & check_val)), 100, 20000);
|
||||
if (ret) {
|
||||
dev_err(mtu->dev, "clks of sts1 are not stable!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = readl_poll_timeout(ibase + U3D_SSUSB_IP_PW_STS2, value,
|
||||
(value & SSUSB_U2_MAC_SYS_RST_B_STS), 100, 10000);
|
||||
if (ret) {
|
||||
dev_err(mtu->dev, "mac2 clock is not stable\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssusb_rscs_init(struct mtu3 *mtu)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = regulator_enable(mtu->vusb33);
|
||||
if (ret) {
|
||||
dev_err(mtu->dev, "failed to enable vusb33\n");
|
||||
goto vusb33_err;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(mtu->sys_clk);
|
||||
if (ret) {
|
||||
dev_err(mtu->dev, "failed to enable sys_clk\n");
|
||||
goto clk_err;
|
||||
}
|
||||
|
||||
ret = phy_init(mtu->phy);
|
||||
if (ret) {
|
||||
dev_err(mtu->dev, "failed to init phy\n");
|
||||
goto phy_init_err;
|
||||
}
|
||||
|
||||
ret = phy_power_on(mtu->phy);
|
||||
if (ret) {
|
||||
dev_err(mtu->dev, "failed to power on phy\n");
|
||||
goto phy_err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
phy_err:
|
||||
phy_exit(mtu->phy);
|
||||
|
||||
phy_init_err:
|
||||
clk_disable_unprepare(mtu->sys_clk);
|
||||
|
||||
clk_err:
|
||||
regulator_disable(mtu->vusb33);
|
||||
|
||||
vusb33_err:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ssusb_rscs_exit(struct mtu3 *mtu)
|
||||
{
|
||||
clk_disable_unprepare(mtu->sys_clk);
|
||||
regulator_disable(mtu->vusb33);
|
||||
phy_power_off(mtu->phy);
|
||||
phy_exit(mtu->phy);
|
||||
}
|
||||
|
||||
static void ssusb_ip_sw_reset(struct mtu3 *mtu)
|
||||
{
|
||||
mtu3_setbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST);
|
||||
udelay(1);
|
||||
mtu3_clrbits(mtu->ippc_base, U3D_SSUSB_IP_PW_CTRL0, SSUSB_IP_SW_RST);
|
||||
}
|
||||
|
||||
static int get_ssusb_rscs(struct platform_device *pdev, struct mtu3 *mtu)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *res;
|
||||
|
||||
mtu->phy = devm_of_phy_get_by_index(dev, node, 0);
|
||||
if (IS_ERR(mtu->phy)) {
|
||||
dev_err(dev, "failed to get phy\n");
|
||||
return PTR_ERR(mtu->phy);
|
||||
}
|
||||
|
||||
mtu->irq = platform_get_irq(pdev, 0);
|
||||
if (mtu->irq <= 0) {
|
||||
dev_err(dev, "fail to get irq number\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_info(dev, "irq %d\n", mtu->irq);
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mac");
|
||||
mtu->mac_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(mtu->mac_base)) {
|
||||
dev_err(dev, "error mapping memory for dev mac\n");
|
||||
return PTR_ERR(mtu->mac_base);
|
||||
}
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ippc");
|
||||
mtu->ippc_base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(mtu->ippc_base)) {
|
||||
dev_err(dev, "failed to map memory for ippc\n");
|
||||
return PTR_ERR(mtu->ippc_base);
|
||||
}
|
||||
|
||||
mtu->vusb33 = devm_regulator_get(&pdev->dev, "vusb33");
|
||||
if (IS_ERR(mtu->vusb33)) {
|
||||
dev_err(dev, "failed to get vusb33\n");
|
||||
return PTR_ERR(mtu->vusb33);
|
||||
}
|
||||
|
||||
mtu->sys_clk = devm_clk_get(dev, "sys_ck");
|
||||
if (IS_ERR(mtu->sys_clk)) {
|
||||
dev_err(dev, "failed to get sys clock\n");
|
||||
return PTR_ERR(mtu->sys_clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mtu3_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mtu3 *mtu;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
/* all elements are set to ZERO as default value */
|
||||
mtu = devm_kzalloc(dev, sizeof(struct mtu3), GFP_KERNEL);
|
||||
if (!mtu)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
|
||||
if (ret) {
|
||||
dev_err(dev, "No suitable DMA config available\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, mtu);
|
||||
mtu->dev = dev;
|
||||
spin_lock_init(&mtu->lock);
|
||||
|
||||
ret = get_ssusb_rscs(pdev, mtu);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* enable power domain */
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
device_enable_async_suspend(dev);
|
||||
|
||||
ret = ssusb_rscs_init(mtu);
|
||||
if (ret)
|
||||
goto comm_init_err;
|
||||
|
||||
ssusb_ip_sw_reset(mtu);
|
||||
|
||||
ret = ssusb_gadget_init(mtu);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to initialize gadget\n");
|
||||
goto comm_exit;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
comm_exit:
|
||||
ssusb_rscs_exit(mtu);
|
||||
|
||||
comm_init_err:
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mtu3_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mtu3 *mtu = platform_get_drvdata(pdev);
|
||||
|
||||
ssusb_gadget_exit(mtu);
|
||||
ssusb_rscs_exit(mtu);
|
||||
pm_runtime_put_sync(&pdev->dev);
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
|
||||
static const struct of_device_id mtu3_of_match[] = {
|
||||
{.compatible = "mediatek,mt8173-mtu3",},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, mtu3_of_match);
|
||||
|
||||
#endif
|
||||
|
||||
static struct platform_driver mtu3_driver = {
|
||||
.probe = mtu3_probe,
|
||||
.remove = mtu3_remove,
|
||||
.driver = {
|
||||
.name = MTU3_DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(mtu3_of_match),
|
||||
},
|
||||
};
|
||||
module_platform_driver(mtu3_driver);
|
||||
|
||||
MODULE_AUTHOR("Chunfeng Yun <chunfeng.yun@mediatek.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("MediaTek USB3 DRD Controller Driver");
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* mtu3_qmu.h - Queue Management Unit driver header
|
||||
*
|
||||
* Copyright (C) 2016 MediaTek Inc.
|
||||
*
|
||||
* Author: Chunfeng Yun <chunfeng.yun@mediatek.com>
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MTK_QMU_H__
|
||||
#define __MTK_QMU_H__
|
||||
|
||||
#define MAX_GPD_NUM 64
|
||||
#define QMU_GPD_SIZE (sizeof(struct qmu_gpd))
|
||||
#define QMU_GPD_RING_SIZE (MAX_GPD_NUM * QMU_GPD_SIZE)
|
||||
|
||||
#define GPD_BUF_SIZE 65532
|
||||
|
||||
void mtu3_qmu_stop(struct mtu3_ep *mep);
|
||||
int mtu3_qmu_start(struct mtu3_ep *mep);
|
||||
void mtu3_qmu_resume(struct mtu3_ep *mep);
|
||||
void mtu3_qmu_flush(struct mtu3_ep *mep);
|
||||
|
||||
void mtu3_insert_gpd(struct mtu3_ep *mep, struct mtu3_request *mreq);
|
||||
int mtu3_prepare_transfer(struct mtu3_ep *mep);
|
||||
|
||||
int mtu3_gpd_ring_alloc(struct mtu3_ep *mep);
|
||||
void mtu3_gpd_ring_free(struct mtu3_ep *mep);
|
||||
|
||||
irqreturn_t mtu3_qmu_isr(struct mtu3 *mtu);
|
||||
int mtu3_qmu_init(struct mtu3 *mtu);
|
||||
void mtu3_qmu_exit(struct mtu3 *mtu);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user