1/* 2 * drivers/usb/otg/nop-usb-xceiv.c 3 * 4 * NOP USB transceiver for all USB transceiver which are either built-in 5 * into USB IP or which are mostly autonomous. 6 * 7 * Copyright (C) 2009 Texas Instruments Inc 8 * Author: Ajay Kumar Gupta <ajay.gupta@ti.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 * 24 * Current status: 25 * This provides a "nop" transceiver for PHYs which are 26 * autonomous such as isp1504, isp1707, etc. 27 */ 28 29#include <linux/module.h> 30#include <linux/platform_device.h> 31#include <linux/dma-mapping.h> 32#include <linux/usb/otg.h> 33#include <linux/slab.h> 34 35struct nop_usb_xceiv { 36 struct otg_transceiver otg; 37 struct device *dev; 38}; 39 40static struct platform_device *pd; 41 42void usb_nop_xceiv_register(void) 43{ 44 if (pd) 45 return; 46 pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0); 47 if (!pd) { 48 printk(KERN_ERR "Unable to register usb nop transceiver\n"); 49 return; 50 } 51} 52EXPORT_SYMBOL(usb_nop_xceiv_register); 53 54void usb_nop_xceiv_unregister(void) 55{ 56 platform_device_unregister(pd); 57 pd = NULL; 58} 59EXPORT_SYMBOL(usb_nop_xceiv_unregister); 60 61static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) 62{ 63 return container_of(x, struct nop_usb_xceiv, otg); 64} 65 66static int nop_set_suspend(struct otg_transceiver *x, int suspend) 67{ 68 return 0; 69} 70 71static int nop_set_peripheral(struct otg_transceiver *x, 72 struct usb_gadget *gadget) 73{ 74 struct nop_usb_xceiv *nop; 75 76 if (!x) 77 return -ENODEV; 78 79 nop = xceiv_to_nop(x); 80 81 if (!gadget) { 82 nop->otg.gadget = NULL; 83 return -ENODEV; 84 } 85 86 nop->otg.gadget = gadget; 87 nop->otg.state = OTG_STATE_B_IDLE; 88 return 0; 89} 90 91static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) 92{ 93 struct nop_usb_xceiv *nop; 94 95 if (!x) 96 return -ENODEV; 97 98 nop = xceiv_to_nop(x); 99 100 if (!host) { 101 nop->otg.host = NULL; 102 return -ENODEV; 103 } 104 105 nop->otg.host = host; 106 return 0; 107} 108 109static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) 110{ 111 struct nop_usb_xceiv *nop; 112 int err; 113 114 nop = kzalloc(sizeof *nop, GFP_KERNEL); 115 if (!nop) 116 return -ENOMEM; 117 118 nop->dev = &pdev->dev; 119 nop->otg.dev = nop->dev; 120 nop->otg.label = "nop-xceiv"; 121 nop->otg.state = OTG_STATE_UNDEFINED; 122 nop->otg.set_host = nop_set_host; 123 nop->otg.set_peripheral = nop_set_peripheral; 124 nop->otg.set_suspend = nop_set_suspend; 125 126 err = otg_set_transceiver(&nop->otg); 127 if (err) { 128 dev_err(&pdev->dev, "can't register transceiver, err: %d\n", 129 err); 130 goto exit; 131 } 132 133 platform_set_drvdata(pdev, nop); 134 135 return 0; 136exit: 137 kfree(nop); 138 return err; 139} 140 141static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) 142{ 143 struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); 144 145 otg_set_transceiver(NULL); 146 147 platform_set_drvdata(pdev, NULL); 148 kfree(nop); 149 150 return 0; 151} 152 153static struct platform_driver nop_usb_xceiv_driver = { 154 .probe = nop_usb_xceiv_probe, 155 .remove = __devexit_p(nop_usb_xceiv_remove), 156 .driver = { 157 .name = "nop_usb_xceiv", 158 .owner = THIS_MODULE, 159 }, 160}; 161 162static int __init nop_usb_xceiv_init(void) 163{ 164 return platform_driver_register(&nop_usb_xceiv_driver); 165} 166subsys_initcall(nop_usb_xceiv_init); 167 168static void __exit nop_usb_xceiv_exit(void) 169{ 170 platform_driver_unregister(&nop_usb_xceiv_driver); 171} 172module_exit(nop_usb_xceiv_exit); 173 174MODULE_ALIAS("platform:nop_usb_xceiv"); 175MODULE_AUTHOR("Texas Instruments Inc"); 176MODULE_DESCRIPTION("NOP USB Transceiver driver"); 177MODULE_LICENSE("GPL"); 178