/*-----------------------------------------------------------------------------
 * drivers/usb/mcd/usb_mcd_otg.h
 * 
 * USB controller driver
 * 
 * Copyright 2005,2006,2008 Sony Corporation
 *
 * This file is part of the Inventra Controller Driver for Linux.
 * 
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA  02110-1301, USA.
 *---------------------------------------------------------------------------*/

#ifndef _USB_MCD_OTG_H_
#define _USB_MCD_OTG_H_

/*
 *	数値
 */

/* ユーザIO制御 */
enum {
	USB_OTG_IO_START_CONTROL,
	USB_OTG_IO_STOP_CONTROL,
	USB_OTG_IO_START_GADGET,
	USB_OTG_IO_STOP_GADGET,
	USB_OTG_IO_ENABLE_RCHOST,
	USB_OTG_IO_DISABLE_RCHOST,
	USB_OTG_IO_STOP_RCHOST,
	USB_OTG_IO_START_HOST,
	USB_OTG_IO_STOP_HOST,
	USB_OTG_IO_START_RCGADGET,
	USB_OTG_IO_STOP_RCGADGET,
	USB_OTG_IO_INIT_SRP,
	USB_OTG_IO_FINISH_SRP,

	USB_OTG_IO_START_VBUSOUT,
	USB_OTG_IO_STOP_VBUSOUT,

	USB_OTG_IO_CHANGE_CID,
	USB_OTG_IO_DISCONN,

	USB_OTG_IO_SUSPEND,
	USB_OTG_IO_FREEZE,
	USB_OTG_IO_PRETHAW,
	USB_OTG_IO_RESUME,
	USB_OTG_IO_SHUTDOWN,
};

/* Vbus制御 */
#define USB_OTG_OFF	0
#define USB_OTG_ON 	1
#define USB_OTG_THRU 	2

/* 内部状態 */
enum {
	MCD_OTGC_S_STOP = 1,
	MCD_OTGC_S_AB_IDLE,
	MCD_OTGC_S_B_PERIPH,
	MCD_OTGC_S_B_WAIT_ACON,
	MCD_OTGC_S_B_HOST,
	MCD_OTGC_S_A_HOST,
	MCD_OTGC_S_A_PERIPH,
};

/* OTG属性 */
#define MCD_OTG_ATTR_ALL_INT_PORT	(1<<0)
#define MCD_OTG_ATTR_USING_PHY_VBUS	(1<<1)
#define MCD_OTG_ATTR_USING_PHY_CID	(1<<2)

/* OTG Control名最大長 */
#define MCD_OTG_MAX_NAME_LEN	256

/*
 *	内部構造体
 */

struct mcd_otg_intdat_ops {
	int (*get_port_info) (struct usb_otg_control *,
			      struct usb_otg_control_port_info * info);
	int (*select_port) (struct usb_otg_control *, u32 pn);
	bool (*check_suspend) (struct usb_otg_control *);
	int (*control_io) (struct usb_otg_control *, u32 control);
	int (*control_vbus) (struct usb_otg_control *, u32 control);
	int (*control_test) (struct usb_otg_control *,
			     enum usb_otg_control_test_mode test_mode);
};

struct mcd_otg_port {
	u32 cid_filter_count;
	u32 vbus_filter_count;
	u32 cid_check_count;
	s32 last_cid;
	s32 ref_cid;
	u32 vbus_check_count;
	enum usb_otg_vbus_stat last_vbus;
	enum usb_otg_vbus_stat ref_vbus;
	/* operation functions */
	int (*check_cid) (struct usb_otg_control *, u32);
	enum usb_otg_vbus_stat (*check_vbus) (struct usb_otg_control *, u32);
};

struct mcd_otg_intdat {
	struct usb_otg_control otgc;
	struct mcd_otg_intdat_ops *ops;
	spinlock_t lock;
	u32 state;
	u32 attributes;
	struct timer_list detector;
	struct timer_list timer;
	u32 periodic_delay;
	struct list_head event_list;
	u32 port_num;
	struct mcd_otg_port *port;
};

struct mcd_otg_event_container {
	union usb_otg_event event;
	struct list_head list;
};

/*
 *	ユーザー実装関数
 */

struct mcd_device;

/*
 * 関数：mcd_board_map
 * GPIO等ユーザー実装部の初期化、ユーザー実装関数
 */

extern int mcd_board_map(struct mcd_device *mdev);

/*
 * 関数：mcd_board_unmap
 * GPIO等ユーザー実装部の終了、ユーザー実装関数
 */

extern int mcd_board_unmap(struct mcd_device *mdev);

/*
 *	ユーザー実装関数内呼び出し関数
 */

/*
 * 関数：mcd_otg_control_create_object
 * usb_otg_control構造体のインスタンスオブジェクトの生成
 */

extern int mcd_otg_control_create_object(struct mcd_device * mdev,
					 u32 periodic_delay,
					 struct mcd_otg_intdat_ops *ops,
					 const char *name);

/*
 * 関数：mcd_otg_control_destroy_object
 * usb_otg_control構造体のインスタンスオブジェクトの生成
 */

extern int mcd_otg_control_destroy_object(struct mcd_device *mdev);

/*
 * 関数：mcd_otg_control_attach_port
 * OTGコントローラへのUSBポート情報の設定
 */

extern int
mcd_otg_control_attach_port(struct usb_otg_control *otg_control,
			    u32 i, u32 cid_filter_count, u32 vbus_filter_count,
			    int (*check_cid) (struct usb_otg_control *, u32),
			    enum usb_otg_vbus_stat (*check_vbus) (
				    struct usb_otg_control *, u32));

