root/drivers/usb/renesas_usbhs/mod.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. usbhsm_autonomy_get_vbus
  2. usbhsm_autonomy_irq_vbus
  3. usbhs_mod_autonomy_mode
  4. usbhs_mod_non_autonomy_mode
  5. usbhs_mod_register
  6. usbhs_mod_get
  7. usbhs_mod_is_host
  8. usbhs_mod_get_current
  9. usbhs_mod_change
  10. usbhs_mod_probe
  11. usbhs_mod_remove
  12. usbhs_status_get_device_state
  13. usbhs_status_get_ctrl_stage
  14. usbhs_status_get_each_irq
  15. usbhs_interrupt
  16. usbhs_irq_callback_update

   1 // SPDX-License-Identifier: GPL-1.0+
   2 /*
   3  * Renesas USB driver
   4  *
   5  * Copyright (C) 2011 Renesas Solutions Corp.
   6  * Copyright (C) 2019 Renesas Electronics Corporation
   7  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
   8  */
   9 #include <linux/interrupt.h>
  10 
  11 #include "common.h"
  12 #include "mod.h"
  13 
  14 /*
  15  *              autonomy
  16  *
  17  * these functions are used if platform doesn't have external phy.
  18  *  -> there is no "notify_hotplug" callback from platform
  19  *  -> call "notify_hotplug" by itself
  20  *  -> use own interrupt to connect/disconnect
  21  *  -> it mean module clock is always ON
  22  *             ~~~~~~~~~~~~~~~~~~~~~~~~~
  23  */
  24 static int usbhsm_autonomy_get_vbus(struct platform_device *pdev)
  25 {
  26         struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
  27 
  28         return  VBSTS & usbhs_read(priv, INTSTS0);
  29 }
  30 
  31 static int usbhsm_autonomy_irq_vbus(struct usbhs_priv *priv,
  32                                     struct usbhs_irq_state *irq_state)
  33 {
  34         struct platform_device *pdev = usbhs_priv_to_pdev(priv);
  35 
  36         usbhsc_schedule_notify_hotplug(pdev);
  37 
  38         return 0;
  39 }
  40 
  41 void usbhs_mod_autonomy_mode(struct usbhs_priv *priv)
  42 {
  43         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
  44 
  45         info->irq_vbus = usbhsm_autonomy_irq_vbus;
  46         info->get_vbus = usbhsm_autonomy_get_vbus;
  47 
  48         usbhs_irq_callback_update(priv, NULL);
  49 }
  50 
  51 void usbhs_mod_non_autonomy_mode(struct usbhs_priv *priv)
  52 {
  53         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
  54 
  55         info->get_vbus = priv->pfunc->get_vbus;
  56 }
  57 
  58 /*
  59  *              host / gadget functions
  60  *
  61  * renesas_usbhs host/gadget can register itself by below functions.
  62  * these functions are called when probe
  63  *
  64  */
  65 void usbhs_mod_register(struct usbhs_priv *priv, struct usbhs_mod *mod, int id)
  66 {
  67         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
  68 
  69         info->mod[id]   = mod;
  70         mod->priv       = priv;
  71 }
  72 
  73 struct usbhs_mod *usbhs_mod_get(struct usbhs_priv *priv, int id)
  74 {
  75         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
  76         struct usbhs_mod *ret = NULL;
  77 
  78         switch (id) {
  79         case USBHS_HOST:
  80         case USBHS_GADGET:
  81                 ret = info->mod[id];
  82                 break;
  83         }
  84 
  85         return ret;
  86 }
  87 
  88 int usbhs_mod_is_host(struct usbhs_priv *priv)
  89 {
  90         struct usbhs_mod *mod = usbhs_mod_get_current(priv);
  91         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
  92 
  93         if (!mod)
  94                 return -EINVAL;
  95 
  96         return info->mod[USBHS_HOST] == mod;
  97 }
  98 
  99 struct usbhs_mod *usbhs_mod_get_current(struct usbhs_priv *priv)
 100 {
 101         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
 102 
 103         return info->curt;
 104 }
 105 
 106 int usbhs_mod_change(struct usbhs_priv *priv, int id)
 107 {
 108         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
 109         struct usbhs_mod *mod = NULL;
 110         int ret = 0;
 111 
 112         /* id < 0 mean no current */
 113         switch (id) {
 114         case USBHS_HOST:
 115         case USBHS_GADGET:
 116                 mod = info->mod[id];
 117                 break;
 118         default:
 119                 ret = -EINVAL;
 120         }
 121         info->curt = mod;
 122 
 123         return ret;
 124 }
 125 
 126 static irqreturn_t usbhs_interrupt(int irq, void *data);
 127 int usbhs_mod_probe(struct usbhs_priv *priv)
 128 {
 129         struct device *dev = usbhs_priv_to_dev(priv);
 130         int ret;
 131 
 132         /*
 133          * install host/gadget driver
 134          */
 135         ret = usbhs_mod_host_probe(priv);
 136         if (ret < 0)
 137                 return ret;
 138 
 139         ret = usbhs_mod_gadget_probe(priv);
 140         if (ret < 0)
 141                 goto mod_init_host_err;
 142 
 143         /* irq settings */
 144         ret = devm_request_irq(dev, priv->irq, usbhs_interrupt,
 145                           priv->irqflags, dev_name(dev), priv);
 146         if (ret) {
 147                 dev_err(dev, "irq request err\n");
 148                 goto mod_init_gadget_err;
 149         }
 150 
 151         return ret;
 152 
 153 mod_init_gadget_err:
 154         usbhs_mod_gadget_remove(priv);
 155 mod_init_host_err:
 156         usbhs_mod_host_remove(priv);
 157 
 158         return ret;
 159 }
 160 
 161 void usbhs_mod_remove(struct usbhs_priv *priv)
 162 {
 163         usbhs_mod_host_remove(priv);
 164         usbhs_mod_gadget_remove(priv);
 165 }
 166 
 167 /*
 168  *              status functions
 169  */
 170 int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
 171 {
 172         int state = irq_state->intsts0 & DVSQ_MASK;
 173 
 174         switch (state) {
 175         case POWER_STATE:
 176         case DEFAULT_STATE:
 177         case ADDRESS_STATE:
 178         case CONFIGURATION_STATE:
 179                 return state;
 180         }
 181 
 182         return -EIO;
 183 }
 184 
 185 int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
 186 {
 187         /*
 188          * return value
 189          *
 190          * IDLE_SETUP_STAGE
 191          * READ_DATA_STAGE
 192          * READ_STATUS_STAGE
 193          * WRITE_DATA_STAGE
 194          * WRITE_STATUS_STAGE
 195          * NODATA_STATUS_STAGE
 196          * SEQUENCE_ERROR
 197          */
 198         return (int)irq_state->intsts0 & CTSQ_MASK;
 199 }
 200 
 201 static int usbhs_status_get_each_irq(struct usbhs_priv *priv,
 202                                      struct usbhs_irq_state *state)
 203 {
 204         struct usbhs_mod *mod = usbhs_mod_get_current(priv);
 205         u16 intenb0, intenb1;
 206         unsigned long flags;
 207 
 208         /********************  spin lock ********************/
 209         usbhs_lock(priv, flags);
 210         state->intsts0 = usbhs_read(priv, INTSTS0);
 211         intenb0 = usbhs_read(priv, INTENB0);
 212 
 213         if (usbhs_mod_is_host(priv)) {
 214                 state->intsts1 = usbhs_read(priv, INTSTS1);
 215                 intenb1 = usbhs_read(priv, INTENB1);
 216         } else {
 217                 state->intsts1 = intenb1 = 0;
 218         }
 219 
 220         /* mask */
 221         if (mod) {
 222                 state->brdysts = usbhs_read(priv, BRDYSTS);
 223                 state->nrdysts = usbhs_read(priv, NRDYSTS);
 224                 state->bempsts = usbhs_read(priv, BEMPSTS);
 225 
 226                 state->bempsts &= mod->irq_bempsts;
 227                 state->brdysts &= mod->irq_brdysts;
 228         }
 229         usbhs_unlock(priv, flags);
 230         /********************  spin unlock ******************/
 231 
 232         /*
 233          * Check whether the irq enable registers and the irq status are set
 234          * when IRQF_SHARED is set.
 235          */
 236         if (priv->irqflags & IRQF_SHARED) {
 237                 if (!(intenb0 & state->intsts0) &&
 238                     !(intenb1 & state->intsts1) &&
 239                     !(state->bempsts) &&
 240                     !(state->brdysts))
 241                         return -EIO;
 242         }
 243 
 244         return 0;
 245 }
 246 
 247 /*
 248  *              interrupt
 249  */
 250 #define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */
 251 #define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */
 252 static irqreturn_t usbhs_interrupt(int irq, void *data)
 253 {
 254         struct usbhs_priv *priv = data;
 255         struct usbhs_irq_state irq_state;
 256 
 257         if (usbhs_status_get_each_irq(priv, &irq_state) < 0)
 258                 return IRQ_NONE;
 259 
 260         /*
 261          * clear interrupt
 262          *
 263          * The hardware is _very_ picky to clear interrupt bit.
 264          * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value.
 265          *
 266          * see
 267          *      "Operation"
 268          *       - "Control Transfer (DCP)"
 269          *         - Function :: VALID bit should 0
 270          */
 271         usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
 272         if (usbhs_mod_is_host(priv))
 273                 usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
 274 
 275         /*
 276          * The driver should not clear the xxxSTS after the line of
 277          * "call irq callback functions" because each "if" statement is
 278          * possible to call the callback function for avoiding any side effects.
 279          */
 280         if (irq_state.intsts0 & BRDY)
 281                 usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
 282         usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
 283         if (irq_state.intsts0 & BEMP)
 284                 usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
 285 
 286         /*
 287          * call irq callback functions
 288          * see also
 289          *      usbhs_irq_setting_update
 290          */
 291 
 292         /* INTSTS0 */
 293         if (irq_state.intsts0 & VBINT)
 294                 usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
 295 
 296         if (irq_state.intsts0 & DVST)
 297                 usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
 298 
 299         if (irq_state.intsts0 & CTRT)
 300                 usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
 301 
 302         if (irq_state.intsts0 & BEMP)
 303                 usbhs_mod_call(priv, irq_empty, priv, &irq_state);
 304 
 305         if (irq_state.intsts0 & BRDY)
 306                 usbhs_mod_call(priv, irq_ready, priv, &irq_state);
 307 
 308         if (usbhs_mod_is_host(priv)) {
 309                 /* INTSTS1 */
 310                 if (irq_state.intsts1 & ATTCH)
 311                         usbhs_mod_call(priv, irq_attch, priv, &irq_state);
 312 
 313                 if (irq_state.intsts1 & DTCH)
 314                         usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
 315 
 316                 if (irq_state.intsts1 & SIGN)
 317                         usbhs_mod_call(priv, irq_sign, priv, &irq_state);
 318 
 319                 if (irq_state.intsts1 & SACK)
 320                         usbhs_mod_call(priv, irq_sack, priv, &irq_state);
 321         }
 322         return IRQ_HANDLED;
 323 }
 324 
 325 void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
 326 {
 327         u16 intenb0 = 0;
 328         u16 intenb1 = 0;
 329         struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
 330 
 331         /*
 332          * BEMPENB/BRDYENB are picky.
 333          * below method is required
 334          *
 335          *  - clear  INTSTS0
 336          *  - update BEMPENB/BRDYENB
 337          *  - update INTSTS0
 338          */
 339         usbhs_write(priv, INTENB0, 0);
 340         if (usbhs_mod_is_host(priv))
 341                 usbhs_write(priv, INTENB1, 0);
 342 
 343         usbhs_write(priv, BEMPENB, 0);
 344         usbhs_write(priv, BRDYENB, 0);
 345 
 346         /*
 347          * see also
 348          *      usbhs_interrupt
 349          */
 350 
 351         /*
 352          * it don't enable DVSE (intenb0) here
 353          * but "mod->irq_dev_state" will be called.
 354          */
 355         if (info->irq_vbus)
 356                 intenb0 |= VBSE;
 357 
 358         if (mod) {
 359                 /*
 360                  * INTSTS0
 361                  */
 362                 if (mod->irq_ctrl_stage)
 363                         intenb0 |= CTRE;
 364 
 365                 if (mod->irq_empty && mod->irq_bempsts) {
 366                         usbhs_write(priv, BEMPENB, mod->irq_bempsts);
 367                         intenb0 |= BEMPE;
 368                 }
 369 
 370                 if (mod->irq_ready && mod->irq_brdysts) {
 371                         usbhs_write(priv, BRDYENB, mod->irq_brdysts);
 372                         intenb0 |= BRDYE;
 373                 }
 374 
 375                 if (usbhs_mod_is_host(priv)) {
 376                         /*
 377                          * INTSTS1
 378                          */
 379                         if (mod->irq_attch)
 380                                 intenb1 |= ATTCHE;
 381 
 382                         if (mod->irq_dtch)
 383                                 intenb1 |= DTCHE;
 384 
 385                         if (mod->irq_sign)
 386                                 intenb1 |= SIGNE;
 387 
 388                         if (mod->irq_sack)
 389                                 intenb1 |= SACKE;
 390                 }
 391         }
 392 
 393         if (intenb0)
 394                 usbhs_write(priv, INTENB0, intenb0);
 395 
 396         if (usbhs_mod_is_host(priv) && intenb1)
 397                 usbhs_write(priv, INTENB1, intenb1);
 398 }

/* [<][>][^][v][top][bottom][index][help] */