2 * otg.c - ChipIdea USB IP core OTG driver
4 * Copyright (C) 2013 Freescale Semiconductor, Inc.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
14 * This file mainly handles otgsc register, OTG fsm operations for HNP and SRP
18 #include <linux/usb/otg.h>
19 #include <linux/usb/gadget.h>
20 #include <linux/usb/chipidea.h>
28 * hw_read_otgsc returns otgsc register bits value.
29 * @mask: bitfield mask
31 u32
hw_read_otgsc(struct ci_hdrc
*ci
, u32 mask
)
33 return hw_read(ci
, OP_OTGSC
, mask
);
37 * hw_write_otgsc updates target bits of OTGSC register.
38 * @mask: bitfield mask
39 * @data: to be written
41 void hw_write_otgsc(struct ci_hdrc
*ci
, u32 mask
, u32 data
)
43 hw_write(ci
, OP_OTGSC
, mask
| OTGSC_INT_STATUS_BITS
, data
);
47 * ci_otg_role - pick role based on ID pin state
50 enum ci_role
ci_otg_role(struct ci_hdrc
*ci
)
52 enum ci_role role
= hw_read_otgsc(ci
, OTGSC_ID
)
59 void ci_handle_vbus_change(struct ci_hdrc
*ci
)
64 if (hw_read_otgsc(ci
, OTGSC_BSV
))
65 usb_gadget_vbus_connect(&ci
->gadget
);
67 usb_gadget_vbus_disconnect(&ci
->gadget
);
70 #define CI_VBUS_STABLE_TIMEOUT_MS 5000
71 static void ci_handle_id_switch(struct ci_hdrc
*ci
)
73 enum ci_role role
= ci_otg_role(ci
);
75 if (role
!= ci
->role
) {
76 dev_dbg(ci
->dev
, "switching from %s to %s\n",
77 ci_role(ci
)->name
, ci
->roles
[role
]->name
);
80 /* wait vbus lower than OTGSC_BSV */
81 hw_wait_reg(ci
, OP_OTGSC
, OTGSC_BSV
, 0,
82 CI_VBUS_STABLE_TIMEOUT_MS
);
83 ci_role_start(ci
, role
);
87 * ci_otg_work - perform otg (vbus/id) event handle
90 static void ci_otg_work(struct work_struct
*work
)
92 struct ci_hdrc
*ci
= container_of(work
, struct ci_hdrc
, work
);
94 if (ci_otg_is_fsm_mode(ci
) && !ci_otg_fsm_work(ci
)) {
100 ci
->id_event
= false;
101 ci_handle_id_switch(ci
);
102 } else if (ci
->b_sess_valid_event
) {
103 ci
->b_sess_valid_event
= false;
104 ci_handle_vbus_change(ci
);
106 dev_err(ci
->dev
, "unexpected event occurs at %s\n", __func__
);
113 * ci_hdrc_otg_init - initialize otg struct
116 int ci_hdrc_otg_init(struct ci_hdrc
*ci
)
118 INIT_WORK(&ci
->work
, ci_otg_work
);
119 ci
->wq
= create_freezable_workqueue("ci_otg");
121 dev_err(ci
->dev
, "can't create workqueue\n");
125 if (ci_otg_is_fsm_mode(ci
))
126 return ci_hdrc_otg_fsm_init(ci
);
132 * ci_hdrc_otg_destroy - destroy otg struct
135 void ci_hdrc_otg_destroy(struct ci_hdrc
*ci
)
138 flush_workqueue(ci
->wq
);
139 destroy_workqueue(ci
->wq
);
141 /* Disable all OTG irq and clear status */
142 hw_write_otgsc(ci
, OTGSC_INT_EN_BITS
| OTGSC_INT_STATUS_BITS
,
143 OTGSC_INT_STATUS_BITS
);
144 if (ci_otg_is_fsm_mode(ci
))
145 ci_hdrc_otg_fsm_remove(ci
);