s3c-hsotg.c revision 19c190f9e0fe926db28122a804111a7538dc3498
15b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/* linux/drivers/usb/gadget/s3c-hsotg.c 25b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 35b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Copyright 2008 Openmoko, Inc. 45b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Copyright 2008 Simtec Electronics 55b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Ben Dooks <ben@simtec.co.uk> 65b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * http://armlinux.simtec.co.uk/ 75b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 85b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * S3C USB2.0 High-speed / OtG driver 95b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This program is free software; you can redistribute it and/or modify 115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * it under the terms of the GNU General Public License version 2 as 125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * published by the Free Software Foundation. 135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/kernel.h> 165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/module.h> 175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/spinlock.h> 185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/interrupt.h> 195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/platform_device.h> 205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/dma-mapping.h> 215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/debugfs.h> 225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/seq_file.h> 235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/delay.h> 245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/io.h> 255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/usb/ch9.h> 285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <linux/usb/gadget.h> 295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <mach/map.h> 315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <plat/regs-usb-hsotg-phy.h> 335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <plat/regs-usb-hsotg.h> 34f9fed7cd7efaa0d050f21f6f9ed532d3143b7369Mark Brown#include <mach/regs-sys.h> 355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#include <plat/udc-hs.h> 365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define DMA_ADDR_INVALID (~((dma_addr_t)0)) 385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/* EP0_MPS_LIMIT 405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Unfortunately there seems to be a limit of the amount of data that can 425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * be transfered by IN transactions on EP0. This is either 127 bytes or 3 435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * packets (which practially means 1 packet and 63 bytes of data) when the 445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * MPS is set to 64. 455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This means if we are wanting to move >127 bytes of data, we need to 475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * split the transactions up, but just doing one packet at a time does 485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * not work (this may be an implicit DATA0 PID on first packet of the 495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * transaction) and doing 2 packets is outside the controller's limits. 505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * If we try to lower the MPS size for EP0, then no transfers work properly 525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * for EP0, and the system will fail basic enumeration. As no cause for this 535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * has currently been found, we cannot support any large IN transfers for 545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * EP0. 555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define EP0_MPS_LIMIT 64 575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstruct s3c_hsotg; 595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstruct s3c_hsotg_req; 605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * struct s3c_hsotg_ep - driver endpoint definition. 635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The gadget layer representation of the endpoint. 645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @name: The driver generated name for the endpoint. 655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @queue: Queue of requests for this endpoint. 665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @parent: Reference back to the parent device structure. 675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @req: The current request that the endpoint is processing. This is 685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * used to indicate an request has been loaded onto the endpoint 695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * and has yet to be completed (maybe due to data move, or simply 705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * awaiting an ack from the core all the data has been completed). 715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @debugfs: File entry for debugfs file for this endpoint. 725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @lock: State lock to protect contents of endpoint. 735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @dir_in: Set to true if this endpoint is of the IN direction, which 745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * means that it is sending data to the Host. 755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @index: The index for the endpoint registers. 765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @name: The name array passed to the USB core. 775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @halted: Set if the endpoint has been halted. 785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @periodic: Set if this is a periodic ep, such as Interrupt 795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @sent_zlp: Set if we've sent a zero-length packet. 805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @total_data: The total number of data bytes done. 815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @fifo_size: The size of the FIFO (for periodic IN endpoints) 825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @fifo_load: The amount of data loaded into the FIFO (periodic IN) 835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @last_load: The offset of data for the last start of request. 845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @size_loaded: The last loaded size for DxEPTSIZE for periodic IN 855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This is the driver's state for each registered enpoint, allowing it 875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to keep track of transactions that need doing. Each endpoint has a 885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * lock to protect the state, to try and avoid using an overall lock 895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * for the host controller as much as possible. 905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * For periodic IN endpoints, we have fifo_size and fifo_load to try 925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * and keep track of the amount of data in the periodic FIFO for each 935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * of these as we don't have a status register that tells us how much 945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * is in each of them. 955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstruct s3c_hsotg_ep { 975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_ep ep; 985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct list_head queue; 995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *parent; 1005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *req; 1015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct dentry *debugfs; 1025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spinlock_t lock; 1045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long total_data; 1065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int size_loaded; 1075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int last_load; 1085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int fifo_load; 1095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned short fifo_size; 1105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned char dir_in; 1125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned char index; 1135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int halted:1; 1155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int periodic:1; 1165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int sent_zlp:1; 1175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks char name[10]; 1195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 1205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define S3C_HSOTG_EPS (8+1) /* limit to 9 for the moment */ 1225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 1245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * struct s3c_hsotg - driver state. 1255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @dev: The parent device supplied to the probe function 1265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @driver: USB gadget driver 1275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @plat: The platform specific configuration data. 1285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @regs: The memory area mapped for accessing registers. 1295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @regs_res: The resource that was allocated when claiming register space. 1305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @irq: The IRQ number we are using 1315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @debug_root: root directrory for debugfs. 1325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @debug_file: main status file for debugfs. 1335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @debug_fifo: FIFO status file for debugfs. 1345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep0_reply: Request used for ep0 reply. 1355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep0_buff: Buffer for EP0 reply data, if needed. 1365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ctrl_buff: Buffer for EP0 control requests. 1375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ctrl_req: Request for EP0 control packets. 1385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @eps: The endpoints being supplied to the gadget framework 1395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 1405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstruct s3c_hsotg { 1415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct device *dev; 1425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_gadget_driver *driver; 1435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_plat *plat; 1445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void __iomem *regs; 1465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct resource *regs_res; 1475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int irq; 1485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct dentry *debug_root; 1505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct dentry *debug_file; 1515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct dentry *debug_fifo; 1525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *ep0_reply; 1545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *ctrl_req; 1555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u8 ep0_buff[8]; 1565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u8 ctrl_buff[8]; 1575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_gadget gadget; 1595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep eps[]; 1605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 1615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 1635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * struct s3c_hsotg_req - data transfer request 1645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @req: The USB gadget request 1655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @queue: The list of requests for the endpoint this is queued for. 1665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @in_progress: Has already had size/packets written to core 1675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @mapped: DMA buffer for this request has been mapped via dma_map_single(). 1685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 1695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstruct s3c_hsotg_req { 1705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request req; 1715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct list_head queue; 1725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned char in_progress; 1735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned char mapped; 1745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 1755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/* conversion functions */ 1775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic inline struct s3c_hsotg_req *our_req(struct usb_request *req) 1785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 1795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return container_of(req, struct s3c_hsotg_req, req); 1805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 1815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic inline struct s3c_hsotg_ep *our_ep(struct usb_ep *ep) 1835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 1845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return container_of(ep, struct s3c_hsotg_ep, ep); 1855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 1865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic inline struct s3c_hsotg *to_hsotg(struct usb_gadget *gadget) 1885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 1895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return container_of(gadget, struct s3c_hsotg, gadget); 1905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 1915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic inline void __orr32(void __iomem *ptr, u32 val) 1935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 1945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(readl(ptr) | val, ptr); 1955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 1965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 1975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic inline void __bic32(void __iomem *ptr, u32 val) 1985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 1995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(readl(ptr) & ~val, ptr); 2005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 2015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/* forward decleration of functions */ 2035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_dump(struct s3c_hsotg *hsotg); 2045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 2065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * using_dma - return the DMA status of the driver. 2075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The driver state. 2085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 2095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Return true if we're using DMA. 2105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 2115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Currently, we have the DMA support code worked into everywhere 2125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * that needs it, but the AMBA DMA implementation in the hardware can 2135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * only DMA from 32bit aligned addresses. This means that gadgets such 2145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * as the CDC Ethernet cannot work as they often pass packets which are 2155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * not 32bit aligned. 2165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 2175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Unfortunately the choice to use DMA or not is global to the controller 2185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * and seems to be only settable when the controller is being put through 2195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * a core reset. This means we either need to fix the gadgets to take 2205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * account of DMA alignment, or add bounce buffers (yuerk). 2215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 2225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Until this issue is sorted out, we always return 'false'. 2235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 2245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic inline bool using_dma(struct s3c_hsotg *hsotg) 2255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 2265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return false; /* support is not complete */ 2275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 2285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 2305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_en_gsint - enable one or more of the general interrupt 2315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 2325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ints: A bitmask of the interrupts to enable 2335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 2345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_en_gsint(struct s3c_hsotg *hsotg, u32 ints) 2355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 2365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); 2375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 new_gsintmsk; 2385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks new_gsintmsk = gsintmsk | ints; 2405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (new_gsintmsk != gsintmsk) { 2425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "gsintmsk now 0x%08x\n", new_gsintmsk); 2435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); 2445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 2455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 2465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 2485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_disable_gsint - disable one or more of the general interrupt 2495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 2505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ints: A bitmask of the interrupts to enable 2515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 2525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_disable_gsint(struct s3c_hsotg *hsotg, u32 ints) 2535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 2545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 gsintmsk = readl(hsotg->regs + S3C_GINTMSK); 2555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 new_gsintmsk; 2565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks new_gsintmsk = gsintmsk & ~ints; 2585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (new_gsintmsk != gsintmsk) 2605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(new_gsintmsk, hsotg->regs + S3C_GINTMSK); 2615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 2625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 2645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_ctrl_epint - enable/disable an endpoint irq 2655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 2665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The endpoint index 2675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @dir_in: True if direction is in. 2685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @en: The enable value, true to enable 2695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 2705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Set or clear the mask for an individual endpoint's interrupt 2715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * request. 2725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 2735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_ctrl_epint(struct s3c_hsotg *hsotg, 2745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int ep, unsigned int dir_in, 2755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int en) 2765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 2775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 2785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 bit = 1 << ep; 2795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 daint; 2805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!dir_in) 2825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks bit <<= 16; 2835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks local_irq_save(flags); 2855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks daint = readl(hsotg->regs + S3C_DAINTMSK); 2865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (en) 2875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks daint |= bit; 2885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 2895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks daint &= ~bit; 2905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(daint, hsotg->regs + S3C_DAINTMSK); 2915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks local_irq_restore(flags); 2925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 2935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 2955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_init_fifo - initialise non-periodic FIFOs 2965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device instance. 2975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 2985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_init_fifo(struct s3c_hsotg *hsotg) 2995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 3005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* the ryu 2.6.24 release ahs 3015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(0x1C0, hsotg->regs + S3C_GRXFSIZ); 3025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GNPTXFSIZ_NPTxFStAddr(0x200) | 3035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GNPTXFSIZ_NPTxFDep(0x1C0), 3045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GNPTXFSIZ); 3055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 3065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* set FIFO sizes to 2048/0x1C0 */ 3085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(2048, hsotg->regs + S3C_GRXFSIZ); 3105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GNPTXFSIZ_NPTxFStAddr(2048) | 3115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GNPTXFSIZ_NPTxFDep(0x1C0), 3125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GNPTXFSIZ); 3135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 3145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 3165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: USB endpoint to allocate request for. 3175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @flags: Allocation flags 3185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 3195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Allocate a new USB request structure appropriate for the specified endpoint 3205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 3210978f8c55cdc7c06b2f1440b030e93fda2c53b2bMark Brownstatic struct usb_request *s3c_hsotg_ep_alloc_request(struct usb_ep *ep, 3220978f8c55cdc7c06b2f1440b030e93fda2c53b2bMark Brown gfp_t flags) 3235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 3245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *req; 3255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req = kzalloc(sizeof(struct s3c_hsotg_req), flags); 3275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!req) 3285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return NULL; 3295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks INIT_LIST_HEAD(&req->queue); 3315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->req.dma = DMA_ADDR_INVALID; 3335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return &req->req; 3345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 3355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 3375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * is_ep_periodic - return true if the endpoint is in periodic mode. 3385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint to query. 3395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 3405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Returns true if the endpoint is in periodic mode, meaning it is being 3415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * used for an Interrupt or ISO transfer. 3425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 3435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic inline int is_ep_periodic(struct s3c_hsotg_ep *hs_ep) 3445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 3455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return hs_ep->periodic; 3465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 3475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 3495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_unmap_dma - unmap the DMA memory being used for the request 3505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 3515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint for the request 3525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_req: The request being processed. 3535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 3545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This is the reverse of s3c_hsotg_map_dma(), called for the completion 3555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * of a request to ensure the buffer is ready for access by the caller. 3565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 3575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_unmap_dma(struct s3c_hsotg *hsotg, 3585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep, 3595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req) 3605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 3615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req = &hs_req->req; 3625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks enum dma_data_direction dir; 3635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE; 3655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* ignore this if we're not moving any data */ 3675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req->req.length == 0) 3685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 3695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req->mapped) { 3715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* we mapped this, so unmap and remove the dma */ 3725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dma_unmap_single(hsotg->dev, req->dma, req->length, dir); 3745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->dma = DMA_ADDR_INVALID; 3765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->mapped = 0; 3775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else { 3785b520259ab6d661b8d5eb39dd17cc5e4e4553c62FUJITA Tomonori dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); 3795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 3805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 3815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 3825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 3835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_write_fifo - write packet Data to the TxFIFO 3845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The controller state. 3855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint we're going to write for. 3865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_req: The request to write data for. 3875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 3885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This is called when the TxFIFO has some space in it to hold a new 3895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * transmission and we have something to give it. The actual setup of 3905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * the data size is done elsewhere, so all we have to do is to actually 3915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * write the data. 3925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 3935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * The return value is zero if there is more space (or nothing was done) 3945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * otherwise -ENOSPC is returned if the FIFO space was used up. 3955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 3965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This routine is only needed for PIO 3975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 3985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, 3995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep, 4005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req) 4015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 4025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks bool periodic = is_ep_periodic(hs_ep); 4035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 gnptxsts = readl(hsotg->regs + S3C_GNPTXSTS); 4045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int buf_pos = hs_req->req.actual; 4055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int to_write = hs_ep->size_loaded; 4065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void *data; 4075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int can_write; 4085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int pkt_round; 4095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks to_write -= (buf_pos - hs_ep->last_load); 4115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* if there's nothing to write, get out early */ 4135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (to_write == 0) 4145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 4155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (periodic) { 4175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); 4185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int size_left; 4195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int size_done; 4205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* work out how much data was loaded so we can calculate 4225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * how much data is left in the fifo. */ 4235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); 4255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: left=%d, load=%d, fifo=%d, size %d\n", 4275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, size_left, 4285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->size_loaded, hs_ep->fifo_load, hs_ep->fifo_size); 4295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* how much of the data has moved */ 4315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_done = hs_ep->size_loaded - size_left; 4325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* how much data is left in the fifo */ 4345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks can_write = hs_ep->fifo_load - size_done; 4355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: => can_write1=%d\n", 4365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, can_write); 4375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks can_write = hs_ep->fifo_size - can_write; 4395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: => can_write2=%d\n", 4405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, can_write); 4415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (can_write <= 0) { 4435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_PTxFEmp); 4445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOSPC; 4455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 4465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else { 4475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (S3C_GNPTXSTS_NPTxQSpcAvail_GET(gnptxsts) == 0) { 4485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, 4495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "%s: no queue slots available (0x%08x)\n", 4505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, gnptxsts); 4515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); 4535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOSPC; 4545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 4555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks can_write = S3C_GNPTXSTS_NPTxFSpcAvail_GET(gnptxsts); 4575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 4585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", 4605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket); 4615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* limit to 512 bytes of data, it seems at least on the non-periodic 4635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * FIFO, requests of >512 cause the endpoint to get stuck with a 4645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * fragment of the end of the transfer in it. 4655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 4665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (can_write > 512) 4675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks can_write = 512; 4685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* see if we can write data */ 4705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (to_write > can_write) { 4725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks to_write = can_write; 4735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks pkt_round = to_write % hs_ep->ep.maxpacket; 4745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Not sure, but we probably shouldn't be writing partial 4765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * packets into the FIFO, so round the write down to an 4775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * exact number of packets. 4785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 4795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Note, we do not currently check to see if we can ever 4805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * write a full packet or not to the FIFO. 4815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 4825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (pkt_round) 4845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks to_write -= pkt_round; 4855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* enable correct FIFO interrupt to alert us when there 4875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * is more room left. */ 4885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_en_gsint(hsotg, 4905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks periodic ? S3C_GINTSTS_PTxFEmp : 4915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_NPTxFEmp); 4925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 4935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "write %d/%d, can_write %d, done %d\n", 4955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks to_write, hs_req->req.length, can_write, buf_pos); 4965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 4975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (to_write <= 0) 4985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOSPC; 4995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->req.actual = buf_pos + to_write; 5015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->total_data += to_write; 5025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (periodic) 5045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->fifo_load += to_write; 5055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks to_write = DIV_ROUND_UP(to_write, 4); 5075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks data = hs_req->req.buf + buf_pos; 5085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writesl(hsotg->regs + S3C_EPFIFO(hs_ep->index), data, to_write); 5105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return (to_write >= can_write) ? -ENOSPC : 0; 5125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 5135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 5155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * get_ep_limit - get the maximum data legnth for this endpoint 5165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint 5175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 5185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Return the maximum data that can be queued in one go on a given endpoint 5195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * so that transfers that are too long can be split. 5205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 5215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic unsigned get_ep_limit(struct s3c_hsotg_ep *hs_ep) 5225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 5235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int index = hs_ep->index; 5245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned maxsize; 5255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned maxpkt; 5265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (index != 0) { 5285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxsize = S3C_DxEPTSIZ_XferSize_LIMIT + 1; 5295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxpkt = S3C_DxEPTSIZ_PktCnt_LIMIT + 1; 5305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else { 5315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_ep->dir_in) { 5325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* maxsize = S3C_DIEPTSIZ0_XferSize_LIMIT + 1; */ 5335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxsize = 64+64+1; 5345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxpkt = S3C_DIEPTSIZ0_PktCnt_LIMIT + 1; 5355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else { 5365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxsize = 0x3f; 5375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxpkt = 2; 5385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 5395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 5405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* we made the constant loading easier above by using +1 */ 5425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxpkt--; 5435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxsize--; 5445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* constrain by packet count if maxpkts*pktsize is greater 5465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * than the length register size. */ 5475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if ((maxpkt * hs_ep->ep.maxpacket) < maxsize) 5495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxsize = maxpkt * hs_ep->ep.maxpacket; 5505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return maxsize; 5525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 5535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 5555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_start_req - start a USB request from an endpoint's queue 5565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The controller state. 5575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint to process a request for 5585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_req: The request to start. 5595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @continuing: True if we are doing more for the current request. 5605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 5615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Start the given request running by setting the endpoint registers 5625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * appropriately, and writing any data to the FIFOs. 5635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 5645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, 5655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep, 5665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req, 5675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks bool continuing) 5685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 5695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *ureq = &hs_req->req; 5705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int index = hs_ep->index; 5715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int dir_in = hs_ep->dir_in; 5725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epctrl_reg; 5735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epsize_reg; 5745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epsize; 5755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 ctrl; 5765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned length; 5775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned packets; 5785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned maxreq; 5795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (index != 0) { 5815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_ep->req && !continuing) { 5825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: active request\n", __func__); 5835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON(1); 5845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 5855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else if (hs_ep->req != hs_req && continuing) { 5865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, 5875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "%s: continue different req\n", __func__); 5885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON(1); 5895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 5905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 5915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 5925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); 5945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epsize_reg = dir_in ? S3C_DIEPTSIZ(index) : S3C_DOEPTSIZ(index); 5955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 5965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x, ep %d, dir %s\n", 5975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, readl(hsotg->regs + epctrl_reg), index, 5985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->dir_in ? "in" : "out"); 5995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks length = ureq->length - ureq->actual; 6015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (0) 6035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, 6045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "REQ buf %p len %d dma 0x%08x noi=%d zp=%d snok=%d\n", 6055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ureq->buf, length, ureq->dma, 6065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ureq->no_interrupt, ureq->zero, ureq->short_not_ok); 6075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxreq = get_ep_limit(hs_ep); 6095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (length > maxreq) { 6105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int round = maxreq % hs_ep->ep.maxpacket; 6115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: length %d, max-req %d, r %d\n", 6135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, length, maxreq, round); 6145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* round down to multiple of packets */ 6165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (round) 6175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks maxreq -= round; 6185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks length = maxreq; 6205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 6215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (length) 6235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks packets = DIV_ROUND_UP(length, hs_ep->ep.maxpacket); 6245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 6255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks packets = 1; /* send one packet if length is zero. */ 6265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in && index != 0) 6285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epsize = S3C_DxEPTSIZ_MC(1); 6295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 6305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epsize = 0; 6315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (index != 0 && ureq->zero) { 6335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* test for the packets being exactly right for the 6345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * transfer */ 6355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (length == (packets * hs_ep->ep.maxpacket)) 6375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks packets++; 6385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 6395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epsize |= S3C_DxEPTSIZ_PktCnt(packets); 6415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epsize |= S3C_DxEPTSIZ_XferSize(length); 6425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: %d@%d/%d, 0x%08x => 0x%08x\n", 6445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, packets, length, ureq->length, epsize, epsize_reg); 6455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* store the request as the current one we're doing */ 6475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->req = hs_req; 6485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* write size / packets */ 6505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(epsize, hsotg->regs + epsize_reg); 6515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl = readl(hsotg->regs + epctrl_reg); 6535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ctrl & S3C_DxEPCTL_Stall) { 6555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index); 6565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* not sure what we can do here, if it is EP0 then we should 6585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * get this cleared once the endpoint has transmitted the 6595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * STALL packet, otherwise it needs to be cleared by the 6605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * host. 6615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 6625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 6635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (using_dma(hsotg)) { 6655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int dma_reg; 6665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* write DMA address to control register, buffer already 6685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * synced by s3c_hsotg_ep_queue(). */ 6695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dma_reg = dir_in ? S3C_DIEPDMA(index) : S3C_DOEPDMA(index); 6715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(ureq->dma, hsotg->regs + dma_reg); 6725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: 0x%08x => 0x%08x\n", 6745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, ureq->dma, dma_reg); 6755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 6765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ 6785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_USBActEp; 6795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ 6805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); 6825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(ctrl, hsotg->regs + epctrl_reg); 6835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* set these, it seems that DMA support increments past the end 6855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * of the packet buffer so we need to calculate the length from 6865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * this information. */ 6875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->size_loaded = length; 6885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->last_load = ureq->actual; 6895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in && !using_dma(hsotg)) { 6915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* set these anyway, we may need them for non-periodic in */ 6925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->fifo_load = 0; 6935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); 6955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 6965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 6975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* clear the INTknTXFEmpMsk when we start request, more as a aide 6985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to debugging to see what is going on. */ 6995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in) 7005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DIEPMSK_INTknTXFEmpMsk, 7015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DIEPINT(index)); 7025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Note, trying to clear the NAK here causes problems with transmit 7045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * on the S3C6400 ending up with the TXFIFO becomming full. */ 7055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* check ep is enabled */ 7075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!(readl(hsotg->regs + epctrl_reg) & S3C_DxEPCTL_EPEna)) 7085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, 7095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "ep%d: failed to become enabled (DxEPCTL=0x%08x)?\n", 7105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks index, readl(hsotg->regs + epctrl_reg)); 7115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", 7135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, readl(hsotg->regs + epctrl_reg)); 7145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 7155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 7175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_map_dma - map the DMA memory being used for the request 7185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 7195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint the request is on. 7205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @req: The request being processed. 7215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 7225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * We've been asked to queue a request, so ensure that the memory buffer 7235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * is correctly setup for DMA. If we've been passed an extant DMA address 7245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * then ensure the buffer has been synced to memory. If our buffer has no 7255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * DMA memory, then we map the memory and mark our request to allow us to 7265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * cleanup on completion. 7275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 7285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_map_dma(struct s3c_hsotg *hsotg, 7295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep, 7305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req) 7315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 7325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks enum dma_data_direction dir; 7335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = our_req(req); 7345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dir = hs_ep->dir_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE; 7365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* if the length is zero, ignore the DMA data */ 7385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req->req.length == 0) 7395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 7405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (req->dma == DMA_ADDR_INVALID) { 7425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dma_addr_t dma; 7435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dma = dma_map_single(hsotg->dev, req->buf, req->length, dir); 7455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (unlikely(dma_mapping_error(hsotg->dev, dma))) 7475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto dma_error; 7485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dma & 3) { 7505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: unaligned dma buffer\n", 7515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__); 7525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dma_unmap_single(hsotg->dev, dma, req->length, dir); 7545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 7555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 7565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->mapped = 1; 7585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->dma = dma; 7595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else { 7605b520259ab6d661b8d5eb39dd17cc5e4e4553c62FUJITA Tomonori dma_sync_single_for_cpu(hsotg->dev, req->dma, req->length, dir); 7615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->mapped = 0; 7625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 7635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 7655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksdma_error: 7675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: failed to map buffer %p, %d bytes\n", 7685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, req->buf, req->length); 7695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EIO; 7715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 7725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, 7745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks gfp_t gfp_flags) 7755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 7765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = our_req(req); 7775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = our_ep(ep); 7785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hs = hs_ep->parent; 7795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long irqflags; 7805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks bool first; 7815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hs->dev, "%s: req %p: %d@%p, noi=%d, zero=%d, snok=%d\n", 7835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep->name, req, req->length, req->buf, req->no_interrupt, 7845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->zero, req->short_not_ok); 7855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* initialise status of the request */ 7875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks INIT_LIST_HEAD(&hs_req->queue); 7885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->actual = 0; 7895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->status = -EINPROGRESS; 7905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* if we're using DMA, sync the buffers as necessary */ 7925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (using_dma(hs)) { 7935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ret = s3c_hsotg_map_dma(hs, hs_ep, req); 7945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret) 7955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return ret; 7965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 7975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 7985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&hs_ep->lock, irqflags); 7995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks first = list_empty(&hs_ep->queue); 8015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks list_add_tail(&hs_req->queue, &hs_ep->queue); 8025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (first) 8045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_start_req(hs, hs_ep, hs_req, false); 8055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&hs_ep->lock, irqflags); 8075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 8095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 8105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_ep_free_request(struct usb_ep *ep, 8125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req) 8135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 8145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = our_req(req); 8155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kfree(hs_req); 8175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 8185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 8205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_complete_oursetup - setup completion callback 8215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The endpoint the request was on. 8225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @req: The request completed. 8235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 8245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Called on completion of any requests the driver itself 8255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * submitted that need cleaning up. 8265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 8275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_complete_oursetup(struct usb_ep *ep, 8285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req) 8295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 8305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = our_ep(ep); 8315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = hs_ep->parent; 8325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: ep %p, req %p\n", __func__, ep, req); 8345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_ep_free_request(ep, req); 8365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 8375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 8395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * ep_from_windex - convert control wIndex value to endpoint 8405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The driver state. 8415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @windex: The control request wIndex field (in host order). 8425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 8435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Convert the given wIndex into a pointer to an driver endpoint 8445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * structure, or return NULL if it is not a valid endpoint. 8455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 8465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic struct s3c_hsotg_ep *ep_from_windex(struct s3c_hsotg *hsotg, 8475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 windex) 8485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 8495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep = &hsotg->eps[windex & 0x7F]; 8505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int dir = (windex & USB_DIR_IN) ? 1 : 0; 8515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int idx = windex & 0x7F; 8525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (windex >= 0x100) 8545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return NULL; 8555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (idx > S3C_HSOTG_EPS) 8575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return NULL; 8585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (idx && ep->dir_in != dir) 8605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return NULL; 8615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return ep; 8635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 8645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 8665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_send_reply - send reply to control request 8675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 8685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: Endpoint 0 8695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @buff: Buffer for request 8705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @length: Length of reply. 8715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 8725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Create a request and queue it on the given endpoint. This is useful as 8735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * an internal method of sending replies to certain control requests, etc. 8745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 8755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_send_reply(struct s3c_hsotg *hsotg, 8765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep, 8775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void *buff, 8785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int length) 8795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 8805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req; 8815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ret; 8825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: buff %p, len %d\n", __func__, buff, length); 8845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req = s3c_hsotg_ep_alloc_request(&ep->ep, GFP_ATOMIC); 8865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->ep0_reply = req; 8875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!req) { 8885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "%s: cannot alloc req\n", __func__); 8895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOMEM; 8905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 8915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->buf = hsotg->ep0_buff; 8935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->length = length; 8945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->zero = 1; /* always do zero-length final transfer */ 8955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->complete = s3c_hsotg_complete_oursetup; 8965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 8975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (length) 8985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks memcpy(req->buf, buff, length); 8995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 9005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep->sent_zlp = 1; 9015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_ep_queue(&ep->ep, req, GFP_ATOMIC); 9035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret) { 9045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "%s: cannot queue req\n", __func__); 9055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return ret; 9065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 9075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 9095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 9105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 9125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_process_req_status - process request GET_STATUS 9135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 9145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ctrl: USB control request 9155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 9165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_process_req_status(struct s3c_hsotg *hsotg, 9175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_ctrlrequest *ctrl) 9185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 9195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; 9205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep; 9215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __le16 reply; 9225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ret; 9235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: USB_REQ_GET_STATUS\n", __func__); 9255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!ep0->dir_in) { 9275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "%s: direction out?\n", __func__); 9285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 9295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 9305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks switch (ctrl->bRequestType & USB_RECIP_MASK) { 9325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_RECIP_DEVICE: 9335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reply = cpu_to_le16(0); /* bit 0 => self powered, 9345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * bit 1 => remote wakeup */ 9355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 9365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_RECIP_INTERFACE: 9385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* currently, the data result should be zero */ 9395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reply = cpu_to_le16(0); 9405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 9415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_RECIP_ENDPOINT: 9435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep = ep_from_windex(hsotg, le16_to_cpu(ctrl->wIndex)); 9445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!ep) 9455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOENT; 9465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reply = cpu_to_le16(ep->halted ? 1 : 0); 9485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 9495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks default: 9515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 9525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 9535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (le16_to_cpu(ctrl->wLength) != 2) 9555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 9565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_send_reply(hsotg, ep0, &reply, 2); 9585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret) { 9595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: failed to send reply\n", __func__); 9605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return ret; 9615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 9625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 1; 9645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 9655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value); 9675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 9695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_process_req_featire - process request {SET,CLEAR}_FEATURE 9705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 9715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ctrl: USB control request 9725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 9735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg, 9745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_ctrlrequest *ctrl) 9755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 9765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks bool set = (ctrl->bRequest == USB_REQ_SET_FEATURE); 9775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep; 9785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: %s_FEATURE\n", 9805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, set ? "SET" : "CLEAR"); 9815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ctrl->bRequestType == USB_RECIP_ENDPOINT) { 9835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep = ep_from_windex(hsotg, le16_to_cpu(ctrl->wIndex)); 9845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!ep) { 9855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: no endpoint for 0x%04x\n", 9865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, le16_to_cpu(ctrl->wIndex)); 9875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOENT; 9885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 9895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks switch (le16_to_cpu(ctrl->wValue)) { 9915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_ENDPOINT_HALT: 9925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_ep_sethalt(&ep->ep, set); 9935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 9945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 9955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks default: 9965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOENT; 9975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 9985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else 9995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOENT; /* currently only deal with endpoint */ 10005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 1; 10025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 10035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 10055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_process_control - process a control request 10065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 10075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ctrl: The control request received 10085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 10095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * The controller has received the SETUP phase of a control request, and 10105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * needs to work out what to do next (and whether to pass it on to the 10115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * gadget driver). 10125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 10135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_process_control(struct s3c_hsotg *hsotg, 10145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_ctrlrequest *ctrl) 10155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 10165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep0 = &hsotg->eps[0]; 10175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ret = 0; 10185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 dcfg; 10195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep0->sent_zlp = 0; 10215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n", 10235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl->bRequest, ctrl->bRequestType, 10245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl->wValue, ctrl->wLength); 10255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* record the direction of the request, for later use when enquing 10275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * packets onto EP0. */ 10285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep0->dir_in = (ctrl->bRequestType & USB_DIR_IN) ? 1 : 0; 10305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "ctrl: dir_in=%d\n", ep0->dir_in); 10315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* if we've no data with this request, then the last part of the 10335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * transaction is going to implicitly be IN. */ 10345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ctrl->wLength == 0) 10355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep0->dir_in = 1; 10365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if ((ctrl->bRequestType & USB_TYPE_MASK) == USB_TYPE_STANDARD) { 10385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks switch (ctrl->bRequest) { 10395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_REQ_SET_ADDRESS: 10405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dcfg = readl(hsotg->regs + S3C_DCFG); 10415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dcfg &= ~S3C_DCFG_DevAddr_MASK; 10425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dcfg |= ctrl->wValue << S3C_DCFG_DevAddr_SHIFT; 10435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(dcfg, hsotg->regs + S3C_DCFG); 10445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "new address %d\n", ctrl->wValue); 10465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); 10485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 10495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_REQ_GET_STATUS: 10515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_process_req_status(hsotg, ctrl); 10525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 10535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_REQ_CLEAR_FEATURE: 10555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_REQ_SET_FEATURE: 10565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_process_req_feature(hsotg, ctrl); 10575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 10585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 10595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 10605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* as a fallback, try delivering it to the driver to deal with */ 10625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret == 0 && hsotg->driver) { 10645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = hsotg->driver->setup(&hsotg->gadget, ctrl); 10655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret < 0) 10665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "driver->setup() ret %d\n", ret); 10675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 10685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret > 0) { 10705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!ep0->dir_in) { 10715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* need to generate zlp in reply or take data */ 10725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* todo - deal with any data we might be sent? */ 10735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_send_reply(hsotg, ep0, NULL, 0); 10745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 10755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 10765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* the request is either unhandlable, or is not formatted correctly 10785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * so respond with a STALL for the status stage to indicate failure. 10795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 10805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret < 0) { 10825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 reg; 10835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 ctrl; 10845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in); 10865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reg = (ep0->dir_in) ? S3C_DIEPCTL0 : S3C_DOEPCTL0; 10875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* S3C_DxEPCTL_Stall will be cleared by EP once it has 10895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * taken effect, so no need to clear later. */ 10905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl = readl(hsotg->regs + reg); 10925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_Stall; 10935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_CNAK; 10945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(ctrl, hsotg->regs + reg); 10955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 10965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, 10975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "writen DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n", 10985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl, reg, readl(hsotg->regs + reg)); 10995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* don't belive we need to anything more to get the EP 11015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to reply with a STALL packet */ 11025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 11035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 11045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg); 11065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 11085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_complete_setup - completion of a setup transfer 11095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The endpoint the request was on. 11105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @req: The request completed. 11115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 11125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Called on completion of any requests the driver itself submitted for 11135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * EP0 setup packets 11145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 11155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_complete_setup(struct usb_ep *ep, 11165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req) 11175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 11185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = our_ep(ep); 11195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = hs_ep->parent; 11205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (req->status < 0) { 11225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: failed %d\n", __func__, req->status); 11235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 11245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 11255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (req->actual == 0) 11275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_enqueue_setup(hsotg); 11285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 11295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_process_control(hsotg, req->buf); 11305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 11315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 11335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_enqueue_setup - start a request for EP0 packets 11345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 11355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 11365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Enqueue a request on EP0 if necessary to received any SETUP packets 11375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * received from the host. 11385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 11395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg) 11405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 11415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req = hsotg->ctrl_req; 11425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = our_req(req); 11435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ret; 11445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: queueing setup request\n", __func__); 11465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->zero = 0; 11485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->length = 8; 11495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->buf = hsotg->ctrl_buff; 11505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->complete = s3c_hsotg_complete_setup; 11515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!list_empty(&hs_req->queue)) { 11535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s already queued???\n", __func__); 11545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 11555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 11565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->eps[0].dir_in = 0; 11585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_ep_queue(&hsotg->eps[0].ep, req, GFP_ATOMIC); 11605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret < 0) { 11615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: failed queue (%d)\n", __func__, ret); 11625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Don't think there's much we can do other than watch the 11635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * driver fail. */ 11645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 11655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 11665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 11685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * get_ep_head - return the first request on the endpoint 11695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The controller endpoint to get 11705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 11715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Get the first request on the endpoint. 11725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 11735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic struct s3c_hsotg_req *get_ep_head(struct s3c_hsotg_ep *hs_ep) 11745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 11755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (list_empty(&hs_ep->queue)) 11765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return NULL; 11775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return list_first_entry(&hs_ep->queue, struct s3c_hsotg_req, queue); 11795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 11805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 11815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 11825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_complete_request - complete a request given to us 11835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 11845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint the request was on. 11855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_req: The request to complete. 11865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @result: The result code (0 => Ok, otherwise errno) 11875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 11885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * The given request has finished, so call the necessary completion 11895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * if it has one and then look to see if we can start a new request 11905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * on the endpoint. 11915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 11925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Note, expects the ep to already be locked as appropriate. 11935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 11945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_complete_request(struct s3c_hsotg *hsotg, 11955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep, 11965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req, 11975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int result) 11985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 11995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks bool restart; 12005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hs_req) { 12025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: nothing to complete?\n", __func__); 12035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 12045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 12055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "complete: ep %p %s, req %p, %d => %p\n", 12075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep, hs_ep->ep.name, hs_req, result, hs_req->req.complete); 12085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* only replace the status if we've not already set an error 12105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * from a previous transaction */ 12115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req->req.status == -EINPROGRESS) 12135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->req.status = result; 12145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->req = NULL; 12165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks list_del_init(&hs_req->queue); 12175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (using_dma(hsotg)) 12195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_unmap_dma(hsotg, hs_ep, hs_req); 12205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* call the complete request with the locks off, just in case the 12225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * request tries to queue more work for this endpoint. */ 12235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req->req.complete) { 12255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock(&hs_ep->lock); 12265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->req.complete(&hs_ep->ep, &hs_req->req); 12275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock(&hs_ep->lock); 12285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 12295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Look to see if there is anything else to do. Note, the completion 12315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * of the previous request may have caused a new request to be started 12325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * so be careful when doing this. */ 12335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hs_ep->req && result >= 0) { 12355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks restart = !list_empty(&hs_ep->queue); 12365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (restart) { 12375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req = get_ep_head(hs_ep); 12385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_start_req(hsotg, hs_ep, hs_req, false); 12395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 12405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 12415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 12425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 12445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_complete_request_lock - complete a request given to us (locked) 12455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 12465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint the request was on. 12475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_req: The request to complete. 12485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @result: The result code (0 => Ok, otherwise errno) 12495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 12505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * See s3c_hsotg_complete_request(), but called with the endpoint's 12515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * lock held. 12525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 12535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_complete_request_lock(struct s3c_hsotg *hsotg, 12545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep, 12555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req, 12565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int result) 12575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 12585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 12595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&hs_ep->lock, flags); 12615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_complete_request(hsotg, hs_ep, hs_req, result); 12625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&hs_ep->lock, flags); 12635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 12645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 12665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_rx_data - receive data from the FIFO for an endpoint 12675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 12685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep_idx: The endpoint index for the data 12695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @size: The size of data in the fifo, in bytes 12705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 12715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * The FIFO status shows there is data to read from the FIFO for a given 12725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * endpoint, so sort out whether we need to read the data into a request 12735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * that has been made for that endpoint. 12745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 12755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_rx_data(struct s3c_hsotg *hsotg, int ep_idx, int size) 12765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 12775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep_idx]; 12785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = hs_ep->req; 12795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void __iomem *fifo = hsotg->regs + S3C_EPFIFO(ep_idx); 12805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int to_read; 12815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int max_req; 12825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int read_ptr; 12835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hs_req) { 12855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epctl = readl(hsotg->regs + S3C_DOEPCTL(ep_idx)); 12865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ptr; 12875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, 12895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "%s: FIFO %d bytes on ep%d but no req (DxEPCTl=0x%08x)\n", 12905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, size, ep_idx, epctl); 12915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* dump the data from the FIFO, we've nothing we can do */ 12935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (ptr = 0; ptr < size; ptr += 4) 12945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks (void)readl(fifo); 12955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 12975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 12985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 12995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock(&hs_ep->lock); 13005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks to_read = size; 13025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks read_ptr = hs_req->req.actual; 13035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks max_req = hs_req->req.length - read_ptr; 13045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (to_read > max_req) { 13065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* more data appeared than we where willing 13075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to deal with in this request. 13085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 13095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* currently we don't deal this */ 13115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON_ONCE(1); 13125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 13135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: read %d/%d, done %d/%d\n", 13155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, to_read, max_req, read_ptr, hs_req->req.length); 13165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->total_data += to_read; 13185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->req.actual += to_read; 13195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks to_read = DIV_ROUND_UP(to_read, 4); 13205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* note, we might over-write the buffer end by 3 bytes depending on 13225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * alignment of the data. */ 13235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readsl(fifo, hs_req->req.buf + read_ptr, to_read); 13245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock(&hs_ep->lock); 13265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 13275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 13295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_send_zlp - send zero-length packet on control endpoint 13305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device instance 13315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @req: The request currently on this endpoint 13325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 13335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Generate a zero-length IN packet request for terminating a SETUP 13345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * transaction. 13355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 13365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Note, since we don't write any data to the TxFIFO, then it is 13375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * currently belived that we do not need to wait for any space in 13385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * the TxFIFO. 13395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 13405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_send_zlp(struct s3c_hsotg *hsotg, 13415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *req) 13425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 13435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 ctrl; 13445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!req) { 13465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "%s: no request?\n", __func__); 13475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 13485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 13495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (req->req.length == 0) { 13515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->eps[0].sent_zlp = 1; 13525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_enqueue_setup(hsotg); 13535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 13545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 13555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->eps[0].dir_in = 1; 13575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->eps[0].sent_zlp = 1; 13585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "sending zero-length packet\n"); 13605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* issue a zero-sized packet to terminate this */ 13625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | 13635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DxEPTSIZ_XferSize(0), hsotg->regs + S3C_DIEPTSIZ(0)); 13645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl = readl(hsotg->regs + S3C_DIEPCTL0); 13665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_CNAK; /* clear NAK set by core */ 13675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_EPEna; /* ensure ep enabled */ 13685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_USBActEp; 13695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(ctrl, hsotg->regs + S3C_DIEPCTL0); 13705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 13715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 13735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_handle_outdone - handle receiving OutDone/SetupDone from RXFIFO 13745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device instance 13755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @epnum: The endpoint received from 13765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @was_setup: Set if processing a SetupDone event. 13775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 13785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * The RXFIFO has delivered an OutDone event, which means that the data 13795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * transfer for an OUT endpoint has been completed, either by a short 13805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * packet or by the finish of a transfer. 13815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 13825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_handle_outdone(struct s3c_hsotg *hsotg, 13835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int epnum, bool was_setup) 13845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 13855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = &hsotg->eps[epnum]; 13865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = hs_ep->req; 13875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct usb_request *req = &hs_req->req; 13885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int result = 0; 13895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hs_req) { 13915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: no request active\n", __func__); 13925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 13935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 13945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 13955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (using_dma(hsotg)) { 13965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epsize = readl(hsotg->regs + S3C_DOEPTSIZ(epnum)); 13975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned size_done; 13985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned size_left; 13995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Calculate the size of the transfer by checking how much 14015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * is left in the endpoint size register and then working it 14025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * out from the amount we loaded for the transfer. 14035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 14045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * We need to do this as DMA pointers are always 32bit aligned 14055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * so may overshoot/undershoot the transfer. 14065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 14075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); 14095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_done = hs_ep->size_loaded - size_left; 14115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_done += hs_ep->last_load; 14125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->actual = size_done; 14145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 14155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (req->actual < req->length && req->short_not_ok) { 14175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: got %d/%d (short not ok) => error\n", 14185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, req->actual, req->length); 14195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* todo - what should we return here? there's no one else 14215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * even bothering to check the status. */ 14225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 14235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (epnum == 0) { 14255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!was_setup && req->complete != s3c_hsotg_complete_setup) 14265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_send_zlp(hsotg, hs_req); 14275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 14285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, result); 14305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 14315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 14335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_read_frameno - read current frame number 14345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device instance 14355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 14365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Return the current frame number 14375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 14385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic u32 s3c_hsotg_read_frameno(struct s3c_hsotg *hsotg) 14395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 14405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 dsts; 14415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dsts = readl(hsotg->regs + S3C_DSTS); 14435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dsts &= S3C_DSTS_SOFFN_MASK; 14445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dsts >>= S3C_DSTS_SOFFN_SHIFT; 14455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return dsts; 14475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 14485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 14505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_handle_rx - RX FIFO has data 14515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device instance 14525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 14535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * The IRQ handler has detected that the RX FIFO has some data in it 14545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * that requires processing, so find out what is in there and do the 14555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * appropriate read. 14565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 14575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * The RXFIFO is a true FIFO, the packets comming out are still in packet 14585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * chunks, so if you have x packets received on an endpoint you'll get x 14595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * FIFO events delivered, each with a packet's worth of data in it. 14605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 14615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * When using DMA, we should not be processing events from the RXFIFO 14625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * as the actual data should be sent to the memory directly and we turn 14635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * on the completion interrupts to get notifications of transfer completion. 14645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 14650978f8c55cdc7c06b2f1440b030e93fda2c53b2bMark Brownstatic void s3c_hsotg_handle_rx(struct s3c_hsotg *hsotg) 14665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 14675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 grxstsr = readl(hsotg->regs + S3C_GRXSTSP); 14685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epnum, status, size; 14695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON(using_dma(hsotg)); 14715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epnum = grxstsr & S3C_GRXSTS_EPNum_MASK; 14735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks status = grxstsr & S3C_GRXSTS_PktSts_MASK; 14745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size = grxstsr & S3C_GRXSTS_ByteCnt_MASK; 14765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size >>= S3C_GRXSTS_ByteCnt_SHIFT; 14775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (1) 14795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: GRXSTSP=0x%08x (%d@%d)\n", 14805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, grxstsr, size, epnum); 14815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define __status(x) ((x) >> S3C_GRXSTS_PktSts_SHIFT) 14835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks switch (status >> S3C_GRXSTS_PktSts_SHIFT) { 14855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case __status(S3C_GRXSTS_PktSts_GlobalOutNAK): 14865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "GlobalOutNAK\n"); 14875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 14885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case __status(S3C_GRXSTS_PktSts_OutDone): 14905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "OutDone (Frame=0x%08x)\n", 14915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_read_frameno(hsotg)); 14925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!using_dma(hsotg)) 14945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_handle_outdone(hsotg, epnum, false); 14955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 14965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 14975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case __status(S3C_GRXSTS_PktSts_SetupDone): 14985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, 14995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "SetupDone (Frame=0x%08x, DOPEPCTL=0x%08x)\n", 15005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_read_frameno(hsotg), 15015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DOEPCTL(0))); 15025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_handle_outdone(hsotg, epnum, true); 15045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 15055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case __status(S3C_GRXSTS_PktSts_OutRX): 15075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_rx_data(hsotg, epnum, size); 15085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 15095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case __status(S3C_GRXSTS_PktSts_SetupRX): 15115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, 15125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "SetupRX (Frame=0x%08x, DOPEPCTL=0x%08x)\n", 15135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_read_frameno(hsotg), 15145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DOEPCTL(0))); 15155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_rx_data(hsotg, epnum, size); 15175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 15185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks default: 15205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "%s: unknown status %08x\n", 15215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, grxstsr); 15225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_dump(hsotg); 15245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 15255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 15265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 15275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 15295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_ep0_mps - turn max packet size into register setting 15305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @mps: The maximum packet size in bytes. 15315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 15325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic u32 s3c_hsotg_ep0_mps(unsigned int mps) 15335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 15345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks switch (mps) { 15355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case 64: 15365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return S3C_D0EPCTL_MPS_64; 15375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case 32: 15385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return S3C_D0EPCTL_MPS_32; 15395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case 16: 15405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return S3C_D0EPCTL_MPS_16; 15415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case 8: 15425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return S3C_D0EPCTL_MPS_8; 15435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 15445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* bad max packet size, warn and return invalid result */ 15465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON(1); 15475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return (u32)-1; 15485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 15495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 15515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_set_ep_maxpacket - set endpoint's max-packet field 15525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The driver state. 15535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The index number of the endpoint 15545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @mps: The maximum packet size in bytes 15555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 15565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Configure the maximum packet size for the given endpoint, updating 15575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * the hardware control registers to reflect this. 15585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 15595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, 15605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned int ep, unsigned int mps) 15615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 15625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep]; 15635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void __iomem *regs = hsotg->regs; 15645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 mpsval; 15655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 reg; 15665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ep == 0) { 15685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* EP0 is a special case */ 15695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks mpsval = s3c_hsotg_ep0_mps(mps); 15705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (mpsval > 3) 15715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto bad_mps; 15725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else { 15735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (mps >= S3C_DxEPCTL_MPS_LIMIT+1) 15745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto bad_mps; 15755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks mpsval = mps; 15775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 15785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->ep.maxpacket = mps; 15805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* update both the in and out endpoint controldir_ registers, even 15825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * if one of the directions may not be in use. */ 15835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reg = readl(regs + S3C_DIEPCTL(ep)); 15855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reg &= ~S3C_DxEPCTL_MPS_MASK; 15865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reg |= mpsval; 15875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(reg, regs + S3C_DIEPCTL(ep)); 15885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reg = readl(regs + S3C_DOEPCTL(ep)); 15905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reg &= ~S3C_DxEPCTL_MPS_MASK; 15915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks reg |= mpsval; 15925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(reg, regs + S3C_DOEPCTL(ep)); 15935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 15955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 15965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksbad_mps: 15975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "ep%d: bad mps of %d\n", ep, mps); 15985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 15995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 16025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_trytx - check to see if anything needs transmitting 16035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The driver state 16045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The driver endpoint to check. 16055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 16065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Check to see if there is a request that has data to send, and if so 16075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * make an attempt to write data into the FIFO. 16085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 16095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_trytx(struct s3c_hsotg *hsotg, 16105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep) 16115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 16125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = hs_ep->req; 16135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hs_ep->dir_in || !hs_req) 16155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 16165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req->req.actual < hs_req->req.length) { 16185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "trying to write more for ep%d\n", 16195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->index); 16205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return s3c_hsotg_write_fifo(hsotg, hs_ep, hs_req); 16215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 16225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 16245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 16255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 16275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_complete_in - complete IN transfer 16285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 16295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint that has just completed. 16305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 16315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * An IN transfer has been completed, update the transfer's state and then 16325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * call the relevant completion routines. 16335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 16345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_complete_in(struct s3c_hsotg *hsotg, 16355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep) 16365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 16375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = hs_ep->req; 16385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epsize = readl(hsotg->regs + S3C_DIEPTSIZ(hs_ep->index)); 16395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int size_left, size_done; 16405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hs_req) { 16425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "XferCompl but no req\n"); 16435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 16445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 16455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Calculate the size of the transfer by checking how much is left 16475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * in the endpoint size register and then working it out from 16485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * the amount we loaded for the transfer. 16495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 16505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * We do this even for DMA, as the transfer may have incremented 16515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * past the end of the buffer (DMA transfers are always 32bit 16525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * aligned). 16535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 16545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_left = S3C_DxEPTSIZ_XferSize_GET(epsize); 16565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_done = hs_ep->size_loaded - size_left; 16585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks size_done += hs_ep->last_load; 16595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req->req.actual != size_done) 16615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: adjusting size done %d => %d\n", 16625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, hs_req->req.actual, size_done); 16635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_req->req.actual = size_done; 16655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* if we did all of the transfer, and there is more data left 16675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * around, then try restarting the rest of the request */ 16685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!size_left && hs_req->req.actual < hs_req->req.length) { 16705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s trying more for req...\n", __func__); 16715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_start_req(hsotg, hs_ep, hs_req, true); 16725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else 16735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_complete_request_lock(hsotg, hs_ep, hs_req, 0); 16745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 16755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 16775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_epint - handle an in/out endpoint interrupt 16785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The driver state 16795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @idx: The index for the endpoint (0..15) 16805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @dir_in: Set if this is an IN endpoint 16815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 16825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Process and clear any interrupt pending for an individual endpoint 16835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 16845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_epint(struct s3c_hsotg *hsotg, unsigned int idx, 16855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int dir_in) 16865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 16875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = &hsotg->eps[idx]; 16885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epint_reg = dir_in ? S3C_DIEPINT(idx) : S3C_DOEPINT(idx); 16895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epctl_reg = dir_in ? S3C_DIEPCTL(idx) : S3C_DOEPCTL(idx); 16905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epsiz_reg = dir_in ? S3C_DIEPTSIZ(idx) : S3C_DOEPTSIZ(idx); 16915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 ints; 16925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 clear = 0; 16935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ints = readl(hsotg->regs + epint_reg); 16955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: ep%d(%s) DxEPINT=0x%08x\n", 16975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, idx, dir_in ? "in" : "out", ints); 16985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 16995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ints & S3C_DxEPINT_XferCompl) { 17005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, 17015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "%s: XferCompl: DxEPCTL=0x%08x, DxEPTSIZ=%08x\n", 17025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, readl(hsotg->regs + epctl_reg), 17035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + epsiz_reg)); 17045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* we get OutDone from the FIFO, so we only need to look 17065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * at completing IN requests here */ 17075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in) { 17085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_complete_in(hsotg, hs_ep); 17095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (idx == 0) 17115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_enqueue_setup(hsotg); 17125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else if (using_dma(hsotg)) { 17135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* We're using DMA, we need to fire an OutDone here 17145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * as we ignore the RXFIFO. */ 17155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_handle_outdone(hsotg, idx, false); 17175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks clear |= S3C_DxEPINT_XferCompl; 17205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ints & S3C_DxEPINT_EPDisbld) { 17235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: EPDisbld\n", __func__); 17245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks clear |= S3C_DxEPINT_EPDisbld; 17255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ints & S3C_DxEPINT_AHBErr) { 17285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: AHBErr\n", __func__); 17295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks clear |= S3C_DxEPINT_AHBErr; 17305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ints & S3C_DxEPINT_Setup) { /* Setup or Timeout */ 17335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: Setup/Timeout\n", __func__); 17345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (using_dma(hsotg) && idx == 0) { 17365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* this is the notification we've received a 17375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * setup packet. In non-DMA mode we'd get this 17385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * from the RXFIFO, instead we need to process 17395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * the setup here. */ 17405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in) 17425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON_ONCE(1); 17435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 17445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_handle_outdone(hsotg, 0, true); 17455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks clear |= S3C_DxEPINT_Setup; 17485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ints & S3C_DxEPINT_Back2BackSetup) { 17515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: B2BSetup/INEPNakEff\n", __func__); 17525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks clear |= S3C_DxEPINT_Back2BackSetup; 17535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in) { 17565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* not sure if this is important, but we'll clear it anyway 17575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 17585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ints & S3C_DIEPMSK_INTknTXFEmpMsk) { 17595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: ep%d: INTknTXFEmpMsk\n", 17605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, idx); 17615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks clear |= S3C_DIEPMSK_INTknTXFEmpMsk; 17625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* this probably means something bad is happening */ 17655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ints & S3C_DIEPMSK_INTknEPMisMsk) { 17665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "%s: ep%d: INTknEP\n", 17675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, idx); 17685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks clear |= S3C_DIEPMSK_INTknEPMisMsk; 17695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 17715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(clear, hsotg->regs + epint_reg); 17735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 17745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 17765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_irq_enumdone - Handle EnumDone interrupt (enumeration done) 17775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 17785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 17795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Handle updating the device settings after the enumeration phase has 17805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * been completed. 17815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 17825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_irq_enumdone(struct s3c_hsotg *hsotg) 17835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 17845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 dsts = readl(hsotg->regs + S3C_DSTS); 17855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ep0_mps = 0, ep_mps; 17865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* This should signal the finish of the enumeration phase 17885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * of the USB handshaking, so we should now know what rate 17895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * we connected at. */ 17905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "EnumDone (DSTS=0x%08x)\n", dsts); 17925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* note, since we're limited by the size of transfer on EP0, and 17945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * it seems IN transfers must be a even number of packets we do 17955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * not advertise a 64byte MPS on EP0. */ 17965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 17975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* catch both EnumSpd_FS and EnumSpd_FS48 */ 17985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks switch (dsts & S3C_DSTS_EnumSpd_MASK) { 17995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case S3C_DSTS_EnumSpd_FS: 18005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case S3C_DSTS_EnumSpd_FS48: 18015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.speed = USB_SPEED_FULL; 18025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "new device is full-speed\n"); 18035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep0_mps = EP0_MPS_LIMIT; 18055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep_mps = 64; 18065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 18075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case S3C_DSTS_EnumSpd_HS: 18095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "new device is high-speed\n"); 18105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.speed = USB_SPEED_HIGH; 18115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep0_mps = EP0_MPS_LIMIT; 18135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep_mps = 512; 18145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 18155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case S3C_DSTS_EnumSpd_LS: 18175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.speed = USB_SPEED_LOW; 18185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "new device is low-speed\n"); 18195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* note, we don't actually support LS in this driver at the 18215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * moment, and the documentation seems to imply that it isn't 18225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * supported by the PHYs on some of the devices. 18235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 18245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 18255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 18265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* we should now know the maximum packet size for an 18285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * endpoint, so set the endpoints to a default value. */ 18295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ep0_mps) { 18315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int i; 18325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_set_ep_maxpacket(hsotg, 0, ep0_mps); 18335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (i = 1; i < S3C_HSOTG_EPS; i++) 18345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_set_ep_maxpacket(hsotg, i, ep_mps); 18355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 18365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* ensure after enumeration our EP0 is active */ 18385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_enqueue_setup(hsotg); 18405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", 18425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DIEPCTL0), 18435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DOEPCTL0)); 18445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 18455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 18475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * kill_all_requests - remove all requests from the endpoint's queue 18485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 18495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The endpoint the requests may be on. 18505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @result: The result code to use. 18515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @force: Force removal of any current requests 18525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 18535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Go through the requests on the given endpoint and mark them 18545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * completed with the given result code. 18555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 18565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void kill_all_requests(struct s3c_hsotg *hsotg, 18575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep, 18585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int result, bool force) 18595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 18605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *req, *treq; 18615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 18625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&ep->lock, flags); 18645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks list_for_each_entry_safe(req, treq, &ep->queue, queue) { 18665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* currently, we can't do much about an already 18675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * running request on an in endpoint */ 18685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ep->req == req && ep->dir_in && !force) 18705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks continue; 18715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_complete_request(hsotg, ep, req, 18735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks result); 18745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 18755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&ep->lock, flags); 18775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 18785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define call_gadget(_hs, _entry) \ 18805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if ((_hs)->gadget.speed != USB_SPEED_UNKNOWN && \ 18815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks (_hs)->driver && (_hs)->driver->_entry) \ 18825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks (_hs)->driver->_entry(&(_hs)->gadget); 18835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 18855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_disconnect_irq - disconnect irq service 18865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 18875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 18885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * A disconnect IRQ has been received, meaning that the host has 18895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * lost contact with the bus. Remove all current transactions 18905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * and signal the gadget driver that this has happened. 18915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 18925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_disconnect_irq(struct s3c_hsotg *hsotg) 18935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 18945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned ep; 18955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (ep = 0; ep < S3C_HSOTG_EPS; ep++) 18975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kill_all_requests(hsotg, &hsotg->eps[ep], -ESHUTDOWN, true); 18985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 18995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks call_gadget(hsotg, disconnect); 19005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 19015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 19035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_irq_fifoempty - TX FIFO empty interrupt handler 19045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state: 19055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @periodic: True if this is a periodic FIFO interrupt 19065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 19075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_irq_fifoempty(struct s3c_hsotg *hsotg, bool periodic) 19085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 19095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep; 19105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int epno, ret; 19115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* look through for any more data to transmit */ 19135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (epno = 0; epno < S3C_HSOTG_EPS; epno++) { 19155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep = &hsotg->eps[epno]; 19165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!ep->dir_in) 19185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks continue; 19195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if ((periodic && !ep->periodic) || 19215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks (!periodic && ep->periodic)) 19225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks continue; 19235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = s3c_hsotg_trytx(hsotg, ep); 19255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret < 0) 19265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 19275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 19285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 19295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic struct s3c_hsotg *our_hsotg; 19315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/* IRQ flags which will trigger a retry around the IRQ loop */ 19335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define IRQ_RETRY_MASK (S3C_GINTSTS_NPTxFEmp | \ 19345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_PTxFEmp | \ 19355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_RxFLvl) 19365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 19385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_irq - handle device interrupt 19395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @irq: The IRQ number triggered 19405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @pw: The pw value when registered the handler. 19415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 19425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic irqreturn_t s3c_hsotg_irq(int irq, void *pw) 19435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 19445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = pw; 19455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int retry_count = 8; 19465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 gintsts; 19475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 gintmsk; 19485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksirq_retry: 19505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks gintsts = readl(hsotg->regs + S3C_GINTSTS); 19515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks gintmsk = readl(hsotg->regs + S3C_GINTMSK); 19525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: %08x %08x (%08x) retry %d\n", 19545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, gintsts, gintsts & gintmsk, gintmsk, retry_count); 19555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks gintsts &= gintmsk; 19575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_OTGInt) { 19595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 otgint = readl(hsotg->regs + S3C_GOTGINT); 19605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "OTGInt: %08x\n", otgint); 19625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(otgint, hsotg->regs + S3C_GOTGINT); 19645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_OTGInt, hsotg->regs + S3C_GINTSTS); 19655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 19665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_DisconnInt) { 19685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: DisconnInt\n", __func__); 19695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_DisconnInt, hsotg->regs + S3C_GINTSTS); 19705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_disconnect_irq(hsotg); 19725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 19735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_SessReqInt) { 19755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: SessReqInt\n", __func__); 19765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_SessReqInt, hsotg->regs + S3C_GINTSTS); 19775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 19785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_EnumDone) { 19805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_irq_enumdone(hsotg); 19815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_EnumDone, hsotg->regs + S3C_GINTSTS); 19825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 19835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_ConIDStsChng) { 19855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "ConIDStsChg (DSTS=0x%08x, GOTCTL=%08x)\n", 19865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DSTS), 19875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_GOTGCTL)); 19885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_ConIDStsChng, hsotg->regs + S3C_GINTSTS); 19905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 19915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt)) { 19935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 daint = readl(hsotg->regs + S3C_DAINT); 19945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 daint_out = daint >> S3C_DAINT_OutEP_SHIFT; 19955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 daint_in = daint & ~(daint_out << S3C_DAINT_OutEP_SHIFT); 19965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ep; 19975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 19985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: daint=%08x\n", __func__, daint); 19995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (ep = 0; ep < 15 && daint_out; ep++, daint_out >>= 1) { 20015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (daint_out & 1) 20025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_epint(hsotg, ep, 0); 20035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (ep = 0; ep < 15 && daint_in; ep++, daint_in >>= 1) { 20065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (daint_in & 1) 20075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_epint(hsotg, ep, 1); 20085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(daint, hsotg->regs + S3C_DAINT); 20115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(gintsts & (S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt), 20125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GINTSTS); 20135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_USBRst) { 20165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "%s: USBRst\n", __func__); 20175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n", 20185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_GNPTXSTS)); 20195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kill_all_requests(hsotg, &hsotg->eps[0], -ECONNRESET, true); 20215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* it seems after a reset we can end up with a situation 20235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * where the TXFIFO still has data in it... try flushing 20245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * it to remove anything that may still be in it. 20255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 20265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (1) { 20285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GRSTCTL_TxFNum(0) | S3C_GRSTCTL_TxFFlsh, 20295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GRSTCTL); 20305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "GNPTXSTS=%08x\n", 20325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_GNPTXSTS)); 20335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_enqueue_setup(hsotg); 20365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_USBRst, hsotg->regs + S3C_GINTSTS); 20385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* check both FIFOs */ 20415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_NPTxFEmp) { 20435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "NPTxFEmp\n"); 20445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Disable the interrupt to stop it happening again 20465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * unless one of these endpoint routines decides that 20475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * it needs re-enabling */ 20485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_NPTxFEmp); 20505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_irq_fifoempty(hsotg, false); 20515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_NPTxFEmp, hsotg->regs + S3C_GINTSTS); 20535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_PTxFEmp) { 20565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "PTxFEmp\n"); 20575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* See note in S3C_GINTSTS_NPTxFEmp */ 20595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_disable_gsint(hsotg, S3C_GINTSTS_PTxFEmp); 20615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_irq_fifoempty(hsotg, true); 20625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_PTxFEmp, hsotg->regs + S3C_GINTSTS); 20645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_RxFLvl) { 20675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* note, since GINTSTS_RxFLvl doubles as FIFO-not-empty, 20685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * we need to retry s3c_hsotg_handle_rx if this is still 20695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * set. */ 20705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_handle_rx(hsotg); 20725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_RxFLvl, hsotg->regs + S3C_GINTSTS); 20735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_ModeMis) { 20765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_warn(hsotg->dev, "warning, mode mismatch triggered\n"); 20775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_ModeMis, hsotg->regs + S3C_GINTSTS); 20785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_USBSusp) { 20815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "S3C_GINTSTS_USBSusp\n"); 20825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_USBSusp, hsotg->regs + S3C_GINTSTS); 20835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks call_gadget(hsotg, suspend); 20855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_WkUpInt) { 20885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "S3C_GINTSTS_WkUpIn\n"); 20895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_WkUpInt, hsotg->regs + S3C_GINTSTS); 20905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks call_gadget(hsotg, resume); 20925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_ErlySusp) { 20955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "S3C_GINTSTS_ErlySusp\n"); 20965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_ErlySusp, hsotg->regs + S3C_GINTSTS); 20975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 20985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 20995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* these next two seem to crop-up occasionally causing the core 21005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to shutdown the USB transfer, so try clearing them and logging 21015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * the occurence. */ 21025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_GOUTNakEff) { 21045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "GOUTNakEff triggered\n"); 21055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_dump(hsotg); 21075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DCTL_CGOUTNak, hsotg->regs + S3C_DCTL); 21095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_GOUTNakEff, hsotg->regs + S3C_GINTSTS); 21105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 21115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & S3C_GINTSTS_GINNakEff) { 21135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "GINNakEff triggered\n"); 21145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_dump(hsotg); 21165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DCTL_CGNPInNAK, hsotg->regs + S3C_DCTL); 21185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_GINNakEff, hsotg->regs + S3C_GINTSTS); 21195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 21205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* if we've had fifo events, we should try and go around the 21225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * loop again to see if there's any point in returning yet. */ 21235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (gintsts & IRQ_RETRY_MASK && --retry_count > 0) 21255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto irq_retry; 21265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return IRQ_HANDLED; 21285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 21295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 21315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_ep_enable - enable the given endpoint 21325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The USB endpint to configure 21335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @desc: The USB endpoint descriptor to configure with. 21345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 21355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This is called from the USB gadget code's usb_ep_enable(). 21365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 21375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_ep_enable(struct usb_ep *ep, 21385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks const struct usb_endpoint_descriptor *desc) 21395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 21405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = our_ep(ep); 21415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = hs_ep->parent; 21425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 21435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int index = hs_ep->index; 21445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epctrl_reg; 21455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epctrl; 21465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 mps; 21475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int dir_in; 214819c190f9e0fe926db28122a804111a7538dc3498Julia Lawall int ret = 0; 21495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, 21515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "%s: ep %s: a 0x%02x, attr 0x%02x, mps 0x%04x, intr %d\n", 21525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, ep->name, desc->bEndpointAddress, desc->bmAttributes, 21535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks desc->wMaxPacketSize, desc->bInterval); 21545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* not to be called for EP0 */ 21565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON(index == 0); 21575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dir_in = (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) ? 1 : 0; 21595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in != hs_ep->dir_in) { 21605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: direction mismatch!\n", __func__); 21615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 21625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 21635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks mps = le16_to_cpu(desc->wMaxPacketSize); 21655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* note, we handle this here instead of s3c_hsotg_set_ep_maxpacket */ 21675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); 21695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl = readl(hsotg->regs + epctrl_reg); 21705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", 21725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, epctrl, epctrl_reg); 21735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&hs_ep->lock, flags); 21755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl &= ~(S3C_DxEPCTL_EPType_MASK | S3C_DxEPCTL_MPS_MASK); 21775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_MPS(mps); 21785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* mark the endpoint as active, otherwise the core may ignore 21805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * transactions entirely for this endpoint */ 21815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_USBActEp; 21825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* set the NAK status on the endpoint, otherwise we might try and 21845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * do something with data that we've yet got a request to process 21855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * since the RXFIFO will take data for an endpoint even if the 21865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * size register hasn't been set. 21875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 21885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_SNAK; 21905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* update the endpoint state */ 21925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->ep.maxpacket = mps; 21935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* default, set to non-periodic */ 21955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->periodic = 0; 21965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 21975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { 21985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_ENDPOINT_XFER_ISOC: 21995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "no current ISOC support\n"); 220019c190f9e0fe926db28122a804111a7538dc3498Julia Lawall ret = -EINVAL; 220119c190f9e0fe926db28122a804111a7538dc3498Julia Lawall goto out; 22025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_ENDPOINT_XFER_BULK: 22045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_EPType_Bulk; 22055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 22065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_ENDPOINT_XFER_INT: 22085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (dir_in) { 22095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Allocate our TxFNum by simply using the index 22105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * of the endpoint for the moment. We could do 22115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * something better if the host indicates how 22125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * many FIFOs we are expecting to use. */ 22135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->periodic = 1; 22155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_TxFNum(index); 22165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 22175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_EPType_Intterupt; 22195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 22205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks case USB_ENDPOINT_XFER_CONTROL: 22225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_EPType_Control; 22235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 22245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 22255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* for non control endpoints, set PID to D0 */ 22275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (index) 22285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl |= S3C_DxEPCTL_SetD0PID; 22295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: write DxEPCTL=0x%08x\n", 22315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, epctrl); 22325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(epctrl, hsotg->regs + epctrl_reg); 22345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x\n", 22355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, readl(hsotg->regs + epctrl_reg)); 22365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* enable the endpoint interrupt */ 22385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_ctrl_epint(hsotg, index, dir_in, 1); 22395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 224019c190f9e0fe926db28122a804111a7538dc3498Julia Lawallout: 22415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&hs_ep->lock, flags); 224219c190f9e0fe926db28122a804111a7538dc3498Julia Lawall return ret; 22435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 22445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_ep_disable(struct usb_ep *ep) 22465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 22475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = our_ep(ep); 22485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = hs_ep->parent; 22495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int dir_in = hs_ep->dir_in; 22505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int index = hs_ep->index; 22515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 22525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epctrl_reg; 22535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 ctrl; 22545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "%s(ep %p)\n", __func__, ep); 22565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ep == &hsotg->eps[0].ep) { 22585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: called for ep0\n", __func__); 22595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 22605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 22615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctrl_reg = dir_in ? S3C_DIEPCTL(index) : S3C_DOEPCTL(index); 22635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* terminate all requests with shutdown */ 22655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kill_all_requests(hsotg, hs_ep, -ESHUTDOWN, false); 22665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&hs_ep->lock, flags); 22685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl = readl(hsotg->regs + epctrl_reg); 22705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl &= ~S3C_DxEPCTL_EPEna; 22715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl &= ~S3C_DxEPCTL_USBActEp; 22725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ctrl |= S3C_DxEPCTL_SNAK; 22735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "%s: DxEPCTL=0x%08x\n", __func__, ctrl); 22755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(ctrl, hsotg->regs + epctrl_reg); 22765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* disable endpoint interrupts */ 22785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_ctrl_epint(hsotg, hs_ep->index, hs_ep->dir_in, 0); 22795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&hs_ep->lock, flags); 22815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 22825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 22835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 22855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * on_list - check request is on the given endpoint 22865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @ep: The endpoint to check. 22875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @test: The request to test if it is on the endpoint. 22885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 22895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic bool on_list(struct s3c_hsotg_ep *ep, struct s3c_hsotg_req *test) 22905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 22915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *req, *treq; 22925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks list_for_each_entry_safe(req, treq, &ep->queue, queue) { 22945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (req == test) 22955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return true; 22965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 22975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 22985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return false; 22995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 23005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_ep_dequeue(struct usb_ep *ep, struct usb_request *req) 23025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 23035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *hs_req = our_req(req); 23045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = our_ep(ep); 23055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hs = hs_ep->parent; 23065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 23075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hs->dev, "ep_dequeue(%p,%p)\n", ep, req); 23095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (hs_req == hs_ep->req) { 23115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hs->dev, "%s: already in progress\n", __func__); 23125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINPROGRESS; 23135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 23145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&hs_ep->lock, flags); 23165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!on_list(hs_ep, hs_req)) { 23185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&hs_ep->lock, flags); 23195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 23205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 23215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET); 23235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&hs_ep->lock, flags); 23245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 23265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 23275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value) 23295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 23305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep = our_ep(ep); 23315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hs = hs_ep->parent; 23325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int index = hs_ep->index; 23335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long irqflags; 23345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epreg; 23355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 epctl; 23365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value); 23385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&hs_ep->lock, irqflags); 23405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* write both IN and OUT control registers */ 23425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epreg = S3C_DIEPCTL(index); 23445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctl = readl(hs->regs + epreg); 23455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (value) 23475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctl |= S3C_DxEPCTL_Stall; 23485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 23495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctl &= ~S3C_DxEPCTL_Stall; 23505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(epctl, hs->regs + epreg); 23525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epreg = S3C_DOEPCTL(index); 23545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctl = readl(hs->regs + epreg); 23555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (value) 23575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctl |= S3C_DxEPCTL_Stall; 23585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 23595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks epctl &= ~S3C_DxEPCTL_Stall; 23605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(epctl, hs->regs + epreg); 23625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&hs_ep->lock, irqflags); 23645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 23665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 23675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic struct usb_ep_ops s3c_hsotg_ep_ops = { 23695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .enable = s3c_hsotg_ep_enable, 23705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .disable = s3c_hsotg_ep_disable, 23715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .alloc_request = s3c_hsotg_ep_alloc_request, 23725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .free_request = s3c_hsotg_ep_free_request, 23735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .queue = s3c_hsotg_ep_queue, 23745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .dequeue = s3c_hsotg_ep_dequeue, 23755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .set_halt = s3c_hsotg_ep_sethalt, 23765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* note, don't belive we have any call for the fifo routines */ 23775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 23785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 23805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_corereset - issue softreset to the core 23815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state 23825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 23835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Issue a soft reset to the core, and await the core finishing it. 23845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 23855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) 23865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 23875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int timeout; 23885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 grstctl; 23895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "resetting core\n"); 23915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* issue soft reset */ 23935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GRSTCTL_CSftRst, hsotg->regs + S3C_GRSTCTL); 23945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 23955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks timeout = 1000; 23965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks do { 23975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks grstctl = readl(hsotg->regs + S3C_GRSTCTL); 23985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } while (!(grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); 23995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 2400b7800218bccb52dbcb1613bb51425b21441b81f9Roel Kluin if (!(grstctl & S3C_GRSTCTL_CSftRst)) { 24015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); 24025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 24035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks timeout = 1000; 24065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks while (1) { 24085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 grstctl = readl(hsotg->regs + S3C_GRSTCTL); 24095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (timeout-- < 0) { 24115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, 24125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "%s: reset failed, GRSTCTL=%08x\n", 24135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __func__, grstctl); 24145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ETIMEDOUT; 24155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (grstctl & S3C_GRSTCTL_CSftRst) 24185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks continue; 24195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!(grstctl & S3C_GRSTCTL_AHBIdle)) 24215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks continue; 24225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; /* reset done */ 24245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_dbg(hsotg->dev, "reset successful\n"); 24275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 24285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 24295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksint usb_gadget_register_driver(struct usb_gadget_driver *driver) 24315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 24325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = our_hsotg; 24335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ret; 24345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hsotg) { 24365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks printk(KERN_ERR "%s: called with no device\n", __func__); 24375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENODEV; 24385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!driver) { 24415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: no driver\n", __func__); 24425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 24435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (driver->speed != USB_SPEED_HIGH && 24465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks driver->speed != USB_SPEED_FULL) { 24475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: bad speed\n", __func__); 24485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!driver->bind || !driver->setup) { 24515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: missing entry points\n", __func__); 24525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 24535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks WARN_ON(hsotg->driver); 24565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks driver->driver.bus = NULL; 24585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->driver = driver; 24595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.dev.driver = &driver->driver; 24605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.dev.dma_mask = hsotg->dev->dma_mask; 24615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.speed = USB_SPEED_UNKNOWN; 24625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = device_add(&hsotg->gadget.dev); 24645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret) { 24655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "failed to register gadget device\n"); 24665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err; 24675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = driver->bind(&hsotg->gadget); 24705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret) { 24715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "failed bind %s\n", driver->driver.name); 24725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.dev.driver = NULL; 24745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->driver = NULL; 24755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err; 24765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 24775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* we must now enable ep0 ready for host detection and then 24795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * set configuration. */ 24805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_corereset(hsotg); 24825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* set the PLL on, remove the HNP/SRP and set the PHY */ 24845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | 24855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks (0x5 << 10), hsotg->regs + S3C_GUSBCFG); 24865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* looks like soft-reset changes state of FIFOs */ 24885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_init_fifo(hsotg); 24895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); 24915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(1 << 18 | S3C_DCFG_DevSpd_HS, hsotg->regs + S3C_DCFG); 24935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 24945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GINTSTS_DisconnInt | S3C_GINTSTS_SessReqInt | 24955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_ConIDStsChng | S3C_GINTSTS_USBRst | 24965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_EnumDone | S3C_GINTSTS_OTGInt | 24975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_USBSusp | S3C_GINTSTS_WkUpInt | 24985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_GOUTNakEff | S3C_GINTSTS_GINNakEff | 24995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GINTSTS_ErlySusp, 25005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GINTMSK); 25015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (using_dma(hsotg)) 25035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GAHBCFG_GlblIntrEn | S3C_GAHBCFG_DMAEn | 25045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_GAHBCFG_HBstLen_Incr4, 25055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GAHBCFG); 25065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 25075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GAHBCFG_GlblIntrEn, hsotg->regs + S3C_GAHBCFG); 25085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Enabling INTknTXFEmpMsk here seems to be a big mistake, we end 25105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * up being flooded with interrupts if the host is polling the 25115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * endpoint to try and read data. */ 25125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | 25145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DIEPMSK_INTknEPMisMsk | 25155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, 25165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DIEPMSK); 25175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* don't need XferCompl, we get that from RXFIFO in slave mode. In 25195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * DMA mode we may need this. */ 25205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | 25215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DOEPMSK_EPDisbldMsk | 2522b7800218bccb52dbcb1613bb51425b21441b81f9Roel Kluin (using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk | 2523b7800218bccb52dbcb1613bb51425b21441b81f9Roel Kluin S3C_DIEPMSK_TimeOUTMsk) : 0), 25245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DOEPMSK); 25255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(0, hsotg->regs + S3C_DAINTMSK); 25275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", 25295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DIEPCTL0), 25305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DOEPCTL0)); 25315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* enable in and out endpoint interrupts */ 25335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_OEPInt | S3C_GINTSTS_IEPInt); 25345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Enable the RXFIFO when in slave mode, as this is how we collect 25365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * the data. In DMA mode, we get events from the FIFO but also 25375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * things we cannot process, so do not use it. */ 25385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!using_dma(hsotg)) 25395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_en_gsint(hsotg, S3C_GINTSTS_RxFLvl); 25405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Enable interrupts for EP0 in and out */ 25425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_ctrl_epint(hsotg, 0, 0, 1); 25435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_ctrl_epint(hsotg, 0, 1, 1); 25445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __orr32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); 25465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks udelay(10); /* see openiboot */ 25475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_PWROnPrgDone); 25485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "DCTL=0x%08x\n", readl(hsotg->regs + S3C_DCTL)); 25505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* S3C_DxEPCTL_USBActEp says RO in manual, but seems to be set by 25525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writing to the EPCTL register.. */ 25535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* set to read 1 8byte packet */ 25555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DxEPTSIZ_MC(1) | S3C_DxEPTSIZ_PktCnt(1) | 25565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DxEPTSIZ_XferSize(8), hsotg->regs + DOEPTSIZ0); 25575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | 25595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DxEPCTL_CNAK | S3C_DxEPCTL_EPEna | 25605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DxEPCTL_USBActEp, 25615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DOEPCTL0); 25625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* enable, but don't activate EP0in */ 25645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(s3c_hsotg_ep0_mps(hsotg->eps[0].ep.maxpacket) | 25655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DxEPCTL_USBActEp, hsotg->regs + S3C_DIEPCTL0); 25665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_enqueue_setup(hsotg); 25685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n", 25705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DIEPCTL0), 25715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_DOEPCTL0)); 25725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* clear global NAKs */ 25745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DCTL_CGOUTNak | S3C_DCTL_CGNPInNAK, 25755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DCTL); 25765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* remove the soft-disconnect and let's go */ 25785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __bic32(hsotg->regs + S3C_DCTL, S3C_DCTL_SftDiscon); 25795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* report to the user, and return */ 25815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); 25835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 25845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dookserr: 25865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->driver = NULL; 25875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.dev.driver = NULL; 25885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return ret; 25895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 25906feb63b69f4f6e876ea5a2edc6119b8e7ac90102Mark BrownEXPORT_SYMBOL(usb_gadget_register_driver); 25915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksint usb_gadget_unregister_driver(struct usb_gadget_driver *driver) 25935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 25945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = our_hsotg; 25955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ep; 25965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 25975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hsotg) 25985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENODEV; 25995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!driver || driver != hsotg->driver || !driver->unbind) 26015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -EINVAL; 26025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* all endpoints should be shutdown */ 26045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (ep = 0; ep < S3C_HSOTG_EPS; ep++) 26055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_ep_disable(&hsotg->eps[ep].ep); 26065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks call_gadget(hsotg, disconnect); 26085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks driver->unbind(&hsotg->gadget); 26105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->driver = NULL; 26115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.speed = USB_SPEED_UNKNOWN; 26125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks device_del(&hsotg->gadget.dev); 26145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "unregistered gadget driver '%s'\n", 26165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks driver->driver.name); 26175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 26195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 26205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben DooksEXPORT_SYMBOL(usb_gadget_unregister_driver); 26215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int s3c_hsotg_gadget_getframe(struct usb_gadget *gadget) 26235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 26245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return s3c_hsotg_read_frameno(to_hsotg(gadget)); 26255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 26265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic struct usb_gadget_ops s3c_hsotg_gadget_ops = { 26285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .get_frame = s3c_hsotg_gadget_getframe, 26295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 26305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 26325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_initep - initialise a single endpoint 26335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The device state. 26345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hs_ep: The endpoint to be initialised. 26355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @epnum: The endpoint number 26365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 26375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Initialise the given endpoint (as part of the probe and device state 26385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * creation) to give to the gadget driver. Setup the endpoint name, any 26395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * direction information and other state that may be required. 26405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 26415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void __devinit s3c_hsotg_initep(struct s3c_hsotg *hsotg, 26425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *hs_ep, 26435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int epnum) 26445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 26455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 ptxfifo; 26465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks char *dir; 26475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (epnum == 0) 26495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dir = ""; 26505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else if ((epnum % 2) == 0) { 26515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dir = "out"; 26525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } else { 26535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dir = "in"; 26545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->dir_in = 1; 26555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 26565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->index = epnum; 26585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks snprintf(hs_ep->name, sizeof(hs_ep->name), "ep%d%s", epnum, dir); 26605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks INIT_LIST_HEAD(&hs_ep->queue); 26625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks INIT_LIST_HEAD(&hs_ep->ep.ep_list); 26635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_init(&hs_ep->lock); 26655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* add to the list of endpoints known by the gadget driver */ 26675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (epnum) 26685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks list_add_tail(&hs_ep->ep.ep_list, &hsotg->gadget.ep_list); 26695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->parent = hsotg; 26715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->ep.name = hs_ep->name; 26725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->ep.maxpacket = epnum ? 512 : EP0_MPS_LIMIT; 26735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->ep.ops = &s3c_hsotg_ep_ops; 26745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* Read the FIFO size for the Periodic TX FIFO, even if we're 26765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * an OUT endpoint, we may as well do this if in future the 26775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * code is changed to make each endpoint's direction changeable. 26785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 26795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ptxfifo = readl(hsotg->regs + S3C_DPTXFSIZn(epnum)); 26815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hs_ep->fifo_size = S3C_DPTXFSIZn_DPTxFSize_GET(ptxfifo); 26825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* if we're using dma, we need to set the next-endpoint pointer 26845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to be something valid. 26855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 26865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (using_dma(hsotg)) { 26885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 next = S3C_DxEPCTL_NextEp((epnum + 1) % 15); 26895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(next, hsotg->regs + S3C_DIEPCTL(epnum)); 26905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(next, hsotg->regs + S3C_DOEPCTL(epnum)); 26915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 26925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 26935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 26945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 26955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_otgreset - reset the OtG phy block 26965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The host state. 26975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 26985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Power up the phy, set the basic configuration and start the PHY. 26995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 27005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_otgreset(struct s3c_hsotg *hsotg) 27015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 27025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 osc; 27035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(0, S3C_PHYPWR); 27055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks mdelay(1); 27065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks osc = hsotg->plat->is_osc ? S3C_PHYCLK_EXT_OSC : 0; 27085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(osc | 0x10, S3C_PHYCLK); 27105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* issue a full set of resets to the otg and core */ 27125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_RSTCON_PHY, S3C_RSTCON); 27145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks udelay(20); /* at-least 10uS */ 27155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(0, S3C_RSTCON); 27165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 27175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_init(struct s3c_hsotg *hsotg) 27205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 27215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* unmask subset of endpoint interrupts */ 27225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DIEPMSK_TimeOUTMsk | S3C_DIEPMSK_AHBErrMsk | 27245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DIEPMSK_EPDisbldMsk | S3C_DIEPMSK_XferComplMsk, 27255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DIEPMSK); 27265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | 27285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks S3C_DOEPMSK_EPDisbldMsk | S3C_DOEPMSK_XferComplMsk, 27295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DOEPMSK); 27305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(0, hsotg->regs + S3C_DAINTMSK); 27325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (0) { 27345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* post global nak until we're ready */ 27355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_DCTL_SGNPInNAK | S3C_DCTL_SGOUTNak, 27365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_DCTL); 27375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 27385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* setup fifos */ 27405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(hsotg->dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", 27425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_GRXFSIZ), 27435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(hsotg->regs + S3C_GNPTXFSIZ)); 27445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_init_fifo(hsotg); 27465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* set the PLL on, remove the HNP/SRP and set the PHY */ 27485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(S3C_GUSBCFG_PHYIf16 | S3C_GUSBCFG_TOutCal(7) | (0x5 << 10), 27495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GUSBCFG); 27505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks writel(using_dma(hsotg) ? S3C_GAHBCFG_DMAEn : 0x0, 27525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs + S3C_GAHBCFG); 27535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 27545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_dump(struct s3c_hsotg *hsotg) 27565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 27575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct device *dev = hsotg->dev; 27585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void __iomem *regs = hsotg->regs; 27595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 val; 27605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int idx; 27615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, "DCFG=0x%08x, DCTL=0x%08x, DIEPMSK=%08x\n", 27635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DCFG), readl(regs + S3C_DCTL), 27645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPMSK)); 27655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, "GAHBCFG=0x%08x, 0x44=0x%08x\n", 27675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_GAHBCFG), readl(regs + 0x44)); 27685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, "GRXFSIZ=0x%08x, GNPTXFSIZ=0x%08x\n", 27705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_GRXFSIZ), readl(regs + S3C_GNPTXFSIZ)); 27715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* show periodic fifo settings */ 27735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (idx = 1; idx <= 15; idx++) { 27755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val = readl(regs + S3C_DPTXFSIZn(idx)); 27765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, "DPTx[%d] FSize=%d, StAddr=0x%08x\n", idx, 27775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, 27785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); 27795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 27805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (idx = 0; idx < 15; idx++) { 27825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, 27835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "ep%d-in: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", idx, 27845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPCTL(idx)), 27855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPTSIZ(idx)), 27865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPDMA(idx))); 27875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val = readl(regs + S3C_DOEPCTL(idx)); 27895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, 27905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks "ep%d-out: EPCTL=0x%08x, SIZ=0x%08x, DMA=0x%08x\n", 27915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks idx, readl(regs + S3C_DOEPCTL(idx)), 27925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DOEPTSIZ(idx)), 27935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DOEPDMA(idx))); 27945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 27965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 27975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, "DVBUSDIS=0x%08x, DVBUSPULSE=%08x\n", 27985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DVBUSDIS), readl(regs + S3C_DVBUSPULSE)); 27995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 28005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 28035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * state_show - debugfs: show overall driver and device state. 28045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @seq: The seq file to write to. 28055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @v: Unused parameter. 28065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 28075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This debugfs entry shows the overall state of the hardware and 28085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * some general information about each of the endpoints available 28095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to the system. 28105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 28115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int state_show(struct seq_file *seq, void *v) 28125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 28135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = seq->private; 28145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void __iomem *regs = hsotg->regs; 28155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int idx; 28165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "DCFG=0x%08x, DCTL=0x%08x, DSTS=0x%08x\n", 28185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DCFG), 28195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DCTL), 28205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DSTS)); 28215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "DIEPMSK=0x%08x, DOEPMASK=0x%08x\n", 28235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPMSK), readl(regs + S3C_DOEPMSK)); 28245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "GINTMSK=0x%08x, GINTSTS=0x%08x\n", 28265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_GINTMSK), 28275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_GINTSTS)); 28285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "DAINTMSK=0x%08x, DAINT=0x%08x\n", 28305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DAINTMSK), 28315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DAINT)); 28325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "GNPTXSTS=0x%08x, GRXSTSR=%08x\n", 28345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_GNPTXSTS), 28355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_GRXSTSR)); 28365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\nEndpoint status:\n"); 28385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (idx = 0; idx < 15; idx++) { 28405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 in, out; 28415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks in = readl(regs + S3C_DIEPCTL(idx)); 28435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks out = readl(regs + S3C_DOEPCTL(idx)); 28445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "ep%d: DIEPCTL=0x%08x, DOEPCTL=0x%08x", 28465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks idx, in, out); 28475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks in = readl(regs + S3C_DIEPTSIZ(idx)); 28495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks out = readl(regs + S3C_DOEPTSIZ(idx)); 28505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, ", DIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x", 28525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks in, out); 28535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\n"); 28555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 28565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 28585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 28595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int state_open(struct inode *inode, struct file *file) 28615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 28625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return single_open(file, state_show, inode->i_private); 28635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 28645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic const struct file_operations state_fops = { 28665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .owner = THIS_MODULE, 28675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .open = state_open, 28685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .read = seq_read, 28695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .llseek = seq_lseek, 28705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .release = single_release, 28715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 28725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 28745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * fifo_show - debugfs: show the fifo information 28755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @seq: The seq_file to write data to. 28765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @v: Unused parameter. 28775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 28785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Show the FIFO information for the overall fifo and all the 28795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * periodic transmission FIFOs. 28805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 28815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int fifo_show(struct seq_file *seq, void *v) 28825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 28835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = seq->private; 28845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void __iomem *regs = hsotg->regs; 28855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 val; 28865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int idx; 28875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "Non-periodic FIFOs:\n"); 28895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "RXFIFO: Size %d\n", readl(regs + S3C_GRXFSIZ)); 28905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val = readl(regs + S3C_GNPTXFSIZ); 28925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "NPTXFIFO: Size %d, Start 0x%08x\n", 28935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val >> S3C_GNPTXFSIZ_NPTxFDep_SHIFT, 28945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val & S3C_GNPTXFSIZ_NPTxFStAddr_MASK); 28955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\nPeriodic TXFIFOs:\n"); 28975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 28985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (idx = 1; idx <= 15; idx++) { 28995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val = readl(regs + S3C_DPTXFSIZn(idx)); 29005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\tDPTXFIFO%2d: Size %d, Start 0x%08x\n", idx, 29025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val >> S3C_DPTXFSIZn_DPTxFSize_SHIFT, 29035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks val & S3C_DPTXFSIZn_DPTxFStAddr_MASK); 29045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 29055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 29075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 29085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int fifo_open(struct inode *inode, struct file *file) 29105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 29115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return single_open(file, fifo_show, inode->i_private); 29125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 29135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic const struct file_operations fifo_fops = { 29155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .owner = THIS_MODULE, 29165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .open = fifo_open, 29175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .read = seq_read, 29185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .llseek = seq_lseek, 29195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .release = single_release, 29205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 29215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic const char *decode_direction(int is_in) 29245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 29255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return is_in ? "in" : "out"; 29265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 29275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 29295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * ep_show - debugfs: show the state of an endpoint. 29305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @seq: The seq_file to write data to. 29315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @v: Unused parameter. 29325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 29335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * This debugfs entry shows the state of the given endpoint (one is 29345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * registered for each available). 29355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 29365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int ep_show(struct seq_file *seq, void *v) 29375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 29385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep = seq->private; 29395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = ep->parent; 29405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_req *req; 29415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks void __iomem *regs = hsotg->regs; 29425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int index = ep->index; 29435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int show_limit = 15; 29445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 29455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "Endpoint index %d, named %s, dir %s:\n", 29475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep->index, ep->ep.name, decode_direction(ep->dir_in)); 29485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* first show the register state */ 29505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\tDIEPCTL=0x%08x, DOEPCTL=0x%08x\n", 29525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPCTL(index)), 29535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DOEPCTL(index))); 29545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\tDIEPDMA=0x%08x, DOEPDMA=0x%08x\n", 29565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPDMA(index)), 29575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DOEPDMA(index))); 29585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\tDIEPINT=0x%08x, DOEPINT=0x%08x\n", 29605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPINT(index)), 29615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DOEPINT(index))); 29625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\tDIEPTSIZ=0x%08x, DOEPTSIZ=0x%08x\n", 29645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DIEPTSIZ(index)), 29655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks readl(regs + S3C_DOEPTSIZ(index))); 29665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "\n"); 29685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "mps %d\n", ep->ep.maxpacket); 29695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "total_data=%ld\n", ep->total_data); 29705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "request list (%p,%p):\n", 29725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep->queue.next, ep->queue.prev); 29735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_lock_irqsave(&ep->lock, flags); 29755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks list_for_each_entry(req, &ep->queue, queue) { 29775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (--show_limit < 0) { 29785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "not showing more requests...\n"); 29795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks break; 29805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 29815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "%c req %p: %d bytes @%p, ", 29835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req == ep->req ? '*' : ' ', 29845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req, req->req.length, req->req.buf); 29855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks seq_printf(seq, "%d done, res %d\n", 29865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks req->req.actual, req->req.status); 29875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 29885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks spin_unlock_irqrestore(&ep->lock, flags); 29905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 29925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 29935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int ep_open(struct inode *inode, struct file *file) 29955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 29965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return single_open(file, ep_show, inode->i_private); 29975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 29985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 29995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic const struct file_operations ep_fops = { 30005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .owner = THIS_MODULE, 30015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .open = ep_open, 30025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .read = seq_read, 30035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .llseek = seq_lseek, 30045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .release = single_release, 30055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 30065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 30085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_create_debug - create debugfs directory and files 30095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The driver state 30105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 30115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Create the debugfs files to allow the user to get information 30125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * about the state of the system. The directory name is created 30135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * with the same name as the device itself, in case we end up 30145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * with multiple blocks in future systems. 30155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 30165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void __devinit s3c_hsotg_create_debug(struct s3c_hsotg *hsotg) 30175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 30185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct dentry *root; 30195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned epidx; 30205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks root = debugfs_create_dir(dev_name(hsotg->dev), NULL); 30225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->debug_root = root; 30235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (IS_ERR(root)) { 30245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "cannot create debug root\n"); 30255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return; 30265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 30275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* create general state file */ 30295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->debug_file = debugfs_create_file("state", 0444, root, 30315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg, &state_fops); 30325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (IS_ERR(hsotg->debug_file)) 30345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: failed to create state\n", __func__); 30355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->debug_fifo = debugfs_create_file("fifo", 0444, root, 30375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg, &fifo_fops); 30385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (IS_ERR(hsotg->debug_fifo)) 30405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "%s: failed to create fifo\n", __func__); 30415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* create one file for each endpoint */ 30435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { 30455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; 30465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep->debugfs = debugfs_create_file(ep->name, 0444, 30485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks root, ep, &ep_fops); 30495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (IS_ERR(ep->debugfs)) 30515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(hsotg->dev, "failed to create %s debug file\n", 30525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ep->name); 30535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 30545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 30555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 30575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_delete_debug - cleanup debugfs entries 30585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @hsotg: The driver state 30595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 30605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Cleanup (remove) the debugfs files for use on module exit. 30615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks*/ 30625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void __devexit s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) 30635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 30645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned epidx; 30655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (epidx = 0; epidx < S3C_HSOTG_EPS; epidx++) { 30675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_ep *ep = &hsotg->eps[epidx]; 30685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks debugfs_remove(ep->debugfs); 30695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 30705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks debugfs_remove(hsotg->debug_file); 30725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks debugfs_remove(hsotg->debug_fifo); 30735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks debugfs_remove(hsotg->debug_root); 30745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 30755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks/** 30775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * s3c_hsotg_gate - set the hardware gate for the block 30785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @pdev: The device we bound to 30795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * @on: On or off. 30805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * 30815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * Set the hardware gate setting into the block. If we end up on 30825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * something other than an S3C64XX, then we might need to change this 30835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks * to using a platform data callback, or some other mechanism. 30845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks */ 30855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void s3c_hsotg_gate(struct platform_device *pdev, bool on) 30865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 30875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks unsigned long flags; 30885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks u32 others; 30895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks local_irq_save(flags); 30915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks others = __raw_readl(S3C64XX_OTHERS); 30935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (on) 30945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks others |= S3C64XX_OTHERS_USBMASK; 30955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks else 30965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks others &= ~S3C64XX_OTHERS_USBMASK; 30975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks __raw_writel(others, S3C64XX_OTHERS); 30985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 30995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks local_irq_restore(flags); 31005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 31015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31020978f8c55cdc7c06b2f1440b030e93fda2c53b2bMark Brownstatic struct s3c_hsotg_plat s3c_hsotg_default_pdata; 31035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int __devinit s3c_hsotg_probe(struct platform_device *pdev) 31055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 31065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg_plat *plat = pdev->dev.platform_data; 31075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct device *dev = &pdev->dev; 31085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg; 31095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct resource *res; 31105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int epnum; 31115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks int ret; 31125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!plat) 31145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks plat = &s3c_hsotg_default_pdata; 31155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg = kzalloc(sizeof(struct s3c_hsotg) + 31175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks sizeof(struct s3c_hsotg_ep) * S3C_HSOTG_EPS, 31185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks GFP_KERNEL); 31195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hsotg) { 31205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(dev, "cannot get memory\n"); 31215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return -ENOMEM; 31225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 31235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->dev = dev; 31255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->plat = plat; 31265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks platform_set_drvdata(pdev, hsotg); 31285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 31305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!res) { 31315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(dev, "cannot find register resource 0\n"); 31325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = -EINVAL; 31335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err_mem; 31345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 31355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs_res = request_mem_region(res->start, resource_size(res), 31375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_name(dev)); 31385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hsotg->regs_res) { 31395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(dev, "cannot reserve registers\n"); 31405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = -ENOENT; 31415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err_mem; 31425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 31435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->regs = ioremap(res->start, resource_size(res)); 31455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hsotg->regs) { 31465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(dev, "cannot map registers\n"); 31475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = -ENXIO; 31485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err_regs_res; 31495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 31505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = platform_get_irq(pdev, 0); 31525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret < 0) { 31535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(dev, "cannot find IRQ\n"); 31545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err_regs; 31555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 31565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->irq = ret; 31585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks ret = request_irq(ret, s3c_hsotg_irq, 0, dev_name(dev), hsotg); 31605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (ret < 0) { 31615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(dev, "cannot claim IRQ\n"); 31625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err_regs; 31635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 31645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_info(dev, "regs %p, irq %d\n", hsotg->regs, hsotg->irq); 31665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks device_initialize(&hsotg->gadget.dev); 31685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_set_name(&hsotg->gadget.dev, "gadget"); 31705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.is_dualspeed = 1; 31725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.ops = &s3c_hsotg_gadget_ops; 31735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.name = dev_name(dev); 31745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.dev.parent = dev; 31765b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.dev.dma_mask = dev->dma_mask; 31775b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31785b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* setup endpoint information */ 31795b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31805b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks INIT_LIST_HEAD(&hsotg->gadget.ep_list); 31815b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->gadget.ep0 = &hsotg->eps[0].ep; 31825b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31835b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* allocate EP0 request */ 31845b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31855b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks hsotg->ctrl_req = s3c_hsotg_ep_alloc_request(&hsotg->eps[0].ep, 31865b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks GFP_KERNEL); 31875b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks if (!hsotg->ctrl_req) { 31885b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks dev_err(dev, "failed to allocate ctrl req\n"); 31895b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks goto err_regs; 31905b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks } 31915b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31925b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* reset the system */ 31935b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31945b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_gate(pdev, true); 31955b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 31965b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_otgreset(hsotg); 31975b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_corereset(hsotg); 31985b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_init(hsotg); 31995b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32005b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks /* initialise the endpoints now the core has been initialised */ 32015b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks for (epnum = 0; epnum < S3C_HSOTG_EPS; epnum++) 32025b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_initep(hsotg, &hsotg->eps[epnum], epnum); 32035b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32045b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_create_debug(hsotg); 32055b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32065b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_dump(hsotg); 32075b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32085b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks our_hsotg = hsotg; 32095b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 32105b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32115b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dookserr_regs: 32125b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks iounmap(hsotg->regs); 32135b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32145b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dookserr_regs_res: 32155b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks release_resource(hsotg->regs_res); 32165b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kfree(hsotg->regs_res); 32175b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32185b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dookserr_mem: 32195b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kfree(hsotg); 32205b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return ret; 32215b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 32225b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32235b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int __devexit s3c_hsotg_remove(struct platform_device *pdev) 32245b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 32255b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks struct s3c_hsotg *hsotg = platform_get_drvdata(pdev); 32265b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32275b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_delete_debug(hsotg); 32285b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32295b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks usb_gadget_unregister_driver(hsotg->driver); 32305b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32315b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks free_irq(hsotg->irq, hsotg); 32325b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks iounmap(hsotg->regs); 32335b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32345b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks release_resource(hsotg->regs_res); 32355b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kfree(hsotg->regs_res); 32365b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32375b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks s3c_hsotg_gate(pdev, false); 32385b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32395b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks kfree(hsotg); 32405b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return 0; 32415b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 32425b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32435b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#if 1 32445b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define s3c_hsotg_suspend NULL 32455b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#define s3c_hsotg_resume NULL 32465b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks#endif 32475b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32485b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic struct platform_driver s3c_hsotg_driver = { 32495b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .driver = { 32505b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .name = "s3c-hsotg", 32515b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .owner = THIS_MODULE, 32525b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks }, 32535b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .probe = s3c_hsotg_probe, 32545b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .remove = __devexit_p(s3c_hsotg_remove), 32555b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .suspend = s3c_hsotg_suspend, 32565b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks .resume = s3c_hsotg_resume, 32575b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks}; 32585b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32595b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic int __init s3c_hsotg_modinit(void) 32605b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 32615b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks return platform_driver_register(&s3c_hsotg_driver); 32625b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 32635b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32645b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksstatic void __exit s3c_hsotg_modexit(void) 32655b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks{ 32665b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks platform_driver_unregister(&s3c_hsotg_driver); 32675b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks} 32685b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32695b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksmodule_init(s3c_hsotg_modinit); 32705b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooksmodule_exit(s3c_hsotg_modexit); 32715b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben Dooks 32725b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben DooksMODULE_DESCRIPTION("Samsung S3C USB High-speed/OtG device"); 32735b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben DooksMODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); 32745b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben DooksMODULE_LICENSE("GPL"); 32755b7d70c6dbf2db786395cbd21750a1a4ce222f84Ben DooksMODULE_ALIAS("platform:s3c-hsotg"); 3276