Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.8.
  1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
  2 *
  3 * This program is free software; you can redistribute it and/or modify
  4 * it under the terms of the GNU General Public License version 2 and
  5 * only version 2 as published by the Free Software Foundation.
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/platform_device.h>
 10#include <linux/pm_runtime.h>
 11#include <linux/usb/msm_hsusb_hw.h>
 12#include <linux/usb/ulpi.h>
 13#include <linux/usb/gadget.h>
 14#include <linux/usb/chipidea.h>
 15
 16#include "ci.h"
 17
 18#define MSM_USB_BASE	(udc->hw_bank.abs)
 19
 20static void ci13xxx_msm_notify_event(struct ci13xxx *udc, unsigned event)
 21{
 22	struct device *dev = udc->gadget.dev.parent;
 23	int val;
 24
 25	switch (event) {
 26	case CI13XXX_CONTROLLER_RESET_EVENT:
 27		dev_dbg(dev, "CI13XXX_CONTROLLER_RESET_EVENT received\n");
 28		writel(0, USB_AHBBURST);
 29		writel(0, USB_AHBMODE);
 30		break;
 31	case CI13XXX_CONTROLLER_STOPPED_EVENT:
 32		dev_dbg(dev, "CI13XXX_CONTROLLER_STOPPED_EVENT received\n");
 33		/*
 34		 * Put the transceiver in non-driving mode. Otherwise host
 35		 * may not detect soft-disconnection.
 36		 */
 37		val = usb_phy_io_read(udc->transceiver, ULPI_FUNC_CTRL);
 38		val &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
 39		val |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
 40		usb_phy_io_write(udc->transceiver, val, ULPI_FUNC_CTRL);
 41		break;
 42	default:
 43		dev_dbg(dev, "unknown ci13xxx_udc event\n");
 44		break;
 45	}
 46}
 47
 48static struct ci13xxx_udc_driver ci13xxx_msm_udc_driver = {
 49	.name			= "ci13xxx_msm",
 50	.flags			= CI13XXX_REGS_SHARED |
 51				  CI13XXX_REQUIRE_TRANSCEIVER |
 52				  CI13XXX_PULLUP_ON_VBUS |
 53				  CI13XXX_DISABLE_STREAMING,
 54
 55	.notify_event		= ci13xxx_msm_notify_event,
 56};
 57
 58static int ci13xxx_msm_probe(struct platform_device *pdev)
 59{
 60	struct platform_device *plat_ci;
 61	int ret;
 62
 63	dev_dbg(&pdev->dev, "ci13xxx_msm_probe\n");
 64
 65	plat_ci = platform_device_alloc("ci_hdrc", -1);
 66	if (!plat_ci) {
 67		dev_err(&pdev->dev, "can't allocate ci_hdrc platform device\n");
 68		return -ENOMEM;
 69	}
 70
 71	ret = platform_device_add_resources(plat_ci, pdev->resource,
 72					    pdev->num_resources);
 73	if (ret) {
 74		dev_err(&pdev->dev, "can't add resources to platform device\n");
 75		goto put_platform;
 76	}
 77
 78	ret = platform_device_add_data(plat_ci, &ci13xxx_msm_udc_driver,
 79				       sizeof(ci13xxx_msm_udc_driver));
 80	if (ret)
 81		goto put_platform;
 82
 83	ret = platform_device_add(plat_ci);
 84	if (ret)
 85		goto put_platform;
 86
 87	pm_runtime_no_callbacks(&pdev->dev);
 88	pm_runtime_enable(&pdev->dev);
 89
 90	return 0;
 91
 92put_platform:
 93	platform_device_put(plat_ci);
 94
 95	return ret;
 96}
 97
 98static struct platform_driver ci13xxx_msm_driver = {
 99	.probe = ci13xxx_msm_probe,
100	.driver = { .name = "msm_hsusb", },
101};
102MODULE_ALIAS("platform:msm_hsusb");
103
104static int __init ci13xxx_msm_init(void)
105{
106	return platform_driver_register(&ci13xxx_msm_driver);
107}
108module_init(ci13xxx_msm_init);
109
110MODULE_LICENSE("GPL v2");