0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/interrupt.h>
0010
0011 #include "common.h"
0012 #include "mod.h"
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 static int usbhsm_autonomy_get_vbus(struct platform_device *pdev)
0025 {
0026 struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
0027
0028 return VBSTS & usbhs_read(priv, INTSTS0);
0029 }
0030
0031 static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
0032 struct usbhs_irq_state *irq_state)
0033 {
0034 struct platform_device *pdev = usbhs_priv_to_pdev(priv);
0035
0036 usbhsc_schedule_notify_hotplug(pdev);
0037
0038 return 0;
0039 }
0040
0041 void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
0042 {
0043 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0044
0045 info->irq_vbus = usbhsm_autonomy_irq_vbus;
0046 info->get_vbus = usbhsm_autonomy_get_vbus;
0047
0048 usbhs_irq_callback_update(priv, NULL);
0049 }
0050
0051 void usbhs_mod_non_autonomy_mode(struct usbhs_priv *priv)
0052 {
0053 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0054
0055 info->get_vbus = priv->pfunc->get_vbus;
0056 }
0057
0058
0059
0060
0061
0062
0063
0064
0065 void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id)
0066 {
0067 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0068
0069 info->mod[id] = mod;
0070 mod->priv = priv;
0071 }
0072
0073 struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
0074 {
0075 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0076 struct usbhs_mod *ret = NULL;
0077
0078 switch (id) {
0079 case USBHS_HOST:
0080 case USBHS_GADGET:
0081 ret = info->mod[id];
0082 break;
0083 }
0084
0085 return ret;
0086 }
0087
0088 int usbhs_mod_is_host(struct usbhs_priv *priv)
0089 {
0090 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
0091 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0092
0093 if (!mod)
0094 return -EINVAL;
0095
0096 return info->mod[USBHS_HOST] == mod;
0097 }
0098
0099 struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv)
0100 {
0101 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0102
0103 return info->curt;
0104 }
0105
0106 int usbhs_mod_change(struct usbhs_priv *priv, int id)
0107 {
0108 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0109 struct usbhs_mod *mod = NULL;
0110 int ret = 0;
0111
0112
0113 switch (id) {
0114 case USBHS_HOST:
0115 case USBHS_GADGET:
0116 mod = info->mod[id];
0117 break;
0118 default:
0119 ret = -EINVAL;
0120 }
0121 info->curt = mod;
0122
0123 return ret;
0124 }
0125
0126 static irqreturn_t usbhs_interrupt(int irq, void *data);
0127 int usbhs_mod_probe(struct usbhs_priv *priv)
0128 {
0129 struct device *dev = usbhs_priv_to_dev(priv);
0130 int ret;
0131
0132
0133
0134
0135 ret = usbhs_mod_host_probe(priv);
0136 if (ret < 0)
0137 return ret;
0138
0139 ret = usbhs_mod_gadget_probe(priv);
0140 if (ret < 0)
0141 goto mod_init_host_err;
0142
0143
0144 ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
0145 0, dev_name(dev), priv);
0146 if (ret) {
0147 dev_err(dev, "irq request err\n");
0148 goto mod_init_gadget_err;
0149 }
0150
0151 return ret;
0152
0153 mod_init_gadget_err:
0154 usbhs_mod_gadget_remove(priv);
0155 mod_init_host_err:
0156 usbhs_mod_host_remove(priv);
0157
0158 return ret;
0159 }
0160
0161 void usbhs_mod_remove(struct usbhs_priv *priv)
0162 {
0163 usbhs_mod_host_remove(priv);
0164 usbhs_mod_gadget_remove(priv);
0165 }
0166
0167
0168
0169
0170 int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
0171 {
0172 return (int)irq_state->intsts0 & DVSQ_MASK;
0173 }
0174
0175 int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
0176 {
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 return (int)irq_state->intsts0 & CTSQ_MASK;
0189 }
0190
0191 static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
0192 struct usbhs_irq_state *state)
0193 {
0194 struct usbhs_mod *mod = usbhs_mod_get_current(priv);
0195 u16 intenb0, intenb1;
0196 unsigned long flags;
0197
0198
0199 usbhs_lock(priv, flags);
0200 state->intsts0 = usbhs_read(priv, INTSTS0);
0201 intenb0 = usbhs_read(priv, INTENB0);
0202
0203 if (usbhs_mod_is_host(priv)) {
0204 state->intsts1 = usbhs_read(priv, INTSTS1);
0205 intenb1 = usbhs_read(priv, INTENB1);
0206 } else {
0207 state->intsts1 = intenb1 = 0;
0208 }
0209
0210
0211 if (mod) {
0212 state->brdysts = usbhs_read(priv, BRDYSTS);
0213 state->nrdysts = usbhs_read(priv, NRDYSTS);
0214 state->bempsts = usbhs_read(priv, BEMPSTS);
0215
0216 state->bempsts &= mod->irq_bempsts;
0217 state->brdysts &= mod->irq_brdysts;
0218 }
0219 usbhs_unlock(priv, flags);
0220
0221
0222 return 0;
0223 }
0224
0225
0226
0227
0228 #define INTSTS0_MAGIC 0xF800
0229 #define INTSTS1_MAGIC 0xA870
0230 static irqreturn_t usbhs_interrupt(int irq, void *data)
0231 {
0232 struct usbhs_priv *priv = data;
0233 struct usbhs_irq_state irq_state;
0234
0235 if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
0236 return IRQ_NONE;
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249 usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
0250 if (usbhs_mod_is_host(priv))
0251 usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
0252
0253
0254
0255
0256
0257
0258 if (irq_state.intsts0 & BRDY)
0259 usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
0260 usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
0261 if (irq_state.intsts0 & BEMP)
0262 usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
0263
0264
0265
0266
0267
0268
0269
0270
0271 if (irq_state.intsts0 & VBINT)
0272 usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
0273
0274 if (irq_state.intsts0 & DVST)
0275 usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
0276
0277 if (irq_state.intsts0 & CTRT)
0278 usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
0279
0280 if (irq_state.intsts0 & BEMP)
0281 usbhs_mod_call(priv, irq_empty, priv, &irq_state);
0282
0283 if (irq_state.intsts0 & BRDY)
0284 usbhs_mod_call(priv, irq_ready, priv, &irq_state);
0285
0286 if (usbhs_mod_is_host(priv)) {
0287
0288 if (irq_state.intsts1 & ATTCH)
0289 usbhs_mod_call(priv, irq_attch, priv, &irq_state);
0290
0291 if (irq_state.intsts1 & DTCH)
0292 usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
0293
0294 if (irq_state.intsts1 & SIGN)
0295 usbhs_mod_call(priv, irq_sign, priv, &irq_state);
0296
0297 if (irq_state.intsts1 & SACK)
0298 usbhs_mod_call(priv, irq_sack, priv, &irq_state);
0299 }
0300 return IRQ_HANDLED;
0301 }
0302
0303 void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
0304 {
0305 u16 intenb0 = 0;
0306 u16 intenb1 = 0;
0307 struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317 usbhs_write(priv, INTENB0, 0);
0318 if (usbhs_mod_is_host(priv))
0319 usbhs_write(priv, INTENB1, 0);
0320
0321 usbhs_write(priv, BEMPENB, 0);
0322 usbhs_write(priv, BRDYENB, 0);
0323
0324
0325
0326
0327
0328
0329 if (info->irq_vbus)
0330 intenb0 |= VBSE;
0331
0332 if (mod) {
0333
0334
0335
0336 if (mod->irq_ctrl_stage)
0337 intenb0 |= CTRE;
0338
0339 if (mod->irq_dev_state)
0340 intenb0 |= DVSE;
0341
0342 if (mod->irq_empty && mod->irq_bempsts) {
0343 usbhs_write(priv, BEMPENB, mod->irq_bempsts);
0344 intenb0 |= BEMPE;
0345 }
0346
0347 if (mod->irq_ready && mod->irq_brdysts) {
0348 usbhs_write(priv, BRDYENB, mod->irq_brdysts);
0349 intenb0 |= BRDYE;
0350 }
0351
0352 if (usbhs_mod_is_host(priv)) {
0353
0354
0355
0356 if (mod->irq_attch)
0357 intenb1 |= ATTCHE;
0358
0359 if (mod->irq_dtch)
0360 intenb1 |= DTCHE;
0361
0362 if (mod->irq_sign)
0363 intenb1 |= SIGNE;
0364
0365 if (mod->irq_sack)
0366 intenb1 |= SACKE;
0367 }
0368 }
0369
0370 if (intenb0)
0371 usbhs_write(priv, INTENB0, intenb0);
0372
0373 if (usbhs_mod_is_host(priv) && intenb1)
0374 usbhs_write(priv, INTENB1, intenb1);
0375 }