18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * ci.h - common structures, functions, and macros of the ChipIdea driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2008 Chipidea - MIPS Technologies, Inc. All rights reserved. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Author: David Lopo 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifndef __DRIVERS_USB_CHIPIDEA_CI_H 118c2ecf20Sopenharmony_ci#define __DRIVERS_USB_CHIPIDEA_CI_H 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/list.h> 148c2ecf20Sopenharmony_ci#include <linux/irqreturn.h> 158c2ecf20Sopenharmony_ci#include <linux/usb.h> 168c2ecf20Sopenharmony_ci#include <linux/usb/gadget.h> 178c2ecf20Sopenharmony_ci#include <linux/usb/otg-fsm.h> 188c2ecf20Sopenharmony_ci#include <linux/usb/otg.h> 198c2ecf20Sopenharmony_ci#include <linux/usb/role.h> 208c2ecf20Sopenharmony_ci#include <linux/ulpi/interface.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/****************************************************************************** 238c2ecf20Sopenharmony_ci * DEFINE 248c2ecf20Sopenharmony_ci *****************************************************************************/ 258c2ecf20Sopenharmony_ci#define TD_PAGE_COUNT 5 268c2ecf20Sopenharmony_ci#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */ 278c2ecf20Sopenharmony_ci#define ENDPT_MAX 32 288c2ecf20Sopenharmony_ci#define CI_MAX_BUF_SIZE (TD_PAGE_COUNT * CI_HDRC_PAGE_SIZE) 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/****************************************************************************** 318c2ecf20Sopenharmony_ci * REGISTERS 328c2ecf20Sopenharmony_ci *****************************************************************************/ 338c2ecf20Sopenharmony_ci/* Identification Registers */ 348c2ecf20Sopenharmony_ci#define ID_ID 0x0 358c2ecf20Sopenharmony_ci#define ID_HWGENERAL 0x4 368c2ecf20Sopenharmony_ci#define ID_HWHOST 0x8 378c2ecf20Sopenharmony_ci#define ID_HWDEVICE 0xc 388c2ecf20Sopenharmony_ci#define ID_HWTXBUF 0x10 398c2ecf20Sopenharmony_ci#define ID_HWRXBUF 0x14 408c2ecf20Sopenharmony_ci#define ID_SBUSCFG 0x90 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci/* register indices */ 438c2ecf20Sopenharmony_cienum ci_hw_regs { 448c2ecf20Sopenharmony_ci CAP_CAPLENGTH, 458c2ecf20Sopenharmony_ci CAP_HCCPARAMS, 468c2ecf20Sopenharmony_ci CAP_DCCPARAMS, 478c2ecf20Sopenharmony_ci CAP_TESTMODE, 488c2ecf20Sopenharmony_ci CAP_LAST = CAP_TESTMODE, 498c2ecf20Sopenharmony_ci OP_USBCMD, 508c2ecf20Sopenharmony_ci OP_USBSTS, 518c2ecf20Sopenharmony_ci OP_USBINTR, 528c2ecf20Sopenharmony_ci OP_DEVICEADDR, 538c2ecf20Sopenharmony_ci OP_ENDPTLISTADDR, 548c2ecf20Sopenharmony_ci OP_TTCTRL, 558c2ecf20Sopenharmony_ci OP_BURSTSIZE, 568c2ecf20Sopenharmony_ci OP_ULPI_VIEWPORT, 578c2ecf20Sopenharmony_ci OP_PORTSC, 588c2ecf20Sopenharmony_ci OP_DEVLC, 598c2ecf20Sopenharmony_ci OP_OTGSC, 608c2ecf20Sopenharmony_ci OP_USBMODE, 618c2ecf20Sopenharmony_ci OP_ENDPTSETUPSTAT, 628c2ecf20Sopenharmony_ci OP_ENDPTPRIME, 638c2ecf20Sopenharmony_ci OP_ENDPTFLUSH, 648c2ecf20Sopenharmony_ci OP_ENDPTSTAT, 658c2ecf20Sopenharmony_ci OP_ENDPTCOMPLETE, 668c2ecf20Sopenharmony_ci OP_ENDPTCTRL, 678c2ecf20Sopenharmony_ci /* endptctrl1..15 follow */ 688c2ecf20Sopenharmony_ci OP_LAST = OP_ENDPTCTRL + ENDPT_MAX / 2, 698c2ecf20Sopenharmony_ci}; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci/****************************************************************************** 728c2ecf20Sopenharmony_ci * STRUCTURES 738c2ecf20Sopenharmony_ci *****************************************************************************/ 748c2ecf20Sopenharmony_ci/** 758c2ecf20Sopenharmony_ci * struct ci_hw_ep - endpoint representation 768c2ecf20Sopenharmony_ci * @ep: endpoint structure for gadget drivers 778c2ecf20Sopenharmony_ci * @dir: endpoint direction (TX/RX) 788c2ecf20Sopenharmony_ci * @num: endpoint number 798c2ecf20Sopenharmony_ci * @type: endpoint type 808c2ecf20Sopenharmony_ci * @name: string description of the endpoint 818c2ecf20Sopenharmony_ci * @qh: queue head for this endpoint 828c2ecf20Sopenharmony_ci * @wedge: is the endpoint wedged 838c2ecf20Sopenharmony_ci * @ci: pointer to the controller 848c2ecf20Sopenharmony_ci * @lock: pointer to controller's spinlock 858c2ecf20Sopenharmony_ci * @td_pool: pointer to controller's TD pool 868c2ecf20Sopenharmony_ci */ 878c2ecf20Sopenharmony_cistruct ci_hw_ep { 888c2ecf20Sopenharmony_ci struct usb_ep ep; 898c2ecf20Sopenharmony_ci u8 dir; 908c2ecf20Sopenharmony_ci u8 num; 918c2ecf20Sopenharmony_ci u8 type; 928c2ecf20Sopenharmony_ci char name[16]; 938c2ecf20Sopenharmony_ci struct { 948c2ecf20Sopenharmony_ci struct list_head queue; 958c2ecf20Sopenharmony_ci struct ci_hw_qh *ptr; 968c2ecf20Sopenharmony_ci dma_addr_t dma; 978c2ecf20Sopenharmony_ci } qh; 988c2ecf20Sopenharmony_ci int wedge; 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* global resources */ 1018c2ecf20Sopenharmony_ci struct ci_hdrc *ci; 1028c2ecf20Sopenharmony_ci spinlock_t *lock; 1038c2ecf20Sopenharmony_ci struct dma_pool *td_pool; 1048c2ecf20Sopenharmony_ci struct td_node *pending_td; 1058c2ecf20Sopenharmony_ci}; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cienum ci_role { 1088c2ecf20Sopenharmony_ci CI_ROLE_HOST = 0, 1098c2ecf20Sopenharmony_ci CI_ROLE_GADGET, 1108c2ecf20Sopenharmony_ci CI_ROLE_END, 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cienum ci_revision { 1148c2ecf20Sopenharmony_ci CI_REVISION_1X = 10, /* Revision 1.x */ 1158c2ecf20Sopenharmony_ci CI_REVISION_20 = 20, /* Revision 2.0 */ 1168c2ecf20Sopenharmony_ci CI_REVISION_21, /* Revision 2.1 */ 1178c2ecf20Sopenharmony_ci CI_REVISION_22, /* Revision 2.2 */ 1188c2ecf20Sopenharmony_ci CI_REVISION_23, /* Revision 2.3 */ 1198c2ecf20Sopenharmony_ci CI_REVISION_24, /* Revision 2.4 */ 1208c2ecf20Sopenharmony_ci CI_REVISION_25, /* Revision 2.5 */ 1218c2ecf20Sopenharmony_ci CI_REVISION_25_PLUS, /* Revision above than 2.5 */ 1228c2ecf20Sopenharmony_ci CI_REVISION_UNKNOWN = 99, /* Unknown Revision */ 1238c2ecf20Sopenharmony_ci}; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/** 1268c2ecf20Sopenharmony_ci * struct ci_role_driver - host/gadget role driver 1278c2ecf20Sopenharmony_ci * @start: start this role 1288c2ecf20Sopenharmony_ci * @stop: stop this role 1298c2ecf20Sopenharmony_ci * @irq: irq handler for this role 1308c2ecf20Sopenharmony_ci * @name: role name string (host/gadget) 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistruct ci_role_driver { 1338c2ecf20Sopenharmony_ci int (*start)(struct ci_hdrc *); 1348c2ecf20Sopenharmony_ci void (*stop)(struct ci_hdrc *); 1358c2ecf20Sopenharmony_ci irqreturn_t (*irq)(struct ci_hdrc *); 1368c2ecf20Sopenharmony_ci const char *name; 1378c2ecf20Sopenharmony_ci}; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/** 1408c2ecf20Sopenharmony_ci * struct hw_bank - hardware register mapping representation 1418c2ecf20Sopenharmony_ci * @lpm: set if the device is LPM capable 1428c2ecf20Sopenharmony_ci * @phys: physical address of the controller's registers 1438c2ecf20Sopenharmony_ci * @abs: absolute address of the beginning of register window 1448c2ecf20Sopenharmony_ci * @cap: capability registers 1458c2ecf20Sopenharmony_ci * @op: operational registers 1468c2ecf20Sopenharmony_ci * @size: size of the register window 1478c2ecf20Sopenharmony_ci * @regmap: register lookup table 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_cistruct hw_bank { 1508c2ecf20Sopenharmony_ci unsigned lpm; 1518c2ecf20Sopenharmony_ci resource_size_t phys; 1528c2ecf20Sopenharmony_ci void __iomem *abs; 1538c2ecf20Sopenharmony_ci void __iomem *cap; 1548c2ecf20Sopenharmony_ci void __iomem *op; 1558c2ecf20Sopenharmony_ci size_t size; 1568c2ecf20Sopenharmony_ci void __iomem *regmap[OP_LAST + 1]; 1578c2ecf20Sopenharmony_ci}; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci/** 1608c2ecf20Sopenharmony_ci * struct ci_hdrc - chipidea device representation 1618c2ecf20Sopenharmony_ci * @dev: pointer to parent device 1628c2ecf20Sopenharmony_ci * @lock: access synchronization 1638c2ecf20Sopenharmony_ci * @hw_bank: hardware register mapping 1648c2ecf20Sopenharmony_ci * @irq: IRQ number 1658c2ecf20Sopenharmony_ci * @roles: array of supported roles for this controller 1668c2ecf20Sopenharmony_ci * @role: current role 1678c2ecf20Sopenharmony_ci * @is_otg: if the device is otg-capable 1688c2ecf20Sopenharmony_ci * @fsm: otg finite state machine 1698c2ecf20Sopenharmony_ci * @otg_fsm_hrtimer: hrtimer for otg fsm timers 1708c2ecf20Sopenharmony_ci * @hr_timeouts: time out list for active otg fsm timers 1718c2ecf20Sopenharmony_ci * @enabled_otg_timer_bits: bits of enabled otg timers 1728c2ecf20Sopenharmony_ci * @next_otg_timer: next nearest enabled timer to be expired 1738c2ecf20Sopenharmony_ci * @work: work for role changing 1748c2ecf20Sopenharmony_ci * @wq: workqueue thread 1758c2ecf20Sopenharmony_ci * @qh_pool: allocation pool for queue heads 1768c2ecf20Sopenharmony_ci * @td_pool: allocation pool for transfer descriptors 1778c2ecf20Sopenharmony_ci * @gadget: device side representation for peripheral controller 1788c2ecf20Sopenharmony_ci * @driver: gadget driver 1798c2ecf20Sopenharmony_ci * @resume_state: save the state of gadget suspend from 1808c2ecf20Sopenharmony_ci * @hw_ep_max: total number of endpoints supported by hardware 1818c2ecf20Sopenharmony_ci * @ci_hw_ep: array of endpoints 1828c2ecf20Sopenharmony_ci * @ep0_dir: ep0 direction 1838c2ecf20Sopenharmony_ci * @ep0out: pointer to ep0 OUT endpoint 1848c2ecf20Sopenharmony_ci * @ep0in: pointer to ep0 IN endpoint 1858c2ecf20Sopenharmony_ci * @status: ep0 status request 1868c2ecf20Sopenharmony_ci * @setaddr: if we should set the address on status completion 1878c2ecf20Sopenharmony_ci * @address: usb address received from the host 1888c2ecf20Sopenharmony_ci * @remote_wakeup: host-enabled remote wakeup 1898c2ecf20Sopenharmony_ci * @suspended: suspended by host 1908c2ecf20Sopenharmony_ci * @test_mode: the selected test mode 1918c2ecf20Sopenharmony_ci * @platdata: platform specific information supplied by parent device 1928c2ecf20Sopenharmony_ci * @vbus_active: is VBUS active 1938c2ecf20Sopenharmony_ci * @ulpi: pointer to ULPI device, if any 1948c2ecf20Sopenharmony_ci * @ulpi_ops: ULPI read/write ops for this device 1958c2ecf20Sopenharmony_ci * @phy: pointer to PHY, if any 1968c2ecf20Sopenharmony_ci * @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework 1978c2ecf20Sopenharmony_ci * @hcd: pointer to usb_hcd for ehci host driver 1988c2ecf20Sopenharmony_ci * @debugfs: root dentry for this controller in debugfs 1998c2ecf20Sopenharmony_ci * @id_event: indicates there is an id event, and handled at ci_otg_work 2008c2ecf20Sopenharmony_ci * @b_sess_valid_event: indicates there is a vbus event, and handled 2018c2ecf20Sopenharmony_ci * at ci_otg_work 2028c2ecf20Sopenharmony_ci * @imx28_write_fix: Freescale imx28 needs swp instruction for writing 2038c2ecf20Sopenharmony_ci * @supports_runtime_pm: if runtime pm is supported 2048c2ecf20Sopenharmony_ci * @in_lpm: if the core in low power mode 2058c2ecf20Sopenharmony_ci * @wakeup_int: if wakeup interrupt occur 2068c2ecf20Sopenharmony_ci * @rev: The revision number for controller 2078c2ecf20Sopenharmony_ci * @mutex: protect code from concorrent running when doing role switch 2088c2ecf20Sopenharmony_ci */ 2098c2ecf20Sopenharmony_cistruct ci_hdrc { 2108c2ecf20Sopenharmony_ci struct device *dev; 2118c2ecf20Sopenharmony_ci spinlock_t lock; 2128c2ecf20Sopenharmony_ci struct hw_bank hw_bank; 2138c2ecf20Sopenharmony_ci int irq; 2148c2ecf20Sopenharmony_ci struct ci_role_driver *roles[CI_ROLE_END]; 2158c2ecf20Sopenharmony_ci enum ci_role role; 2168c2ecf20Sopenharmony_ci bool is_otg; 2178c2ecf20Sopenharmony_ci struct usb_otg otg; 2188c2ecf20Sopenharmony_ci struct otg_fsm fsm; 2198c2ecf20Sopenharmony_ci struct hrtimer otg_fsm_hrtimer; 2208c2ecf20Sopenharmony_ci ktime_t hr_timeouts[NUM_OTG_FSM_TIMERS]; 2218c2ecf20Sopenharmony_ci unsigned enabled_otg_timer_bits; 2228c2ecf20Sopenharmony_ci enum otg_fsm_timer next_otg_timer; 2238c2ecf20Sopenharmony_ci struct usb_role_switch *role_switch; 2248c2ecf20Sopenharmony_ci struct work_struct work; 2258c2ecf20Sopenharmony_ci struct workqueue_struct *wq; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci struct dma_pool *qh_pool; 2288c2ecf20Sopenharmony_ci struct dma_pool *td_pool; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci struct usb_gadget gadget; 2318c2ecf20Sopenharmony_ci struct usb_gadget_driver *driver; 2328c2ecf20Sopenharmony_ci enum usb_device_state resume_state; 2338c2ecf20Sopenharmony_ci unsigned hw_ep_max; 2348c2ecf20Sopenharmony_ci struct ci_hw_ep ci_hw_ep[ENDPT_MAX]; 2358c2ecf20Sopenharmony_ci u32 ep0_dir; 2368c2ecf20Sopenharmony_ci struct ci_hw_ep *ep0out, *ep0in; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci struct usb_request *status; 2398c2ecf20Sopenharmony_ci bool setaddr; 2408c2ecf20Sopenharmony_ci u8 address; 2418c2ecf20Sopenharmony_ci u8 remote_wakeup; 2428c2ecf20Sopenharmony_ci u8 suspended; 2438c2ecf20Sopenharmony_ci u8 test_mode; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci struct ci_hdrc_platform_data *platdata; 2468c2ecf20Sopenharmony_ci int vbus_active; 2478c2ecf20Sopenharmony_ci struct ulpi *ulpi; 2488c2ecf20Sopenharmony_ci struct ulpi_ops ulpi_ops; 2498c2ecf20Sopenharmony_ci struct phy *phy; 2508c2ecf20Sopenharmony_ci /* old usb_phy interface */ 2518c2ecf20Sopenharmony_ci struct usb_phy *usb_phy; 2528c2ecf20Sopenharmony_ci struct usb_hcd *hcd; 2538c2ecf20Sopenharmony_ci struct dentry *debugfs; 2548c2ecf20Sopenharmony_ci bool id_event; 2558c2ecf20Sopenharmony_ci bool b_sess_valid_event; 2568c2ecf20Sopenharmony_ci bool imx28_write_fix; 2578c2ecf20Sopenharmony_ci bool supports_runtime_pm; 2588c2ecf20Sopenharmony_ci bool in_lpm; 2598c2ecf20Sopenharmony_ci bool wakeup_int; 2608c2ecf20Sopenharmony_ci enum ci_revision rev; 2618c2ecf20Sopenharmony_ci struct mutex mutex; 2628c2ecf20Sopenharmony_ci}; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci BUG_ON(ci->role >= CI_ROLE_END || !ci->roles[ci->role]); 2678c2ecf20Sopenharmony_ci return ci->roles[ci->role]; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci int ret; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (role >= CI_ROLE_END) 2758c2ecf20Sopenharmony_ci return -EINVAL; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci if (!ci->roles[role]) 2788c2ecf20Sopenharmony_ci return -ENXIO; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci ret = ci->roles[role]->start(ci); 2818c2ecf20Sopenharmony_ci if (!ret) 2828c2ecf20Sopenharmony_ci ci->role = role; 2838c2ecf20Sopenharmony_ci return ret; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic inline void ci_role_stop(struct ci_hdrc *ci) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci enum ci_role role = ci->role; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci if (role == CI_ROLE_END) 2918c2ecf20Sopenharmony_ci return; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci ci->role = CI_ROLE_END; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci ci->roles[role]->stop(ci); 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic inline enum usb_role ci_role_to_usb_role(struct ci_hdrc *ci) 2998c2ecf20Sopenharmony_ci{ 3008c2ecf20Sopenharmony_ci if (ci->role == CI_ROLE_HOST) 3018c2ecf20Sopenharmony_ci return USB_ROLE_HOST; 3028c2ecf20Sopenharmony_ci else if (ci->role == CI_ROLE_GADGET && ci->vbus_active) 3038c2ecf20Sopenharmony_ci return USB_ROLE_DEVICE; 3048c2ecf20Sopenharmony_ci else 3058c2ecf20Sopenharmony_ci return USB_ROLE_NONE; 3068c2ecf20Sopenharmony_ci} 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic inline enum ci_role usb_role_to_ci_role(enum usb_role role) 3098c2ecf20Sopenharmony_ci{ 3108c2ecf20Sopenharmony_ci if (role == USB_ROLE_HOST) 3118c2ecf20Sopenharmony_ci return CI_ROLE_HOST; 3128c2ecf20Sopenharmony_ci else if (role == USB_ROLE_DEVICE) 3138c2ecf20Sopenharmony_ci return CI_ROLE_GADGET; 3148c2ecf20Sopenharmony_ci else 3158c2ecf20Sopenharmony_ci return CI_ROLE_END; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci/** 3198c2ecf20Sopenharmony_ci * hw_read_id_reg: reads from a identification register 3208c2ecf20Sopenharmony_ci * @ci: the controller 3218c2ecf20Sopenharmony_ci * @offset: offset from the beginning of identification registers region 3228c2ecf20Sopenharmony_ci * @mask: bitfield mask 3238c2ecf20Sopenharmony_ci * 3248c2ecf20Sopenharmony_ci * This function returns register contents 3258c2ecf20Sopenharmony_ci */ 3268c2ecf20Sopenharmony_cistatic inline u32 hw_read_id_reg(struct ci_hdrc *ci, u32 offset, u32 mask) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci return ioread32(ci->hw_bank.abs + offset) & mask; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci/** 3328c2ecf20Sopenharmony_ci * hw_write_id_reg: writes to a identification register 3338c2ecf20Sopenharmony_ci * @ci: the controller 3348c2ecf20Sopenharmony_ci * @offset: offset from the beginning of identification registers region 3358c2ecf20Sopenharmony_ci * @mask: bitfield mask 3368c2ecf20Sopenharmony_ci * @data: new value 3378c2ecf20Sopenharmony_ci */ 3388c2ecf20Sopenharmony_cistatic inline void hw_write_id_reg(struct ci_hdrc *ci, u32 offset, 3398c2ecf20Sopenharmony_ci u32 mask, u32 data) 3408c2ecf20Sopenharmony_ci{ 3418c2ecf20Sopenharmony_ci if (~mask) 3428c2ecf20Sopenharmony_ci data = (ioread32(ci->hw_bank.abs + offset) & ~mask) 3438c2ecf20Sopenharmony_ci | (data & mask); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci iowrite32(data, ci->hw_bank.abs + offset); 3468c2ecf20Sopenharmony_ci} 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci/** 3498c2ecf20Sopenharmony_ci * hw_read: reads from a hw register 3508c2ecf20Sopenharmony_ci * @ci: the controller 3518c2ecf20Sopenharmony_ci * @reg: register index 3528c2ecf20Sopenharmony_ci * @mask: bitfield mask 3538c2ecf20Sopenharmony_ci * 3548c2ecf20Sopenharmony_ci * This function returns register contents 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_cistatic inline u32 hw_read(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci return ioread32(ci->hw_bank.regmap[reg]) & mask; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci#ifdef CONFIG_SOC_IMX28 3628c2ecf20Sopenharmony_cistatic inline void imx28_ci_writel(u32 val, volatile void __iomem *addr) 3638c2ecf20Sopenharmony_ci{ 3648c2ecf20Sopenharmony_ci __asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr)); 3658c2ecf20Sopenharmony_ci} 3668c2ecf20Sopenharmony_ci#else 3678c2ecf20Sopenharmony_cistatic inline void imx28_ci_writel(u32 val, volatile void __iomem *addr) 3688c2ecf20Sopenharmony_ci{ 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci#endif 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_cistatic inline void __hw_write(struct ci_hdrc *ci, u32 val, 3738c2ecf20Sopenharmony_ci void __iomem *addr) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci if (ci->imx28_write_fix) 3768c2ecf20Sopenharmony_ci imx28_ci_writel(val, addr); 3778c2ecf20Sopenharmony_ci else 3788c2ecf20Sopenharmony_ci iowrite32(val, addr); 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci/** 3828c2ecf20Sopenharmony_ci * hw_write: writes to a hw register 3838c2ecf20Sopenharmony_ci * @ci: the controller 3848c2ecf20Sopenharmony_ci * @reg: register index 3858c2ecf20Sopenharmony_ci * @mask: bitfield mask 3868c2ecf20Sopenharmony_ci * @data: new value 3878c2ecf20Sopenharmony_ci */ 3888c2ecf20Sopenharmony_cistatic inline void hw_write(struct ci_hdrc *ci, enum ci_hw_regs reg, 3898c2ecf20Sopenharmony_ci u32 mask, u32 data) 3908c2ecf20Sopenharmony_ci{ 3918c2ecf20Sopenharmony_ci if (~mask) 3928c2ecf20Sopenharmony_ci data = (ioread32(ci->hw_bank.regmap[reg]) & ~mask) 3938c2ecf20Sopenharmony_ci | (data & mask); 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci __hw_write(ci, data, ci->hw_bank.regmap[reg]); 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci/** 3998c2ecf20Sopenharmony_ci * hw_test_and_clear: tests & clears a hw register 4008c2ecf20Sopenharmony_ci * @ci: the controller 4018c2ecf20Sopenharmony_ci * @reg: register index 4028c2ecf20Sopenharmony_ci * @mask: bitfield mask 4038c2ecf20Sopenharmony_ci * 4048c2ecf20Sopenharmony_ci * This function returns register contents 4058c2ecf20Sopenharmony_ci */ 4068c2ecf20Sopenharmony_cistatic inline u32 hw_test_and_clear(struct ci_hdrc *ci, enum ci_hw_regs reg, 4078c2ecf20Sopenharmony_ci u32 mask) 4088c2ecf20Sopenharmony_ci{ 4098c2ecf20Sopenharmony_ci u32 val = ioread32(ci->hw_bank.regmap[reg]) & mask; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci __hw_write(ci, val, ci->hw_bank.regmap[reg]); 4128c2ecf20Sopenharmony_ci return val; 4138c2ecf20Sopenharmony_ci} 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_ci/** 4168c2ecf20Sopenharmony_ci * hw_test_and_write: tests & writes a hw register 4178c2ecf20Sopenharmony_ci * @ci: the controller 4188c2ecf20Sopenharmony_ci * @reg: register index 4198c2ecf20Sopenharmony_ci * @mask: bitfield mask 4208c2ecf20Sopenharmony_ci * @data: new value 4218c2ecf20Sopenharmony_ci * 4228c2ecf20Sopenharmony_ci * This function returns register contents 4238c2ecf20Sopenharmony_ci */ 4248c2ecf20Sopenharmony_cistatic inline u32 hw_test_and_write(struct ci_hdrc *ci, enum ci_hw_regs reg, 4258c2ecf20Sopenharmony_ci u32 mask, u32 data) 4268c2ecf20Sopenharmony_ci{ 4278c2ecf20Sopenharmony_ci u32 val = hw_read(ci, reg, ~0); 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci hw_write(ci, reg, mask, data); 4308c2ecf20Sopenharmony_ci return (val & mask) >> __ffs(mask); 4318c2ecf20Sopenharmony_ci} 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci/** 4348c2ecf20Sopenharmony_ci * ci_otg_is_fsm_mode: runtime check if otg controller 4358c2ecf20Sopenharmony_ci * is in otg fsm mode. 4368c2ecf20Sopenharmony_ci * 4378c2ecf20Sopenharmony_ci * @ci: chipidea device 4388c2ecf20Sopenharmony_ci */ 4398c2ecf20Sopenharmony_cistatic inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci) 4408c2ecf20Sopenharmony_ci{ 4418c2ecf20Sopenharmony_ci#ifdef CONFIG_USB_OTG_FSM 4428c2ecf20Sopenharmony_ci struct usb_otg_caps *otg_caps = &ci->platdata->ci_otg_caps; 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci return ci->is_otg && ci->roles[CI_ROLE_HOST] && 4458c2ecf20Sopenharmony_ci ci->roles[CI_ROLE_GADGET] && (otg_caps->srp_support || 4468c2ecf20Sopenharmony_ci otg_caps->hnp_support || otg_caps->adp_support); 4478c2ecf20Sopenharmony_ci#else 4488c2ecf20Sopenharmony_ci return false; 4498c2ecf20Sopenharmony_ci#endif 4508c2ecf20Sopenharmony_ci} 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ciint ci_ulpi_init(struct ci_hdrc *ci); 4538c2ecf20Sopenharmony_civoid ci_ulpi_exit(struct ci_hdrc *ci); 4548c2ecf20Sopenharmony_ciint ci_ulpi_resume(struct ci_hdrc *ci); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ciu32 hw_read_intr_enable(struct ci_hdrc *ci); 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ciu32 hw_read_intr_status(struct ci_hdrc *ci); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ciint hw_device_reset(struct ci_hdrc *ci); 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ciint hw_port_test_set(struct ci_hdrc *ci, u8 mode); 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ciu8 hw_port_test_get(struct ci_hdrc *ci); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_civoid hw_phymode_configure(struct ci_hdrc *ci); 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_civoid ci_platform_configure(struct ci_hdrc *ci); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_civoid dbg_create_files(struct ci_hdrc *ci); 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_civoid dbg_remove_files(struct ci_hdrc *ci); 4738c2ecf20Sopenharmony_ci#endif /* __DRIVERS_USB_CHIPIDEA_CI_H */ 474