0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/usb/otg.h>
0016 #include <linux/usb/gadget.h>
0017 #include <linux/usb/chipidea.h>
0018
0019 #include "ci.h"
0020 #include "bits.h"
0021 #include "otg.h"
0022 #include "otg_fsm.h"
0023
0024
0025
0026
0027
0028
0029 u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
0030 {
0031 struct ci_hdrc_cable *cable;
0032 u32 val = hw_read(ci, OP_OTGSC, mask);
0033
0034
0035
0036
0037
0038 cable = &ci->platdata->vbus_extcon;
0039 if (!IS_ERR(cable->edev) || ci->role_switch) {
0040 if (cable->changed)
0041 val |= OTGSC_BSVIS;
0042 else
0043 val &= ~OTGSC_BSVIS;
0044
0045 if (cable->connected)
0046 val |= OTGSC_BSV;
0047 else
0048 val &= ~OTGSC_BSV;
0049
0050 if (cable->enabled)
0051 val |= OTGSC_BSVIE;
0052 else
0053 val &= ~OTGSC_BSVIE;
0054 }
0055
0056 cable = &ci->platdata->id_extcon;
0057 if (!IS_ERR(cable->edev) || ci->role_switch) {
0058 if (cable->changed)
0059 val |= OTGSC_IDIS;
0060 else
0061 val &= ~OTGSC_IDIS;
0062
0063 if (cable->connected)
0064 val &= ~OTGSC_ID;
0065 else
0066 val |= OTGSC_ID;
0067
0068 if (cable->enabled)
0069 val |= OTGSC_IDIE;
0070 else
0071 val &= ~OTGSC_IDIE;
0072 }
0073
0074 return val & mask;
0075 }
0076
0077
0078
0079
0080
0081
0082
0083 void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
0084 {
0085 struct ci_hdrc_cable *cable;
0086
0087 cable = &ci->platdata->vbus_extcon;
0088 if (!IS_ERR(cable->edev) || ci->role_switch) {
0089 if (data & mask & OTGSC_BSVIS)
0090 cable->changed = false;
0091
0092
0093 if (data & mask & OTGSC_BSVIE) {
0094 cable->enabled = true;
0095 data &= ~OTGSC_BSVIE;
0096 } else if (mask & OTGSC_BSVIE) {
0097 cable->enabled = false;
0098 }
0099 }
0100
0101 cable = &ci->platdata->id_extcon;
0102 if (!IS_ERR(cable->edev) || ci->role_switch) {
0103 if (data & mask & OTGSC_IDIS)
0104 cable->changed = false;
0105
0106
0107 if (data & mask & OTGSC_IDIE) {
0108 cable->enabled = true;
0109 data &= ~OTGSC_IDIE;
0110 } else if (mask & OTGSC_IDIE) {
0111 cable->enabled = false;
0112 }
0113 }
0114
0115 hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
0116 }
0117
0118
0119
0120
0121
0122 enum ci_role ci_otg_role(struct ci_hdrc *ci)
0123 {
0124 enum ci_role role = hw_read_otgsc(ci, OTGSC_ID)
0125 ? CI_ROLE_GADGET
0126 : CI_ROLE_HOST;
0127
0128 return role;
0129 }
0130
0131 void ci_handle_vbus_change(struct ci_hdrc *ci)
0132 {
0133 if (!ci->is_otg)
0134 return;
0135
0136 if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active)
0137 usb_gadget_vbus_connect(&ci->gadget);
0138 else if (!hw_read_otgsc(ci, OTGSC_BSV) && ci->vbus_active)
0139 usb_gadget_vbus_disconnect(&ci->gadget);
0140 }
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
0152 {
0153 unsigned long elapse = jiffies + msecs_to_jiffies(5000);
0154 u32 mask = OTGSC_BSV;
0155
0156 while (hw_read_otgsc(ci, mask)) {
0157 if (time_after(jiffies, elapse)) {
0158 dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
0159 mask);
0160 return -ETIMEDOUT;
0161 }
0162 msleep(20);
0163 }
0164
0165 return 0;
0166 }
0167
0168 static void ci_handle_id_switch(struct ci_hdrc *ci)
0169 {
0170 enum ci_role role = ci_otg_role(ci);
0171
0172 if (role != ci->role) {
0173 dev_dbg(ci->dev, "switching from %s to %s\n",
0174 ci_role(ci)->name, ci->roles[role]->name);
0175
0176 if (ci->vbus_active && ci->role == CI_ROLE_GADGET)
0177
0178
0179
0180
0181 usb_gadget_vbus_disconnect(&ci->gadget);
0182
0183 ci_role_stop(ci);
0184
0185 if (role == CI_ROLE_GADGET &&
0186 IS_ERR(ci->platdata->vbus_extcon.edev))
0187
0188
0189
0190
0191
0192
0193
0194 hw_wait_vbus_lower_bsv(ci);
0195
0196 ci_role_start(ci, role);
0197
0198 if (role == CI_ROLE_GADGET)
0199 ci_handle_vbus_change(ci);
0200 }
0201 }
0202
0203
0204
0205
0206 static void ci_otg_work(struct work_struct *work)
0207 {
0208 struct ci_hdrc *ci = container_of(work, struct ci_hdrc, work);
0209
0210 if (ci_otg_is_fsm_mode(ci) && !ci_otg_fsm_work(ci)) {
0211 enable_irq(ci->irq);
0212 return;
0213 }
0214
0215 pm_runtime_get_sync(ci->dev);
0216
0217 if (ci->id_event) {
0218 ci->id_event = false;
0219 ci_handle_id_switch(ci);
0220 }
0221
0222 if (ci->b_sess_valid_event) {
0223 ci->b_sess_valid_event = false;
0224 ci_handle_vbus_change(ci);
0225 }
0226
0227 pm_runtime_put_sync(ci->dev);
0228
0229 enable_irq(ci->irq);
0230 }
0231
0232
0233
0234
0235
0236
0237 int ci_hdrc_otg_init(struct ci_hdrc *ci)
0238 {
0239 INIT_WORK(&ci->work, ci_otg_work);
0240 ci->wq = create_freezable_workqueue("ci_otg");
0241 if (!ci->wq) {
0242 dev_err(ci->dev, "can't create workqueue\n");
0243 return -ENODEV;
0244 }
0245
0246 if (ci_otg_is_fsm_mode(ci))
0247 return ci_hdrc_otg_fsm_init(ci);
0248
0249 return 0;
0250 }
0251
0252
0253
0254
0255
0256 void ci_hdrc_otg_destroy(struct ci_hdrc *ci)
0257 {
0258 if (ci->wq)
0259 destroy_workqueue(ci->wq);
0260
0261
0262 hw_write_otgsc(ci, OTGSC_INT_EN_BITS | OTGSC_INT_STATUS_BITS,
0263 OTGSC_INT_STATUS_BITS);
0264 if (ci_otg_is_fsm_mode(ci))
0265 ci_hdrc_otg_fsm_remove(ci);
0266 }