/* * OMAP OTG controller driver * * Based on code from tahvo-usb.c and isp1301_omap.c drivers. * * Copyright (C) 2005-2006 Nokia Corporation * Copyright (C) 2004 Texas Instruments * Copyright (C) 2004 David Brownell * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this * archive for more details. * * 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 struct otg_device { void __iomem *base; bool id; bool vbus; struct extcon_dev *extcon; struct notifier_block vbus_nb; struct notifier_block id_nb; }; #define OMAP_OTG_CTRL 0x0c #define OMAP_OTG_ASESSVLD (1 << 20) #define OMAP_OTG_BSESSEND (1 << 19) #define OMAP_OTG_BSESSVLD (1 << 18) #define OMAP_OTG_VBUSVLD (1 << 17) #define OMAP_OTG_ID (1 << 16) #define OMAP_OTG_XCEIV_OUTPUTS \ (OMAP_OTG_ASESSVLD | OMAP_OTG_BSESSEND | OMAP_OTG_BSESSVLD | \ OMAP_OTG_VBUSVLD | OMAP_OTG_ID) static void omap_otg_ctrl(struct otg_device *otg_dev, u32 outputs) { u32 l; l = readl(otg_dev->base + OMAP_OTG_CTRL); l &= ~OMAP_OTG_XCEIV_OUTPUTS; l |= outputs; writel(l, otg_dev->base + OMAP_OTG_CTRL); } static void omap_otg_set_mode(struct otg_device *otg_dev) { if (!otg_dev->id && otg_dev->vbus) /* Set B-session valid. */ omap_otg_ctrl(otg_dev, OMAP_OTG_ID | OMAP_OTG_BSESSVLD); else if (otg_dev->vbus) /* Set A-session valid. */ omap_otg_ctrl(otg_dev, OMAP_OTG_ASESSVLD); else if (!otg_dev->id) /* Set B-session end to indicate no VBUS. */ omap_otg_ctrl(otg_dev, OMAP_OTG_ID | OMAP_OTG_BSESSEND); } static int omap_otg_id_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { struct otg_device *otg_dev = container_of(nb, struct otg_device, id_nb); otg_dev->id = event; omap_otg_set_mode(otg_dev); return NOTIFY_DONE; } static int omap_otg_vbus_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { struct otg_device *otg_dev = container_of(nb, struct otg_device, vbus_nb); otg_dev->vbus = event; omap_otg_set_mode(otg_dev); return NOTIFY_DONE; } static int omap_otg_probe(struct platform_device *pdev) { const struct omap_usb_config *config = pdev->dev.platform_data; struct otg_device *otg_dev; struct extcon_dev *extcon; int ret; u32 rev; if (!config || !config->extcon) return -ENODEV; extcon = extcon_get_extcon_dev(config->extcon); if (!extcon) return -EPROBE_DEFER; otg_dev = devm_kzalloc(&pdev->dev, sizeof(*otg_dev), GFP_KERNEL); if (!otg_dev) return -ENOMEM; otg_dev->base = devm_ioremap_resource(&pdev->dev, &pdev->resource[0]); if (IS_ERR(otg_dev->base)) return PTR_ERR(otg_dev->base); otg_dev->extcon = extcon; otg_dev->id_nb.notifier_call = omap_otg_id_notifier; otg_dev->vbus_nb.notifier_call = omap_otg_vbus_notifier; ret = extcon_register_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb); if (ret) return ret; ret = extcon_register_notifier(extcon, EXTCON_USB, &otg_dev->vbus_nb); if (ret) { extcon_unregister_notifier(extcon, EXTCON_USB_HOST, &otg_dev->id_nb); return ret; } otg_dev->id = extcon_get_cable_state_(extcon, EXTCON_USB_HOST); otg_dev->vbus = extcon_get_cable_state_(extcon, EXTCON_USB); omap_otg_set_mode(otg_dev); rev = readl(otg_dev->base); dev_info(&pdev->dev, "OMAP USB OTG controller rev %d.%d (%s, id=%d, vbus=%d)\n", (rev >> 4) & 0xf, rev & 0xf, config->extcon, otg_dev->id, otg_dev->vbus); platform_set_drvdata(pdev, otg_dev); return 0; } static int omap_otg_remove(struct platform_device *pdev) { struct otg_device *otg_dev = platform_get_drvdata(pdev); struct extcon_dev *edev = otg_dev->extcon; extcon_unregister_notifier(edev, EXTCON_USB_HOST, &otg_dev->id_nb); extcon_unregister_notifier(edev, EXTCON_USB, &otg_dev->vbus_nb); return 0; } static struct platform_driver omap_otg_driver = { .probe = omap_otg_probe, .remove = omap_otg_remove, .driver = { .name = "omap_otg", }, }; module_platform_driver(omap_otg_driver); MODULE_DESCRIPTION("OMAP USB OTG controller driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Aaro Koskinen "); nput type='submit' value='reload'/>
authorLinus Torvalds <torvalds@linux-foundation.org>2017-01-05 10:32:16 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2017-01-05 10:32:16 -0800
commitb40079273279999d0a259e78d9ecb53ad82d042f (patch)
tree62e15c30dc3787493f9bce847cda7eae99aae781 /net/tipc
parent383378d115ab6e702d77896071d36056875602db (diff)
parent1b9ec81258827001c869f003e0b8dd2ddc104717 (diff)
Merge tag 'armsoc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC fixes from Arnd Bergmann: "This is a rather large set of bugfixes, as we just returned from the Christmas break. Most of these are relatively unimportant fixes for regressions introduced during the merge window, and about half of the changes are for mach-omap2. A couple of patches are just cleanups and dead code removal that I would not normally have considered for merging after -rc2, but I decided to take them along with the fixes this time. Notable fixes include: - removing the skeleton.dtsi include broke a number of machines, and we have to put empty /chosen nodes back to be able to pass kernel command lines as before - enabling Samsung platforms no longer hardwires CONFIG_HZ to 200, as it had been for no good reason for a long time" * tag 'armsoc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (46 commits) MAINTAINERS: extend PSCI entry to cover the newly add PSCI checker code drivers: psci: annotate timer on stack to silence odebug messages ARM64: defconfig: enable DRM_MESON as module ARM64: dts: meson-gx: Add Graphic Controller nodes ARM64: dts: meson-gxl: fix GPIO include ARM: dts: imx6: Disable "weim" node in the dtsi files ARM: dts: qcom: apq8064: Add missing scm clock ARM: davinci: da8xx: Fix sleeping function called from invalid context ARM: davinci: Make __clk_{enable,disable} functions public ARM: davinci: da850: don't add emac clock to lookup table twice ARM: davinci: da850: fix infinite loop in clk_set_rate() ARM: i.MX: remove map_io callback ARM: dts: vf610-zii-dev-rev-b: Add missing newline ARM: dts: imx6qdl-nitrogen6x: remove duplicate iomux entry ARM: dts: imx31: fix AVIC base address ARM: dts: am572x-idk: Add gpios property to control PCIE_RESETn arm64: dts: vexpress: Support GICC_DIR operations ARM: dts: vexpress: Support GICC_DIR operations firmware: arm_scpi: fix reading sensor values on pre-1.0 SCPI firmwares arm64: dts: msm8996: Add required memory carveouts ...
Diffstat (limited to 'net/tipc')