1 /* 2 * Copyright (C) 2010 ST-Ericsson AB 3 * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> 4 * 5 * Based on omap2430.c 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20 */ 21 22 #include <linux/module.h> 23 #include <linux/kernel.h> 24 #include <linux/init.h> 25 #include <linux/clk.h> 26 #include <linux/io.h> 27 #include <linux/platform_device.h> 28 29 #include "musb_core.h" 30 31 struct ux500_glue { 32 struct device *dev; 33 struct platform_device *musb; 34 struct clk *clk; 35 }; 36 #define glue_to_musb(g) platform_get_drvdata(g->musb) 37 38 static int ux500_musb_init(struct musb *musb) 39 { 40 musb->xceiv = usb_get_transceiver(); 41 if (!musb->xceiv) { 42 pr_err("HS USB OTG: no transceiver configured\n"); 43 return -ENODEV; 44 } 45 46 return 0; 47 } 48 49 static int ux500_musb_exit(struct musb *musb) 50 { 51 usb_put_transceiver(musb->xceiv); 52 53 return 0; 54 } 55 56 static const struct musb_platform_ops ux500_ops = { 57 .init = ux500_musb_init, 58 .exit = ux500_musb_exit, 59 }; 60 61 static int __devinit ux500_probe(struct platform_device *pdev) 62 { 63 struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; 64 struct platform_device *musb; 65 struct ux500_glue *glue; 66 struct clk *clk; 67 68 int ret = -ENOMEM; 69 70 glue = kzalloc(sizeof(*glue), GFP_KERNEL); 71 if (!glue) { 72 dev_err(&pdev->dev, "failed to allocate glue context\n"); 73 goto err0; 74 } 75 76 musb = platform_device_alloc("musb-hdrc", -1); 77 if (!musb) { 78 dev_err(&pdev->dev, "failed to allocate musb device\n"); 79 goto err1; 80 } 81 82 clk = clk_get(&pdev->dev, "usb"); 83 if (IS_ERR(clk)) { 84 dev_err(&pdev->dev, "failed to get clock\n"); 85 ret = PTR_ERR(clk); 86 goto err2; 87 } 88 89 ret = clk_enable(clk); 90 if (ret) { 91 dev_err(&pdev->dev, "failed to enable clock\n"); 92 goto err3; 93 } 94 95 musb->dev.parent = &pdev->dev; 96 musb->dev.dma_mask = pdev->dev.dma_mask; 97 musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; 98 99 glue->dev = &pdev->dev; 100 glue->musb = musb; 101 glue->clk = clk; 102 103 pdata->platform_ops = &ux500_ops; 104 105 platform_set_drvdata(pdev, glue); 106 107 ret = platform_device_add_resources(musb, pdev->resource, 108 pdev->num_resources); 109 if (ret) { 110 dev_err(&pdev->dev, "failed to add resources\n"); 111 goto err4; 112 } 113 114 ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); 115 if (ret) { 116 dev_err(&pdev->dev, "failed to add platform_data\n"); 117 goto err4; 118 } 119 120 ret = platform_device_add(musb); 121 if (ret) { 122 dev_err(&pdev->dev, "failed to register musb device\n"); 123 goto err4; 124 } 125 126 return 0; 127 128 err4: 129 clk_disable(clk); 130 131 err3: 132 clk_put(clk); 133 134 err2: 135 platform_device_put(musb); 136 137 err1: 138 kfree(glue); 139 140 err0: 141 return ret; 142 } 143 144 static int __devexit ux500_remove(struct platform_device *pdev) 145 { 146 struct ux500_glue *glue = platform_get_drvdata(pdev); 147 148 platform_device_del(glue->musb); 149 platform_device_put(glue->musb); 150 clk_disable(glue->clk); 151 clk_put(glue->clk); 152 kfree(glue); 153 154 return 0; 155 } 156 157 #ifdef CONFIG_PM 158 static int ux500_suspend(struct device *dev) 159 { 160 struct ux500_glue *glue = dev_get_drvdata(dev); 161 struct musb *musb = glue_to_musb(glue); 162 163 usb_phy_set_suspend(musb->xceiv, 1); 164 clk_disable(glue->clk); 165 166 return 0; 167 } 168 169 static int ux500_resume(struct device *dev) 170 { 171 struct ux500_glue *glue = dev_get_drvdata(dev); 172 struct musb *musb = glue_to_musb(glue); 173 int ret; 174 175 ret = clk_enable(glue->clk); 176 if (ret) { 177 dev_err(dev, "failed to enable clock\n"); 178 return ret; 179 } 180 181 usb_phy_set_suspend(musb->xceiv, 0); 182 183 return 0; 184 } 185 186 static const struct dev_pm_ops ux500_pm_ops = { 187 .suspend = ux500_suspend, 188 .resume = ux500_resume, 189 }; 190 191 #define DEV_PM_OPS (&ux500_pm_ops) 192 #else 193 #define DEV_PM_OPS NULL 194 #endif 195 196 static struct platform_driver ux500_driver = { 197 .probe = ux500_probe, 198 .remove = __devexit_p(ux500_remove), 199 .driver = { 200 .name = "musb-ux500", 201 .pm = DEV_PM_OPS, 202 }, 203 }; 204 205 MODULE_DESCRIPTION("UX500 MUSB Glue Layer"); 206 MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>"); 207 MODULE_LICENSE("GPL v2"); 208 209 static int __init ux500_init(void) 210 { 211 return platform_driver_register(&ux500_driver); 212 } 213 module_init(ux500_init); 214 215 static void __exit ux500_exit(void) 216 { 217 platform_driver_unregister(&ux500_driver); 218 } 219 module_exit(ux500_exit); 220