From: Patrice Chotard <patrice.chot...@st.com>

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 <patrice.chot...@st.com>
---

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 <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <usb_phy-uclass.h>
+
+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 <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _USB_PHY_UCLASS_H
+#define _USB_PHY_UCLASS_H
+
+/* See usb_phy.h for background documentation. */
+
+#include <usb_phy.h>
+
+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 <patrice.chot...@st.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#ifndef _USB_PHY_H
+#define _USB_PHY_H
+
+#include <linux/errno.h>
+
+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
-- 
1.9.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to