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