Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright (C) 2007,2008 Freescale Semiconductor, Inc.
0004  */
0005 
0006 #ifndef __LINUX_USB_OTG_FSM_H
0007 #define __LINUX_USB_OTG_FSM_H
0008 
0009 #include <linux/mutex.h>
0010 #include <linux/errno.h>
0011 
0012 #define PROTO_UNDEF (0)
0013 #define PROTO_HOST  (1)
0014 #define PROTO_GADGET    (2)
0015 
0016 #define OTG_STS_SELECTOR    0xF000  /* OTG status selector, according to
0017                      * OTG and EH 2.0 Chapter 6.2.3
0018                      * Table:6-4
0019                      */
0020 
0021 #define HOST_REQUEST_FLAG   1   /* Host request flag, according to
0022                      * OTG and EH 2.0 Charpter 6.2.3
0023                      * Table:6-5
0024                      */
0025 
0026 #define T_HOST_REQ_POLL     (1500)  /* 1500ms, HNP polling interval */
0027 
0028 enum otg_fsm_timer {
0029     /* Standard OTG timers */
0030     A_WAIT_VRISE,
0031     A_WAIT_VFALL,
0032     A_WAIT_BCON,
0033     A_AIDL_BDIS,
0034     B_ASE0_BRST,
0035     A_BIDL_ADIS,
0036     B_AIDL_BDIS,
0037 
0038     /* Auxiliary timers */
0039     B_SE0_SRP,
0040     B_SRP_FAIL,
0041     A_WAIT_ENUM,
0042     B_DATA_PLS,
0043     B_SSEND_SRP,
0044 
0045     NUM_OTG_FSM_TIMERS,
0046 };
0047 
0048 /**
0049  * struct otg_fsm - OTG state machine according to the OTG spec
0050  *
0051  * OTG hardware Inputs
0052  *
0053  *  Common inputs for A and B device
0054  * @id:     TRUE for B-device, FALSE for A-device.
0055  * @adp_change: TRUE when current ADP measurement (n) value, compared to the
0056  *      ADP measurement taken at n-2, differs by more than CADP_THR
0057  * @power_up:   TRUE when the OTG device first powers up its USB system and
0058  *      ADP measurement taken if ADP capable
0059  *
0060  *  A-Device state inputs
0061  * @a_srp_det:  TRUE if the A-device detects SRP
0062  * @a_vbus_vld: TRUE when VBUS voltage is in regulation
0063  * @b_conn: TRUE if the A-device detects connection from the B-device
0064  * @a_bus_resume: TRUE when the B-device detects that the A-device is signaling
0065  *        a resume (K state)
0066  *  B-Device state inputs
0067  * @a_bus_suspend: TRUE when the B-device detects that the A-device has put the
0068  *      bus into suspend
0069  * @a_conn: TRUE if the B-device detects a connection from the A-device
0070  * @b_se0_srp:  TRUE when the line has been at SE0 for more than the minimum
0071  *      time before generating SRP
0072  * @b_ssend_srp: TRUE when the VBUS has been below VOTG_SESS_VLD for more than
0073  *       the minimum time before generating SRP
0074  * @b_sess_vld: TRUE when the B-device detects that the voltage on VBUS is
0075  *      above VOTG_SESS_VLD
0076  * @test_device: TRUE when the B-device switches to B-Host and detects an OTG
0077  *      test device. This must be set by host/hub driver
0078  *
0079  *  Application inputs (A-Device)
0080  * @a_bus_drop: TRUE when A-device application needs to power down the bus
0081  * @a_bus_req:  TRUE when A-device application wants to use the bus.
0082  *      FALSE to suspend the bus
0083  *
0084  *  Application inputs (B-Device)
0085  * @b_bus_req:  TRUE during the time that the Application running on the
0086  *      B-device wants to use the bus
0087  *
0088  *  Auxiliary inputs (OTG v1.3 only. Obsolete now.)
0089  * @a_sess_vld: TRUE if the A-device detects that VBUS is above VA_SESS_VLD
0090  * @b_bus_suspend: TRUE when the A-device detects that the B-device has put
0091  *      the bus into suspend
0092  * @b_bus_resume: TRUE when the A-device detects that the B-device is signaling
0093  *       resume on the bus
0094  *
0095  * OTG Output status. Read only for users. Updated by OTG FSM helpers defined
0096  * in this file
0097  *
0098  *  Outputs for Both A and B device
0099  * @drv_vbus:   TRUE when A-device is driving VBUS
0100  * @loc_conn:   TRUE when the local device has signaled that it is connected
0101  *      to the bus
0102  * @loc_sof:    TRUE when the local device is generating activity on the bus
0103  * @adp_prb:    TRUE when the local device is in the process of doing
0104  *      ADP probing
0105  *
0106  *  Outputs for B-device state
0107  * @adp_sns:    TRUE when the B-device is in the process of carrying out
0108  *      ADP sensing
0109  * @data_pulse: TRUE when the B-device is performing data line pulsing
0110  *
0111  * Internal Variables
0112  *
0113  * a_set_b_hnp_en: TRUE when the A-device has successfully set the
0114  *      b_hnp_enable bit in the B-device.
0115  *         Unused as OTG fsm uses otg->host->b_hnp_enable instead
0116  * b_srp_done:  TRUE when the B-device has completed initiating SRP
0117  * b_hnp_enable: TRUE when the B-device has accepted the
0118  *      SetFeature(b_hnp_enable) B-device.
0119  *      Unused as OTG fsm uses otg->gadget->b_hnp_enable instead
0120  * a_clr_err:   Asserted (by application ?) to clear a_vbus_err due to an
0121  *      overcurrent condition and causes the A-device to transition
0122  *      to a_wait_vfall
0123  */
0124 struct otg_fsm {
0125     /* Input */
0126     int id;
0127     int adp_change;
0128     int power_up;
0129     int a_srp_det;
0130     int a_vbus_vld;
0131     int b_conn;
0132     int a_bus_resume;
0133     int a_bus_suspend;
0134     int a_conn;
0135     int b_se0_srp;
0136     int b_ssend_srp;
0137     int b_sess_vld;
0138     int test_device;
0139     int a_bus_drop;
0140     int a_bus_req;
0141     int b_bus_req;
0142 
0143     /* Auxiliary inputs */
0144     int a_sess_vld;
0145     int b_bus_resume;
0146     int b_bus_suspend;
0147 
0148     /* Output */
0149     int drv_vbus;
0150     int loc_conn;
0151     int loc_sof;
0152     int adp_prb;
0153     int adp_sns;
0154     int data_pulse;
0155 
0156     /* Internal variables */
0157     int a_set_b_hnp_en;
0158     int b_srp_done;
0159     int b_hnp_enable;
0160     int a_clr_err;
0161 
0162     /* Informative variables. All unused as of now */
0163     int a_bus_drop_inf;
0164     int a_bus_req_inf;
0165     int a_clr_err_inf;
0166     int b_bus_req_inf;
0167     /* Auxiliary informative variables */
0168     int a_suspend_req_inf;
0169 
0170     /* Timeout indicator for timers */
0171     int a_wait_vrise_tmout;
0172     int a_wait_vfall_tmout;
0173     int a_wait_bcon_tmout;
0174     int a_aidl_bdis_tmout;
0175     int b_ase0_brst_tmout;
0176     int a_bidl_adis_tmout;
0177 
0178     struct otg_fsm_ops *ops;
0179     struct usb_otg *otg;
0180 
0181     /* Current usb protocol used: 0:undefine; 1:host; 2:client */
0182     int protocol;
0183     struct mutex lock;
0184     u8 *host_req_flag;
0185     struct delayed_work hnp_polling_work;
0186     bool hnp_work_inited;
0187     bool state_changed;
0188 };
0189 
0190 struct otg_fsm_ops {
0191     void    (*chrg_vbus)(struct otg_fsm *fsm, int on);
0192     void    (*drv_vbus)(struct otg_fsm *fsm, int on);
0193     void    (*loc_conn)(struct otg_fsm *fsm, int on);
0194     void    (*loc_sof)(struct otg_fsm *fsm, int on);
0195     void    (*start_pulse)(struct otg_fsm *fsm);
0196     void    (*start_adp_prb)(struct otg_fsm *fsm);
0197     void    (*start_adp_sns)(struct otg_fsm *fsm);
0198     void    (*add_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer);
0199     void    (*del_timer)(struct otg_fsm *fsm, enum otg_fsm_timer timer);
0200     int (*start_host)(struct otg_fsm *fsm, int on);
0201     int (*start_gadget)(struct otg_fsm *fsm, int on);
0202 };
0203 
0204 
0205 static inline int otg_chrg_vbus(struct otg_fsm *fsm, int on)
0206 {
0207     if (!fsm->ops->chrg_vbus)
0208         return -EOPNOTSUPP;
0209     fsm->ops->chrg_vbus(fsm, on);
0210     return 0;
0211 }
0212 
0213 static inline int otg_drv_vbus(struct otg_fsm *fsm, int on)
0214 {
0215     if (!fsm->ops->drv_vbus)
0216         return -EOPNOTSUPP;
0217     if (fsm->drv_vbus != on) {
0218         fsm->drv_vbus = on;
0219         fsm->ops->drv_vbus(fsm, on);
0220     }
0221     return 0;
0222 }
0223 
0224 static inline int otg_loc_conn(struct otg_fsm *fsm, int on)
0225 {
0226     if (!fsm->ops->loc_conn)
0227         return -EOPNOTSUPP;
0228     if (fsm->loc_conn != on) {
0229         fsm->loc_conn = on;
0230         fsm->ops->loc_conn(fsm, on);
0231     }
0232     return 0;
0233 }
0234 
0235 static inline int otg_loc_sof(struct otg_fsm *fsm, int on)
0236 {
0237     if (!fsm->ops->loc_sof)
0238         return -EOPNOTSUPP;
0239     if (fsm->loc_sof != on) {
0240         fsm->loc_sof = on;
0241         fsm->ops->loc_sof(fsm, on);
0242     }
0243     return 0;
0244 }
0245 
0246 static inline int otg_start_pulse(struct otg_fsm *fsm)
0247 {
0248     if (!fsm->ops->start_pulse)
0249         return -EOPNOTSUPP;
0250     if (!fsm->data_pulse) {
0251         fsm->data_pulse = 1;
0252         fsm->ops->start_pulse(fsm);
0253     }
0254     return 0;
0255 }
0256 
0257 static inline int otg_start_adp_prb(struct otg_fsm *fsm)
0258 {
0259     if (!fsm->ops->start_adp_prb)
0260         return -EOPNOTSUPP;
0261     if (!fsm->adp_prb) {
0262         fsm->adp_sns = 0;
0263         fsm->adp_prb = 1;
0264         fsm->ops->start_adp_prb(fsm);
0265     }
0266     return 0;
0267 }
0268 
0269 static inline int otg_start_adp_sns(struct otg_fsm *fsm)
0270 {
0271     if (!fsm->ops->start_adp_sns)
0272         return -EOPNOTSUPP;
0273     if (!fsm->adp_sns) {
0274         fsm->adp_sns = 1;
0275         fsm->ops->start_adp_sns(fsm);
0276     }
0277     return 0;
0278 }
0279 
0280 static inline int otg_add_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer)
0281 {
0282     if (!fsm->ops->add_timer)
0283         return -EOPNOTSUPP;
0284     fsm->ops->add_timer(fsm, timer);
0285     return 0;
0286 }
0287 
0288 static inline int otg_del_timer(struct otg_fsm *fsm, enum otg_fsm_timer timer)
0289 {
0290     if (!fsm->ops->del_timer)
0291         return -EOPNOTSUPP;
0292     fsm->ops->del_timer(fsm, timer);
0293     return 0;
0294 }
0295 
0296 static inline int otg_start_host(struct otg_fsm *fsm, int on)
0297 {
0298     if (!fsm->ops->start_host)
0299         return -EOPNOTSUPP;
0300     return fsm->ops->start_host(fsm, on);
0301 }
0302 
0303 static inline int otg_start_gadget(struct otg_fsm *fsm, int on)
0304 {
0305     if (!fsm->ops->start_gadget)
0306         return -EOPNOTSUPP;
0307     return fsm->ops->start_gadget(fsm, on);
0308 }
0309 
0310 int otg_statemachine(struct otg_fsm *fsm);
0311 
0312 #endif /* __LINUX_USB_OTG_FSM_H */