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