/* * Copyright (c) 2016 Sascha Hauer * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ #include #include #include #include #include #include #include #include #include #include struct nop_usbphy { struct usb_phy usb_phy; struct phy *phy; struct phy_provider *provider; }; static struct phy *nop_usbphy_xlate(struct device_d *dev, struct of_phandle_args *args) { struct nop_usbphy *nopphy = dev->priv; return nopphy->phy; } static struct usb_phy *nop_usbphy_to_usbphy(struct phy *phy) { struct nop_usbphy *nopphy = phy_get_drvdata(phy); return &nopphy->usb_phy; } static const struct phy_ops nop_phy_ops = { .to_usbphy = nop_usbphy_to_usbphy, }; static int nop_usbphy_probe(struct device_d *dev) { int ret; struct nop_usbphy *nopphy; nopphy = xzalloc(sizeof(*nopphy)); dev->priv = nopphy; /* FIXME: Add clk support */ /* FIXME: Add vbus regulator support */ /* FIXME: Add vbus-detect-gpio support */ nopphy->usb_phy.dev = dev; nopphy->phy = phy_create(dev, NULL, &nop_phy_ops, NULL); if (IS_ERR(nopphy->phy)) { ret = PTR_ERR(nopphy->phy); goto err_free; } phy_set_drvdata(nopphy->phy, nopphy); nopphy->provider = of_phy_provider_register(dev, nop_usbphy_xlate); if (IS_ERR(nopphy->provider)) { ret = PTR_ERR(nopphy->provider); goto err_free; } return 0; err_free: free(nopphy); return ret; }; static __maybe_unused struct of_device_id nop_usbphy_dt_ids[] = { { .compatible = "usb-nop-xceiv", }, { /* sentinel */ }, }; static struct driver_d nop_usbphy_driver = { .name = "usb-nop-xceiv", .probe = nop_usbphy_probe, .of_compatible = DRV_OF_COMPAT(nop_usbphy_dt_ids), }; static int nop_usbphy_init(void) { return platform_driver_register(&nop_usbphy_driver); } fs_initcall(nop_usbphy_init);