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 = request_irq(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        free_irq(priv->irq, priv);
 176}
 177
 178/*
 179 *              status functions
 180 */
 181int usbhs_status_get_device_state(struct usbhs_irq_state *irq_state)
 182{
 183        int state = irq_state->intsts0 & DVSQ_MASK;
 184
 185        switch (state) {
 186        case POWER_STATE:
 187        case DEFAULT_STATE:
 188        case ADDRESS_STATE:
 189        case CONFIGURATION_STATE:
 190                return state;
 191        }
 192
 193        return -EIO;
 194}
 195
 196int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state)
 197{
 198        /*
 199         * return value
 200         *
 201         * IDLE_SETUP_STAGE
 202         * READ_DATA_STAGE
 203         * READ_STATUS_STAGE
 204         * WRITE_DATA_STAGE
 205         * WRITE_STATUS_STAGE
 206         * NODATA_STATUS_STAGE
 207         * SEQUENCE_ERROR
 208         */
 209        return (int)irq_state->intsts0 & CTSQ_MASK;
 210}
 211
 212static void usbhs_status_get_each_irq(struct usbhs_priv *priv,
 213                                      struct usbhs_irq_state *state)
 214{
 215        struct usbhs_mod *mod = usbhs_mod_get_current(priv);
 216
 217        state->intsts0 = usbhs_read(priv, INTSTS0);
 218        state->intsts1 = usbhs_read(priv, INTSTS1);
 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}
 230
 231/*
 232 *              interrupt
 233 */
 234#define INTSTS0_MAGIC 0xF800 /* acknowledge magical interrupt sources */
 235#define INTSTS1_MAGIC 0xA870 /* acknowledge magical interrupt sources */
 236static irqreturn_t usbhs_interrupt(int irq, void *data)
 237{
 238        struct usbhs_priv *priv = data;
 239        struct usbhs_irq_state irq_state;
 240
 241        usbhs_status_get_each_irq(priv, &irq_state);
 242
 243        /*
 244         * clear interrupt
 245         *
 246         * The hardware is _very_ picky to clear interrupt bit.
 247         * Especially INTSTS0_MAGIC, INTSTS1_MAGIC value.
 248         *
 249         * see
 250         *      "Operation"
 251         *       - "Control Transfer (DCP)"
 252         *         - Function :: VALID bit should 0
 253         */
 254        usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
 255        usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
 256
 257        usbhs_write(priv, BRDYSTS, 0);
 258        usbhs_write(priv, NRDYSTS, 0);
 259        usbhs_write(priv, BEMPSTS, 0);
 260
 261        /*
 262         * call irq callback functions
 263         * see also
 264         *      usbhs_irq_setting_update
 265         */
 266
 267        /* INTSTS0 */
 268        if (irq_state.intsts0 & VBINT)
 269                usbhs_mod_info_call(priv, irq_vbus, priv, &irq_state);
 270
 271        if (irq_state.intsts0 & DVST)
 272                usbhs_mod_call(priv, irq_dev_state, priv, &irq_state);
 273
 274        if (irq_state.intsts0 & CTRT)
 275                usbhs_mod_call(priv, irq_ctrl_stage, priv, &irq_state);
 276
 277        if (irq_state.intsts0 & BEMP)
 278                usbhs_mod_call(priv, irq_empty, priv, &irq_state);
 279
 280        if (irq_state.intsts0 & BRDY)
 281                usbhs_mod_call(priv, irq_ready, priv, &irq_state);
 282
 283        /* INTSTS1 */
 284        if (irq_state.intsts1 & ATTCH)
 285                usbhs_mod_call(priv, irq_attch, priv, &irq_state);
 286
 287        if (irq_state.intsts1 & DTCH)
 288                usbhs_mod_call(priv, irq_dtch, priv, &irq_state);
 289
 290        if (irq_state.intsts1 & SIGN)
 291                usbhs_mod_call(priv, irq_sign, priv, &irq_state);
 292
 293        if (irq_state.intsts1 & SACK)
 294                usbhs_mod_call(priv, irq_sack, priv, &irq_state);
 295
 296        return IRQ_HANDLED;
 297}
 298
 299void usbhs_irq_callback_update(struct usbhs_priv *priv, struct usbhs_mod *mod)
 300{
 301        u16 intenb0 = 0;
 302        u16 intenb1 = 0;
 303        struct usbhs_mod_info *info = usbhs_priv_to_modinfo(priv);
 304
 305        /*
 306         * BEMPENB/BRDYENB are picky.
 307         * below method is required
 308         *
 309         *  - clear  INTSTS0
 310         *  - update BEMPENB/BRDYENB
 311         *  - update INTSTS0
 312         */
 313        usbhs_write(priv, INTENB0, 0);
 314        usbhs_write(priv, INTENB1, 0);
 315
 316        usbhs_write(priv, BEMPENB, 0);
 317        usbhs_write(priv, BRDYENB, 0);
 318
 319        /*
 320         * see also
 321         *      usbhs_interrupt
 322         */
 323
 324        /*
 325         * it don't enable DVSE (intenb0) here
 326         * but "mod->irq_dev_state" will be called.
 327         */
 328        if (info->irq_vbus)
 329                intenb0 |= VBSE;
 330
 331        if (mod) {
 332                /*
 333                 * INTSTS0
 334                 */
 335                if (mod->irq_ctrl_stage)
 336                        intenb0 |= CTRE;
 337
 338                if (mod->irq_empty && mod->irq_bempsts) {
 339                        usbhs_write(priv, BEMPENB, mod->irq_bempsts);
 340                        intenb0 |= BEMPE;
 341                }
 342
 343                if (mod->irq_ready && mod->irq_brdysts) {
 344                        usbhs_write(priv, BRDYENB, mod->irq_brdysts);
 345                        intenb0 |= BRDYE;
 346                }
 347
 348                /*
 349                 * INTSTS1
 350                 */
 351                if (mod->irq_attch)
 352                        intenb1 |= ATTCHE;
 353
 354                if (mod->irq_dtch)
 355                        intenb1 |= DTCHE;
 356
 357                if (mod->irq_sign)
 358                        intenb1 |= SIGNE;
 359
 360                if (mod->irq_sack)
 361                        intenb1 |= SACKE;
 362        }
 363
 364        if (intenb0)
 365                usbhs_write(priv, INTENB0, intenb0);
 366
 367        if (intenb1)
 368                usbhs_write(priv, INTENB1, intenb1);
 369}
 370