linux/drivers/usb/renesas_usbhs/common.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/err.h>
  18#include <linux/io.h>
  19#include <linux/module.h>
  20#include <linux/pm_runtime.h>
  21#include <linux/slab.h>
  22#include <linux/sysfs.h>
  23#include "common.h"
  24
  25/*
  26 *              image of renesas_usbhs
  27 *
  28 * ex) gadget case
  29
  30 * mod.c
  31 * mod_gadget.c
  32 * mod_host.c           pipe.c          fifo.c
  33 *
  34 *                      +-------+       +-----------+
  35 *                      | pipe0 |------>| fifo pio  |
  36 * +------------+       +-------+       +-----------+
  37 * | mod_gadget |=====> | pipe1 |--+
  38 * +------------+       +-------+  |    +-----------+
  39 *                      | pipe2 |  |  +-| fifo dma0 |
  40 * +------------+       +-------+  |  | +-----------+
  41 * | mod_host   |       | pipe3 |<-|--+
  42 * +------------+       +-------+  |    +-----------+
  43 *                      | ....  |  +--->| fifo dma1 |
  44 *                      | ....  |       +-----------+
  45 */
  46
  47
  48#define USBHSF_RUNTIME_PWCTRL   (1 << 0)
  49
  50/* status */
  51#define usbhsc_flags_init(p)   do {(p)->flags = 0; } while (0)
  52#define usbhsc_flags_set(p, b) ((p)->flags |=  (b))
  53#define usbhsc_flags_clr(p, b) ((p)->flags &= ~(b))
  54#define usbhsc_flags_has(p, b) ((p)->flags &   (b))
  55
  56/*
  57 * platform call back
  58 *
  59 * renesas usb support platform callback function.
  60 * Below macro call it.
  61 * if platform doesn't have callback, it return 0 (no error)
  62 */
  63#define usbhs_platform_call(priv, func, args...)\
  64        (!(priv) ? -ENODEV :                    \
  65         !((priv)->pfunc.func) ? 0 :            \
  66         (priv)->pfunc.func(args))
  67
  68/*
  69 *              common functions
  70 */
  71u16 usbhs_read(struct usbhs_priv *priv, u32 reg)
  72{
  73        return ioread16(priv->base + reg);
  74}
  75
  76void usbhs_write(struct usbhs_priv *priv, u32 reg, u16 data)
  77{
  78        iowrite16(data, priv->base + reg);
  79}
  80
  81void usbhs_bset(struct usbhs_priv *priv, u32 reg, u16 mask, u16 data)
  82{
  83        u16 val = usbhs_read(priv, reg);
  84
  85        val &= ~mask;
  86        val |= data & mask;
  87
  88        usbhs_write(priv, reg, val);
  89}
  90
  91struct usbhs_priv *usbhs_pdev_to_priv(struct platform_device *pdev)
  92{
  93        return dev_get_drvdata(&pdev->dev);
  94}
  95
  96/*
  97 *              syscfg functions
  98 */
  99static void usbhs_sys_clock_ctrl(struct usbhs_priv *priv, int enable)
 100{
 101        usbhs_bset(priv, SYSCFG, SCKE, enable ? SCKE : 0);
 102}
 103
 104void usbhs_sys_host_ctrl(struct usbhs_priv *priv, int enable)
 105{
 106        u16 mask = DCFM | DRPD | DPRPU | HSE | USBE;
 107        u16 val  = DCFM | DRPD | HSE | USBE;
 108        int has_otg = usbhs_get_dparam(priv, has_otg);
 109
 110        if (has_otg)
 111                usbhs_bset(priv, DVSTCTR, (EXTLP | PWEN), (EXTLP | PWEN));
 112
 113        /*
 114         * if enable
 115         *
 116         * - select Host mode
 117         * - D+ Line/D- Line Pull-down
 118         */
 119        usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
 120}
 121
 122void usbhs_sys_function_ctrl(struct usbhs_priv *priv, int enable)
 123{
 124        u16 mask = DCFM | DRPD | DPRPU | HSE | USBE;
 125        u16 val  = DPRPU | HSE | USBE;
 126
 127        /*
 128         * if enable
 129         *
 130         * - select Function mode
 131         * - D+ Line Pull-up
 132         */
 133        usbhs_bset(priv, SYSCFG, mask, enable ? val : 0);
 134}
 135
 136void usbhs_sys_function_pullup(struct usbhs_priv *priv, int enable)
 137{
 138        usbhs_bset(priv, SYSCFG, DPRPU, enable ? DPRPU : 0);
 139}
 140
 141void usbhs_sys_set_test_mode(struct usbhs_priv *priv, u16 mode)
 142{
 143        usbhs_write(priv, TESTMODE, mode);
 144}
 145
 146/*
 147 *              frame functions
 148 */
 149int usbhs_frame_get_num(struct usbhs_priv *priv)
 150{
 151        return usbhs_read(priv, FRMNUM) & FRNM_MASK;
 152}
 153
 154/*
 155 *              usb request functions
 156 */
 157void usbhs_usbreq_get_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
 158{
 159        u16 val;
 160
 161        val = usbhs_read(priv, USBREQ);
 162        req->bRequest           = (val >> 8) & 0xFF;
 163        req->bRequestType       = (val >> 0) & 0xFF;
 164
 165        req->wValue     = usbhs_read(priv, USBVAL);
 166        req->wIndex     = usbhs_read(priv, USBINDX);
 167        req->wLength    = usbhs_read(priv, USBLENG);
 168}
 169
 170void usbhs_usbreq_set_val(struct usbhs_priv *priv, struct usb_ctrlrequest *req)
 171{
 172        usbhs_write(priv, USBREQ,  (req->bRequest << 8) | req->bRequestType);
 173        usbhs_write(priv, USBVAL,  req->wValue);
 174        usbhs_write(priv, USBINDX, req->wIndex);
 175        usbhs_write(priv, USBLENG, req->wLength);
 176
 177        usbhs_bset(priv, DCPCTR, SUREQ, SUREQ);
 178}
 179
 180/*
 181 *              bus/vbus functions
 182 */
 183void usbhs_bus_send_sof_enable(struct usbhs_priv *priv)
 184{
 185        u16 status = usbhs_read(priv, DVSTCTR) & (USBRST | UACT);
 186
 187        if (status != USBRST) {
 188                struct device *dev = usbhs_priv_to_dev(priv);
 189                dev_err(dev, "usbhs should be reset\n");
 190        }
 191
 192        usbhs_bset(priv, DVSTCTR, (USBRST | UACT), UACT);
 193}
 194
 195void usbhs_bus_send_reset(struct usbhs_priv *priv)
 196{
 197        usbhs_bset(priv, DVSTCTR, (USBRST | UACT), USBRST);
 198}
 199
 200int usbhs_bus_get_speed(struct usbhs_priv *priv)
 201{
 202        u16 dvstctr = usbhs_read(priv, DVSTCTR);
 203
 204        switch (RHST & dvstctr) {
 205        case RHST_LOW_SPEED:
 206                return USB_SPEED_LOW;
 207        case RHST_FULL_SPEED:
 208                return USB_SPEED_FULL;
 209        case RHST_HIGH_SPEED:
 210                return USB_SPEED_HIGH;
 211        }
 212
 213        return USB_SPEED_UNKNOWN;
 214}
 215
 216int usbhs_vbus_ctrl(struct usbhs_priv *priv, int enable)
 217{
 218        struct platform_device *pdev = usbhs_priv_to_pdev(priv);
 219
 220        return usbhs_platform_call(priv, set_vbus, pdev, enable);
 221}
 222
 223static void usbhsc_bus_init(struct usbhs_priv *priv)
 224{
 225        usbhs_write(priv, DVSTCTR, 0);
 226
 227        usbhs_vbus_ctrl(priv, 0);
 228}
 229
 230/*
 231 *              device configuration
 232 */
 233int usbhs_set_device_config(struct usbhs_priv *priv, int devnum,
 234                           u16 upphub, u16 hubport, u16 speed)
 235{
 236        struct device *dev = usbhs_priv_to_dev(priv);
 237        u16 usbspd = 0;
 238        u32 reg = DEVADD0 + (2 * devnum);
 239
 240        if (devnum > 10) {
 241                dev_err(dev, "cannot set speed to unknown device %d\n", devnum);
 242                return -EIO;
 243        }
 244
 245        if (upphub > 0xA) {
 246                dev_err(dev, "unsupported hub number %d\n", upphub);
 247                return -EIO;
 248        }
 249
 250        switch (speed) {
 251        case USB_SPEED_LOW:
 252                usbspd = USBSPD_SPEED_LOW;
 253                break;
 254        case USB_SPEED_FULL:
 255                usbspd = USBSPD_SPEED_FULL;
 256                break;
 257        case USB_SPEED_HIGH:
 258                usbspd = USBSPD_SPEED_HIGH;
 259                break;
 260        default:
 261                dev_err(dev, "unsupported speed %d\n", speed);
 262                return -EIO;
 263        }
 264
 265        usbhs_write(priv, reg,  UPPHUB(upphub)  |
 266                                HUBPORT(hubport)|
 267                                USBSPD(usbspd));
 268
 269        return 0;
 270}
 271
 272/*
 273 *              local functions
 274 */
 275static void usbhsc_set_buswait(struct usbhs_priv *priv)
 276{
 277        int wait = usbhs_get_dparam(priv, buswait_bwait);
 278
 279        /* set bus wait if platform have */
 280        if (wait)
 281                usbhs_bset(priv, BUSWAIT, 0x000F, wait);
 282}
 283
 284/*
 285 *              platform default param
 286 */
 287static u32 usbhsc_default_pipe_type[] = {
 288                USB_ENDPOINT_XFER_CONTROL,
 289                USB_ENDPOINT_XFER_ISOC,
 290                USB_ENDPOINT_XFER_ISOC,
 291                USB_ENDPOINT_XFER_BULK,
 292                USB_ENDPOINT_XFER_BULK,
 293                USB_ENDPOINT_XFER_BULK,
 294                USB_ENDPOINT_XFER_INT,
 295                USB_ENDPOINT_XFER_INT,
 296                USB_ENDPOINT_XFER_INT,
 297                USB_ENDPOINT_XFER_INT,
 298};
 299
 300/*
 301 *              power control
 302 */
 303static void usbhsc_power_ctrl(struct usbhs_priv *priv, int enable)
 304{
 305        struct platform_device *pdev = usbhs_priv_to_pdev(priv);
 306        struct device *dev = usbhs_priv_to_dev(priv);
 307
 308        if (enable) {
 309                /* enable PM */
 310                pm_runtime_get_sync(dev);
 311
 312                /* enable platform power */
 313                usbhs_platform_call(priv, power_ctrl, pdev, priv->base, enable);
 314
 315                /* USB on */
 316                usbhs_sys_clock_ctrl(priv, enable);
 317        } else {
 318                /* USB off */
 319                usbhs_sys_clock_ctrl(priv, enable);
 320
 321                /* disable platform power */
 322                usbhs_platform_call(priv, power_ctrl, pdev, priv->base, enable);
 323
 324                /* disable PM */
 325                pm_runtime_put_sync(dev);
 326        }
 327}
 328
 329/*
 330 *              hotplug
 331 */
 332static void usbhsc_hotplug(struct usbhs_priv *priv)
 333{
 334        struct platform_device *pdev = usbhs_priv_to_pdev(priv);
 335        struct usbhs_mod *mod = usbhs_mod_get_current(priv);
 336        int id;
 337        int enable;
 338        int ret;
 339
 340        /*
 341         * get vbus status from platform
 342         */
 343        enable = usbhs_platform_call(priv, get_vbus, pdev);
 344
 345        /*
 346         * get id from platform
 347         */
 348        id = usbhs_platform_call(priv, get_id, pdev);
 349
 350        if (enable && !mod) {
 351                ret = usbhs_mod_change(priv, id);
 352                if (ret < 0)
 353                        return;
 354
 355                dev_dbg(&pdev->dev, "%s enable\n", __func__);
 356
 357                /* power on */
 358                if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
 359                        usbhsc_power_ctrl(priv, enable);
 360
 361                /* bus init */
 362                usbhsc_set_buswait(priv);
 363                usbhsc_bus_init(priv);
 364
 365                /* module start */
 366                usbhs_mod_call(priv, start, priv);
 367
 368        } else if (!enable && mod) {
 369                dev_dbg(&pdev->dev, "%s disable\n", __func__);
 370
 371                /* module stop */
 372                usbhs_mod_call(priv, stop, priv);
 373
 374                /* bus init */
 375                usbhsc_bus_init(priv);
 376
 377                /* power off */
 378                if (usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
 379                        usbhsc_power_ctrl(priv, enable);
 380
 381                usbhs_mod_change(priv, -1);
 382
 383                /* reset phy for next connection */
 384                usbhs_platform_call(priv, phy_reset, pdev);
 385        }
 386}
 387
 388/*
 389 *              notify hotplug
 390 */
 391static void usbhsc_notify_hotplug(struct work_struct *work)
 392{
 393        struct usbhs_priv *priv = container_of(work,
 394                                               struct usbhs_priv,
 395                                               notify_hotplug_work.work);
 396        usbhsc_hotplug(priv);
 397}
 398
 399static int usbhsc_drvcllbck_notify_hotplug(struct platform_device *pdev)
 400{
 401        struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
 402        int delay = usbhs_get_dparam(priv, detection_delay);
 403
 404        /*
 405         * This functions will be called in interrupt.
 406         * To make sure safety context,
 407         * use workqueue for usbhs_notify_hotplug
 408         */
 409        schedule_delayed_work(&priv->notify_hotplug_work,
 410                              msecs_to_jiffies(delay));
 411        return 0;
 412}
 413
 414/*
 415 *              platform functions
 416 */
 417static int usbhs_probe(struct platform_device *pdev)
 418{
 419        struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
 420        struct renesas_usbhs_driver_callback *dfunc;
 421        struct usbhs_priv *priv;
 422        struct resource *res, *irq_res;
 423        int ret;
 424
 425        /* check platform information */
 426        if (!info ||
 427            !info->platform_callback.get_id) {
 428                dev_err(&pdev->dev, "no platform information\n");
 429                return -EINVAL;
 430        }
 431
 432        /* platform data */
 433        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 434        irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 435        if (!res || !irq_res) {
 436                dev_err(&pdev->dev, "Not enough Renesas USB platform resources.\n");
 437                return -ENODEV;
 438        }
 439
 440        /* usb private data */
 441        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 442        if (!priv) {
 443                dev_err(&pdev->dev, "Could not allocate priv\n");
 444                return -ENOMEM;
 445        }
 446
 447        priv->base = devm_ioremap_resource(&pdev->dev, res);
 448        if (IS_ERR(priv->base))
 449                return PTR_ERR(priv->base);
 450
 451        /*
 452         * care platform info
 453         */
 454        memcpy(&priv->pfunc,
 455               &info->platform_callback,
 456               sizeof(struct renesas_usbhs_platform_callback));
 457        memcpy(&priv->dparam,
 458               &info->driver_param,
 459               sizeof(struct renesas_usbhs_driver_param));
 460
 461        /* set driver callback functions for platform */
 462        dfunc                   = &info->driver_callback;
 463        dfunc->notify_hotplug   = usbhsc_drvcllbck_notify_hotplug;
 464
 465        /* set default param if platform doesn't have */
 466        if (!priv->dparam.pipe_type) {
 467                priv->dparam.pipe_type = usbhsc_default_pipe_type;
 468                priv->dparam.pipe_size = ARRAY_SIZE(usbhsc_default_pipe_type);
 469        }
 470        if (!priv->dparam.pio_dma_border)
 471                priv->dparam.pio_dma_border = 64; /* 64byte */
 472
 473        /* FIXME */
 474        /* runtime power control ? */
 475        if (priv->pfunc.get_vbus)
 476                usbhsc_flags_set(priv, USBHSF_RUNTIME_PWCTRL);
 477
 478        /*
 479         * priv settings
 480         */
 481        priv->irq       = irq_res->start;
 482        if (irq_res->flags & IORESOURCE_IRQ_SHAREABLE)
 483                priv->irqflags = IRQF_SHARED;
 484        priv->pdev      = pdev;
 485        INIT_DELAYED_WORK(&priv->notify_hotplug_work, usbhsc_notify_hotplug);
 486        spin_lock_init(usbhs_priv_to_lock(priv));
 487
 488        /* call pipe and module init */
 489        ret = usbhs_pipe_probe(priv);
 490        if (ret < 0)
 491                return ret;
 492
 493        ret = usbhs_fifo_probe(priv);
 494        if (ret < 0)
 495                goto probe_end_pipe_exit;
 496
 497        ret = usbhs_mod_probe(priv);
 498        if (ret < 0)
 499                goto probe_end_fifo_exit;
 500
 501        /* dev_set_drvdata should be called after usbhs_mod_init */
 502        dev_set_drvdata(&pdev->dev, priv);
 503
 504        /*
 505         * deviece reset here because
 506         * USB device might be used in boot loader.
 507         */
 508        usbhs_sys_clock_ctrl(priv, 0);
 509
 510        /*
 511         * platform call
 512         *
 513         * USB phy setup might depend on CPU/Board.
 514         * If platform has its callback functions,
 515         * call it here.
 516         */
 517        ret = usbhs_platform_call(priv, hardware_init, pdev);
 518        if (ret < 0) {
 519                dev_err(&pdev->dev, "platform prove failed.\n");
 520                goto probe_end_mod_exit;
 521        }
 522
 523        /* reset phy for connection */
 524        usbhs_platform_call(priv, phy_reset, pdev);
 525
 526        /* power control */
 527        pm_runtime_enable(&pdev->dev);
 528        if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) {
 529                usbhsc_power_ctrl(priv, 1);
 530                usbhs_mod_autonomy_mode(priv);
 531        }
 532
 533        /*
 534         * manual call notify_hotplug for cold plug
 535         */
 536        ret = usbhsc_drvcllbck_notify_hotplug(pdev);
 537        if (ret < 0)
 538                goto probe_end_call_remove;
 539
 540        dev_info(&pdev->dev, "probed\n");
 541
 542        return ret;
 543
 544probe_end_call_remove:
 545        usbhs_platform_call(priv, hardware_exit, pdev);
 546probe_end_mod_exit:
 547        usbhs_mod_remove(priv);
 548probe_end_fifo_exit:
 549        usbhs_fifo_remove(priv);
 550probe_end_pipe_exit:
 551        usbhs_pipe_remove(priv);
 552
 553        dev_info(&pdev->dev, "probe failed\n");
 554
 555        return ret;
 556}
 557
 558static int usbhs_remove(struct platform_device *pdev)
 559{
 560        struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
 561        struct renesas_usbhs_platform_info *info = pdev->dev.platform_data;
 562        struct renesas_usbhs_driver_callback *dfunc = &info->driver_callback;
 563
 564        dev_dbg(&pdev->dev, "usb remove\n");
 565
 566        dfunc->notify_hotplug = NULL;
 567
 568        /* power off */
 569        if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
 570                usbhsc_power_ctrl(priv, 0);
 571
 572        pm_runtime_disable(&pdev->dev);
 573
 574        usbhs_platform_call(priv, hardware_exit, pdev);
 575        usbhs_mod_remove(priv);
 576        usbhs_fifo_remove(priv);
 577        usbhs_pipe_remove(priv);
 578
 579        return 0;
 580}
 581
 582static int usbhsc_suspend(struct device *dev)
 583{
 584        struct usbhs_priv *priv = dev_get_drvdata(dev);
 585        struct usbhs_mod *mod = usbhs_mod_get_current(priv);
 586
 587        if (mod) {
 588                usbhs_mod_call(priv, stop, priv);
 589                usbhs_mod_change(priv, -1);
 590        }
 591
 592        if (mod || !usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
 593                usbhsc_power_ctrl(priv, 0);
 594
 595        return 0;
 596}
 597
 598static int usbhsc_resume(struct device *dev)
 599{
 600        struct usbhs_priv *priv = dev_get_drvdata(dev);
 601        struct platform_device *pdev = usbhs_priv_to_pdev(priv);
 602
 603        if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
 604                usbhsc_power_ctrl(priv, 1);
 605
 606        usbhs_platform_call(priv, phy_reset, pdev);
 607
 608        usbhsc_drvcllbck_notify_hotplug(pdev);
 609
 610        return 0;
 611}
 612
 613static int usbhsc_runtime_nop(struct device *dev)
 614{
 615        /* Runtime PM callback shared between ->runtime_suspend()
 616         * and ->runtime_resume(). Simply returns success.
 617         *
 618         * This driver re-initializes all registers after
 619         * pm_runtime_get_sync() anyway so there is no need
 620         * to save and restore registers here.
 621         */
 622        return 0;
 623}
 624
 625static const struct dev_pm_ops usbhsc_pm_ops = {
 626        .suspend                = usbhsc_suspend,
 627        .resume                 = usbhsc_resume,
 628        .runtime_suspend        = usbhsc_runtime_nop,
 629        .runtime_resume         = usbhsc_runtime_nop,
 630};
 631
 632static struct platform_driver renesas_usbhs_driver = {
 633        .driver         = {
 634                .name   = "renesas_usbhs",
 635                .pm     = &usbhsc_pm_ops,
 636        },
 637        .probe          = usbhs_probe,
 638        .remove         = usbhs_remove,
 639};
 640
 641module_platform_driver(renesas_usbhs_driver);
 642
 643MODULE_LICENSE("GPL");
 644MODULE_DESCRIPTION("Renesas USB driver");
 645MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
 646