1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (c) 2021 Nuvoton Technology Corp. 4 */ 5 6#include <common.h> 7#include <dm.h> 8#include <generic-phy.h> 9#include <reset.h> 10#include <asm/io.h> 11#include <dm/device_compat.h> 12#include <linux/delay.h> 13#include "ohci.h" 14 15struct npcm_ohci_priv { 16 ohci_t ohci; 17 struct phy phy; 18}; 19 20static int npcm_ohci_setup_phy(struct udevice *dev, struct phy *phy) 21{ 22 int ret; 23 24 if (!phy) 25 return 0; 26 27 ret = generic_phy_get_by_index(dev, 0, phy); 28 if (ret) { 29 if (ret != -ENOENT) { 30 dev_err(dev, "failed to get usb phy\n"); 31 return ret; 32 } 33 } else { 34 ret = generic_phy_init(phy); 35 if (ret) { 36 dev_err(dev, "failed to init usb phy\n"); 37 return ret; 38 } 39 } 40 41 return 0; 42} 43 44static int npcm_ohci_init(struct udevice *dev) 45{ 46 struct npcm_ohci_priv *priv = dev_get_priv(dev); 47 struct reset_ctl reset; 48 int ret; 49 50 ret = reset_get_by_index(dev, 0, &reset); 51 if (ret && ret != -ENOENT && ret != -ENOTSUPP) { 52 dev_err(dev, "failed to get reset\n"); 53 return ret; 54 } 55 56 /* reset controller */ 57 if (reset_valid(&reset)) 58 reset_assert(&reset); 59 60 /* setup phy */ 61 ret = npcm_ohci_setup_phy(dev, &priv->phy); 62 if (ret) 63 return ret; 64 65 /* release controller from reset */ 66 if (reset_valid(&reset)) 67 reset_deassert(&reset); 68 69 return 0; 70} 71 72static int npcm_ohci_probe(struct udevice *dev) 73{ 74 struct ohci_regs *regs = dev_read_addr_ptr(dev); 75 int ret; 76 77 ret = npcm_ohci_init(dev); 78 if (ret) 79 return ret; 80 81 return ohci_register(dev, regs); 82} 83 84static int npcm_ohci_remove(struct udevice *dev) 85{ 86 struct npcm_ohci_priv *priv = dev_get_priv(dev); 87 88 generic_phy_exit(&priv->phy); 89 90 return ohci_deregister(dev); 91} 92 93static const struct udevice_id npcm_ohci_ids[] = { 94 { .compatible = "nuvoton,npcm845-ohci" }, 95 { .compatible = "nuvoton,npcm750-ohci" }, 96 { } 97}; 98 99U_BOOT_DRIVER(ohci_npcm) = { 100 .name = "ohci_npcm", 101 .id = UCLASS_USB, 102 .of_match = npcm_ohci_ids, 103 .probe = npcm_ohci_probe, 104 .remove = npcm_ohci_remove, 105 .ops = &ohci_usb_ops, 106 .priv_auto = sizeof(struct npcm_ohci_priv), 107 .flags = DM_FLAG_ALLOC_PRIV_DMA, 108}; 109