/*
 * 関数：mcd_otg_control_detach_port
 * OTGコントローラへのUSBポート情報の設定解除
 */

extern int
mcd_otg_control_detach_port(struct usb_otg_control *otg_control, u32 i);

/*
 * 関数：mcd_otg_control_notify_vbuserror
 * Vbusエラーを通知する。
 */
extern int
mcd_otg_control_notify_vbuserror(struct usb_otg_control *otg_control);

/*
 * 関数：mcd_otg_control_force_vbus
 * Vbusを制御する
 */
extern int
mcd_otg_control_force_vbus(struct usb_otg_control *otg_control,
			   u32 control);

/*
 * 関数：mcd_otg_control_check_suspend
 * デバイスのSuspend状態をチェックする
 */
extern bool
mcd_otg_control_check_suspend(struct usb_otg_control *otg_control,
			      bool expected);

/*
 * 関数：mcd_otg_control_start_detecotr
 * Vbus/CID検知タイマーdetectorを開始する。
 */
extern void mcd_otg_control_start_detector(struct usb_otg_control *otg_control);

/*
 * 関数：mcd_otg_control_stop_detecotr
 * Vbus/CID検知タイマーdetectorを停止する。
 */
extern void mcd_otg_control_stop_detector(struct usb_otg_control *otg_control);

/*
 * 関数：mcd_otg_control_suspend
 * コントローラをSuspendする
 */
extern int mcd_otg_control_suspend(struct usb_otg_control *otg_control,
				   pm_message_t message);

/*
 * 関数：mcd_otg_control_resume
 * コントローラをResumeする
 */
extern int mcd_otg_control_resume(struct usb_otg_control *otg_control);

/*
 * 関数：mcd_otg_control_shutdown
 * コントローラをShutdownする
 */
extern int mcd_otg_control_shutdown(struct usb_otg_control *otg_control);

/*
 * 関数：mcd_otg_control_signal
 * OTGステートマシンへシグナルを入力する。
 */
extern int
mcd_otg_control_signal(struct usb_otg_control *otg_control,
		       union usb_otg_event *otg_event);

/*
 * 関数：mcd_otg_control_signal_interrupt
 * 割り込みからOTGステートマシンへシグナルを入力する。
 */
extern void
mcd_otg_control_signal_interrupt(struct usb_otg_control *otg_control,
				 union usb_otg_event *otg_event);

/*
 * 関数：mcd_otg_control_start_rchost
 * Suspend信号をトリガとしてControllerをRCHOSTモードにする。
 */

extern int mcd_otg_control_start_rchost(struct usb_otg_control *otg_control);

/* 関数：mcd_otga_check_vbus
 * Vbusの状態を取得する
 */

extern enum usb_otg_vbus_stat mcd_otga_check_vbus(void *regs);

/*
 * 関数：mcd_otga_enable_role_change
 * b-device時にHostReqをセットしてRoleChangeを許可する。
 */

extern int mcd_otga_enable_role_change(void *regs);

/*
 * 関数：mcd_otga_disable_role_change
 * b-device時にHostReqをクリアしてRoleChangeを不許可とする。
 */

extern int mcd_otga_disable_role_change(void *regs);

/*
 * 関数：mcd_otga_suspend
 * RoleChangeに伴うSuspendを行う。
 */

extern int mcd_otga_suspend(void *regs);

/*
 * 関数：mcd_otga_start_session
 * a-device時にSessionビットをセットしてVbus供給を開始する。
 */

extern int mcd_otga_start_session(void *regs);

/*
 * 関数：mcd_otga_end_session
 * a-device時にSessionビットをクリアしてVbus供給を停止する。
 */

extern int mcd_otga_end_session(void *regs);

/*
 * 関数：mcd_otga_request_session
 * idle時にSessionビットをセットしてSRPを発行する。
 */

extern int mcd_otga_request_session(void *regs);

/*
 * 関数：mcd_otga_set_speed
 * HSEnableをセット解除する。
 */

extern int mcd_otga_set_speed(void *regs, u32 speed);

/*
 * 関数：mcd_otga_get_speed
 * 現状のスピード状態を取得する。
 */

extern enum usb_otg_control_speed mcd_otga_get_speed(void *regs);

/*
 * 関数：mcd_otga_set_test_mode
 * テストモード設定する
 */

extern int
mcd_otga_set_test_mode(void *regs, enum usb_otg_control_test_mode test_mode);

/*
 * 関数：mcd_otga_get_test_mode
 * テストモード取得する
 */

extern enum usb_otg_control_test_mode mcd_otga_get_test_mode(void *regs);


/*
 * 関数：mcd_otg_control_io
 * IOを制御する
 */
extern int mcd_otg_control_io(struct usb_otg_control *otg_control, u32 control);

/*
 * 関数：mcd_otg_start_vbusout
 * Vbus供給を開始する
 */

static inline int mcd_otg_start_vbusout(struct usb_otg_control *otg_control)
{
	return mcd_otg_control_io(otg_control, USB_OTG_IO_START_VBUSOUT);
}

/*
 * 関数：mcd_otg_start_vbusout
 * Vbus供給を停止する
 */

static inline int mcd_otg_stop_vbusout(struct usb_otg_control *otg_control)
{
	return mcd_otg_control_io(otg_control, USB_OTG_IO_STOP_VBUSOUT);
}

#endif				/* _USB_MCD_OTG_H_ */
