linux/drivers/usb/musb/sunxi.c
<<
>>
Prefs
   1/*
   2 * Allwinner sun4i MUSB Glue Layer
   3 *
   4 * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
   5 *
   6 * Based on code from
   7 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or
  12 * (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 */
  19
  20#include <linux/clk.h>
  21#include <linux/err.h>
  22#include <linux/extcon.h>
  23#include <linux/io.h>
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/of.h>
  27#include <linux/phy/phy-sun4i-usb.h>
  28#include <linux/platform_device.h>
  29#include <linux/reset.h>
  30#include <linux/soc/sunxi/sunxi_sram.h>
  31#include <linux/usb/musb.h>
  32#include <linux/usb/of.h>
  33#include <linux/usb/usb_phy_generic.h>
  34#include <linux/workqueue.h>
  35#include "musb_core.h"
  36
  37/*
  38 * Register offsets, note sunxi musb has a different layout then most
  39 * musb implementations, we translate the layout in musb_readb & friends.
  40 */
  41#define SUNXI_MUSB_POWER                        0x0040
  42#define SUNXI_MUSB_DEVCTL                       0x0041
  43#define SUNXI_MUSB_INDEX                        0x0042
  44#define SUNXI_MUSB_VEND0                        0x0043
  45#define SUNXI_MUSB_INTRTX                       0x0044
  46#define SUNXI_MUSB_INTRRX                       0x0046
  47#define SUNXI_MUSB_INTRTXE                      0x0048
  48#define SUNXI_MUSB_INTRRXE                      0x004a
  49#define SUNXI_MUSB_INTRUSB                      0x004c
  50#define SUNXI_MUSB_INTRUSBE                     0x0050
  51#define SUNXI_MUSB_FRAME                        0x0054
  52#define SUNXI_MUSB_TXFIFOSZ                     0x0090
  53#define SUNXI_MUSB_TXFIFOADD                    0x0092
  54#define SUNXI_MUSB_RXFIFOSZ                     0x0094
  55#define SUNXI_MUSB_RXFIFOADD                    0x0096
  56#define SUNXI_MUSB_FADDR                        0x0098
  57#define SUNXI_MUSB_TXFUNCADDR                   0x0098
  58#define SUNXI_MUSB_TXHUBADDR                    0x009a
  59#define SUNXI_MUSB_TXHUBPORT                    0x009b
  60#define SUNXI_MUSB_RXFUNCADDR                   0x009c
  61#define SUNXI_MUSB_RXHUBADDR                    0x009e
  62#define SUNXI_MUSB_RXHUBPORT                    0x009f
  63#define SUNXI_MUSB_CONFIGDATA                   0x00c0
  64
  65/* VEND0 bits */
  66#define SUNXI_MUSB_VEND0_PIO_MODE               0
  67
  68/* flags */
  69#define SUNXI_MUSB_FL_ENABLED                   0
  70#define SUNXI_MUSB_FL_HOSTMODE                  1
  71#define SUNXI_MUSB_FL_HOSTMODE_PEND             2
  72#define SUNXI_MUSB_FL_VBUS_ON                   3
  73#define SUNXI_MUSB_FL_PHY_ON                    4
  74#define SUNXI_MUSB_FL_HAS_SRAM                  5
  75#define SUNXI_MUSB_FL_HAS_RESET                 6
  76#define SUNXI_MUSB_FL_NO_CONFIGDATA             7
  77#define SUNXI_MUSB_FL_PHY_MODE_PEND             8
  78
  79/* Our read/write methods need access and do not get passed in a musb ref :| */
  80static struct musb *sunxi_musb;
  81
  82struct sunxi_glue {
  83        struct device           *dev;
  84        struct musb             *musb;
  85        struct platform_device  *musb_pdev;
  86        struct clk              *clk;
  87        struct reset_control    *rst;
  88        struct phy              *phy;
  89        struct platform_device  *usb_phy;
  90        struct usb_phy          *xceiv;
  91        enum phy_mode           phy_mode;
  92        unsigned long           flags;
  93        struct work_struct      work;
  94        struct extcon_dev       *extcon;
  95        struct notifier_block   host_nb;
  96};
  97
  98/* phy_power_on / off may sleep, so we use a workqueue  */
  99static void sunxi_musb_work(struct work_struct *work)
 100{
 101        struct sunxi_glue *glue = container_of(work, struct sunxi_glue, work);
 102        bool vbus_on, phy_on;
 103
 104        if (!test_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
 105                return;
 106
 107        if (test_and_clear_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags)) {
 108                struct musb *musb = glue->musb;
 109                unsigned long flags;
 110                u8 devctl;
 111
 112                spin_lock_irqsave(&musb->lock, flags);
 113
 114                devctl = readb(musb->mregs + SUNXI_MUSB_DEVCTL);
 115                if (test_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags)) {
 116                        set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 117                        musb->xceiv->otg->default_a = 1;
 118                        musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 119                        MUSB_HST_MODE(musb);
 120                        devctl |= MUSB_DEVCTL_SESSION;
 121                } else {
 122                        clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 123                        musb->xceiv->otg->default_a = 0;
 124                        musb->xceiv->otg->state = OTG_STATE_B_IDLE;
 125                        MUSB_DEV_MODE(musb);
 126                        devctl &= ~MUSB_DEVCTL_SESSION;
 127                }
 128                writeb(devctl, musb->mregs + SUNXI_MUSB_DEVCTL);
 129
 130                spin_unlock_irqrestore(&musb->lock, flags);
 131        }
 132
 133        vbus_on = test_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 134        phy_on = test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 135
 136        if (phy_on != vbus_on) {
 137                if (vbus_on) {
 138                        phy_power_on(glue->phy);
 139                        set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 140                } else {
 141                        phy_power_off(glue->phy);
 142                        clear_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
 143                }
 144        }
 145
 146        if (test_and_clear_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags))
 147                phy_set_mode(glue->phy, glue->phy_mode);
 148}
 149
 150static void sunxi_musb_set_vbus(struct musb *musb, int is_on)
 151{
 152        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 153
 154        if (is_on) {
 155                set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 156                musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
 157        } else {
 158                clear_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
 159        }
 160
 161        schedule_work(&glue->work);
 162}
 163
 164static void sunxi_musb_pre_root_reset_end(struct musb *musb)
 165{
 166        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 167
 168        sun4i_usb_phy_set_squelch_detect(glue->phy, false);
 169}
 170
 171static void sunxi_musb_post_root_reset_end(struct musb *musb)
 172{
 173        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 174
 175        sun4i_usb_phy_set_squelch_detect(glue->phy, true);
 176}
 177
 178static irqreturn_t sunxi_musb_interrupt(int irq, void *__hci)
 179{
 180        struct musb *musb = __hci;
 181        unsigned long flags;
 182
 183        spin_lock_irqsave(&musb->lock, flags);
 184
 185        musb->int_usb = readb(musb->mregs + SUNXI_MUSB_INTRUSB);
 186        if (musb->int_usb)
 187                writeb(musb->int_usb, musb->mregs + SUNXI_MUSB_INTRUSB);
 188
 189        if ((musb->int_usb & MUSB_INTR_RESET) && !is_host_active(musb)) {
 190                /* ep0 FADDR must be 0 when (re)entering peripheral mode */
 191                musb_ep_select(musb->mregs, 0);
 192                musb_writeb(musb->mregs, MUSB_FADDR, 0);
 193        }
 194
 195        musb->int_tx = readw(musb->mregs + SUNXI_MUSB_INTRTX);
 196        if (musb->int_tx)
 197                writew(musb->int_tx, musb->mregs + SUNXI_MUSB_INTRTX);
 198
 199        musb->int_rx = readw(musb->mregs + SUNXI_MUSB_INTRRX);
 200        if (musb->int_rx)
 201                writew(musb->int_rx, musb->mregs + SUNXI_MUSB_INTRRX);
 202
 203        musb_interrupt(musb);
 204
 205        spin_unlock_irqrestore(&musb->lock, flags);
 206
 207        return IRQ_HANDLED;
 208}
 209
 210static int sunxi_musb_host_notifier(struct notifier_block *nb,
 211                                    unsigned long event, void *ptr)
 212{
 213        struct sunxi_glue *glue = container_of(nb, struct sunxi_glue, host_nb);
 214
 215        if (event)
 216                set_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
 217        else
 218                clear_bit(SUNXI_MUSB_FL_HOSTMODE, &glue->flags);
 219
 220        set_bit(SUNXI_MUSB_FL_HOSTMODE_PEND, &glue->flags);
 221        schedule_work(&glue->work);
 222
 223        return NOTIFY_DONE;
 224}
 225
 226static int sunxi_musb_init(struct musb *musb)
 227{
 228        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 229        int ret;
 230
 231        sunxi_musb = musb;
 232        musb->phy = glue->phy;
 233        musb->xceiv = glue->xceiv;
 234
 235        if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) {
 236                ret = sunxi_sram_claim(musb->controller->parent);
 237                if (ret)
 238                        return ret;
 239        }
 240
 241        ret = clk_prepare_enable(glue->clk);
 242        if (ret)
 243                goto error_sram_release;
 244
 245        if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
 246                ret = reset_control_deassert(glue->rst);
 247                if (ret)
 248                        goto error_clk_disable;
 249        }
 250
 251        writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
 252
 253        /* Register notifier before calling phy_init() */
 254        ret = devm_extcon_register_notifier(glue->dev, glue->extcon,
 255                                        EXTCON_USB_HOST, &glue->host_nb);
 256        if (ret)
 257                goto error_reset_assert;
 258
 259        ret = phy_init(glue->phy);
 260        if (ret)
 261                goto error_reset_assert;
 262
 263        musb->isr = sunxi_musb_interrupt;
 264
 265        /* Stop the musb-core from doing runtime pm (not supported on sunxi) */
 266        pm_runtime_get(musb->controller);
 267
 268        return 0;
 269
 270error_reset_assert:
 271        if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 272                reset_control_assert(glue->rst);
 273error_clk_disable:
 274        clk_disable_unprepare(glue->clk);
 275error_sram_release:
 276        if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
 277                sunxi_sram_release(musb->controller->parent);
 278        return ret;
 279}
 280
 281static int sunxi_musb_exit(struct musb *musb)
 282{
 283        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 284
 285        pm_runtime_put(musb->controller);
 286
 287        cancel_work_sync(&glue->work);
 288        if (test_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags))
 289                phy_power_off(glue->phy);
 290
 291        phy_exit(glue->phy);
 292
 293        if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 294                reset_control_assert(glue->rst);
 295
 296        clk_disable_unprepare(glue->clk);
 297        if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags))
 298                sunxi_sram_release(musb->controller->parent);
 299
 300        return 0;
 301}
 302
 303static void sunxi_musb_enable(struct musb *musb)
 304{
 305        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 306
 307        glue->musb = musb;
 308
 309        /* musb_core does not call us in a balanced manner */
 310        if (test_and_set_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags))
 311                return;
 312
 313        schedule_work(&glue->work);
 314}
 315
 316static void sunxi_musb_disable(struct musb *musb)
 317{
 318        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 319
 320        clear_bit(SUNXI_MUSB_FL_ENABLED, &glue->flags);
 321}
 322
 323static struct dma_controller *
 324sunxi_musb_dma_controller_create(struct musb *musb, void __iomem *base)
 325{
 326        return NULL;
 327}
 328
 329static void sunxi_musb_dma_controller_destroy(struct dma_controller *c)
 330{
 331}
 332
 333static int sunxi_musb_set_mode(struct musb *musb, u8 mode)
 334{
 335        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 336        enum phy_mode new_mode;
 337
 338        switch (mode) {
 339        case MUSB_HOST:
 340                new_mode = PHY_MODE_USB_HOST;
 341                break;
 342        case MUSB_PERIPHERAL:
 343                new_mode = PHY_MODE_USB_DEVICE;
 344                break;
 345        case MUSB_OTG:
 346                new_mode = PHY_MODE_USB_OTG;
 347                break;
 348        default:
 349                dev_err(musb->controller->parent,
 350                        "Error requested mode not supported by this kernel\n");
 351                return -EINVAL;
 352        }
 353
 354        if (glue->phy_mode == new_mode)
 355                return 0;
 356
 357        if (musb->port_mode != MUSB_PORT_MODE_DUAL_ROLE) {
 358                dev_err(musb->controller->parent,
 359                        "Error changing modes is only supported in dual role mode\n");
 360                return -EINVAL;
 361        }
 362
 363        if (musb->port1_status & USB_PORT_STAT_ENABLE)
 364                musb_root_disconnect(musb);
 365
 366        /*
 367         * phy_set_mode may sleep, and we're called with a spinlock held,
 368         * so let sunxi_musb_work deal with it.
 369         */
 370        glue->phy_mode = new_mode;
 371        set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
 372        schedule_work(&glue->work);
 373
 374        return 0;
 375}
 376
 377static int sunxi_musb_recover(struct musb *musb)
 378{
 379        struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
 380
 381        /*
 382         * Schedule a phy_set_mode with the current glue->phy_mode value,
 383         * this will force end the current session.
 384         */
 385        set_bit(SUNXI_MUSB_FL_PHY_MODE_PEND, &glue->flags);
 386        schedule_work(&glue->work);
 387
 388        return 0;
 389}
 390
 391/*
 392 * sunxi musb register layout
 393 * 0x00 - 0x17  fifo regs, 1 long per fifo
 394 * 0x40 - 0x57  generic control regs (power - frame)
 395 * 0x80 - 0x8f  ep control regs (addressed through hw_ep->regs, indexed)
 396 * 0x90 - 0x97  fifo control regs (indexed)
 397 * 0x98 - 0x9f  multipoint / busctl regs (indexed)
 398 * 0xc0         configdata reg
 399 */
 400
 401static u32 sunxi_musb_fifo_offset(u8 epnum)
 402{
 403        return (epnum * 4);
 404}
 405
 406static u32 sunxi_musb_ep_offset(u8 epnum, u16 offset)
 407{
 408        WARN_ONCE(offset != 0,
 409                  "sunxi_musb_ep_offset called with non 0 offset\n");
 410
 411        return 0x80; /* indexed, so ignore epnum */
 412}
 413
 414static u32 sunxi_musb_busctl_offset(u8 epnum, u16 offset)
 415{
 416        return SUNXI_MUSB_TXFUNCADDR + offset;
 417}
 418
 419static u8 sunxi_musb_readb(const void __iomem *addr, unsigned offset)
 420{
 421        struct sunxi_glue *glue;
 422
 423        if (addr == sunxi_musb->mregs) {
 424                /* generic control or fifo control reg access */
 425                switch (offset) {
 426                case MUSB_FADDR:
 427                        return readb(addr + SUNXI_MUSB_FADDR);
 428                case MUSB_POWER:
 429                        return readb(addr + SUNXI_MUSB_POWER);
 430                case MUSB_INTRUSB:
 431                        return readb(addr + SUNXI_MUSB_INTRUSB);
 432                case MUSB_INTRUSBE:
 433                        return readb(addr + SUNXI_MUSB_INTRUSBE);
 434                case MUSB_INDEX:
 435                        return readb(addr + SUNXI_MUSB_INDEX);
 436                case MUSB_TESTMODE:
 437                        return 0; /* No testmode on sunxi */
 438                case MUSB_DEVCTL:
 439                        return readb(addr + SUNXI_MUSB_DEVCTL);
 440                case MUSB_TXFIFOSZ:
 441                        return readb(addr + SUNXI_MUSB_TXFIFOSZ);
 442                case MUSB_RXFIFOSZ:
 443                        return readb(addr + SUNXI_MUSB_RXFIFOSZ);
 444                case MUSB_CONFIGDATA + 0x10: /* See musb_read_configdata() */
 445                        glue = dev_get_drvdata(sunxi_musb->controller->parent);
 446                        /* A33 saves a reg, and we get to hardcode this */
 447                        if (test_bit(SUNXI_MUSB_FL_NO_CONFIGDATA,
 448                                     &glue->flags))
 449                                return 0xde;
 450
 451                        return readb(addr + SUNXI_MUSB_CONFIGDATA);
 452                /* Offset for these is fixed by sunxi_musb_busctl_offset() */
 453                case SUNXI_MUSB_TXFUNCADDR:
 454                case SUNXI_MUSB_TXHUBADDR:
 455                case SUNXI_MUSB_TXHUBPORT:
 456                case SUNXI_MUSB_RXFUNCADDR:
 457                case SUNXI_MUSB_RXHUBADDR:
 458                case SUNXI_MUSB_RXHUBPORT:
 459                        /* multipoint / busctl reg access */
 460                        return readb(addr + offset);
 461                default:
 462                        dev_err(sunxi_musb->controller->parent,
 463                                "Error unknown readb offset %u\n", offset);
 464                        return 0;
 465                }
 466        } else if (addr == (sunxi_musb->mregs + 0x80)) {
 467                /* ep control reg access */
 468                /* sunxi has a 2 byte hole before the txtype register */
 469                if (offset >= MUSB_TXTYPE)
 470                        offset += 2;
 471                return readb(addr + offset);
 472        }
 473
 474        dev_err(sunxi_musb->controller->parent,
 475                "Error unknown readb at 0x%x bytes offset\n",
 476                (int)(addr - sunxi_musb->mregs));
 477        return 0;
 478}
 479
 480static void sunxi_musb_writeb(void __iomem *addr, unsigned offset, u8 data)
 481{
 482        if (addr == sunxi_musb->mregs) {
 483                /* generic control or fifo control reg access */
 484                switch (offset) {
 485                case MUSB_FADDR:
 486                        return writeb(data, addr + SUNXI_MUSB_FADDR);
 487                case MUSB_POWER:
 488                        return writeb(data, addr + SUNXI_MUSB_POWER);
 489                case MUSB_INTRUSB:
 490                        return writeb(data, addr + SUNXI_MUSB_INTRUSB);
 491                case MUSB_INTRUSBE:
 492                        return writeb(data, addr + SUNXI_MUSB_INTRUSBE);
 493                case MUSB_INDEX:
 494                        return writeb(data, addr + SUNXI_MUSB_INDEX);
 495                case MUSB_TESTMODE:
 496                        if (data)
 497                                dev_warn(sunxi_musb->controller->parent,
 498                                        "sunxi-musb does not have testmode\n");
 499                        return;
 500                case MUSB_DEVCTL:
 501                        return writeb(data, addr + SUNXI_MUSB_DEVCTL);
 502                case MUSB_TXFIFOSZ:
 503                        return writeb(data, addr + SUNXI_MUSB_TXFIFOSZ);
 504                case MUSB_RXFIFOSZ:
 505                        return writeb(data, addr + SUNXI_MUSB_RXFIFOSZ);
 506                /* Offset for these is fixed by sunxi_musb_busctl_offset() */
 507                case SUNXI_MUSB_TXFUNCADDR:
 508                case SUNXI_MUSB_TXHUBADDR:
 509                case SUNXI_MUSB_TXHUBPORT:
 510                case SUNXI_MUSB_RXFUNCADDR:
 511                case SUNXI_MUSB_RXHUBADDR:
 512                case SUNXI_MUSB_RXHUBPORT:
 513                        /* multipoint / busctl reg access */
 514                        return writeb(data, addr + offset);
 515                default:
 516                        dev_err(sunxi_musb->controller->parent,
 517                                "Error unknown writeb offset %u\n", offset);
 518                        return;
 519                }
 520        } else if (addr == (sunxi_musb->mregs + 0x80)) {
 521                /* ep control reg access */
 522                if (offset >= MUSB_TXTYPE)
 523                        offset += 2;
 524                return writeb(data, addr + offset);
 525        }
 526
 527        dev_err(sunxi_musb->controller->parent,
 528                "Error unknown writeb at 0x%x bytes offset\n",
 529                (int)(addr - sunxi_musb->mregs));
 530}
 531
 532static u16 sunxi_musb_readw(const void __iomem *addr, unsigned offset)
 533{
 534        if (addr == sunxi_musb->mregs) {
 535                /* generic control or fifo control reg access */
 536                switch (offset) {
 537                case MUSB_INTRTX:
 538                        return readw(addr + SUNXI_MUSB_INTRTX);
 539                case MUSB_INTRRX:
 540                        return readw(addr + SUNXI_MUSB_INTRRX);
 541                case MUSB_INTRTXE:
 542                        return readw(addr + SUNXI_MUSB_INTRTXE);
 543                case MUSB_INTRRXE:
 544                        return readw(addr + SUNXI_MUSB_INTRRXE);
 545                case MUSB_FRAME:
 546                        return readw(addr + SUNXI_MUSB_FRAME);
 547                case MUSB_TXFIFOADD:
 548                        return readw(addr + SUNXI_MUSB_TXFIFOADD);
 549                case MUSB_RXFIFOADD:
 550                        return readw(addr + SUNXI_MUSB_RXFIFOADD);
 551                case MUSB_HWVERS:
 552                        return 0; /* sunxi musb version is not known */
 553                default:
 554                        dev_err(sunxi_musb->controller->parent,
 555                                "Error unknown readw offset %u\n", offset);
 556                        return 0;
 557                }
 558        } else if (addr == (sunxi_musb->mregs + 0x80)) {
 559                /* ep control reg access */
 560                return readw(addr + offset);
 561        }
 562
 563        dev_err(sunxi_musb->controller->parent,
 564                "Error unknown readw at 0x%x bytes offset\n",
 565                (int)(addr - sunxi_musb->mregs));
 566        return 0;
 567}
 568
 569static void sunxi_musb_writew(void __iomem *addr, unsigned offset, u16 data)
 570{
 571        if (addr == sunxi_musb->mregs) {
 572                /* generic control or fifo control reg access */
 573                switch (offset) {
 574                case MUSB_INTRTX:
 575                        return writew(data, addr + SUNXI_MUSB_INTRTX);
 576                case MUSB_INTRRX:
 577                        return writew(data, addr + SUNXI_MUSB_INTRRX);
 578                case MUSB_INTRTXE:
 579                        return writew(data, addr + SUNXI_MUSB_INTRTXE);
 580                case MUSB_INTRRXE:
 581                        return writew(data, addr + SUNXI_MUSB_INTRRXE);
 582                case MUSB_FRAME:
 583                        return writew(data, addr + SUNXI_MUSB_FRAME);
 584                case MUSB_TXFIFOADD:
 585                        return writew(data, addr + SUNXI_MUSB_TXFIFOADD);
 586                case MUSB_RXFIFOADD:
 587                        return writew(data, addr + SUNXI_MUSB_RXFIFOADD);
 588                default:
 589                        dev_err(sunxi_musb->controller->parent,
 590                                "Error unknown writew offset %u\n", offset);
 591                        return;
 592                }
 593        } else if (addr == (sunxi_musb->mregs + 0x80)) {
 594                /* ep control reg access */
 595                return writew(data, addr + offset);
 596        }
 597
 598        dev_err(sunxi_musb->controller->parent,
 599                "Error unknown writew at 0x%x bytes offset\n",
 600                (int)(addr - sunxi_musb->mregs));
 601}
 602
 603static const struct musb_platform_ops sunxi_musb_ops = {
 604        .quirks         = MUSB_INDEXED_EP,
 605        .init           = sunxi_musb_init,
 606        .exit           = sunxi_musb_exit,
 607        .enable         = sunxi_musb_enable,
 608        .disable        = sunxi_musb_disable,
 609        .fifo_offset    = sunxi_musb_fifo_offset,
 610        .ep_offset      = sunxi_musb_ep_offset,
 611        .busctl_offset  = sunxi_musb_busctl_offset,
 612        .readb          = sunxi_musb_readb,
 613        .writeb         = sunxi_musb_writeb,
 614        .readw          = sunxi_musb_readw,
 615        .writew         = sunxi_musb_writew,
 616        .dma_init       = sunxi_musb_dma_controller_create,
 617        .dma_exit       = sunxi_musb_dma_controller_destroy,
 618        .set_mode       = sunxi_musb_set_mode,
 619        .recover        = sunxi_musb_recover,
 620        .set_vbus       = sunxi_musb_set_vbus,
 621        .pre_root_reset_end = sunxi_musb_pre_root_reset_end,
 622        .post_root_reset_end = sunxi_musb_post_root_reset_end,
 623};
 624
 625/* Allwinner OTG supports up to 5 endpoints */
 626#define SUNXI_MUSB_MAX_EP_NUM   6
 627#define SUNXI_MUSB_RAM_BITS     11
 628
 629static struct musb_fifo_cfg sunxi_musb_mode_cfg[] = {
 630        MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
 631        MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
 632        MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
 633        MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
 634        MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
 635        MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
 636        MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
 637        MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
 638        MUSB_EP_FIFO_SINGLE(5, FIFO_TX, 512),
 639        MUSB_EP_FIFO_SINGLE(5, FIFO_RX, 512),
 640};
 641
 642/* H3/V3s OTG supports only 4 endpoints */
 643#define SUNXI_MUSB_MAX_EP_NUM_H3        5
 644
 645static struct musb_fifo_cfg sunxi_musb_mode_cfg_h3[] = {
 646        MUSB_EP_FIFO_SINGLE(1, FIFO_TX, 512),
 647        MUSB_EP_FIFO_SINGLE(1, FIFO_RX, 512),
 648        MUSB_EP_FIFO_SINGLE(2, FIFO_TX, 512),
 649        MUSB_EP_FIFO_SINGLE(2, FIFO_RX, 512),
 650        MUSB_EP_FIFO_SINGLE(3, FIFO_TX, 512),
 651        MUSB_EP_FIFO_SINGLE(3, FIFO_RX, 512),
 652        MUSB_EP_FIFO_SINGLE(4, FIFO_TX, 512),
 653        MUSB_EP_FIFO_SINGLE(4, FIFO_RX, 512),
 654};
 655
 656static const struct musb_hdrc_config sunxi_musb_hdrc_config = {
 657        .fifo_cfg       = sunxi_musb_mode_cfg,
 658        .fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg),
 659        .multipoint     = true,
 660        .dyn_fifo       = true,
 661        .soft_con       = true,
 662        .num_eps        = SUNXI_MUSB_MAX_EP_NUM,
 663        .ram_bits       = SUNXI_MUSB_RAM_BITS,
 664        .dma            = 0,
 665};
 666
 667static struct musb_hdrc_config sunxi_musb_hdrc_config_h3 = {
 668        .fifo_cfg       = sunxi_musb_mode_cfg_h3,
 669        .fifo_cfg_size  = ARRAY_SIZE(sunxi_musb_mode_cfg_h3),
 670        .multipoint     = true,
 671        .dyn_fifo       = true,
 672        .soft_con       = true,
 673        .num_eps        = SUNXI_MUSB_MAX_EP_NUM_H3,
 674        .ram_bits       = SUNXI_MUSB_RAM_BITS,
 675        .dma            = 0,
 676};
 677
 678
 679static int sunxi_musb_probe(struct platform_device *pdev)
 680{
 681        struct musb_hdrc_platform_data  pdata;
 682        struct platform_device_info     pinfo;
 683        struct sunxi_glue               *glue;
 684        struct device_node              *np = pdev->dev.of_node;
 685        int ret;
 686
 687        if (!np) {
 688                dev_err(&pdev->dev, "Error no device tree node found\n");
 689                return -EINVAL;
 690        }
 691
 692        glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
 693        if (!glue)
 694                return -ENOMEM;
 695
 696        memset(&pdata, 0, sizeof(pdata));
 697        switch (usb_get_dr_mode(&pdev->dev)) {
 698#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
 699        case USB_DR_MODE_HOST:
 700                pdata.mode = MUSB_PORT_MODE_HOST;
 701                glue->phy_mode = PHY_MODE_USB_HOST;
 702                break;
 703#endif
 704#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET
 705        case USB_DR_MODE_PERIPHERAL:
 706                pdata.mode = MUSB_PORT_MODE_GADGET;
 707                glue->phy_mode = PHY_MODE_USB_DEVICE;
 708                break;
 709#endif
 710#ifdef CONFIG_USB_MUSB_DUAL_ROLE
 711        case USB_DR_MODE_OTG:
 712                pdata.mode = MUSB_PORT_MODE_DUAL_ROLE;
 713                glue->phy_mode = PHY_MODE_USB_OTG;
 714                break;
 715#endif
 716        default:
 717                dev_err(&pdev->dev, "Invalid or missing 'dr_mode' property\n");
 718                return -EINVAL;
 719        }
 720        pdata.platform_ops      = &sunxi_musb_ops;
 721        if (!of_device_is_compatible(np, "allwinner,sun8i-h3-musb"))
 722                pdata.config = &sunxi_musb_hdrc_config;
 723        else
 724                pdata.config = &sunxi_musb_hdrc_config_h3;
 725
 726        glue->dev = &pdev->dev;
 727        INIT_WORK(&glue->work, sunxi_musb_work);
 728        glue->host_nb.notifier_call = sunxi_musb_host_notifier;
 729
 730        if (of_device_is_compatible(np, "allwinner,sun4i-a10-musb"))
 731                set_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags);
 732
 733        if (of_device_is_compatible(np, "allwinner,sun6i-a31-musb"))
 734                set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
 735
 736        if (of_device_is_compatible(np, "allwinner,sun8i-a33-musb") ||
 737            of_device_is_compatible(np, "allwinner,sun8i-h3-musb")) {
 738                set_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags);
 739                set_bit(SUNXI_MUSB_FL_NO_CONFIGDATA, &glue->flags);
 740        }
 741
 742        glue->clk = devm_clk_get(&pdev->dev, NULL);
 743        if (IS_ERR(glue->clk)) {
 744                dev_err(&pdev->dev, "Error getting clock: %ld\n",
 745                        PTR_ERR(glue->clk));
 746                return PTR_ERR(glue->clk);
 747        }
 748
 749        if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags)) {
 750                glue->rst = devm_reset_control_get(&pdev->dev, NULL);
 751                if (IS_ERR(glue->rst)) {
 752                        if (PTR_ERR(glue->rst) == -EPROBE_DEFER)
 753                                return -EPROBE_DEFER;
 754                        dev_err(&pdev->dev, "Error getting reset %ld\n",
 755                                PTR_ERR(glue->rst));
 756                        return PTR_ERR(glue->rst);
 757                }
 758        }
 759
 760        glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
 761        if (IS_ERR(glue->extcon)) {
 762                if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
 763                        return -EPROBE_DEFER;
 764                dev_err(&pdev->dev, "Invalid or missing extcon\n");
 765                return PTR_ERR(glue->extcon);
 766        }
 767
 768        glue->phy = devm_phy_get(&pdev->dev, "usb");
 769        if (IS_ERR(glue->phy)) {
 770                if (PTR_ERR(glue->phy) == -EPROBE_DEFER)
 771                        return -EPROBE_DEFER;
 772                dev_err(&pdev->dev, "Error getting phy %ld\n",
 773                        PTR_ERR(glue->phy));
 774                return PTR_ERR(glue->phy);
 775        }
 776
 777        glue->usb_phy = usb_phy_generic_register();
 778        if (IS_ERR(glue->usb_phy)) {
 779                dev_err(&pdev->dev, "Error registering usb-phy %ld\n",
 780                        PTR_ERR(glue->usb_phy));
 781                return PTR_ERR(glue->usb_phy);
 782        }
 783
 784        glue->xceiv = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2);
 785        if (IS_ERR(glue->xceiv)) {
 786                ret = PTR_ERR(glue->xceiv);
 787                dev_err(&pdev->dev, "Error getting usb-phy %d\n", ret);
 788                goto err_unregister_usb_phy;
 789        }
 790
 791        platform_set_drvdata(pdev, glue);
 792
 793        memset(&pinfo, 0, sizeof(pinfo));
 794        pinfo.name       = "musb-hdrc";
 795        pinfo.id        = PLATFORM_DEVID_AUTO;
 796        pinfo.parent    = &pdev->dev;
 797        pinfo.res       = pdev->resource;
 798        pinfo.num_res   = pdev->num_resources;
 799        pinfo.data      = &pdata;
 800        pinfo.size_data = sizeof(pdata);
 801
 802        glue->musb_pdev = platform_device_register_full(&pinfo);
 803        if (IS_ERR(glue->musb_pdev)) {
 804                ret = PTR_ERR(glue->musb_pdev);
 805                dev_err(&pdev->dev, "Error registering musb dev: %d\n", ret);
 806                goto err_unregister_usb_phy;
 807        }
 808
 809        return 0;
 810
 811err_unregister_usb_phy:
 812        usb_phy_generic_unregister(glue->usb_phy);
 813        return ret;
 814}
 815
 816static int sunxi_musb_remove(struct platform_device *pdev)
 817{
 818        struct sunxi_glue *glue = platform_get_drvdata(pdev);
 819        struct platform_device *usb_phy = glue->usb_phy;
 820
 821        platform_device_unregister(glue->musb_pdev);
 822        usb_phy_generic_unregister(usb_phy);
 823
 824        return 0;
 825}
 826
 827static const struct of_device_id sunxi_musb_match[] = {
 828        { .compatible = "allwinner,sun4i-a10-musb", },
 829        { .compatible = "allwinner,sun6i-a31-musb", },
 830        { .compatible = "allwinner,sun8i-a33-musb", },
 831        { .compatible = "allwinner,sun8i-h3-musb", },
 832        {}
 833};
 834MODULE_DEVICE_TABLE(of, sunxi_musb_match);
 835
 836static struct platform_driver sunxi_musb_driver = {
 837        .probe = sunxi_musb_probe,
 838        .remove = sunxi_musb_remove,
 839        .driver = {
 840                .name = "musb-sunxi",
 841                .of_match_table = sunxi_musb_match,
 842        },
 843};
 844module_platform_driver(sunxi_musb_driver);
 845
 846MODULE_DESCRIPTION("Allwinner sunxi MUSB Glue Layer");
 847MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 848MODULE_LICENSE("GPL v2");
 849