From patchwork Tue Mar 28 16:03:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrice CHOTARD X-Patchwork-Id: 744392 X-Patchwork-Delegate: marek.vasut@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3vswlW3T3Vz9s3s for ; Wed, 29 Mar 2017 03:07:35 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 29C73C21C3E; Tue, 28 Mar 2017 16:04:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 6C5FEC21C52; Tue, 28 Mar 2017 16:03:38 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 35899C21C29; Tue, 28 Mar 2017 16:03:34 +0000 (UTC) Received: from mx07-00178001.pphosted.com (mx07-00178001.pphosted.com [62.209.51.94]) by lists.denx.de (Postfix) with ESMTPS id E1612C21BE5 for ; Tue, 28 Mar 2017 16:03:33 +0000 (UTC) Received: from pps.filterd (m0046037.ppops.net [127.0.0.1]) by m0046037.ppops.net (8.16.0.11/8.16.0.11) with SMTP id v2SFwp9l009494; Tue, 28 Mar 2017 18:03:31 +0200 Received: from beta.dmz-eu.st.com (beta.dmz-eu.st.com [164.129.1.35]) by mx07-.pphosted.com with ESMTP id 29ftpj03c2-1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NOT); Tue, 28 Mar 2017 18:03:31 +0200 Received: from zeta.dmz-eu.st.com (zeta.dmz-eu.st.com [164.129.230.9]) by beta.dmz-eu.st.com (STMicroelectronics) with ESMTP id E9AA938; Tue, 28 Mar 2017 16:03:30 +0000 (GMT) Received: from Webmail-eu.st.com (sfhdag6node3.st.com [10.75.127.18]) by zeta.dmz-eu.st.com (STMicroelectronics) with ESMTP id B9E5D2C4A; Tue, 28 Mar 2017 16:03:30 +0000 (GMT) Received: from localhost (10.75.127.48) by SFHDAG6NODE3.st.com (10.75.127.18) with Microsoft SMTP Server (TLS) id 15.0.1178.4; Tue, 28 Mar 2017 18:03:29 +0200 From: To: , , , , Date: Tue, 28 Mar 2017 18:03:05 +0200 Message-ID: <1490716994-7581-5-git-send-email-patrice.chotard@st.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1490716994-7581-1-git-send-email-patrice.chotard@st.com> References: <1490716994-7581-1-git-send-email-patrice.chotard@st.com> MIME-Version: 1.0 X-Originating-IP: [10.75.127.48] X-ClientProxiedBy: SFHDAG7NODE2.st.com (10.75.127.20) To SFHDAG6NODE3.st.com (10.75.127.18) X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-03-28_13:, , signatures=0 Cc: christophe.kerello@st.com Subject: [U-Boot] [PATCH v3 04/13] dm: usb: Add a uclass for USB PHY X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" From: Patrice Chotard This is a basic implementation of USB PHY which define a standard API that link USB PHY client to USB PHY driver controller. Signed-off-by: Patrice Chotard --- v3: _ this patch intoduce new USB PHY uclass drivers/usb/Kconfig | 4 ++ drivers/usb/phy/Kconfig | 10 ++++ drivers/usb/phy/Makefile | 1 + drivers/usb/phy/usb_phy_uclass.c | 90 +++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/usb_phy-uclass.h | 42 +++++++++++++++ include/usb_phy.h | 112 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 260 insertions(+) create mode 100644 drivers/usb/phy/Kconfig create mode 100644 drivers/usb/phy/usb_phy_uclass.c create mode 100644 include/usb_phy-uclass.h create mode 100644 include/usb_phy.h diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index da3ec2f..e30c9d6 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -94,4 +94,8 @@ endif source "drivers/usb/gadget/Kconfig" +comment "USB PHY" + +source "drivers/usb/phy/Kconfig" + endif diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig new file mode 100644 index 0000000..0539401 --- /dev/null +++ b/drivers/usb/phy/Kconfig @@ -0,0 +1,10 @@ +menu "USB PHY drivers" + +config USB_PHY + bool "Enable driver model for USB PHY drivers" + depends on DM + help + Enable driver model for USB PHY access. It defines basic + init and exit API. + +endmenu diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index 4e548c2..5314dcb 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -5,6 +5,7 @@ # SPDX-License-Identifier: GPL-2.0+ # +obj-$(CONFIG_USB_PHY) += usb_phy_uclass.o obj-$(CONFIG_TWL4030_USB) += twl4030.o obj-$(CONFIG_OMAP_USB_PHY) += omap_usb_phy.o obj-$(CONFIG_ROCKCHIP_USB2_PHY) += rockchip_usb2_phy.o diff --git a/drivers/usb/phy/usb_phy_uclass.c b/drivers/usb/phy/usb_phy_uclass.c new file mode 100644 index 0000000..11da635 --- /dev/null +++ b/drivers/usb/phy/usb_phy_uclass.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static inline struct usb_phy_ops *usb_phy_dev_ops(struct udevice *dev) +{ + return (struct usb_phy_ops *)dev->driver->ops; +} + +int usb_phy_get_by_index(struct udevice *dev, int index, + struct usb_phy_desc *usb_phy_desc) +{ + struct fdtdec_phandle_args args; + int ret; + struct udevice *dev_usb_phy; + + debug("%s(dev=%p, index=%d, usb_phy_desc=%p)\n", __func__, dev, index, + usb_phy_desc); + + ret = fdtdec_parse_phandle_with_args(gd->fdt_blob, dev_of_offset(dev), + "phys", "#phy-cells", 0, + index, &args); + if (ret) { + debug("%s: fdtdec_parse_phandle_with_args failed: %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_of_offset(UCLASS_USB_PHY, args.node, + &dev_usb_phy); + if (ret) { + debug("%s: uclass_get_device_by_of_offset failed: %d\n", + __func__, ret); + return ret; + } + + usb_phy_desc->dev = dev_usb_phy; + + return 0; +} + +int usb_phy_get_by_name(struct udevice *dev, const char *name, + struct usb_phy_desc *usb_phy_desc) +{ + int index; + + debug("%s(dev=%p, name=%s, usb_phy_desc=%p)\n", __func__, dev, name, + usb_phy_desc); + + index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), + "phy-names", name); + if (index < 0) { + debug("fdt_stringlist_search() failed: %d\n", index); + return index; + } + + return usb_phy_get_by_index(dev, index, usb_phy_desc); +} + +int usb_phy_init(struct usb_phy_desc *usb_phy_desc) +{ + struct usb_phy_ops *ops = usb_phy_dev_ops(usb_phy_desc->dev); + + debug("%s(usb_phy_desc=%p)\n", __func__, usb_phy_desc); + + return ops->init(usb_phy_desc); +} + +int usb_phy_exit(struct usb_phy_desc *usb_phy_desc) +{ + struct usb_phy_ops *ops = usb_phy_dev_ops(usb_phy_desc->dev); + + debug("%s(usb_phy_desc=%p)\n", __func__, usb_phy_desc); + + return ops->exit(usb_phy_desc); +} + +UCLASS_DRIVER(usb_phy) = { + .id = UCLASS_USB_PHY, + .name = "usb_phy", +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 8c92d0b..feb6689 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -80,6 +80,7 @@ enum uclass_id { UCLASS_USB, /* USB bus */ UCLASS_USB_DEV_GENERIC, /* USB generic device */ UCLASS_USB_HUB, /* USB hub */ + UCLASS_USB_PHY, /* USB Phy */ UCLASS_VIDEO, /* Video or LCD device */ UCLASS_VIDEO_BRIDGE, /* Video bridge, e.g. DisplayPort to LVDS */ UCLASS_VIDEO_CONSOLE, /* Text console driver for video device */ diff --git a/include/usb_phy-uclass.h b/include/usb_phy-uclass.h new file mode 100644 index 0000000..07a134c --- /dev/null +++ b/include/usb_phy-uclass.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _USB_PHY_UCLASS_H +#define _USB_PHY_UCLASS_H + +/* See usb_phy.h for background documentation. */ + +#include + +struct udevice; + +/** + * struct usb_phy_ops - The functions that a usb_phy controller driver must + * implement. + */ +struct usb_phy_ops { + /** + * init - operations to be performed for USB PHY initialisation + * + * Typically, registers init and reset deassertion + * + * @usb_phy_desc: The usb_phy struct to init; + * @return 0 if OK, or a negative error code. + */ + int (*init)(struct usb_phy_desc *usb_phy_desc); + /** + * exit - operations to be performed while exiting + * + * Typically reset assertion + * + * @usb_phy_desc: The usb_phy to free. + * @return 0 if OK, or a negative error code. + */ + int (*exit)(struct usb_phy_desc *usb_phy_desc); +}; + +#endif diff --git a/include/usb_phy.h b/include/usb_phy.h new file mode 100644 index 0000000..c2ddf8f --- /dev/null +++ b/include/usb_phy.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2017 + * Patrice Chotard + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _USB_PHY_H +#define _USB_PHY_H + +#include + +struct udevice; + +/** + * struct usb_phy_desc - A handle to a USB PHY. + * + * Clients provide storage for reset control handles. The content of the + * structure is managed solely by the reset API and reset drivers. A reset + * control struct is initialized by "get"ing the reset control struct. The + * reset control struct is passed to all other reset APIs to identify which + * reset signal to operate upon. + * + * @dev: The device which implements the reset signal. + * + */ +struct usb_phy_desc { + struct udevice *dev; +}; + +#ifdef CONFIG_DM_RESET +/** + * reset_get_by_index - Get/request a USB PHY by integer index. + * + * This looks up and requests a USB PHY. The index is relative to the + * client device; each device is assumed to have n USB PHY associated + * with it somehow, and this function finds and requests one of them. + * + * @dev: The client device. + * @index: The index of the USB PHY to request, within the client's + * list of USB PHYs. + * @usb_phy_desc A pointer to a USB PHY struct to initialize. + * @return 0 if OK, or a negative error code. + */ +int usb_phy_get_by_index(struct udevice *dev, int index, + struct usb_phy_desc *usb_phy_desc); + +/** + * usb_phy_get_by_name - Get/request a USB PHY by name. + * + * This looks up and requests a USB PHY. The name is relative to the + * client device; each device is assumed to have n USB PHY associated + * with it somehow, and this function finds and requests one of them. + * + * @dev: The client device. + * @name: The name of the USB PHY to request, within the client's + * list of USB PHYs. + * @usb_phy_desc: A pointer to a USB PHY struct to initialize. + * @return 0 if OK, or a negative error code. + */ +int usb_phy_get_by_name(struct udevice *dev, const char *name, + struct usb_phy_desc *usb_phy_desc); + +/** + * init - Initialize a USB PHY. + * + * Typically initialize PHY specific registers + * and deassert USB PHY associated reset signals. + * + * @usb_phy_desc: A USB PHY struct that was previously successfully + * requested by reset_get_by_*(). + * @return 0 if OK, or a negative error code. + */ +int usb_phy_init(struct usb_phy_desc *usb_phy_desc); + +/** + * exit - operations to be performed while exiting + * + * Typically deassert USB PHY associated reset signals. + * + * @usb_phy_desc: A USB PHY struct that was previously successfully + * requested by reset_get_by_*(). + * @return 0 if OK, or a negative error code. + */ +int usb_phy_exit(struct usb_phy_desc *usb_phy_desc); + +#else +static inline int usb_phy_get_by_index(struct udevice *dev, int index, + struct usb_phy_desc *usb_phy_desc) +{ + return -ENOTSUPP; +} + +static inline int usb_phy_get_by_name(struct udevice *dev, const char *name, + struct usb_phy_desc *usb_phy_desc) +{ + return -ENOTSUPP; +} + +static inline int init(struct usb_phy_desc *usb_phy_desc) +{ + return 0; +} + +static inline int exit(struct usb_phy_desc *usb_phy_desc) +{ + return 0; +} + +#endif + +#endif