14bc36fd3SMian Yousaf Kaukab /* 24bc36fd3SMian Yousaf Kaukab * Copyright (C) 2010 ST-Ericsson AB 34bc36fd3SMian Yousaf Kaukab * Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com> 44bc36fd3SMian Yousaf Kaukab * 54bc36fd3SMian Yousaf Kaukab * Based on omap2430.c 64bc36fd3SMian Yousaf Kaukab * 74bc36fd3SMian Yousaf Kaukab * This program is free software; you can redistribute it and/or modify 84bc36fd3SMian Yousaf Kaukab * it under the terms of the GNU General Public License as published by 94bc36fd3SMian Yousaf Kaukab * the Free Software Foundation; either version 2 of the License, or 104bc36fd3SMian Yousaf Kaukab * (at your option) any later version. 114bc36fd3SMian Yousaf Kaukab * 124bc36fd3SMian Yousaf Kaukab * This program is distributed in the hope that it will be useful, 134bc36fd3SMian Yousaf Kaukab * but WITHOUT ANY WARRANTY; without even the implied warranty of 144bc36fd3SMian Yousaf Kaukab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154bc36fd3SMian Yousaf Kaukab * GNU General Public License for more details. 164bc36fd3SMian Yousaf Kaukab * 174bc36fd3SMian Yousaf Kaukab * You should have received a copy of the GNU General Public License 184bc36fd3SMian Yousaf Kaukab * along with this program; if not, write to the Free Software 194bc36fd3SMian Yousaf Kaukab * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 204bc36fd3SMian Yousaf Kaukab */ 214bc36fd3SMian Yousaf Kaukab 224bc36fd3SMian Yousaf Kaukab #include <linux/module.h> 234bc36fd3SMian Yousaf Kaukab #include <linux/kernel.h> 244bc36fd3SMian Yousaf Kaukab #include <linux/init.h> 254bc36fd3SMian Yousaf Kaukab #include <linux/clk.h> 26ded017eeSKishon Vijay Abraham I #include <linux/err.h> 274bc36fd3SMian Yousaf Kaukab #include <linux/io.h> 284bc36fd3SMian Yousaf Kaukab #include <linux/platform_device.h> 294bc36fd3SMian Yousaf Kaukab 304bc36fd3SMian Yousaf Kaukab #include "musb_core.h" 314bc36fd3SMian Yousaf Kaukab 324bc36fd3SMian Yousaf Kaukab struct ux500_glue { 334bc36fd3SMian Yousaf Kaukab struct device *dev; 344bc36fd3SMian Yousaf Kaukab struct platform_device *musb; 354bc36fd3SMian Yousaf Kaukab struct clk *clk; 364bc36fd3SMian Yousaf Kaukab }; 374bc36fd3SMian Yousaf Kaukab #define glue_to_musb(g) platform_get_drvdata(g->musb) 384bc36fd3SMian Yousaf Kaukab 394bc36fd3SMian Yousaf Kaukab static int ux500_musb_init(struct musb *musb) 404bc36fd3SMian Yousaf Kaukab { 41662dca54SKishon Vijay Abraham I musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); 42ded017eeSKishon Vijay Abraham I if (IS_ERR_OR_NULL(musb->xceiv)) { 434bc36fd3SMian Yousaf Kaukab pr_err("HS USB OTG: no transceiver configured\n"); 444bc36fd3SMian Yousaf Kaukab return -ENODEV; 454bc36fd3SMian Yousaf Kaukab } 464bc36fd3SMian Yousaf Kaukab 474bc36fd3SMian Yousaf Kaukab return 0; 484bc36fd3SMian Yousaf Kaukab } 494bc36fd3SMian Yousaf Kaukab 504bc36fd3SMian Yousaf Kaukab static int ux500_musb_exit(struct musb *musb) 514bc36fd3SMian Yousaf Kaukab { 52721002ecSKishon Vijay Abraham I usb_put_phy(musb->xceiv); 534bc36fd3SMian Yousaf Kaukab 544bc36fd3SMian Yousaf Kaukab return 0; 554bc36fd3SMian Yousaf Kaukab } 564bc36fd3SMian Yousaf Kaukab 574bc36fd3SMian Yousaf Kaukab static const struct musb_platform_ops ux500_ops = { 584bc36fd3SMian Yousaf Kaukab .init = ux500_musb_init, 594bc36fd3SMian Yousaf Kaukab .exit = ux500_musb_exit, 604bc36fd3SMian Yousaf Kaukab }; 614bc36fd3SMian Yousaf Kaukab 62e9e8c85eSFelipe Balbi static int __devinit ux500_probe(struct platform_device *pdev) 634bc36fd3SMian Yousaf Kaukab { 644bc36fd3SMian Yousaf Kaukab struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; 654bc36fd3SMian Yousaf Kaukab struct platform_device *musb; 664bc36fd3SMian Yousaf Kaukab struct ux500_glue *glue; 674bc36fd3SMian Yousaf Kaukab struct clk *clk; 684bc36fd3SMian Yousaf Kaukab 694bc36fd3SMian Yousaf Kaukab int ret = -ENOMEM; 704bc36fd3SMian Yousaf Kaukab 714bc36fd3SMian Yousaf Kaukab glue = kzalloc(sizeof(*glue), GFP_KERNEL); 724bc36fd3SMian Yousaf Kaukab if (!glue) { 734bc36fd3SMian Yousaf Kaukab dev_err(&pdev->dev, "failed to allocate glue context\n"); 744bc36fd3SMian Yousaf Kaukab goto err0; 754bc36fd3SMian Yousaf Kaukab } 764bc36fd3SMian Yousaf Kaukab 7765b3d52dSB, Ravi /* get the musb id */ 7865b3d52dSB, Ravi musbid = musb_get_id(&pdev->dev, GFP_KERNEL); 7965b3d52dSB, Ravi if (musbid < 0) { 8065b3d52dSB, Ravi dev_err(&pdev->dev, "failed to allocate musb id\n"); 8165b3d52dSB, Ravi ret = -ENOMEM; 8265b3d52dSB, Ravi goto err1; 8365b3d52dSB, Ravi } 8465b3d52dSB, Ravi 8565b3d52dSB, Ravi musb = platform_device_alloc("musb-hdrc", musbid); 864bc36fd3SMian Yousaf Kaukab if (!musb) { 874bc36fd3SMian Yousaf Kaukab dev_err(&pdev->dev, "failed to allocate musb device\n"); 8865b3d52dSB, Ravi goto err2; 894bc36fd3SMian Yousaf Kaukab } 904bc36fd3SMian Yousaf Kaukab 914bc36fd3SMian Yousaf Kaukab clk = clk_get(&pdev->dev, "usb"); 924bc36fd3SMian Yousaf Kaukab if (IS_ERR(clk)) { 934bc36fd3SMian Yousaf Kaukab dev_err(&pdev->dev, "failed to get clock\n"); 944bc36fd3SMian Yousaf Kaukab ret = PTR_ERR(clk); 9565b3d52dSB, Ravi goto err3; 964bc36fd3SMian Yousaf Kaukab } 974bc36fd3SMian Yousaf Kaukab 984bc36fd3SMian Yousaf Kaukab ret = clk_enable(clk); 994bc36fd3SMian Yousaf Kaukab if (ret) { 1004bc36fd3SMian Yousaf Kaukab dev_err(&pdev->dev, "failed to enable clock\n"); 10165b3d52dSB, Ravi goto err4; 1024bc36fd3SMian Yousaf Kaukab } 1034bc36fd3SMian Yousaf Kaukab 10465b3d52dSB, Ravi musb->id = musbid; 1054bc36fd3SMian Yousaf Kaukab musb->dev.parent = &pdev->dev; 10687266064SMian Yousaf Kaukab musb->dev.dma_mask = pdev->dev.dma_mask; 10787266064SMian Yousaf Kaukab musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; 1084bc36fd3SMian Yousaf Kaukab 1094bc36fd3SMian Yousaf Kaukab glue->dev = &pdev->dev; 1104bc36fd3SMian Yousaf Kaukab glue->musb = musb; 1114bc36fd3SMian Yousaf Kaukab glue->clk = clk; 1124bc36fd3SMian Yousaf Kaukab 1134bc36fd3SMian Yousaf Kaukab pdata->platform_ops = &ux500_ops; 1144bc36fd3SMian Yousaf Kaukab 1154bc36fd3SMian Yousaf Kaukab platform_set_drvdata(pdev, glue); 1164bc36fd3SMian Yousaf Kaukab 1174bc36fd3SMian Yousaf Kaukab ret = platform_device_add_resources(musb, pdev->resource, 1184bc36fd3SMian Yousaf Kaukab pdev->num_resources); 1194bc36fd3SMian Yousaf Kaukab if (ret) { 1204bc36fd3SMian Yousaf Kaukab dev_err(&pdev->dev, "failed to add resources\n"); 12165b3d52dSB, Ravi goto err5; 1224bc36fd3SMian Yousaf Kaukab } 1234bc36fd3SMian Yousaf Kaukab 1244bc36fd3SMian Yousaf Kaukab ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); 1254bc36fd3SMian Yousaf Kaukab if (ret) { 1264bc36fd3SMian Yousaf Kaukab dev_err(&pdev->dev, "failed to add platform_data\n"); 12765b3d52dSB, Ravi goto err5; 1284bc36fd3SMian Yousaf Kaukab } 1294bc36fd3SMian Yousaf Kaukab 1304bc36fd3SMian Yousaf Kaukab ret = platform_device_add(musb); 1314bc36fd3SMian Yousaf Kaukab if (ret) { 1324bc36fd3SMian Yousaf Kaukab dev_err(&pdev->dev, "failed to register musb device\n"); 13365b3d52dSB, Ravi goto err5; 1344bc36fd3SMian Yousaf Kaukab } 1354bc36fd3SMian Yousaf Kaukab 1364bc36fd3SMian Yousaf Kaukab return 0; 1374bc36fd3SMian Yousaf Kaukab 13865b3d52dSB, Ravi err5: 1394bc36fd3SMian Yousaf Kaukab clk_disable(clk); 1404bc36fd3SMian Yousaf Kaukab 14165b3d52dSB, Ravi err4: 1424bc36fd3SMian Yousaf Kaukab clk_put(clk); 1434bc36fd3SMian Yousaf Kaukab 14465b3d52dSB, Ravi err3: 1454bc36fd3SMian Yousaf Kaukab platform_device_put(musb); 1464bc36fd3SMian Yousaf Kaukab 14765b3d52dSB, Ravi err2: 14865b3d52dSB, Ravi musb_put_id(&pdev->dev, musbid); 14965b3d52dSB, Ravi 1504bc36fd3SMian Yousaf Kaukab err1: 1514bc36fd3SMian Yousaf Kaukab kfree(glue); 1524bc36fd3SMian Yousaf Kaukab 1534bc36fd3SMian Yousaf Kaukab err0: 1544bc36fd3SMian Yousaf Kaukab return ret; 1554bc36fd3SMian Yousaf Kaukab } 1564bc36fd3SMian Yousaf Kaukab 157e9e8c85eSFelipe Balbi static int __devexit ux500_remove(struct platform_device *pdev) 1584bc36fd3SMian Yousaf Kaukab { 1594bc36fd3SMian Yousaf Kaukab struct ux500_glue *glue = platform_get_drvdata(pdev); 1604bc36fd3SMian Yousaf Kaukab 16165b3d52dSB, Ravi musb_put_id(&pdev->dev, glue->musb->id); 1624bc36fd3SMian Yousaf Kaukab platform_device_del(glue->musb); 1634bc36fd3SMian Yousaf Kaukab platform_device_put(glue->musb); 1644bc36fd3SMian Yousaf Kaukab clk_disable(glue->clk); 1654bc36fd3SMian Yousaf Kaukab clk_put(glue->clk); 1664bc36fd3SMian Yousaf Kaukab kfree(glue); 1674bc36fd3SMian Yousaf Kaukab 1684bc36fd3SMian Yousaf Kaukab return 0; 1694bc36fd3SMian Yousaf Kaukab } 1704bc36fd3SMian Yousaf Kaukab 1714bc36fd3SMian Yousaf Kaukab #ifdef CONFIG_PM 1724bc36fd3SMian Yousaf Kaukab static int ux500_suspend(struct device *dev) 1734bc36fd3SMian Yousaf Kaukab { 1744bc36fd3SMian Yousaf Kaukab struct ux500_glue *glue = dev_get_drvdata(dev); 1754bc36fd3SMian Yousaf Kaukab struct musb *musb = glue_to_musb(glue); 1764bc36fd3SMian Yousaf Kaukab 177b96d3b08SHeikki Krogerus usb_phy_set_suspend(musb->xceiv, 1); 1784bc36fd3SMian Yousaf Kaukab clk_disable(glue->clk); 1794bc36fd3SMian Yousaf Kaukab 1804bc36fd3SMian Yousaf Kaukab return 0; 1814bc36fd3SMian Yousaf Kaukab } 1824bc36fd3SMian Yousaf Kaukab 1834bc36fd3SMian Yousaf Kaukab static int ux500_resume(struct device *dev) 1844bc36fd3SMian Yousaf Kaukab { 1854bc36fd3SMian Yousaf Kaukab struct ux500_glue *glue = dev_get_drvdata(dev); 1864bc36fd3SMian Yousaf Kaukab struct musb *musb = glue_to_musb(glue); 1874bc36fd3SMian Yousaf Kaukab int ret; 1884bc36fd3SMian Yousaf Kaukab 1894bc36fd3SMian Yousaf Kaukab ret = clk_enable(glue->clk); 1904bc36fd3SMian Yousaf Kaukab if (ret) { 1914bc36fd3SMian Yousaf Kaukab dev_err(dev, "failed to enable clock\n"); 1924bc36fd3SMian Yousaf Kaukab return ret; 1934bc36fd3SMian Yousaf Kaukab } 1944bc36fd3SMian Yousaf Kaukab 195b96d3b08SHeikki Krogerus usb_phy_set_suspend(musb->xceiv, 0); 1964bc36fd3SMian Yousaf Kaukab 1974bc36fd3SMian Yousaf Kaukab return 0; 1984bc36fd3SMian Yousaf Kaukab } 1994bc36fd3SMian Yousaf Kaukab 2004bc36fd3SMian Yousaf Kaukab static const struct dev_pm_ops ux500_pm_ops = { 2014bc36fd3SMian Yousaf Kaukab .suspend = ux500_suspend, 2024bc36fd3SMian Yousaf Kaukab .resume = ux500_resume, 2034bc36fd3SMian Yousaf Kaukab }; 2044bc36fd3SMian Yousaf Kaukab 2054bc36fd3SMian Yousaf Kaukab #define DEV_PM_OPS (&ux500_pm_ops) 2064bc36fd3SMian Yousaf Kaukab #else 2074bc36fd3SMian Yousaf Kaukab #define DEV_PM_OPS NULL 2084bc36fd3SMian Yousaf Kaukab #endif 2094bc36fd3SMian Yousaf Kaukab 2104bc36fd3SMian Yousaf Kaukab static struct platform_driver ux500_driver = { 211e9e8c85eSFelipe Balbi .probe = ux500_probe, 212e9e8c85eSFelipe Balbi .remove = __devexit_p(ux500_remove), 2134bc36fd3SMian Yousaf Kaukab .driver = { 2144bc36fd3SMian Yousaf Kaukab .name = "musb-ux500", 2154bc36fd3SMian Yousaf Kaukab .pm = DEV_PM_OPS, 2164bc36fd3SMian Yousaf Kaukab }, 2174bc36fd3SMian Yousaf Kaukab }; 2184bc36fd3SMian Yousaf Kaukab 2194bc36fd3SMian Yousaf Kaukab MODULE_DESCRIPTION("UX500 MUSB Glue Layer"); 2204bc36fd3SMian Yousaf Kaukab MODULE_AUTHOR("Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>"); 2214bc36fd3SMian Yousaf Kaukab MODULE_LICENSE("GPL v2"); 2224bc36fd3SMian Yousaf Kaukab 2234bc36fd3SMian Yousaf Kaukab static int __init ux500_init(void) 2244bc36fd3SMian Yousaf Kaukab { 225e9e8c85eSFelipe Balbi return platform_driver_register(&ux500_driver); 2264bc36fd3SMian Yousaf Kaukab } 227e9e8c85eSFelipe Balbi module_init(ux500_init); 2284bc36fd3SMian Yousaf Kaukab 2294bc36fd3SMian Yousaf Kaukab static void __exit ux500_exit(void) 2304bc36fd3SMian Yousaf Kaukab { 2314bc36fd3SMian Yousaf Kaukab platform_driver_unregister(&ux500_driver); 2324bc36fd3SMian Yousaf Kaukab } 2334bc36fd3SMian Yousaf Kaukab module_exit(ux500_exit); 234