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