From patchwork Sun Feb 23 18:00:58 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Barinov X-Patchwork-Id: 3704571 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id AEFC7BF13A for ; Sun, 23 Feb 2014 18:02:16 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id A81F520115 for ; Sun, 23 Feb 2014 18:02:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 7940F2012E for ; Sun, 23 Feb 2014 18:02:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752001AbaBWSCN (ORCPT ); Sun, 23 Feb 2014 13:02:13 -0500 Received: from mail-la0-f53.google.com ([209.85.215.53]:54578 "EHLO mail-la0-f53.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751608AbaBWSBI (ORCPT ); Sun, 23 Feb 2014 13:01:08 -0500 Received: by mail-la0-f53.google.com with SMTP id e16so4538984lan.12 for ; Sun, 23 Feb 2014 10:01:06 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=XB9suqOQ1kInmEBmnZFWzgAoa77I5A5EEWPDcFrMx4U=; b=hL1ESgfLuSfsLZCZZMeHlGYQaJN7QIaozjBSYTi54/rRxneTISoSteM8/Q5YyHeI20 BnniclbJlnpszgL+4ogaWE7d5CPyMqkG/EB54YvZZxG3MODP2YfJBZNxiBhM+J3kbXA0 70e5WOO2EuQImok2BnWIzN+YDt1r/wANkgFRMmATAXEX45LTcR/M7fn4sj5JVCHWIeYC 6/V8NZJAWV/ggKRRtP8rsfRTSkpjcckcc7WWtkkPX5QTgpyMDtZTbBeZDJXJLSz5oKjs FOGqWHS4Jiqvooxum50y4OdE/uCIkJe+Y2a2GUK+bJY6dR4JdbQuknqnPjatW40sCvxe 6Jgg== X-Gm-Message-State: ALoCoQnQ4TbH79UpfyCsodBnQwJMMLAyUe/J6kQ+AbtJLxEw1hakwR7GTucjl5YJ4qSElOMKUm7B X-Received: by 10.152.242.165 with SMTP id wr5mr9842842lac.47.1393178466348; Sun, 23 Feb 2014 10:01:06 -0800 (PST) Received: from localhost.localdomain ([46.32.73.80]) by mx.google.com with ESMTPSA id yq2sm21602112lab.3.2014.02.23.10.01.05 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 23 Feb 2014 10:01:05 -0800 (PST) From: To: Cc: , linux-gpio@vger.kernel.org, , , , , , Subject: [PATCH V4 3/4] ARM: shmobile: koelsch: Add USBHS and internal PCI USB support Date: Sun, 23 Feb 2014 22:00:58 +0400 Message-Id: <1393178459-14637-4-git-send-email-vladimir.barinov@cogentembedded.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1393178459-14637-1-git-send-email-vladimir.barinov@cogentembedded.com> References: <1393178459-14637-1-git-send-email-vladimir.barinov@cogentembedded.com> Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-7.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Vladimir Barinov This adds the following to R-Car M2 Koelsch board: - USBHS PHY - USBHS device - internal PCI USB host devices Depending on state of ID pin from MAX3355E chip the usb0 is configured ether as host or gadget. In case of gadget the USBHS device is registered. In case of host the PCI USB is registered. The USB phy is bound to either USB host or USBHS device respectively, hence configured to ether channel 0 or 2. The USBHS can act as USB Host, and this can be easily configured. But the simplest test with storage stick connected to USBHS Host provides IP resets and system hangs. Even the PWEN pin is not handled and it is nessasary to provide VBUS using gpio. It is easy to see in RCAR H2/M2 documentation that the USBHS IP changed. F.e. the PWEN/EXTLP pins are no more presented in USBHS via DVSTCTR register. And others. Since the USBHS is not stable in Host mode lets connect fully tested PCI USB IP to usb0. Signed-off-by: Valentine Barshak Signed-off-by: Vladimir Barinov Changes in V4: * folded USBHS and internal PCI USB related patches together * added handling of ID pin from MAX3355E chip * removed ifdefs Changes in V3: * fixed a typo in the log message; * fixed the USB1 device name in the pinmux table. Changes in V2: * capitalized ARM in the subject; * rebased on top the latest devel tag; * added pipe_type array to the usbhs platform info since it differs from the default. * capitalized ARM in the subject; * rebased on top the latest devel tag. --- arch/arm/mach-shmobile/board-koelsch.c | 183 +++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) -- To unsubscribe from this list: send the line "unsubscribe linux-sh" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Index: build/arch/arm/mach-shmobile/board-koelsch.c =================================================================== --- build.orig/arch/arm/mach-shmobile/board-koelsch.c 2014-02-23 21:47:44.510571967 +0400 +++ build/arch/arm/mach-shmobile/board-koelsch.c 2014-02-23 21:47:59.358571662 +0400 @@ -36,12 +36,15 @@ #include #include #include +#include #include #include #include #include #include #include +#include +#include #include #include #include @@ -367,6 +370,177 @@ DEFINE_RES_IRQ(gic_spi(168)), }; +/* USBHS */ +static const struct resource usbhs_resources[] __initconst = { + DEFINE_RES_MEM(0xe6590000, 0x100), + DEFINE_RES_IRQ(gic_spi(107)), +}; + +struct usbhs_private { + struct renesas_usbhs_platform_info info; + struct usb_phy *phy; +}; + +#define usbhs_get_priv(pdev) \ + container_of(renesas_usbhs_get_info(pdev), struct usbhs_private, info) + +static int usbhs_power_ctrl(struct platform_device *pdev, + void __iomem *base, int enable) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + if (!priv->phy) + return -ENODEV; + + if (enable) { + int retval = usb_phy_init(priv->phy); + + if (!retval) + retval = usb_phy_set_suspend(priv->phy, 0); + return retval; + } + + usb_phy_set_suspend(priv->phy, 1); + usb_phy_shutdown(priv->phy); + return 0; +} + +static int usbhs_hardware_init(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + struct usb_phy *phy; + + phy = usb_get_phy_dev(&pdev->dev, 0); + if (IS_ERR(phy)) + return PTR_ERR(phy); + + priv->phy = phy; + return 0; +} + +static int usbhs_hardware_exit(struct platform_device *pdev) +{ + struct usbhs_private *priv = usbhs_get_priv(pdev); + + if (!priv->phy) + return 0; + + usb_put_phy(priv->phy); + priv->phy = NULL; + return 0; +} + +static int usbhs_get_id(struct platform_device *pdev) +{ + return USBHS_GADGET; +} + +static u32 koelsch_usbhs_pipe_type[] = { + USB_ENDPOINT_XFER_CONTROL, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_ISOC, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_INT, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, + USB_ENDPOINT_XFER_BULK, +}; + +static struct usbhs_private usbhs_priv __initdata = { + .info = { + .platform_callback = { + .power_ctrl = usbhs_power_ctrl, + .hardware_init = usbhs_hardware_init, + .hardware_exit = usbhs_hardware_exit, + .get_id = usbhs_get_id, + }, + .driver_param = { + .buswait_bwait = 4, + .pipe_type = koelsch_usbhs_pipe_type, + .pipe_size = ARRAY_SIZE(koelsch_usbhs_pipe_type), + }, + } +}; + +static void __init koelsch_add_usb0_gadget(void) +{ + usb_bind_phy("renesas_usbhs", 0, "usb_phy_rcar_gen2"); + platform_device_register_resndata(&platform_bus, + "renesas_usbhs", -1, + usbhs_resources, + ARRAY_SIZE(usbhs_resources), + &usbhs_priv.info, + sizeof(usbhs_priv.info)); +} + +/* Internal PCI0 */ +static const struct resource pci0_resources[] __initconst = { + DEFINE_RES_MEM(0xee090000, 0x10000), /* CFG */ + DEFINE_RES_MEM(0xee080000, 0x10000), /* MEM */ + DEFINE_RES_IRQ(gic_spi(108)), +}; + +static void __init koelsch_add_usb0_host(void) +{ + usb_bind_phy("0000:00:01.0", 0, "usb_phy_rcar_gen2"); + usb_bind_phy("0000:00:02.0", 0, "usb_phy_rcar_gen2"); + platform_device_register_simple("pci-rcar-gen2", + 0, pci0_resources, + ARRAY_SIZE(pci0_resources)); +} + +/* Internal PCI1 */ +static const struct resource pci1_resources[] __initconst = { + DEFINE_RES_MEM(0xee0d0000, 0x10000), /* CFG */ + DEFINE_RES_MEM(0xee0c0000, 0x10000), /* MEM */ + DEFINE_RES_IRQ(gic_spi(113)), +}; + +static void __init koelsch_add_usb1_host(void) +{ + platform_device_register_simple("pci-rcar-gen2", + 1, pci1_resources, + ARRAY_SIZE(pci1_resources)); +} + +/* USBHS PHY */ +static struct rcar_gen2_phy_platform_data usbhs_phy_pdata = { + .chan2_pci = 1, /* Channel 2 is PCI USB host */ +}; + +static const struct resource usbhs_phy_resources[] __initconst = { + DEFINE_RES_MEM(0xe6590100, 0x100), +}; + +/* Add all available USB devices */ +static void __init koelsch_add_usb_devices(void) +{ + /* MAX3355E ID pin */ + gpio_request_one(RCAR_GP_PIN(5, 31), GPIOF_IN, NULL); + if (!gpio_get_value(RCAR_GP_PIN(5, 31))) { + usbhs_phy_pdata.chan0_pci = 1; /* Channel 0 is PCI USB host */ + koelsch_add_usb0_host(); + } else { + usbhs_phy_pdata.chan0_pci = 0; /* Channel 0 is USBHS */ + koelsch_add_usb0_gadget(); + } + + platform_device_register_resndata(&platform_bus, "usb_phy_rcar_gen2", + -1, usbhs_phy_resources, + ARRAY_SIZE(usbhs_phy_resources), + &usbhs_phy_pdata, + sizeof(usbhs_phy_pdata)); + koelsch_add_usb1_host(); +} + static const struct pinctrl_map koelsch_pinctrl_map[] = { /* DU */ PIN_MAP_MUX_GROUP_DEFAULT("rcar-du-r8a7791", "pfc-r8a7791", @@ -429,6 +603,14 @@ "sdhi2_ctrl", "sdhi2"), PIN_MAP_MUX_GROUP_DEFAULT("sh_mobile_sdhi.2", "pfc-r8a7791", "sdhi2_cd", "sdhi2"), + /* USB0 */ + PIN_MAP_MUX_GROUP_DEFAULT("renesas_usbhs", "pfc-r8a7791", + "usb0", "usb0"), + PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.0", "pfc-r8a7791", + "usb0", "usb0"), + /* USB1 */ + PIN_MAP_MUX_GROUP_DEFAULT("pci-rcar-gen2.1", "pfc-r8a7791", + "usb1", "usb1"), }; static void __init koelsch_add_standard_devices(void) @@ -485,6 +667,7 @@ sdhi2_resources, ARRAY_SIZE(sdhi2_resources), &sdhi2_info, sizeof(struct sh_mobile_sdhi_info)); + koelsch_add_usb_devices(); } /*