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