uboot/drivers/usb/musb-new/ux500.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/* Copyright (C) 2019 Stephan Gerhold */
   3
   4#include <common.h>
   5#include <dm.h>
   6#include <generic-phy.h>
   7#include <dm/device_compat.h>
   8#include "musb_uboot.h"
   9
  10static struct musb_hdrc_config ux500_musb_hdrc_config = {
  11        .multipoint     = true,
  12        .dyn_fifo       = true,
  13        .num_eps        = 16,
  14        .ram_bits       = 16,
  15};
  16
  17struct ux500_glue {
  18        struct musb_host_data mdata;
  19        struct device dev;
  20        struct phy phy;
  21        bool enabled;
  22};
  23#define to_ux500_glue(d)        container_of(d, struct ux500_glue, dev)
  24
  25static int ux500_musb_enable(struct musb *musb)
  26{
  27        struct ux500_glue *glue = to_ux500_glue(musb->controller);
  28        int ret;
  29
  30        if (glue->enabled)
  31                return 0;
  32
  33        ret = generic_phy_power_on(&glue->phy);
  34        if (ret) {
  35                printf("%s: failed to power on USB PHY\n", __func__);
  36                return ret;
  37        }
  38
  39        glue->enabled = true;
  40        return 0;
  41}
  42
  43static void ux500_musb_disable(struct musb *musb)
  44{
  45        struct ux500_glue *glue = to_ux500_glue(musb->controller);
  46        int ret;
  47
  48        if (!glue->enabled)
  49                return;
  50
  51        ret = generic_phy_power_off(&glue->phy);
  52        if (ret) {
  53                printf("%s: failed to power off USB PHY\n", __func__);
  54                return;
  55        }
  56
  57        glue->enabled = false;
  58}
  59
  60static int ux500_musb_init(struct musb *musb)
  61{
  62        struct ux500_glue *glue = to_ux500_glue(musb->controller);
  63        int ret;
  64
  65        ret = generic_phy_init(&glue->phy);
  66        if (ret) {
  67                printf("%s: failed to init USB PHY\n", __func__);
  68                return ret;
  69        }
  70
  71        return 0;
  72}
  73
  74static int ux500_musb_exit(struct musb *musb)
  75{
  76        struct ux500_glue *glue = to_ux500_glue(musb->controller);
  77        int ret;
  78
  79        ret = generic_phy_exit(&glue->phy);
  80        if (ret) {
  81                printf("%s: failed to exit USB PHY\n", __func__);
  82                return ret;
  83        }
  84
  85        return 0;
  86}
  87
  88static const struct musb_platform_ops ux500_musb_ops = {
  89        .init           = ux500_musb_init,
  90        .exit           = ux500_musb_exit,
  91        .enable         = ux500_musb_enable,
  92        .disable        = ux500_musb_disable,
  93};
  94
  95int dm_usb_gadget_handle_interrupts(struct udevice *dev)
  96{
  97        struct ux500_glue *glue = dev_get_priv(dev);
  98
  99        glue->mdata.host->isr(0, glue->mdata.host);
 100        return 0;
 101}
 102
 103static int ux500_musb_probe(struct udevice *dev)
 104{
 105#ifdef CONFIG_USB_MUSB_HOST
 106        struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
 107#endif
 108        struct ux500_glue *glue = dev_get_priv(dev);
 109        struct musb_host_data *host = &glue->mdata;
 110        struct musb_hdrc_platform_data pdata;
 111        void *base = dev_read_addr_ptr(dev);
 112        int ret;
 113
 114        if (!base)
 115                return -EINVAL;
 116
 117        ret = generic_phy_get_by_name(dev, "usb", &glue->phy);
 118        if (ret) {
 119                dev_err(dev, "failed to get USB PHY: %d\n", ret);
 120                return ret;
 121        }
 122
 123        memset(&pdata, 0, sizeof(pdata));
 124        pdata.platform_ops = &ux500_musb_ops;
 125        pdata.config = &ux500_musb_hdrc_config;
 126
 127#ifdef CONFIG_USB_MUSB_HOST
 128        priv->desc_before_addr = true;
 129        pdata.mode = MUSB_HOST;
 130
 131        host->host = musb_init_controller(&pdata, &glue->dev, base);
 132        if (!host->host)
 133                return -EIO;
 134
 135        return musb_lowlevel_init(host);
 136#else
 137        pdata.mode = MUSB_PERIPHERAL;
 138        host->host = musb_init_controller(&pdata, &glue->dev, base);
 139        if (!host->host)
 140                return -EIO;
 141
 142        return usb_add_gadget_udc(&glue->dev, &host->host->g);
 143#endif
 144}
 145
 146static int ux500_musb_remove(struct udevice *dev)
 147{
 148        struct ux500_glue *glue = dev_get_priv(dev);
 149        struct musb_host_data *host = &glue->mdata;
 150
 151        usb_del_gadget_udc(&host->host->g);
 152        musb_stop(host->host);
 153        free(host->host);
 154        host->host = NULL;
 155
 156        return 0;
 157}
 158
 159static const struct udevice_id ux500_musb_ids[] = {
 160        { .compatible = "stericsson,db8500-musb" },
 161        { }
 162};
 163
 164U_BOOT_DRIVER(ux500_musb) = {
 165        .name           = "ux500-musb",
 166#ifdef CONFIG_USB_MUSB_HOST
 167        .id             = UCLASS_USB,
 168#else
 169        .id             = UCLASS_USB_GADGET_GENERIC,
 170#endif
 171        .of_match       = ux500_musb_ids,
 172        .probe          = ux500_musb_probe,
 173        .remove         = ux500_musb_remove,
 174#ifdef CONFIG_USB_MUSB_HOST
 175        .ops            = &musb_usb_ops,
 176#endif
 177        .plat_auto      = sizeof(struct usb_plat),
 178        .priv_auto      = sizeof(struct ux500_glue),
 179};
 180