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