/*
* linux/drivers/usb/gadget/s3c2410_udc.c
*
* Samsung S3C24xx series on-chip full speed USB device controllers
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/gpio.h>
#include <linux/prefetch.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
#include <linux/usb.h>
#include <linux/usb/gadget.h>
#include <asm/byteorder.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <plat/regs-udc.h>
#include <plat/udc.h>
#include "s3c2410_udc.h"
#define DRIVER_DESC "S3C2410 USB Device Controller Gadget"
#define DRIVER_VERSION "29 Apr 2007"
#define DRIVER_AUTHOR "Herbert P�tzl <[email protected]>, " \
"Arnaud Patard <[email protected]>"
static const char gadget_name[] = "s3c2410_udc";
static const char driver_desc[] = DRIVER_DESC;
static struct s3c2410_udc *the_controller;
static struct clk *udc_clock;
static struct clk *usb_bus_clock;
static void __iomem *base_addr;
static u64 rsrc_start;
static u64 rsrc_len;
static struct dentry *s3c2410_udc_debugfs_root;
static inline u32 udc_read(u32 reg)
{
return readb(base_addr + reg);
}
static inline void udc_write(u32 value, u32 reg)
{
writeb(value, base_addr + reg);
}
static inline void udc_writeb(void __iomem *base, u32 value, u32 reg)
{
writeb(value, base + reg);
}
static struct s3c2410_udc_mach_info *udc_info;
/*************************** DEBUG FUNCTION ***************************/
#define DEBUG_NORMAL 1
#define DEBUG_VERBOSE 2
#ifdef CONFIG_USB_S3C2410_DEBUG
#define USB_S3C2410_DEBUG_LEVEL 0
static uint32_t s3c2410_ticks = 0;
static int dprintk(int level, const char *fmt, ...)
{
static char printk_buf[1024];
static long prevticks;
static int invocation;
va_list args;
int len;
if (level > USB_S3C2410_DEBUG_LEVEL)
return 0;
if (s3c2410_ticks != prevticks) {
prevticks = s3c2410_ticks;
invocation = 0;
}
len = scnprintf(printk_buf,
sizeof(printk_buf), "%1lu.%02d USB: ",
prevticks, invocation++);
va_start(args, fmt);
len = vscnprintf(printk_buf+len,
sizeof(printk_buf)-len, fmt, args);
va_end(args);
return printk(KERN_DEBUG "%s", printk_buf);
}
#else
static int dprintk(int level, const char *fmt, ...)
{
return 0;
}
#endif
static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
{
u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
u32 ep_int_en_reg, usb_int_en_reg, ep0_csr;
u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2;
u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2;
addr_reg = udc_read(S3C2410_UDC_FUNC_ADDR_REG);
pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
ep_int_reg = udc_read(S3C2410_UDC_EP_INT_REG);
usb_int_reg = udc_read(S3C2410_UDC_USB_INT_REG);
ep_int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG);
usb_int_en_reg = udc_read(S3C2410_UDC_USB_INT_EN_REG);
udc_write(0, S3C2410_UDC_INDEX_REG);
ep0_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
udc_write(1, S3C2410_UDC_INDEX_REG);
ep1_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
ep1_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
ep1_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
ep1_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
udc_write(2, S3C2410_UDC_INDEX_REG);
ep2_i_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
ep2_i_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
ep2_o_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
ep2_o_csr2 = udc_read(S3C2410_UDC_IN_CSR2_REG);
seq_printf(m, "FUNC_ADDR_REG : 0x%04X\n"
"PWR_REG : 0x%04X\n"
"EP_INT_REG : 0x%04X\n"
"USB_INT_REG : 0x%04X\n"
"EP_INT_EN_REG : 0x%04X\n"
"USB_INT_EN_REG : 0x%04X\n"
"EP0_CSR : 0x%04X\n"
"EP1_I_CSR1 : 0x%04X\n"
"EP1_I_CSR2 : 0x%04X\n"
"EP1_O_CSR1 : 0x%04X\n"
"EP1_O_CSR2 : 0x%04X\n"
"EP2_I_CSR1 : 0x%04X\n"
"EP2_I_CSR2 : 0x%04X\n"
"EP2_O_CSR1 : 0x%04X\n"
"EP2_O_CSR2 : 0x%04X\n",
addr_reg,pwr_reg,ep_int_reg,usb_int_reg,
ep_int_en_reg, usb_int_en_reg, ep0_csr,
ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2,
ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2
);
return 0;
}
static int s3c2410_udc_debugfs_fops_open(struct inode *inode,
struct file *file)
{
return single_open(file, s3c2410_udc_debugfs_seq_show, NULL);
}
static const struct file_operations s3c2410_udc_debugfs_fops = {
.open = s3c2410_udc_debugfs_fops_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
.owner = THIS_MODULE,
};
/* io macros */
static inline void s3c2410_udc_clear_ep0_opr(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(base, S3C2410_UDC_EP0_CSR_SOPKTRDY,
S3C2410_UDC_EP0_CSR_REG);
}
static inline void s3c2410_udc_clear_ep0_sst(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
writeb(0x00, base + S3C2410_UDC_EP0_CSR_REG);
}
static inline void s3c2410_udc_clear_ep0_se(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(base, S3C2410_UDC_EP0_CSR_SSE, S3C2410_UDC_EP0_CSR_REG);
}
static inline void s3c2410_udc_set_ep0_ipr(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(base, S3C2410_UDC_EP0_CSR_IPKRDY, S3C2410_UDC_EP0_CSR_REG);
}
static inline void s3c2410_udc_set_ep0_de(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(base, S3C2410_UDC_EP0_CSR_DE, S3C2410_UDC_EP0_CSR_REG);
}
inline void s3c2410_udc_set_ep0_ss(void __iomem *b)
{
udc_writeb(b, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(b, S3C2410_UDC_EP0_CSR_SENDSTL, S3C2410_UDC_EP0_CSR_REG);
}
static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY
| S3C2410_UDC_EP0_CSR_DE),
S3C2410_UDC_EP0_CSR_REG);
}
static inline void s3c2410_udc_set_ep0_sse_out(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY
| S3C2410_UDC_EP0_CSR_SSE),
S3C2410_UDC_EP0_CSR_REG);
}
static inline void s3c2410_udc_set_ep0_de_in(void __iomem *base)
{
udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
udc_writeb(base, (S3C2410_UDC_EP0_CSR_IPKRDY
| S3C2410_UDC_EP0_CSR_DE),
S3C2410_UDC_EP0_CSR_REG);
}
/*------------------------- I/O ----------------------------------*/
/*
* s3c2410_udc_done
*/
static void s3c2410_udc_done(struct s3c2410_ep *ep,
struct s3c2410_request *req, int status)
{
unsigned halted = ep->halted;
list_del_init(&req->queue);
if (likely (req->req.status == -EINPROGRESS))
req->req.status = status;
else
status = req->req.status;
ep->halted = 1;
req->req.complete(&ep->ep, &req->req);
ep->halted = halted;
}
static void s3c2410_udc_nuke(struct s3c2410_udc *udc,
struct s3c2410_ep *ep, int status)
{
/* Sanity check */
if (&ep->queue == NULL)
return;
while (!list_empty (&ep->queue)) {
struct s3c2410_request *req;
req = list_entry (ep->queue.next, struct s3c2410_request,
queue);
s3c2410_udc_done(ep, req, status);
}
}
static inline void s3c2410_udc_clear_ep_state(struct s3c2410_udc *dev)
{
unsigned i;
/* hardware SET_{CONFIGURATION,INTERFACE} automagic resets endpoint
* fifos, and pending transactions mustn't be continued in any case.
*/
for (i = 1; i < S3C2410_ENDPOINTS; i++)
s3c2410_udc_nuke(dev, &dev->ep[i], -ECONNABORTED);
}
static inline int s3c2410_udc_fifo_count_out(void)
{
int tmp;
tmp = udc_read(S3C2410_UDC_OUT_FIFO_CNT2_REG) << 8;
tmp |= udc_read(S3C2410_UDC_OUT_
s3c2410_udc.zip_s3c2410_udc
版权申诉
3 浏览量
2022-09-22
22:55:20
上传
评论
收藏 12KB ZIP 举报
御道御小黑
- 粉丝: 61
- 资源: 1万+
最新资源
- 微信小程序 - 图书管理系统源码.zip
- 微信小程序 - 图片自适应 ,富文本解析源码.zip
- 微信小程序 - 同乐居商城:购物车合算源码
- 1、根据输入的三条边值判断能组成何种三角形,并设计测试数据进行判定覆盖测试 三条边为变量a、b、c,范围为1≤边值≤10,不在范
- SQL server 练习题目8道(小白教学).zip
- Python 手写实现 iD3 决策树算法-根据信息增益公式.zip
- 411675952289057车联助手-小窗版(三星)3.5.1.apk
- 三种快速排序方法合并在一个文件中以便直接运行的Python代码示例
- 937712277954201实习5.word
- 2程序语言基础知识pdf1_1716337722703.jpeg
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
评论0