Added a generic PHY framework that provides a set of APIs for the PHY drivers
to create/destroy a PHY and APIs for the PHY users to obtain a reference to
the PHY with or without using phandle.
This framework will be of use only to devices that uses external PHY (PHY
functionality is not embedded within the controller).
The intention of creating this framework is to bring the phy drivers spread
all over the Linux kernel to drivers/phy to increase code re-use and to
increase code maintainability.
Comments to make PHY as bus wasn't done because PHY devices can be part of
other bus and making a same device attached to multiple bus leads to bad
design.
If the PHY driver has to send notification on connect/disconnect, the PHY
driver should make use of the extcon framework. Using this susbsystem
to use extcon framwork will have to be analysed.
Exynos MIPI CSIS/DSIM PHY and Displayport PHY have started using this
framework. Have included those patches also in this series.
twl4030-usb and omap-usb2 have also been adapted to this framework.
These patches are also available @
git://gitorious.org/linuxphy/linuxphy.git tags/phy-for-v3.12
Jingoo Han (3):
phy: Add driver for Exynos DP PHY
video: exynos_dp: remove non-DT support for Exynos Display Port
video: exynos_dp: Use the generic PHY driver
Kishon Vijay Abraham I (8):
drivers: phy: add generic PHY framework
usb: phy: omap-usb2: use the new generic PHY framework
usb: phy: twl4030: use the new generic PHY framework
ARM: OMAP: USB: Add phy binding information
ARM: dts: omap: update usb_otg_hs data
usb: musb: omap2430: use the new generic PHY framework
usb: phy: omap-usb2: remove *set_suspend* callback from omap-usb2
usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops
Sylwester Nawrocki (4):
phy: Add driver for Exynos MIPI CSIS/DSIM DPHYs
video: exynos_mipi_dsim: Use the generic PHY driver
exynos4-is: Use the generic MIPI CSIS PHY driver
ARM: Samsung: Remove the MIPI PHY setup code
.../devicetree/bindings/phy/phy-bindings.txt | 66 +++
.../devicetree/bindings/phy/samsung-phy.txt | 22 +
Documentation/devicetree/bindings/usb/omap-usb.txt | 5 +
Documentation/devicetree/bindings/usb/usb-phy.txt | 6 +
.../devicetree/bindings/video/exynos_dp.txt | 18 +-
Documentation/phy.txt | 129 +++++
MAINTAINERS | 7 +
arch/arm/boot/dts/omap3-beagle-xm.dts | 2 +
arch/arm/boot/dts/omap3-evm.dts | 2 +
arch/arm/boot/dts/omap3-overo.dtsi | 2 +
arch/arm/boot/dts/omap4.dtsi | 3 +
arch/arm/boot/dts/twl4030.dtsi | 1 +
arch/arm/mach-exynos/include/mach/regs-pmu.h | 5 -
arch/arm/mach-omap2/usb-musb.c | 3 +
arch/arm/mach-s5pv210/include/mach/regs-clock.h | 4 -
arch/arm/plat-samsung/Kconfig | 5 -
arch/arm/plat-samsung/Makefile | 1 -
arch/arm/plat-samsung/setup-mipiphy.c | 60 ---
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/media/platform/exynos4-is/mipi-csis.c | 16 +-
drivers/phy/Kconfig | 28 +
drivers/phy/Makefile | 7 +
drivers/phy/phy-core.c | 544 ++++++++++++++++++++
drivers/phy/phy-exynos-dp-video.c | 111 ++++
drivers/phy/phy-exynos-mipi-video.c | 169 ++++++
drivers/usb/musb/Kconfig | 1 +
drivers/usb/musb/musb_core.c | 1 +
drivers/usb/musb/musb_core.h | 3 +
drivers/usb/musb/omap2430.c | 26 +-
drivers/usb/phy/Kconfig | 1 +
drivers/usb/phy/phy-omap-usb2.c | 60 ++-
drivers/usb/phy/phy-twl4030-usb.c | 63 ++-
drivers/video/exynos/Kconfig | 2 +-
drivers/video/exynos/exynos_dp_core.c | 132 ++---
drivers/video/exynos/exynos_dp_core.h | 110 ++++
drivers/video/exynos/exynos_dp_reg.c | 2 -
drivers/video/exynos/exynos_mipi_dsi.c | 19 +-
include/linux/phy/phy.h | 344 +++++++++++++
include/linux/platform_data/mipi-csis.h | 11 +-
include/linux/usb/musb.h | 3 +
include/video/exynos_dp.h | 131 -----
include/video/exynos_mipi_dsim.h | 6 +-
43 files changed, 1746 insertions(+), 389 deletions(-)
create mode 100644 Documentation/devicetree/bindings/phy/phy-bindings.txt
create mode 100644 Documentation/devicetree/bindings/phy/samsung-phy.txt
create mode 100644 Documentation/phy.txt
delete mode 100644 arch/arm/plat-samsung/setup-mipiphy.c
create mode 100644 drivers/phy/Kconfig
create mode 100644 drivers/phy/Makefile
create mode 100644 drivers/phy/phy-core.c
create mode 100644 drivers/phy/phy-exynos-dp-video.c
create mode 100644 drivers/phy/phy-exynos-mipi-video.c
create mode 100644 include/linux/phy/phy.h
delete mode 100644 include/video/exynos_dp.h
--
1.7.10.4
The PHY framework provides a set of APIs for the PHY drivers to
create/destroy a PHY and APIs for the PHY users to obtain a reference to the
PHY with or without using phandle. For dt-boot, the PHY drivers should
also register *PHY provider* with the framework.
PHY drivers should create the PHY by passing id and ops like init, exit,
power_on and power_off. This framework is also pm runtime enabled.
The documentation for the generic PHY framework is added in
Documentation/phy.txt and the documentation for dt binding can be found at
Documentation/devicetree/bindings/phy/phy-bindings.txt
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Tested-by: Sylwester Nawrocki <[email protected]>
---
.../devicetree/bindings/phy/phy-bindings.txt | 66 +++
Documentation/phy.txt | 129 +++++
MAINTAINERS | 7 +
drivers/Kconfig | 2 +
drivers/Makefile | 2 +
drivers/phy/Kconfig | 13 +
drivers/phy/Makefile | 5 +
drivers/phy/phy-core.c | 544 ++++++++++++++++++++
include/linux/phy/phy.h | 344 +++++++++++++
9 files changed, 1112 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/phy-bindings.txt
create mode 100644 Documentation/phy.txt
create mode 100644 drivers/phy/Kconfig
create mode 100644 drivers/phy/Makefile
create mode 100644 drivers/phy/phy-core.c
create mode 100644 include/linux/phy/phy.h
diff --git a/Documentation/devicetree/bindings/phy/phy-bindings.txt b/Documentation/devicetree/bindings/phy/phy-bindings.txt
new file mode 100644
index 0000000..8ae844f
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-bindings.txt
@@ -0,0 +1,66 @@
+This document explains only the device tree data binding. For general
+information about PHY subsystem refer to Documentation/phy.txt
+
+PHY device node
+===============
+
+Required Properties:
+#phy-cells: Number of cells in a PHY specifier; The meaning of all those
+ cells is defined by the binding for the phy node. The PHY
+ provider can use the values in cells to find the appropriate
+ PHY.
+
+For example:
+
+phys: phy {
+ compatible = "xxx";
+ reg = <...>;
+ .
+ .
+ #phy-cells = <1>;
+ .
+ .
+};
+
+That node describes an IP block (PHY provider) that implements 2 different PHYs.
+In order to differentiate between these 2 PHYs, an additonal specifier should be
+given while trying to get a reference to it.
+
+PHY user node
+=============
+
+Required Properties:
+phys : the phandle for the PHY device (used by the PHY subsystem)
+phy-names : the names of the PHY corresponding to the PHYs present in the
+ *phys* phandle
+
+Example 1:
+usb1: usb_otg_ss@xxx {
+ compatible = "xxx";
+ reg = <xxx>;
+ .
+ .
+ phys = <&usb2_phy>, <&usb3_phy>;
+ phy-names = "usb2phy", "usb3phy";
+ .
+ .
+};
+
+This node represents a controller that uses two PHYs, one for usb2 and one for
+usb3.
+
+Example 2:
+usb2: usb_otg_ss@xxx {
+ compatible = "xxx";
+ reg = <xxx>;
+ .
+ .
+ phys = <&phys 1>;
+ phy-names = "usbphy";
+ .
+ .
+};
+
+This node represents a controller that uses one of the PHYs of the PHY provider
+device defined previously. Note that the phy handle has an additional specifier
+"1" to differentiate between the two PHYs.
diff --git a/Documentation/phy.txt b/Documentation/phy.txt
new file mode 100644
index 0000000..05f8fda
--- /dev/null
+++ b/Documentation/phy.txt
@@ -0,0 +1,129 @@
+ PHY SUBSYSTEM
+ Kishon Vijay Abraham I <[email protected]>
+
+This document explains the Generic PHY Framework along with the APIs provided,
+and how-to-use.
+
+1. Introduction
+
+*PHY* is the abbreviation for physical layer. It is used to connect a device
+to the physical medium e.g., the USB controller has a PHY to provide functions
+such as serialization, de-serialization, encoding, decoding and is responsible
+for obtaining the required data transmission rate. Note that some USB
+controllers have PHY functionality embedded into it and others use an external
+PHY. Other peripherals that use PHY include Wireless LAN, Ethernet,
+SATA etc.
+
+The intention of creating this framework is to bring the PHY drivers spread
+all over the Linux kernel to drivers/phy to increase code re-use and for
+better code maintainability.
+
+This framework will be of use only to devices that use external PHY (PHY
+functionality is not embedded within the controller).
+
+2. Registering/Unregistering the PHY provider
+
+PHY provider refers to an entity that implements one or more PHY instances.
+For the simple case where the PHY provider implements only a single instance of
+the PHY, the framework provides its own implementation of of_xlate in
+of_phy_simple_xlate. If the PHY provider implements multiple instances, it
+should provide its own implementation of of_xlate. of_xlate is used only for
+dt boot case.
+
+struct phy_provider *__of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args));
+struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+
+__of_phy_provider_register and __devm_of_phy_provider_register can be used to
+register the phy_provider and it takes device, owner and of_xlate as
+arguments. For the dt boot case, all PHY providers should use one of the above
+2 APIs to register the PHY provider.
+
+void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider);
+void of_phy_provider_unregister(struct phy_provider *phy_provider);
+
+devm_of_phy_provider_unregister and of_phy_provider_unregister can be used to
+unregister the PHY.
+
+3. Creating the PHY
+
+The PHY driver should create the PHY in order for other peripheral controllers
+to make use of it. The PHY framework provides 2 APIs to create the PHY.
+
+struct phy *phy_create(struct device *dev, u8 id, const struct phy_ops *ops,
+ const char *label);
+extern struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label);
+
+The PHY drivers can use one of the above 2 APIs to create the PHY by passing
+the device pointer, id, phy ops, label and a driver data.
+phy_ops is a set of function pointers for performing PHY operations such as
+init, exit, power_on and power_off. *label* is mandatory for non-dt boot case
+and it should be unique as well.
+
+Inorder to dereference the private data (in phy_ops), the phy provider driver
+can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
+phy_ops to get back the private data.
+
+4. Getting a reference to the PHY
+
+Before the controller can make use of the PHY, it has to get a reference to
+it. This framework provides the following APIs to get a reference to the PHY.
+
+struct phy *phy_get(struct device *dev, const char *string);
+struct phy *devm_phy_get(struct device *dev, const char *string);
+
+phy_get and devm_phy_get can be used to get the PHY. In the case of dt boot,
+the string arguments should contain the phy name as given in the dt data and
+in the case of non-dt boot, it should contain the label of the PHY.
+The only difference between the two APIs is that devm_phy_get associates the
+device with the PHY using devres on successful PHY get. On driver detach,
+release function is invoked on the the devres data and devres data is freed.
+
+5. Releasing a reference to the PHY
+
+When the controller no longer needs the PHY, it has to release the reference
+to the PHY it has obtained using the APIs mentioned in the above section. The
+PHY framework provides 2 APIs to release a reference to the PHY.
+
+void phy_put(struct phy *phy);
+void devm_phy_put(struct device *dev, struct phy *phy);
+
+Both these APIs are used to release a reference to the PHY and devm_phy_put
+destroys the devres associated with this PHY.
+
+6. Destroying the PHY
+
+When the driver that created the PHY is unloaded, it should destroy the PHY it
+created using one of the following 2 APIs.
+
+void phy_destroy(struct phy *phy);
+void devm_phy_destroy(struct device *dev, struct phy *phy);
+
+Both these APIs destroy the PHY and devm_phy_destroy destroys the devres
+associated with this PHY.
+
+7. PM Runtime
+
+This subsystem is pm runtime enabled. So while creating the PHY,
+pm_runtime_enable of the phy device created by this subsystem is called and
+while destroying the PHY, pm_runtime_disable is called. Note that the phy
+device created by this subsystem will be a child of the device that calls
+phy_create (PHY provider device).
+
+So pm_runtime_get_sync of the phy_device created by this subsystem will invoke
+pm_runtime_get_sync of PHY provider device because of parent-child relationship.
+It should also be noted that phy_power_on and phy_power_off performs
+phy_pm_runtime_get_sync and phy_pm_runtime_put respectively.
+There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync,
+phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and
+phy_pm_runtime_forbid for performing PM operations.
+
+8. DeviceTree Binding
+
+The documentation for PHY dt binding can be found @
+Documentation/devicetree/bindings/phy/phy-bindings.txt
diff --git a/MAINTAINERS b/MAINTAINERS
index bf61e04..dd03889 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3594,6 +3594,13 @@ S: Maintained
F: include/asm-generic
F: include/uapi/asm-generic
+GENERIC PHY FRAMEWORK
+M: Kishon Vijay Abraham I <[email protected]>
+L: [email protected]
+S: Supported
+F: drivers/phy/
+F: include/linux/phy/
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <[email protected]>
L: [email protected]
diff --git a/drivers/Kconfig b/drivers/Kconfig
index aa43b91..8f45144 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -166,4 +166,6 @@ source "drivers/reset/Kconfig"
source "drivers/fmc/Kconfig"
+source "drivers/phy/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index ab93de8..687da89 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -8,6 +8,8 @@
obj-y += irqchip/
obj-y += bus/
+obj-$(CONFIG_GENERIC_PHY) += phy/
+
# GPIO must come after pinctrl as gpios may need to mux pins etc
obj-y += pinctrl/
obj-y += gpio/
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
new file mode 100644
index 0000000..5f85909
--- /dev/null
+++ b/drivers/phy/Kconfig
@@ -0,0 +1,13 @@
+#
+# PHY
+#
+
+menuconfig GENERIC_PHY
+ tristate "PHY Subsystem"
+ help
+ Generic PHY support.
+
+ This framework is designed to provide a generic interface for PHY
+ devices present in the kernel. This layer will have the generic
+ API by which phy drivers can create PHY using the phy framework and
+ phy users can obtain reference to the PHY.
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
new file mode 100644
index 0000000..9e9560f
--- /dev/null
+++ b/drivers/phy/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the phy drivers.
+#
+
+obj-$(CONFIG_GENERIC_PHY) += phy-core.o
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
new file mode 100644
index 0000000..6c75dc3
--- /dev/null
+++ b/drivers/phy/phy-core.c
@@ -0,0 +1,544 @@
+/*
+ * phy-core.c -- Generic Phy framework.
+ *
+ * Copyright (C) 2013 Texas Instruments
+ *
+ * Author: Kishon Vijay Abraham I <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/pm_runtime.h>
+
+static struct class *phy_class;
+static DEFINE_MUTEX(phy_provider_mutex);
+static LIST_HEAD(phy_provider_list);
+
+static void devm_phy_release(struct device *dev, void *res)
+{
+ struct phy *phy = *(struct phy **)res;
+
+ phy_put(phy);
+}
+
+static void devm_phy_provider_release(struct device *dev, void *res)
+{
+ struct phy_provider *phy_provider = *(struct phy_provider **)res;
+
+ of_phy_provider_unregister(phy_provider);
+}
+
+static void devm_phy_consume(struct device *dev, void *res)
+{
+ struct phy *phy = *(struct phy **)res;
+
+ phy_destroy(phy);
+}
+
+static int devm_phy_match(struct device *dev, void *res, void *match_data)
+{
+ return res == match_data;
+}
+
+static struct phy *phy_lookup(const char *phy_name)
+{
+ struct phy *phy;
+ struct device *dev;
+ struct class_dev_iter iter;
+
+ class_dev_iter_init(&iter, phy_class, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
+ phy = to_phy(dev);
+ if (strcmp(phy->label, phy_name))
+ continue;
+
+ class_dev_iter_exit(&iter);
+ return phy;
+ }
+
+ class_dev_iter_exit(&iter);
+ return ERR_PTR(-ENODEV);
+}
+
+static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
+{
+ struct phy_provider *phy_provider;
+
+ list_for_each_entry(phy_provider, &phy_provider_list, list) {
+ if (phy_provider->dev->of_node == node)
+ return phy_provider;
+ }
+
+ return ERR_PTR(-EPROBE_DEFER);
+}
+
+/**
+ * of_phy_get() - lookup and obtain a reference to a phy by phandle
+ * @dev: device that requests this phy
+ * @index: the index of the phy
+ *
+ * Returns the phy associated with the given phandle value,
+ * after getting a refcount to it or -ENODEV if there is no such phy or
+ * -EPROBE_DEFER if there is a phandle to the phy, but the device is
+ * not yet loaded. This function uses of_xlate call back function provided
+ * while registering the phy_provider to find the phy instance.
+ */
+static struct phy *of_phy_get(struct device *dev, int index)
+{
+ int ret;
+ struct phy_provider *phy_provider;
+ struct phy *phy = NULL;
+ struct of_phandle_args args;
+
+ ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells",
+ index, &args);
+ if (ret) {
+ dev_dbg(dev, "failed to get phy in %s node\n",
+ dev->of_node->full_name);
+ return ERR_PTR(-ENODEV);
+ }
+
+ mutex_lock(&phy_provider_mutex);
+ phy_provider = of_phy_provider_lookup(args.np);
+ if (IS_ERR(phy_provider) || !try_module_get(phy_provider->owner)) {
+ phy = ERR_PTR(-EPROBE_DEFER);
+ goto err0;
+ }
+
+ phy = phy_provider->of_xlate(phy_provider->dev, &args);
+ module_put(phy_provider->owner);
+
+err0:
+ mutex_unlock(&phy_provider_mutex);
+ of_node_put(args.np);
+
+ return phy;
+}
+
+/**
+ * phy_put() - release the PHY
+ * @phy: the phy returned by phy_get()
+ *
+ * Releases a refcount the caller received from phy_get().
+ */
+void phy_put(struct phy *phy)
+{
+ if (IS_ERR(phy))
+ return;
+
+ module_put(phy->ops->owner);
+ put_device(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_put);
+
+/**
+ * devm_phy_put() - release the PHY
+ * @dev: device that wants to release this phy
+ * @phy: the phy returned by devm_phy_get()
+ *
+ * destroys the devres associated with this phy and invokes phy_put
+ * to release the phy.
+ */
+void devm_phy_put(struct device *dev, struct phy *phy)
+{
+ int r;
+
+ r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
+ dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_phy_put);
+
+/**
+ * of_phy_simple_xlate() - returns the phy instance from phy provider
+ * @dev: the PHY provider device
+ * @args: of_phandle_args (not used here)
+ *
+ * Intended to be used by phy provider for the common case where #phy-cells is
+ * 0. For other cases where #phy-cells is greater than '0', the phy provider
+ * should provide a custom of_xlate function that reads the *args* and returns
+ * the appropriate phy.
+ */
+struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
+ *args)
+{
+ struct phy *phy;
+ struct class_dev_iter iter;
+ struct device_node *node = dev->of_node;
+
+ class_dev_iter_init(&iter, phy_class, NULL, NULL);
+ while ((dev = class_dev_iter_next(&iter))) {
+ phy = to_phy(dev);
+ if (node != phy->dev.of_node)
+ continue;
+
+ class_dev_iter_exit(&iter);
+ return phy;
+ }
+
+ class_dev_iter_exit(&iter);
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(of_phy_simple_xlate);
+
+/**
+ * phy_get() - lookup and obtain a reference to a phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or phy device name
+ * for non-dt case
+ *
+ * Returns the phy driver, after getting a refcount to it; or
+ * -ENODEV if there is no such phy. The caller is responsible for
+ * calling phy_put() to release that count.
+ */
+struct phy *phy_get(struct device *dev, const char *string)
+{
+ int index = 0;
+ struct phy *phy = NULL;
+
+ if (string == NULL) {
+ dev_WARN(dev, "missing string\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (dev->of_node) {
+ index = of_property_match_string(dev->of_node, "phy-names",
+ string);
+ phy = of_phy_get(dev, index);
+ if (IS_ERR(phy)) {
+ dev_WARN(dev, "unable to find phy\n");
+ return phy;
+ }
+ } else {
+ phy = phy_lookup(string);
+ if (IS_ERR(phy)) {
+ dev_WARN(dev, "unable to find phy\n");
+ return phy;
+ }
+ }
+
+ if (!try_module_get(phy->ops->owner))
+ return ERR_PTR(-EPROBE_DEFER);
+
+ get_device(&phy->dev);
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(phy_get);
+
+/**
+ * devm_phy_get() - lookup and obtain a reference to a phy.
+ * @dev: device that requests this phy
+ * @string: the phy name as given in the dt data or phy device name
+ * for non-dt case
+ *
+ * Gets the phy using phy_get(), and associates a device with it using
+ * devres. On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ */
+struct phy *devm_phy_get(struct device *dev, const char *string)
+{
+ struct phy **ptr, *phy;
+
+ ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ phy = phy_get(dev, string);
+ if (!IS_ERR(phy)) {
+ *ptr = phy;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(devm_phy_get);
+
+/**
+ * phy_create() - create a new phy
+ * @dev: device that is creating the new phy
+ * @id: id of the phy
+ * @ops: function pointers for performing phy operations
+ * @label: label given to the phy
+ *
+ * Called to create a phy using phy framework.
+ */
+struct phy *phy_create(struct device *dev, u8 id, const struct phy_ops *ops,
+ const char *label)
+{
+ int ret;
+ struct phy *phy;
+
+ if (!dev) {
+ dev_WARN(dev, "no device provided for PHY\n");
+ ret = -EINVAL;
+ goto err0;
+ }
+
+ phy = kzalloc(sizeof(*phy), GFP_KERNEL);
+ if (!phy) {
+ ret = -ENOMEM;
+ goto err0;
+ }
+
+ device_initialize(&phy->dev);
+ mutex_init(&phy->mutex);
+
+ phy->dev.class = phy_class;
+ phy->dev.parent = dev;
+ phy->dev.of_node = dev->of_node;
+ phy->id = id;
+ phy->ops = ops;
+ phy->label = kstrdup(label, GFP_KERNEL);
+
+ ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
+ if (ret)
+ goto err1;
+
+ ret = device_add(&phy->dev);
+ if (ret)
+ goto err1;
+
+ if (pm_runtime_enabled(dev)) {
+ pm_runtime_enable(&phy->dev);
+ pm_runtime_no_callbacks(&phy->dev);
+ }
+
+ return phy;
+
+err1:
+ put_device(&phy->dev);
+ kfree(phy->label);
+ kfree(phy);
+
+err0:
+ return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(phy_create);
+
+/**
+ * devm_phy_create() - create a new phy
+ * @dev: device that is creating the new phy
+ * @id: id of the phy
+ * @ops: function pointers for performing phy operations
+ * @label: label given to the phy
+ *
+ * Creates a new PHY device adding it to the PHY class.
+ * While at that, it also associates the device with the phy using devres.
+ * On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ */
+struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label)
+{
+ struct phy **ptr, *phy;
+
+ ptr = devres_alloc(devm_phy_consume, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ phy = phy_create(dev, id, ops, label);
+ if (!IS_ERR(phy)) {
+ *ptr = phy;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(devm_phy_create);
+
+/**
+ * phy_destroy() - destroy the phy
+ * @phy: the phy to be destroyed
+ *
+ * Called to destroy the phy.
+ */
+void phy_destroy(struct phy *phy)
+{
+ pm_runtime_disable(&phy->dev);
+ device_unregister(&phy->dev);
+}
+EXPORT_SYMBOL_GPL(phy_destroy);
+
+/**
+ * devm_phy_destroy() - destroy the PHY
+ * @dev: device that wants to release this phy
+ * @phy: the phy returned by devm_phy_get()
+ *
+ * destroys the devres associated with this phy and invokes phy_destroy
+ * to destroy the phy.
+ */
+void devm_phy_destroy(struct device *dev, struct phy *phy)
+{
+ int r;
+
+ r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
+ dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_phy_destroy);
+
+/**
+ * __of_phy_provider_register() - create/register phy provider with the framework
+ * @dev: struct device of the phy provider
+ * @owner: the module owner containing of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy provider
+ *
+ * Creates struct phy_provider from dev and of_xlate function pointer.
+ * This is used in the case of dt boot for finding the phy instance from
+ * phy provider.
+ */
+struct phy_provider *__of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+{
+ struct phy_provider *phy_provider;
+
+ phy_provider = kzalloc(sizeof(*phy_provider), GFP_KERNEL);
+ if (!phy_provider)
+ return ERR_PTR(-ENOMEM);
+
+ phy_provider->dev = dev;
+ phy_provider->owner = owner;
+ phy_provider->of_xlate = of_xlate;
+
+ mutex_lock(&phy_provider_mutex);
+ list_add_tail(&phy_provider->list, &phy_provider_list);
+ mutex_unlock(&phy_provider_mutex);
+
+ return phy_provider;
+}
+EXPORT_SYMBOL_GPL(__of_phy_provider_register);
+
+/**
+ * __devm_of_phy_provider_register() - create/register phy provider with the
+ * framework
+ * @dev: struct device of the phy provider
+ * @owner: the module owner containing of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy provider
+ *
+ * Creates struct phy_provider from dev and of_xlate function pointer.
+ * This is used in the case of dt boot for finding the phy instance from
+ * phy provider. While at that, it also associates the device with the
+ * phy provider using devres. On driver detach, release function is invoked
+ * on the devres data, then, devres data is freed.
+ */
+struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+{
+ struct phy_provider **ptr, *phy_provider;
+
+ ptr = devres_alloc(devm_phy_provider_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ phy_provider = __of_phy_provider_register(dev, owner, of_xlate);
+ if (!IS_ERR(phy_provider)) {
+ *ptr = phy_provider;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return phy_provider;
+}
+EXPORT_SYMBOL_GPL(__devm_of_phy_provider_register);
+
+/**
+ * of_phy_provider_unregister() - unregister phy provider from the framework
+ * @phy_provider: phy provider returned by of_phy_provider_register()
+ *
+ * Removes the phy_provider created using of_phy_provider_register().
+ */
+void of_phy_provider_unregister(struct phy_provider *phy_provider)
+{
+ if (IS_ERR(phy_provider))
+ return;
+
+ mutex_lock(&phy_provider_mutex);
+ list_del(&phy_provider->list);
+ kfree(phy_provider);
+ mutex_unlock(&phy_provider_mutex);
+}
+EXPORT_SYMBOL_GPL(of_phy_provider_unregister);
+
+/**
+ * devm_of_phy_provider_unregister() - remove phy provider from the framework
+ * @dev: struct device of the phy provider
+ *
+ * destroys the devres associated with this phy provider and invokes
+ * of_phy_provider_unregister to unregister the phy provider.
+ */
+void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider) {
+ int r;
+
+ r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
+ phy_provider);
+ dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
+
+/**
+ * phy_release() - release the phy
+ * @dev: the dev member within phy
+ *
+ * When the last reference to the device is removed, it is called
+ * from the embedded kobject as release method.
+ */
+static void phy_release(struct device *dev)
+{
+ struct phy *phy;
+
+ phy = to_phy(dev);
+ dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+ kfree(phy->label);
+ kfree(phy);
+}
+
+static int __init phy_core_init(void)
+{
+ phy_class = class_create(THIS_MODULE, "phy");
+ if (IS_ERR(phy_class)) {
+ pr_err("failed to create phy class --> %ld\n",
+ PTR_ERR(phy_class));
+ return PTR_ERR(phy_class);
+ }
+
+ phy_class->dev_release = phy_release;
+
+ return 0;
+}
+module_init(phy_core_init);
+
+static void __exit phy_core_exit(void)
+{
+ class_destroy(phy_class);
+}
+module_exit(phy_core_exit);
+
+MODULE_DESCRIPTION("Generic PHY Framework");
+MODULE_AUTHOR("Kishon Vijay Abraham I <[email protected]>");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
new file mode 100644
index 0000000..9351a16
--- /dev/null
+++ b/include/linux/phy/phy.h
@@ -0,0 +1,344 @@
+/*
+ * phy.h -- generic phy header file
+ *
+ * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Author: Kishon Vijay Abraham I <[email protected]>
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DRIVERS_PHY_H
+#define __DRIVERS_PHY_H
+
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/device.h>
+#include <linux/pm_runtime.h>
+
+struct phy;
+
+/**
+ * struct phy_ops - set of function pointers for performing phy operations
+ * @init: operation to be performed for initializing phy
+ * @exit: operation to be performed while exiting
+ * @power_on: powering on the phy
+ * @power_off: powering off the phy
+ * @owner: the module owner containing the ops
+ */
+struct phy_ops {
+ int (*init)(struct phy *phy);
+ int (*exit)(struct phy *phy);
+ int (*power_on)(struct phy *phy);
+ int (*power_off)(struct phy *phy);
+ struct module *owner;
+};
+
+/**
+ * struct phy - represents the phy device
+ * @dev: phy device
+ * @id: id of the phy
+ * @ops: function pointers for performing phy operations
+ * @label: label given to the phy
+ * @mutex: mutex to protect phy_ops
+ * @init_count: used to protect when the PHY is used by multiple consumers
+ * @power_count: used to protect when the PHY is used by multiple consumers
+ */
+struct phy {
+ struct device dev;
+ int id;
+ const struct phy_ops *ops;
+ const char *label;
+ struct mutex mutex;
+ int init_count;
+ int power_count;
+};
+
+/**
+ * struct phy_provider - represents the phy provider
+ * @dev: phy provider device
+ * @owner: the module owner having of_xlate
+ * @of_xlate: function pointer to obtain phy instance from phy pointer
+ * @list: to maintain a linked list of PHY providers
+ */
+struct phy_provider {
+ struct device *dev;
+ struct module *owner;
+ struct list_head list;
+ struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args);
+};
+
+#define to_phy(dev) (container_of((dev), struct phy, dev))
+
+#define of_phy_provider_register(dev, xlate) \
+ __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+#define devm_of_phy_provider_register(dev, xlate) \
+ __of_phy_provider_register((dev), THIS_MODULE, (xlate))
+
+static inline void phy_set_drvdata(struct phy *phy, void *data)
+{
+ dev_set_drvdata(&phy->dev, data);
+}
+
+static inline void *phy_get_drvdata(struct phy *phy)
+{
+ return dev_get_drvdata(&phy->dev);
+}
+
+#if IS_ENABLED(CONFIG_GENERIC_PHY)
+extern struct phy *phy_get(struct device *dev, const char *string);
+extern struct phy *devm_phy_get(struct device *dev, const char *string);
+extern void phy_put(struct phy *phy);
+extern void devm_phy_put(struct device *dev, struct phy *phy);
+extern struct phy *of_phy_simple_xlate(struct device *dev,
+ struct of_phandle_args *args);
+extern struct phy *phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label);
+extern struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label);
+extern void phy_destroy(struct phy *phy);
+extern void devm_phy_destroy(struct device *dev, struct phy *phy);
+extern struct phy_provider *__of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args));
+extern struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
+ struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args));
+extern void of_phy_provider_unregister(struct phy_provider *phy_provider);
+extern void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider);
+#else
+static inline struct phy *phy_get(struct device *dev, const char *string)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *devm_phy_get(struct device *dev, const char *string)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void phy_put(struct phy *phy)
+{
+}
+
+static inline void devm_phy_put(struct device *dev, struct phy *phy)
+{
+}
+
+static inline struct phy *of_phy_simple_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy *devm_phy_create(struct device *dev, u8 id,
+ const struct phy_ops *ops, const char *label)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void phy_destroy(struct phy *phy)
+{
+}
+
+static inline void devm_phy_destroy(struct device *dev, struct phy *phy)
+{
+}
+
+static inline struct phy_provider *__of_phy_provider_register(
+ struct device *dev, struct module *owner, struct phy * (*of_xlate)(
+ struct device *dev, struct of_phandle_args *args))
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline struct phy_provider *__devm_of_phy_provider_register(struct device
+ *dev, struct module *owner, struct phy * (*of_xlate)(struct device *dev,
+ struct of_phandle_args *args))
+{
+ return ERR_PTR(-ENOSYS);
+}
+
+static inline void of_phy_provider_unregister(struct phy_provider *phy_provider)
+{
+}
+
+static inline void devm_of_phy_provider_unregister(struct device *dev,
+ struct phy_provider *phy_provider)
+{
+}
+#endif
+
+static inline int phy_pm_runtime_get(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_get(&phy->dev);
+}
+
+static inline int phy_pm_runtime_get_sync(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_get_sync(&phy->dev);
+}
+
+static inline int phy_pm_runtime_put(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_put(&phy->dev);
+}
+
+static inline int phy_pm_runtime_put_sync(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return -EINVAL;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return -ENOTSUPP;
+
+ return pm_runtime_put_sync(&phy->dev);
+}
+
+static inline void phy_pm_runtime_allow(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return;
+
+ pm_runtime_allow(&phy->dev);
+}
+
+static inline void phy_pm_runtime_forbid(struct phy *phy)
+{
+ if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
+ return;
+
+ if (!pm_runtime_enabled(&phy->dev))
+ return;
+
+ pm_runtime_forbid(&phy->dev);
+}
+
+static inline int phy_init(struct phy *phy)
+{
+ int ret;
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+ return ret;
+
+ mutex_lock(&phy->mutex);
+ if (phy->init_count++ == 0 && phy->ops->init) {
+ ret = phy->ops->init(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy init failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put(phy);
+ return ret;
+}
+
+static inline int phy_exit(struct phy *phy)
+{
+ int ret;
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+ return ret;
+
+ mutex_lock(&phy->mutex);
+ if (--phy->init_count == 0 && phy->ops->exit) {
+ ret = phy->ops->exit(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put(phy);
+ return ret;
+}
+
+static inline int phy_power_on(struct phy *phy)
+{
+ int ret = -ENOTSUPP;
+
+ ret = phy_pm_runtime_get_sync(phy);
+ if (ret < 0 && ret != -ENOTSUPP)
+ return ret;
+
+ mutex_lock(&phy->mutex);
+ if (phy->power_count++ == 0 && phy->ops->power_on) {
+ ret = phy->ops->power_on(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+
+ return ret;
+}
+
+static inline int phy_power_off(struct phy *phy)
+{
+ int ret = -ENOTSUPP;
+
+ mutex_lock(&phy->mutex);
+ if (--phy->power_count == 0 && phy->ops->power_off) {
+ ret = phy->ops->power_off(phy);
+ if (ret < 0) {
+ dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
+ goto out;
+ }
+ }
+
+out:
+ mutex_unlock(&phy->mutex);
+ phy_pm_runtime_put(phy);
+
+ return ret;
+}
+
+#endif /* __DRIVERS_PHY_H */
--
1.7.10.4
Used the generic PHY framework API to create the PHY. For powering on
and powering off the PHY, power_on and power_off ops are used. Once the
MUSB OMAP glue is adapted to the new framework, the suspend and resume
ops of usb phy library will be removed.
However using the old usb phy library cannot be completely removed
because otg is intertwined with phy and moving to the new
framework completely will break otg. Once we have a separate otg state machine,
we can get rid of the usb phy library.
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Reviewed-by: Sylwester Nawrocki <[email protected]>
---
drivers/usb/phy/phy-twl4030-usb.c | 50 ++++++++++++++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c
index 8f78d2d..9051756 100644
--- a/drivers/usb/phy/phy-twl4030-usb.c
+++ b/drivers/usb/phy/phy-twl4030-usb.c
@@ -33,6 +33,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/usb/otg.h>
+#include <linux/phy/phy.h>
#include <linux/usb/musb-omap.h>
#include <linux/usb/ulpi.h>
#include <linux/i2c/twl.h>
@@ -431,6 +432,14 @@ static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
dev_dbg(twl->dev, "%s\n", __func__);
}
+static int twl4030_phy_power_off(struct phy *phy)
+{
+ struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+ twl4030_phy_suspend(twl, 0);
+ return 0;
+}
+
static void __twl4030_phy_resume(struct twl4030_usb *twl)
{
twl4030_phy_power(twl, 1);
@@ -459,6 +468,14 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
}
}
+static int twl4030_phy_power_on(struct phy *phy)
+{
+ struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+ twl4030_phy_resume(twl);
+ return 0;
+}
+
static int twl4030_usb_ldo_init(struct twl4030_usb *twl)
{
/* Enable writing to power configuration registers */
@@ -602,13 +619,22 @@ static int twl4030_usb_phy_init(struct usb_phy *phy)
status = twl4030_usb_linkstat(twl);
twl->linkstat = status;
- if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID)
+ if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) {
omap_musb_mailbox(twl->linkstat);
+ twl4030_phy_resume(twl);
+ }
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
return 0;
}
+static int twl4030_phy_init(struct phy *phy)
+{
+ struct twl4030_usb *twl = phy_get_drvdata(phy);
+
+ return twl4030_usb_phy_init(&twl->phy);
+}
+
static int twl4030_set_suspend(struct usb_phy *x, int suspend)
{
struct twl4030_usb *twl = phy_to_twl(x);
@@ -646,13 +672,22 @@ static int twl4030_set_host(struct usb_otg *otg, struct usb_bus *host)
return 0;
}
+static const struct phy_ops ops = {
+ .init = twl4030_phy_init,
+ .power_on = twl4030_phy_power_on,
+ .power_off = twl4030_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
static int twl4030_usb_probe(struct platform_device *pdev)
{
struct twl4030_usb_data *pdata = pdev->dev.platform_data;
struct twl4030_usb *twl;
+ struct phy *phy;
int status, err;
struct usb_otg *otg;
struct device_node *np = pdev->dev.of_node;
+ struct phy_provider *phy_provider;
twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL);
if (!twl)
@@ -689,6 +724,19 @@ static int twl4030_usb_probe(struct platform_device *pdev)
otg->set_host = twl4030_set_host;
otg->set_peripheral = twl4030_set_peripheral;
+ phy_provider = devm_of_phy_provider_register(twl->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ phy = devm_phy_create(twl->dev, 0, &ops, "twl4030");
+ if (IS_ERR(phy)) {
+ dev_dbg(&pdev->dev, "Failed to create PHY\n");
+ return PTR_ERR(phy);
+ }
+
+ phy_set_drvdata(phy, twl);
+
/* init spinlock for workqueue */
spin_lock_init(&twl->lock);
--
1.7.10.4
Updated the usb_otg_hs dt data to include the *phy* and *phy-names*
binding in order for the driver to use the new generic PHY framework.
Also updated the Documentation to include the binding information.
The PHY binding information can be found at
Documentation/devicetree/bindings/phy/phy-bindings.txt
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Reviewed-by: Sylwester Nawrocki <[email protected]>
---
Documentation/devicetree/bindings/usb/omap-usb.txt | 5 +++++
Documentation/devicetree/bindings/usb/usb-phy.txt | 6 ++++++
arch/arm/boot/dts/omap3-beagle-xm.dts | 2 ++
arch/arm/boot/dts/omap3-evm.dts | 2 ++
arch/arm/boot/dts/omap3-overo.dtsi | 2 ++
arch/arm/boot/dts/omap4.dtsi | 3 +++
arch/arm/boot/dts/twl4030.dtsi | 1 +
7 files changed, 21 insertions(+)
diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
index 57e71f6..825790d 100644
--- a/Documentation/devicetree/bindings/usb/omap-usb.txt
+++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
@@ -19,6 +19,9 @@ OMAP MUSB GLUE
- power : Should be "50". This signifies the controller can supply up to
100mA when operating in host mode.
- usb-phy : the phandle for the PHY device
+ - phys : the phandle for the PHY device (used by generic PHY framework)
+ - phy-names : the names of the PHY corresponding to the PHYs present in the
+ *phy* phandle.
Optional properties:
- ctrl-module : phandle of the control module this glue uses to write to
@@ -33,6 +36,8 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
num-eps = <16>;
ram-bits = <12>;
ctrl-module = <&omap_control_usb>;
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
};
Board specific device node entry
diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
index 61496f5..c0245c8 100644
--- a/Documentation/devicetree/bindings/usb/usb-phy.txt
+++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
@@ -5,6 +5,8 @@ OMAP USB2 PHY
Required properties:
- compatible: Should be "ti,omap-usb2"
- reg : Address and length of the register set for the device.
+ - #phy-cells: determine the number of cells that should be given in the
+ phandle while referencing this phy.
Optional properties:
- ctrl-module : phandle of the control module used by PHY driver to power on
@@ -16,6 +18,7 @@ usb2phy@4a0ad080 {
compatible = "ti,omap-usb2";
reg = <0x4a0ad080 0x58>;
ctrl-module = <&omap_control_usb>;
+ #phy-cells = <0>;
};
OMAP USB3 PHY
@@ -25,6 +28,8 @@ Required properties:
- reg : Address and length of the register set for the device.
- reg-names: The names of the register addresses corresponding to the registers
filled in "reg".
+ - #phy-cells: determine the number of cells that should be given in the
+ phandle while referencing this phy.
Optional properties:
- ctrl-module : phandle of the control module used by PHY driver to power on
@@ -39,4 +44,5 @@ usb3phy@4a084400 {
<0x4a084c00 0x40>;
reg-names = "phy_rx", "phy_tx", "pll_ctrl";
ctrl-module = <&omap_control_usb>;
+ #phy-cells = <0>;
};
diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
index afdb164..533b2da 100644
--- a/arch/arm/boot/dts/omap3-beagle-xm.dts
+++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
@@ -144,6 +144,8 @@
&usb_otg_hs {
interface-type = <0>;
usb-phy = <&usb2_phy>;
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
mode = <3>;
power = <50>;
};
diff --git a/arch/arm/boot/dts/omap3-evm.dts b/arch/arm/boot/dts/omap3-evm.dts
index 7d4329d..4134dd0 100644
--- a/arch/arm/boot/dts/omap3-evm.dts
+++ b/arch/arm/boot/dts/omap3-evm.dts
@@ -70,6 +70,8 @@
&usb_otg_hs {
interface-type = <0>;
usb-phy = <&usb2_phy>;
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
mode = <3>;
power = <50>;
};
diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi
index 8f1abec..a461d2f 100644
--- a/arch/arm/boot/dts/omap3-overo.dtsi
+++ b/arch/arm/boot/dts/omap3-overo.dtsi
@@ -76,6 +76,8 @@
&usb_otg_hs {
interface-type = <0>;
usb-phy = <&usb2_phy>;
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
mode = <3>;
power = <50>;
};
diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
index 22d9f2b..1e8e2fe 100644
--- a/arch/arm/boot/dts/omap4.dtsi
+++ b/arch/arm/boot/dts/omap4.dtsi
@@ -520,6 +520,7 @@
compatible = "ti,omap-usb2";
reg = <0x4a0ad080 0x58>;
ctrl-module = <&omap_control_usb>;
+ #phy-cells = <0>;
};
};
@@ -658,6 +659,8 @@
interrupt-names = "mc", "dma";
ti,hwmods = "usb_otg_hs";
usb-phy = <&usb2_phy>;
+ phys = <&usb2_phy>;
+ phy-names = "usb2-phy";
multipoint = <1>;
num-eps = <16>;
ram-bits = <12>;
diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi
index b3034da..ce4cd6f 100644
--- a/arch/arm/boot/dts/twl4030.dtsi
+++ b/arch/arm/boot/dts/twl4030.dtsi
@@ -80,6 +80,7 @@
usb1v8-supply = <&vusb1v8>;
usb3v1-supply = <&vusb3v1>;
usb_mode = <1>;
+ #phy-cells = <0>;
};
twl_pwm: pwm {
--
1.7.10.4
In order for controllers to get PHY in case of non dt boot, the phy
binding information (phy device name) should be added in the platform
data of the controller.
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Reviewed-by: Sylwester Nawrocki <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
---
arch/arm/mach-omap2/usb-musb.c | 3 +++
include/linux/usb/musb.h | 3 +++
2 files changed, 6 insertions(+)
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 8c4de27..6aa7cbf 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -85,6 +85,9 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
musb_plat.mode = board_data->mode;
musb_plat.extvbus = board_data->extvbus;
+ if (cpu_is_omap34xx())
+ musb_plat.phy_label = "twl4030";
+
if (soc_is_am35xx()) {
oh_name = "am35x_otg_hs";
name = "musb-am35x";
diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
index 053c268..596f8c8 100644
--- a/include/linux/usb/musb.h
+++ b/include/linux/usb/musb.h
@@ -104,6 +104,9 @@ struct musb_hdrc_platform_data {
/* for clk_get() */
const char *clock;
+ /* phy label */
+ const char *phy_label;
+
/* (HOST or OTG) switch VBUS on/off */
int (*set_vbus)(struct device *dev, int is_on);
--
1.7.10.4
Use the generic PHY framework API to get the PHY. The usb_phy_set_resume
and usb_phy_set_suspend is replaced with power_on and
power_off to align with the new PHY framework.
musb->xceiv can't be removed as of now because musb core uses xceiv.state and
xceiv.otg. Once there is a separate state machine to handle otg, these can be
moved out of xceiv and then we can start using the generic PHY framework.
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Reviewed-by: Sylwester Nawrocki <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
---
drivers/usb/musb/Kconfig | 1 +
drivers/usb/musb/musb_core.c | 1 +
drivers/usb/musb/musb_core.h | 3 +++
drivers/usb/musb/omap2430.c | 26 ++++++++++++++++++++------
4 files changed, 25 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 797e3fd..01381ac 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -76,6 +76,7 @@ config USB_MUSB_TUSB6010
config USB_MUSB_OMAP2PLUS
tristate "OMAP2430 and onwards"
depends on ARCH_OMAP2PLUS
+ depends on GENERIC_PHY
config USB_MUSB_AM35X
tristate "AM35x"
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 29a24ce..cca12c0 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1814,6 +1814,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
musb->min_power = plat->min_power;
musb->ops = plat->platform_ops;
musb->port_mode = plat->mode;
+ musb->phy_label = plat->phy_label;
/* The musb_platform_init() call:
* - adjusts musb->mregs
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index 7d341c3..8f017ab 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -46,6 +46,7 @@
#include <linux/usb.h>
#include <linux/usb/otg.h>
#include <linux/usb/musb.h>
+#include <linux/phy/phy.h>
struct musb;
struct musb_hw_ep;
@@ -346,6 +347,7 @@ struct musb {
u16 int_tx;
struct usb_phy *xceiv;
+ struct phy *phy;
int nIrq;
unsigned irq_wake:1;
@@ -424,6 +426,7 @@ struct musb {
unsigned double_buffer_not_ok:1;
struct musb_hdrc_config *config;
+ const char *phy_label;
#ifdef MUSB_CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 6708a3b..87dac0f 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -348,11 +348,21 @@ static int omap2430_musb_init(struct musb *musb)
* up through ULPI. TWL4030-family PMICs include one,
* which needs a driver, drivers aren't always needed.
*/
- if (dev->parent->of_node)
+ if (dev->parent->of_node) {
+ musb->phy = devm_phy_get(dev->parent, "usb2-phy");
+
+ /* We can't totally remove musb->xceiv as of now because
+ * musb core uses xceiv.state and xceiv.otg. Once we have
+ * a separate state machine to handle otg, these can be moved
+ * out of xceiv and then we can start using the generic PHY
+ * framework
+ */
musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent,
"usb-phy", 0);
- else
+ } else {
musb->xceiv = devm_usb_get_phy_dev(dev, 0);
+ musb->phy = devm_phy_get(dev, musb->phy_label);
+ }
if (IS_ERR(musb->xceiv)) {
status = PTR_ERR(musb->xceiv);
@@ -364,6 +374,10 @@ static int omap2430_musb_init(struct musb *musb)
return -EPROBE_DEFER;
}
+ if (IS_ERR(musb->phy)) {
+ pr_err("HS USB OTG: no PHY configured\n");
+ return PTR_ERR(musb->phy);
+ }
musb->isr = omap2430_musb_interrupt;
status = pm_runtime_get_sync(dev);
@@ -397,7 +411,7 @@ static int omap2430_musb_init(struct musb *musb)
if (glue->status != OMAP_MUSB_UNKNOWN)
omap_musb_set_mailbox(glue);
- usb_phy_init(musb->xceiv);
+ phy_init(musb->phy);
pm_runtime_put_noidle(musb->controller);
return 0;
@@ -460,6 +474,7 @@ static int omap2430_musb_exit(struct musb *musb)
del_timer_sync(&musb_idle_timer);
omap2430_low_level_exit(musb);
+ phy_exit(musb->phy);
return 0;
}
@@ -633,7 +648,7 @@ static int omap2430_runtime_suspend(struct device *dev)
OTG_INTERFSEL);
omap2430_low_level_exit(musb);
- usb_phy_set_suspend(musb->xceiv, 1);
+ phy_power_off(musb->phy);
}
return 0;
@@ -648,8 +663,7 @@ static int omap2430_runtime_resume(struct device *dev)
omap2430_low_level_init(musb);
musb_writel(musb->mregs, OTG_INTERFSEL,
musb->context.otg_interfsel);
-
- usb_phy_set_suspend(musb->xceiv, 0);
+ phy_power_on(musb->phy);
}
return 0;
--
1.7.10.4
Now that omap-usb2 is adapted to the new generic PHY framework,
*set_suspend* ops can be removed from omap-usb2 driver.
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Reviewed-by: Sylwester Nawrocki <[email protected]>
---
drivers/usb/phy/phy-omap-usb2.c | 25 -------------------------
1 file changed, 25 deletions(-)
diff --git a/drivers/usb/phy/phy-omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c
index 751b30f..3f2b125 100644
--- a/drivers/usb/phy/phy-omap-usb2.c
+++ b/drivers/usb/phy/phy-omap-usb2.c
@@ -97,29 +97,6 @@ static int omap_usb_set_peripheral(struct usb_otg *otg,
return 0;
}
-static int omap_usb2_suspend(struct usb_phy *x, int suspend)
-{
- u32 ret;
- struct omap_usb *phy = phy_to_omapusb(x);
-
- if (suspend && !phy->is_suspended) {
- omap_control_usb_phy_power(phy->control_dev, 0);
- pm_runtime_put_sync(phy->dev);
- phy->is_suspended = 1;
- } else if (!suspend && phy->is_suspended) {
- ret = pm_runtime_get_sync(phy->dev);
- if (ret < 0) {
- dev_err(phy->dev, "get_sync failed with err %d\n",
- ret);
- return ret;
- }
- omap_control_usb_phy_power(phy->control_dev, 1);
- phy->is_suspended = 0;
- }
-
- return 0;
-}
-
static int omap_usb_power_off(struct phy *x)
{
struct omap_usb *phy = phy_get_drvdata(x);
@@ -167,7 +144,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy->phy.dev = phy->dev;
phy->phy.label = "omap-usb2";
- phy->phy.set_suspend = omap_usb2_suspend;
phy->phy.otg = otg;
phy->phy.type = USB_PHY_TYPE_USB2;
@@ -182,7 +158,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
return -ENODEV;
}
- phy->is_suspended = 1;
omap_control_usb_phy_power(phy->control_dev, 0);
otg->set_host = omap_usb_set_host;
--
1.7.10.4
From: Sylwester Nawrocki <[email protected]>
Add a PHY provider driver for the Samsung S5P/Exynos SoC MIPI CSI-2
receiver and MIPI DSI transmitter DPHYs.
Signed-off-by: Sylwester Nawrocki <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
.../devicetree/bindings/phy/samsung-phy.txt | 14 ++
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 3 +-
drivers/phy/phy-exynos-mipi-video.c | 169 ++++++++++++++++++++
4 files changed, 194 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/phy/samsung-phy.txt
create mode 100644 drivers/phy/phy-exynos-mipi-video.c
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
new file mode 100644
index 0000000..5ff208c
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -0,0 +1,14 @@
+Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY
+-------------------------------------------------
+
+Required properties:
+- compatible : should be "samsung,s5pv210-mipi-video-phy";
+- reg : offset and length of the MIPI DPHY register set;
+- #phy-cells : from the generic phy bindings, must be 1;
+
+For "samsung,s5pv210-mipi-video-phy" compatible PHYs the second cell in
+the PHY specifier identifies the PHY and its meaning is as follows:
+ 0 - MIPI CSIS 0,
+ 1 - MIPI DSIM 0,
+ 2 - MIPI CSIS 1,
+ 3 - MIPI DSIM 1.
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 5f85909..6f446d0 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -11,3 +11,12 @@ menuconfig GENERIC_PHY
devices present in the kernel. This layer will have the generic
API by which phy drivers can create PHY using the phy framework and
phy users can obtain reference to the PHY.
+
+if GENERIC_PHY
+
+config PHY_EXYNOS_MIPI_VIDEO
+ tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
+ help
+ Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung
+ S5P and EXYNOS SoCs.
+endif
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 9e9560f..71d8841 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -2,4 +2,5 @@
# Makefile for the phy drivers.
#
-obj-$(CONFIG_GENERIC_PHY) += phy-core.o
+obj-$(CONFIG_GENERIC_PHY) += phy-core.o
+obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
new file mode 100644
index 0000000..7e7fcd7
--- /dev/null
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -0,0 +1,169 @@
+/*
+ * Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Sylwester Nawrocki <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+
+/* MIPI_PHYn_CONTROL register offset: n = 0..1 */
+#define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4)
+#define EXYNOS_MIPI_PHY_ENABLE (1 << 0)
+#define EXYNOS_MIPI_PHY_SRESETN (1 << 1)
+#define EXYNOS_MIPI_PHY_MRESETN (1 << 2)
+#define EXYNOS_MIPI_PHY_RESET_MASK (3 << 1)
+
+enum exynos_mipi_phy_id {
+ EXYNOS_MIPI_PHY_ID_CSIS0,
+ EXYNOS_MIPI_PHY_ID_DSIM0,
+ EXYNOS_MIPI_PHY_ID_CSIS1,
+ EXYNOS_MIPI_PHY_ID_DSIM1,
+ EXYNOS_MIPI_PHYS_NUM
+};
+
+#define IS_EXYNOS_MIPI_DSIM_PHY_ID(id) \
+ ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM0)
+
+struct exynos_mipi_video_phy {
+ spinlock_t slock;
+ struct phy *phys[EXYNOS_MIPI_PHYS_NUM];
+ void __iomem *regs;
+};
+
+static int __set_phy_state(struct exynos_mipi_video_phy *state,
+ enum exynos_mipi_phy_id id, unsigned int on)
+{
+ void __iomem *addr;
+ u32 reg, reset;
+
+ addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
+
+ if (IS_EXYNOS_MIPI_DSIM_PHY_ID(id))
+ reset = EXYNOS_MIPI_PHY_MRESETN;
+ else
+ reset = EXYNOS_MIPI_PHY_SRESETN;
+
+ spin_lock(&state->slock);
+ reg = readl(addr);
+ if (on)
+ reg |= reset;
+ else
+ reg &= ~reset;
+ writel(reg, addr);
+
+ /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set. */
+ if (on)
+ reg |= EXYNOS_MIPI_PHY_ENABLE;
+ else if (!(reg & EXYNOS_MIPI_PHY_RESET_MASK))
+ reg &= ~EXYNOS_MIPI_PHY_ENABLE;
+
+ writel(reg, addr);
+ spin_unlock(&state->slock);
+ return 0;
+}
+
+static int exynos_mipi_video_phy_power_on(struct phy *phy)
+{
+ struct exynos_mipi_video_phy *state = phy_get_drvdata(phy);
+ return __set_phy_state(state, phy->id, 1);
+}
+
+static int exynos_mipi_video_phy_power_off(struct phy *phy)
+{
+ struct exynos_mipi_video_phy *state = phy_get_drvdata(phy);
+ return __set_phy_state(state, phy->id, 0);
+}
+
+static struct phy *exynos_mipi_video_phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct exynos_mipi_video_phy *state = dev_get_drvdata(dev);
+
+ if (WARN_ON(args->args[0] > EXYNOS_MIPI_PHYS_NUM))
+ return ERR_PTR(-ENODEV);
+
+ return state->phys[args->args[0]];
+}
+
+static struct phy_ops exynos_mipi_video_phy_ops = {
+ .power_on = exynos_mipi_video_phy_power_on,
+ .power_off = exynos_mipi_video_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
+{
+ struct exynos_mipi_video_phy *state;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct phy_provider *phy_provider;
+ int i;
+
+ state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ state->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(state->regs))
+ return PTR_ERR(state->regs);
+
+ dev_set_drvdata(dev, state);
+ spin_lock_init(&state->slock);
+
+ phy_provider = devm_of_phy_provider_register(dev,
+ exynos_mipi_video_phy_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
+ char label[8];
+
+ snprintf(label, sizeof(label), "%s.%d",
+ IS_EXYNOS_MIPI_DSIM_PHY_ID(i) ?
+ "dsim" : "csis", i / 2);
+
+ state->phys[i] = devm_phy_create(dev, i,
+ &exynos_mipi_video_phy_ops, label);
+ if (IS_ERR(state->phys[i])) {
+ dev_err(dev, "failed to create PHY %s\n", label);
+ return PTR_ERR(state->phys[i]);
+ }
+ phy_set_drvdata(state->phys[i], state);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id exynos_mipi_video_phy_of_match[] = {
+ { .compatible = "samsung,s5pv210-mipi-video-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, exynos_mipi_video_phy_of_match);
+
+static struct platform_driver exynos_mipi_video_phy_driver = {
+ .probe = exynos_mipi_video_phy_probe,
+ .driver = {
+ .of_match_table = exynos_mipi_video_phy_of_match,
+ .name = "exynos-mipi-video-phy",
+ .owner = THIS_MODULE,
+ }
+};
+module_platform_driver(exynos_mipi_video_phy_driver);
+
+MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC MIPI CSI-2/DSI PHY driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sylwester Nawrocki <[email protected]>");
--
1.7.10.4
From: Sylwester Nawrocki <[email protected]>
Use the generic PHY API instead of the platform callback to control
the MIPI DSIM DPHY. The 'phy_label' field is added to the platform
data structure to allow PHY lookup on non-dt platforms.
Signed-off-by: Sylwester Nawrocki <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Donghwa Lee <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/video/exynos/exynos_mipi_dsi.c | 19 ++++++++++---------
include/video/exynos_mipi_dsim.h | 6 ++++--
2 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/drivers/video/exynos/exynos_mipi_dsi.c b/drivers/video/exynos/exynos_mipi_dsi.c
index 32e5406..248e444 100644
--- a/drivers/video/exynos/exynos_mipi_dsi.c
+++ b/drivers/video/exynos/exynos_mipi_dsi.c
@@ -30,6 +30,7 @@
#include <linux/interrupt.h>
#include <linux/kthread.h>
#include <linux/notifier.h>
+#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/err.h>
@@ -156,8 +157,7 @@ static int exynos_mipi_dsi_blank_mode(struct mipi_dsim_device *dsim, int power)
exynos_mipi_regulator_enable(dsim);
/* enable MIPI-DSI PHY. */
- if (dsim->pd->phy_enable)
- dsim->pd->phy_enable(pdev, true);
+ phy_power_on(dsim->phy);
clk_enable(dsim->clock);
@@ -373,6 +373,10 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
return ret;
}
+ dsim->phy = devm_phy_get(&pdev->dev, dsim_pd->phy_label);
+ if (IS_ERR(dsim->phy))
+ return PTR_ERR(dsim->phy);
+
dsim->clock = devm_clk_get(&pdev->dev, "dsim0");
if (IS_ERR(dsim->clock)) {
dev_err(&pdev->dev, "failed to get dsim clock source\n");
@@ -439,8 +443,7 @@ static int exynos_mipi_dsi_probe(struct platform_device *pdev)
exynos_mipi_regulator_enable(dsim);
/* enable MIPI-DSI PHY. */
- if (dsim->pd->phy_enable)
- dsim->pd->phy_enable(pdev, true);
+ phy_power_on(dsim->phy);
exynos_mipi_update_cfg(dsim);
@@ -504,9 +507,8 @@ static int exynos_mipi_dsi_suspend(struct device *dev)
if (client_drv && client_drv->suspend)
client_drv->suspend(client_dev);
- /* enable MIPI-DSI PHY. */
- if (dsim->pd->phy_enable)
- dsim->pd->phy_enable(pdev, false);
+ /* disable MIPI-DSI PHY. */
+ phy_power_off(dsim->phy);
clk_disable(dsim->clock);
@@ -536,8 +538,7 @@ static int exynos_mipi_dsi_resume(struct device *dev)
exynos_mipi_regulator_enable(dsim);
/* enable MIPI-DSI PHY. */
- if (dsim->pd->phy_enable)
- dsim->pd->phy_enable(pdev, true);
+ phy_power_on(dsim->phy);
clk_enable(dsim->clock);
diff --git a/include/video/exynos_mipi_dsim.h b/include/video/exynos_mipi_dsim.h
index 89dc88a..0e7e43b 100644
--- a/include/video/exynos_mipi_dsim.h
+++ b/include/video/exynos_mipi_dsim.h
@@ -216,6 +216,7 @@ struct mipi_dsim_config {
* automatically.
* @e_clk_src: select byte clock source.
* @pd: pointer to MIPI-DSI driver platform data.
+ * @phy: pointer to the generic PHY
*/
struct mipi_dsim_device {
struct device *dev;
@@ -236,6 +237,7 @@ struct mipi_dsim_device {
bool suspended;
struct mipi_dsim_platform_data *pd;
+ struct phy *phy;
};
/*
@@ -248,7 +250,7 @@ struct mipi_dsim_device {
* @enabled: indicate whether mipi controller got enabled or not.
* @lcd_panel_info: pointer for lcd panel specific structure.
* this structure specifies width, height, timing and polarity and so on.
- * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ * @phy_label: the generic PHY label
*/
struct mipi_dsim_platform_data {
char lcd_panel_name[PANEL_NAME_SIZE];
@@ -257,7 +259,7 @@ struct mipi_dsim_platform_data {
unsigned int enabled;
void *lcd_panel_info;
- int (*phy_enable)(struct platform_device *pdev, bool on);
+ const char *phy_label;
};
/*
--
1.7.10.4
From: Sylwester Nawrocki <[email protected]>
Use the generic PHY API instead of the platform callback to control
the MIPI CSIS DPHY. The 'phy_label' field is added to the platform
data structure to allow PHY lookup on non-dt platforms
Signed-off-by: Sylwester Nawrocki <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Mauro Carvalho Chehab <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/media/platform/exynos4-is/mipi-csis.c | 16 +++++++++++++---
include/linux/platform_data/mipi-csis.h | 11 ++---------
2 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index 0914230..94028ce 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -20,6 +20,7 @@
#include <linux/memory.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/phy/phy.h>
#include <linux/platform_data/mipi-csis.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -180,6 +181,7 @@ struct csis_drvdata {
* @sd: v4l2_subdev associated with CSIS device instance
* @index: the hardware instance index
* @pdev: CSIS platform device
+ * @phy: pointer to the CSIS generic PHY
* @regs: mmaped I/O registers memory
* @supplies: CSIS regulator supplies
* @clock: CSIS clocks
@@ -203,6 +205,8 @@ struct csis_state {
struct v4l2_subdev sd;
u8 index;
struct platform_device *pdev;
+ struct phy *phy;
+ const char *phy_label;
void __iomem *regs;
struct regulator_bulk_data supplies[CSIS_NUM_SUPPLIES];
struct clk *clock[NUM_CSIS_CLOCKS];
@@ -742,6 +746,7 @@ static int s5pcsis_get_platform_data(struct platform_device *pdev,
state->index = max(0, pdev->id);
state->max_num_lanes = state->index ? CSIS1_MAX_LANES :
CSIS0_MAX_LANES;
+ state->phy_label = pdata->phy_label;
return 0;
}
@@ -779,8 +784,9 @@ static int s5pcsis_parse_dt(struct platform_device *pdev,
"samsung,csis-wclk");
state->num_lanes = endpoint.bus.mipi_csi2.num_data_lanes;
-
of_node_put(node);
+
+ state->phy_label = "csis";
return 0;
}
#else
@@ -829,6 +835,10 @@ static int s5pcsis_probe(struct platform_device *pdev)
return -EINVAL;
}
+ state->phy = devm_phy_get(dev, state->phy_label);
+ if (IS_ERR(state->phy))
+ return PTR_ERR(state->phy);
+
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
state->regs = devm_ioremap_resource(dev, mem_res);
if (IS_ERR(state->regs))
@@ -922,7 +932,7 @@ static int s5pcsis_pm_suspend(struct device *dev, bool runtime)
mutex_lock(&state->lock);
if (state->flags & ST_POWERED) {
s5pcsis_stop_stream(state);
- ret = s5p_csis_phy_enable(state->index, false);
+ ret = phy_power_off(state->phy);
if (ret)
goto unlock;
ret = regulator_bulk_disable(CSIS_NUM_SUPPLIES,
@@ -958,7 +968,7 @@ static int s5pcsis_pm_resume(struct device *dev, bool runtime)
state->supplies);
if (ret)
goto unlock;
- ret = s5p_csis_phy_enable(state->index, true);
+ ret = phy_power_on(state->phy);
if (!ret) {
state->flags |= ST_POWERED;
} else {
diff --git a/include/linux/platform_data/mipi-csis.h b/include/linux/platform_data/mipi-csis.h
index bf34e17..9214317 100644
--- a/include/linux/platform_data/mipi-csis.h
+++ b/include/linux/platform_data/mipi-csis.h
@@ -17,21 +17,14 @@
* @wclk_source: CSI wrapper clock selection: 0 - bus clock, 1 - ext. SCLK_CAM
* @lanes: number of data lanes used
* @hs_settle: HS-RX settle time
+ * @phy_label: the generic PHY label
*/
struct s5p_platform_mipi_csis {
unsigned long clk_rate;
u8 wclk_source;
u8 lanes;
u8 hs_settle;
+ const char *phy_label;
};
-/**
- * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
- * @id: MIPI-CSIS harware instance index (0...1)
- * @on: true to enable D-PHY and deassert its reset
- * false to disable D-PHY
- * @return: 0 on success, or negative error code on failure
- */
-int s5p_csis_phy_enable(int id, bool on);
-
#endif /* __PLAT_SAMSUNG_MIPI_CSIS_H_ */
--
1.7.10.4
From: Sylwester Nawrocki <[email protected]>
Generic PHY drivers are used to handle the MIPI CSIS and MIPI DSIM
DPHYs so we can remove now unused code at arch/arm/plat-samsung.
In case there is any board file for S5PV210 platforms using MIPI
CSIS/DSIM (not any upstream currently) it should use the generic
PHY API to bind the PHYs to respective PHY consumer drivers and
a platform device for the PHY provider should be defined.
Signed-off-by: Sylwester Nawrocki <[email protected]>
Signed-off-by: Kyungmin Park <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Acked-by: Kukjin Kim <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
arch/arm/mach-exynos/include/mach/regs-pmu.h | 5 --
arch/arm/mach-s5pv210/include/mach/regs-clock.h | 4 --
arch/arm/plat-samsung/Kconfig | 5 --
arch/arm/plat-samsung/Makefile | 1 -
arch/arm/plat-samsung/setup-mipiphy.c | 60 -----------------------
5 files changed, 75 deletions(-)
delete mode 100644 arch/arm/plat-samsung/setup-mipiphy.c
diff --git a/arch/arm/mach-exynos/include/mach/regs-pmu.h b/arch/arm/mach-exynos/include/mach/regs-pmu.h
index 57344b7..2cdb63e 100644
--- a/arch/arm/mach-exynos/include/mach/regs-pmu.h
+++ b/arch/arm/mach-exynos/include/mach/regs-pmu.h
@@ -44,11 +44,6 @@
#define S5P_DAC_PHY_CONTROL S5P_PMUREG(0x070C)
#define S5P_DAC_PHY_ENABLE (1 << 0)
-#define S5P_MIPI_DPHY_CONTROL(n) S5P_PMUREG(0x0710 + (n) * 4)
-#define S5P_MIPI_DPHY_ENABLE (1 << 0)
-#define S5P_MIPI_DPHY_SRESETN (1 << 1)
-#define S5P_MIPI_DPHY_MRESETN (1 << 2)
-
#define S5P_INFORM0 S5P_PMUREG(0x0800)
#define S5P_INFORM1 S5P_PMUREG(0x0804)
#define S5P_INFORM2 S5P_PMUREG(0x0808)
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-clock.h b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
index 032de66..e345584 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-clock.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-clock.h
@@ -147,10 +147,6 @@
#define S5P_HDMI_PHY_CONTROL S5P_CLKREG(0xE804)
#define S5P_USB_PHY_CONTROL S5P_CLKREG(0xE80C)
#define S5P_DAC_PHY_CONTROL S5P_CLKREG(0xE810)
-#define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
-#define S5P_MIPI_DPHY_ENABLE (1 << 0)
-#define S5P_MIPI_DPHY_SRESETN (1 << 1)
-#define S5P_MIPI_DPHY_MRESETN (1 << 2)
#define S5P_INFORM0 S5P_CLKREG(0xF000)
#define S5P_INFORM1 S5P_CLKREG(0xF004)
diff --git a/arch/arm/plat-samsung/Kconfig b/arch/arm/plat-samsung/Kconfig
index 3dc5cbe..db2d814 100644
--- a/arch/arm/plat-samsung/Kconfig
+++ b/arch/arm/plat-samsung/Kconfig
@@ -402,11 +402,6 @@ config S3C24XX_PWM
Support for exporting the PWM timer blocks via the pwm device
system
-config S5P_SETUP_MIPIPHY
- bool
- help
- Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices
-
config S3C_SETUP_CAMIF
bool
help
diff --git a/arch/arm/plat-samsung/Makefile b/arch/arm/plat-samsung/Makefile
index 98d07d8..98f1e31 100644
--- a/arch/arm/plat-samsung/Makefile
+++ b/arch/arm/plat-samsung/Makefile
@@ -41,7 +41,6 @@ obj-$(CONFIG_S5P_DEV_UART) += s5p-dev-uart.o
obj-$(CONFIG_SAMSUNG_DEV_BACKLIGHT) += dev-backlight.o
obj-$(CONFIG_S3C_SETUP_CAMIF) += setup-camif.o
-obj-$(CONFIG_S5P_SETUP_MIPIPHY) += setup-mipiphy.o
# DMA support
diff --git a/arch/arm/plat-samsung/setup-mipiphy.c b/arch/arm/plat-samsung/setup-mipiphy.c
deleted file mode 100644
index 66df315..0000000
--- a/arch/arm/plat-samsung/setup-mipiphy.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2011 Samsung Electronics Co., Ltd.
- *
- * S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/export.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <mach/regs-clock.h>
-
-static int __s5p_mipi_phy_control(int id, bool on, u32 reset)
-{
- static DEFINE_SPINLOCK(lock);
- void __iomem *addr;
- unsigned long flags;
- u32 cfg;
-
- id = max(0, id);
- if (id > 1)
- return -EINVAL;
-
- addr = S5P_MIPI_DPHY_CONTROL(id);
-
- spin_lock_irqsave(&lock, flags);
-
- cfg = __raw_readl(addr);
- cfg = on ? (cfg | reset) : (cfg & ~reset);
- __raw_writel(cfg, addr);
-
- if (on) {
- cfg |= S5P_MIPI_DPHY_ENABLE;
- } else if (!(cfg & (S5P_MIPI_DPHY_SRESETN |
- S5P_MIPI_DPHY_MRESETN) & ~reset)) {
- cfg &= ~S5P_MIPI_DPHY_ENABLE;
- }
-
- __raw_writel(cfg, addr);
- spin_unlock_irqrestore(&lock, flags);
-
- return 0;
-}
-
-int s5p_csis_phy_enable(int id, bool on)
-{
- return __s5p_mipi_phy_control(id, on, S5P_MIPI_DPHY_SRESETN);
-}
-EXPORT_SYMBOL(s5p_csis_phy_enable);
-
-int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
-{
- return __s5p_mipi_phy_control(pdev->id, on, S5P_MIPI_DPHY_MRESETN);
-}
-EXPORT_SYMBOL(s5p_dsim_phy_enable);
--
1.7.10.4
From: Jingoo Han <[email protected]>
Use the generic PHY API to control the DP PHY.
Signed-off-by: Jingoo Han <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
.../devicetree/bindings/video/exynos_dp.txt | 18 +++++++++---------
drivers/video/exynos/exynos_dp_core.c | 16 ++++++++++++----
drivers/video/exynos/exynos_dp_core.h | 1 +
3 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/Documentation/devicetree/bindings/video/exynos_dp.txt b/Documentation/devicetree/bindings/video/exynos_dp.txt
index 84f10c1..2f56376 100644
--- a/Documentation/devicetree/bindings/video/exynos_dp.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dp.txt
@@ -6,10 +6,10 @@ We use two nodes:
-dptx-phy node(defined inside dp-controller node)
For the DP-PHY initialization, we use the dptx-phy node.
-Required properties for dptx-phy:
- -reg:
+Required properties for dptx-phy: deprecated, use phys and phy-names
+ -reg: deprecated
Base address of DP PHY register.
- -samsung,enable-mask:
+ -samsung,enable-mask: deprecated
The bit-mask used to enable/disable DP PHY.
For the Panel initialization, we read data from dp-controller node.
@@ -25,6 +25,10 @@ Required properties for dp-controller:
from common clock binding: handle to dp clock.
-clock-names:
from common clock binding: Shall be "dp".
+ -phys:
+ from general PHY binding: the phandle for the PHY device.
+ -phy-names:
+ from general PHY binding: Should be "dp".
-interrupt-parent:
phandle to Interrupt combiner node.
-samsung,color-space:
@@ -67,12 +71,8 @@ SOC specific portion:
interrupt-parent = <&combiner>;
clocks = <&clock 342>;
clock-names = "dp";
-
- dptx-phy {
- reg = <0x10040720>;
- samsung,enable-mask = <1>;
- };
-
+ phys = <&dp_phy>;
+ phy-names = "dp";
};
Board Specific portion:
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index 05fed7d..5e1a715 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -19,6 +19,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/of.h>
+#include <linux/phy/phy.h>
#include "exynos_dp_core.h"
@@ -960,8 +961,11 @@ static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
dp_phy_node = of_find_node_by_name(dp_phy_node, "dptx-phy");
if (!dp_phy_node) {
- dev_err(dp->dev, "could not find dptx-phy node\n");
- return -ENODEV;
+ dp->phy = devm_phy_get(dp->dev, "dp");
+ if (IS_ERR(dp->phy))
+ return PTR_ERR(dp->phy);
+ else
+ return 0;
}
if (of_property_read_u32(dp_phy_node, "reg", &phy_base)) {
@@ -992,7 +996,9 @@ err:
static void exynos_dp_phy_init(struct exynos_dp_device *dp)
{
- if (dp->phy_addr) {
+ if (dp->phy) {
+ phy_power_on(dp->phy);
+ } else if (dp->phy_addr) {
u32 reg;
reg = __raw_readl(dp->phy_addr);
@@ -1003,7 +1009,9 @@ static void exynos_dp_phy_init(struct exynos_dp_device *dp)
static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
{
- if (dp->phy_addr) {
+ if (dp->phy) {
+ phy_power_off(dp->phy);
+ } else if (dp->phy_addr) {
u32 reg;
reg = __raw_readl(dp->phy_addr);
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 56cfec8..607e36d 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -151,6 +151,7 @@ struct exynos_dp_device {
struct video_info *video_info;
struct link_train link_train;
struct work_struct hotplug_work;
+ struct phy *phy;
};
/* exynos_dp_reg.c */
--
1.7.10.4
From: Jingoo Han <[email protected]>
Exynos Display Port can be used only for Exynos SoCs. In addition,
non-DT for EXYNOS SoCs is not supported from v3.11; thus, there is
no need to support non-DT for Exynos Display Port.
The 'include/video/exynos_dp.h' file has been used for non-DT
support and the content of file include/video/exynos_dp.h is moved
to drivers/video/exynos/exynos_dp_core.h. Thus, the 'exynos_dp.h'
file is removed. Also, 'struct exynos_dp_platdata' is removed,
because it is not used any more.
Signed-off-by: Jingoo Han <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
drivers/video/exynos/Kconfig | 2 +-
drivers/video/exynos/exynos_dp_core.c | 116 +++++++----------------------
drivers/video/exynos/exynos_dp_core.h | 109 +++++++++++++++++++++++++++
drivers/video/exynos/exynos_dp_reg.c | 2 -
include/video/exynos_dp.h | 131 ---------------------------------
5 files changed, 135 insertions(+), 225 deletions(-)
delete mode 100644 include/video/exynos_dp.h
diff --git a/drivers/video/exynos/Kconfig b/drivers/video/exynos/Kconfig
index 1b035b2..fab9019 100644
--- a/drivers/video/exynos/Kconfig
+++ b/drivers/video/exynos/Kconfig
@@ -29,7 +29,7 @@ config EXYNOS_LCD_S6E8AX0
config EXYNOS_DP
bool "EXYNOS DP driver support"
- depends on ARCH_EXYNOS
+ depends on OF && ARCH_EXYNOS
default n
help
This enables support for DP device.
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c
index 12bbede..05fed7d 100644
--- a/drivers/video/exynos/exynos_dp_core.c
+++ b/drivers/video/exynos/exynos_dp_core.c
@@ -20,8 +20,6 @@
#include <linux/delay.h>
#include <linux/of.h>
-#include <video/exynos_dp.h>
-
#include "exynos_dp_core.h"
static int exynos_dp_init_dp(struct exynos_dp_device *dp)
@@ -894,26 +892,17 @@ static void exynos_dp_hotplug(struct work_struct *work)
dev_err(dp->dev, "unable to config video\n");
}
-#ifdef CONFIG_OF
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
+static struct video_info *exynos_dp_dt_parse_pdata(struct device *dev)
{
struct device_node *dp_node = dev->of_node;
- struct exynos_dp_platdata *pd;
struct video_info *dp_video_config;
- pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
- if (!pd) {
- dev_err(dev, "memory allocation for pdata failed\n");
- return ERR_PTR(-ENOMEM);
- }
dp_video_config = devm_kzalloc(dev,
sizeof(*dp_video_config), GFP_KERNEL);
-
if (!dp_video_config) {
dev_err(dev, "memory allocation for video config failed\n");
return ERR_PTR(-ENOMEM);
}
- pd->video_info = dp_video_config;
dp_video_config->h_sync_polarity =
of_property_read_bool(dp_node, "hsync-active-high");
@@ -960,7 +949,7 @@ static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
return ERR_PTR(-EINVAL);
}
- return pd;
+ return dp_video_config;
}
static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
@@ -1003,48 +992,30 @@ err:
static void exynos_dp_phy_init(struct exynos_dp_device *dp)
{
- u32 reg;
+ if (dp->phy_addr) {
+ u32 reg;
- reg = __raw_readl(dp->phy_addr);
- reg |= dp->enable_mask;
- __raw_writel(reg, dp->phy_addr);
+ reg = __raw_readl(dp->phy_addr);
+ reg |= dp->enable_mask;
+ __raw_writel(reg, dp->phy_addr);
+ }
}
static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
{
- u32 reg;
-
- reg = __raw_readl(dp->phy_addr);
- reg &= ~(dp->enable_mask);
- __raw_writel(reg, dp->phy_addr);
-}
-#else
-static struct exynos_dp_platdata *exynos_dp_dt_parse_pdata(struct device *dev)
-{
- return NULL;
-}
-
-static int exynos_dp_dt_parse_phydata(struct exynos_dp_device *dp)
-{
- return -EINVAL;
-}
-
-static void exynos_dp_phy_init(struct exynos_dp_device *dp)
-{
- return;
-}
+ if (dp->phy_addr) {
+ u32 reg;
-static void exynos_dp_phy_exit(struct exynos_dp_device *dp)
-{
- return;
+ reg = __raw_readl(dp->phy_addr);
+ reg &= ~(dp->enable_mask);
+ __raw_writel(reg, dp->phy_addr);
+ }
}
-#endif /* CONFIG_OF */
static int exynos_dp_probe(struct platform_device *pdev)
{
struct resource *res;
struct exynos_dp_device *dp;
- struct exynos_dp_platdata *pdata;
int ret = 0;
@@ -1057,21 +1028,13 @@ static int exynos_dp_probe(struct platform_device *pdev)
dp->dev = &pdev->dev;
- if (pdev->dev.of_node) {
- pdata = exynos_dp_dt_parse_pdata(&pdev->dev);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
+ dp->video_info = exynos_dp_dt_parse_pdata(&pdev->dev);
+ if (IS_ERR(dp->video_info))
+ return PTR_ERR(dp->video_info);
- ret = exynos_dp_dt_parse_phydata(dp);
- if (ret)
- return ret;
- } else {
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "no platform data\n");
- return -EINVAL;
- }
- }
+ ret = exynos_dp_dt_parse_phydata(dp);
+ if (ret)
+ return ret;
dp->clock = devm_clk_get(&pdev->dev, "dp");
if (IS_ERR(dp->clock)) {
@@ -1095,15 +1058,7 @@ static int exynos_dp_probe(struct platform_device *pdev)
INIT_WORK(&dp->hotplug_work, exynos_dp_hotplug);
- dp->video_info = pdata->video_info;
-
- if (pdev->dev.of_node) {
- if (dp->phy_addr)
- exynos_dp_phy_init(dp);
- } else {
- if (pdata->phy_init)
- pdata->phy_init();
- }
+ exynos_dp_phy_init(dp);
exynos_dp_init_dp(dp);
@@ -1121,18 +1076,11 @@ static int exynos_dp_probe(struct platform_device *pdev)
static int exynos_dp_remove(struct platform_device *pdev)
{
- struct exynos_dp_platdata *pdata = pdev->dev.platform_data;
struct exynos_dp_device *dp = platform_get_drvdata(pdev);
flush_work(&dp->hotplug_work);
- if (pdev->dev.of_node) {
- if (dp->phy_addr)
- exynos_dp_phy_exit(dp);
- } else {
- if (pdata->phy_exit)
- pdata->phy_exit();
- }
+ exynos_dp_phy_exit(dp);
clk_disable_unprepare(dp->clock);
@@ -1143,20 +1091,13 @@ static int exynos_dp_remove(struct platform_device *pdev)
#ifdef CONFIG_PM_SLEEP
static int exynos_dp_suspend(struct device *dev)
{
- struct exynos_dp_platdata *pdata = dev->platform_data;
struct exynos_dp_device *dp = dev_get_drvdata(dev);
disable_irq(dp->irq);
flush_work(&dp->hotplug_work);
- if (dev->of_node) {
- if (dp->phy_addr)
- exynos_dp_phy_exit(dp);
- } else {
- if (pdata->phy_exit)
- pdata->phy_exit();
- }
+ exynos_dp_phy_exit(dp);
clk_disable_unprepare(dp->clock);
@@ -1165,16 +1106,9 @@ static int exynos_dp_suspend(struct device *dev)
static int exynos_dp_resume(struct device *dev)
{
- struct exynos_dp_platdata *pdata = dev->platform_data;
struct exynos_dp_device *dp = dev_get_drvdata(dev);
- if (dev->of_node) {
- if (dp->phy_addr)
- exynos_dp_phy_init(dp);
- } else {
- if (pdata->phy_init)
- pdata->phy_init();
- }
+ exynos_dp_phy_init(dp);
clk_prepare_enable(dp->clock);
@@ -1203,7 +1137,7 @@ static struct platform_driver exynos_dp_driver = {
.name = "exynos-dp",
.owner = THIS_MODULE,
.pm = &exynos_dp_pm_ops,
- .of_match_table = of_match_ptr(exynos_dp_match),
+ .of_match_table = exynos_dp_match,
},
};
diff --git a/drivers/video/exynos/exynos_dp_core.h b/drivers/video/exynos/exynos_dp_core.h
index 6c567bbf..56cfec8 100644
--- a/drivers/video/exynos/exynos_dp_core.h
+++ b/drivers/video/exynos/exynos_dp_core.h
@@ -13,6 +13,99 @@
#ifndef _EXYNOS_DP_CORE_H
#define _EXYNOS_DP_CORE_H
+#define DP_TIMEOUT_LOOP_COUNT 100
+#define MAX_CR_LOOP 5
+#define MAX_EQ_LOOP 5
+
+enum link_rate_type {
+ LINK_RATE_1_62GBPS = 0x06,
+ LINK_RATE_2_70GBPS = 0x0a
+};
+
+enum link_lane_count_type {
+ LANE_COUNT1 = 1,
+ LANE_COUNT2 = 2,
+ LANE_COUNT4 = 4
+};
+
+enum link_training_state {
+ START,
+ CLOCK_RECOVERY,
+ EQUALIZER_TRAINING,
+ FINISHED,
+ FAILED
+};
+
+enum voltage_swing_level {
+ VOLTAGE_LEVEL_0,
+ VOLTAGE_LEVEL_1,
+ VOLTAGE_LEVEL_2,
+ VOLTAGE_LEVEL_3,
+};
+
+enum pre_emphasis_level {
+ PRE_EMPHASIS_LEVEL_0,
+ PRE_EMPHASIS_LEVEL_1,
+ PRE_EMPHASIS_LEVEL_2,
+ PRE_EMPHASIS_LEVEL_3,
+};
+
+enum pattern_set {
+ PRBS7,
+ D10_2,
+ TRAINING_PTN1,
+ TRAINING_PTN2,
+ DP_NONE
+};
+
+enum color_space {
+ COLOR_RGB,
+ COLOR_YCBCR422,
+ COLOR_YCBCR444
+};
+
+enum color_depth {
+ COLOR_6,
+ COLOR_8,
+ COLOR_10,
+ COLOR_12
+};
+
+enum color_coefficient {
+ COLOR_YCBCR601,
+ COLOR_YCBCR709
+};
+
+enum dynamic_range {
+ VESA,
+ CEA
+};
+
+enum pll_status {
+ PLL_UNLOCKED,
+ PLL_LOCKED
+};
+
+enum clock_recovery_m_value_type {
+ CALCULATED_M,
+ REGISTER_M
+};
+
+enum video_timing_recognition_type {
+ VIDEO_TIMING_FROM_CAPTURE,
+ VIDEO_TIMING_FROM_REGISTER
+};
+
+enum analog_power_block {
+ AUX_BLOCK,
+ CH0_BLOCK,
+ CH1_BLOCK,
+ CH2_BLOCK,
+ CH3_BLOCK,
+ ANALOG_TOTAL,
+ POWER_ALL
+};
+
enum dp_irq_type {
DP_IRQ_TYPE_HP_CABLE_IN,
DP_IRQ_TYPE_HP_CABLE_OUT,
@@ -20,6 +113,22 @@ enum dp_irq_type {
DP_IRQ_TYPE_UNKNOWN,
};
+struct video_info {
+ char *name;
+
+ bool h_sync_polarity;
+ bool v_sync_polarity;
+ bool interlaced;
+
+ enum color_space color_space;
+ enum dynamic_range dynamic_range;
+ enum color_coefficient ycbcr_coeff;
+ enum color_depth color_depth;
+
+ enum link_rate_type link_rate;
+ enum link_lane_count_type lane_count;
+};
+
struct link_train {
int eq_loop;
int cr_loop[4];
diff --git a/drivers/video/exynos/exynos_dp_reg.c b/drivers/video/exynos/exynos_dp_reg.c
index 29d9d03..b70da50 100644
--- a/drivers/video/exynos/exynos_dp_reg.c
+++ b/drivers/video/exynos/exynos_dp_reg.c
@@ -14,8 +14,6 @@
#include <linux/io.h>
#include <linux/delay.h>
-#include <video/exynos_dp.h>
-
#include "exynos_dp_core.h"
#include "exynos_dp_reg.h"
diff --git a/include/video/exynos_dp.h b/include/video/exynos_dp.h
deleted file mode 100644
index bd8cabd..0000000
--- a/include/video/exynos_dp.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Samsung SoC DP device support
- *
- * Copyright (C) 2012 Samsung Electronics Co., Ltd.
- * Author: Jingoo Han <[email protected]>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _EXYNOS_DP_H
-#define _EXYNOS_DP_H
-
-#define DP_TIMEOUT_LOOP_COUNT 100
-#define MAX_CR_LOOP 5
-#define MAX_EQ_LOOP 5
-
-enum link_rate_type {
- LINK_RATE_1_62GBPS = 0x06,
- LINK_RATE_2_70GBPS = 0x0a
-};
-
-enum link_lane_count_type {
- LANE_COUNT1 = 1,
- LANE_COUNT2 = 2,
- LANE_COUNT4 = 4
-};
-
-enum link_training_state {
- START,
- CLOCK_RECOVERY,
- EQUALIZER_TRAINING,
- FINISHED,
- FAILED
-};
-
-enum voltage_swing_level {
- VOLTAGE_LEVEL_0,
- VOLTAGE_LEVEL_1,
- VOLTAGE_LEVEL_2,
- VOLTAGE_LEVEL_3,
-};
-
-enum pre_emphasis_level {
- PRE_EMPHASIS_LEVEL_0,
- PRE_EMPHASIS_LEVEL_1,
- PRE_EMPHASIS_LEVEL_2,
- PRE_EMPHASIS_LEVEL_3,
-};
-
-enum pattern_set {
- PRBS7,
- D10_2,
- TRAINING_PTN1,
- TRAINING_PTN2,
- DP_NONE
-};
-
-enum color_space {
- COLOR_RGB,
- COLOR_YCBCR422,
- COLOR_YCBCR444
-};
-
-enum color_depth {
- COLOR_6,
- COLOR_8,
- COLOR_10,
- COLOR_12
-};
-
-enum color_coefficient {
- COLOR_YCBCR601,
- COLOR_YCBCR709
-};
-
-enum dynamic_range {
- VESA,
- CEA
-};
-
-enum pll_status {
- PLL_UNLOCKED,
- PLL_LOCKED
-};
-
-enum clock_recovery_m_value_type {
- CALCULATED_M,
- REGISTER_M
-};
-
-enum video_timing_recognition_type {
- VIDEO_TIMING_FROM_CAPTURE,
- VIDEO_TIMING_FROM_REGISTER
-};
-
-enum analog_power_block {
- AUX_BLOCK,
- CH0_BLOCK,
- CH1_BLOCK,
- CH2_BLOCK,
- CH3_BLOCK,
- ANALOG_TOTAL,
- POWER_ALL
-};
-
-struct video_info {
- char *name;
-
- bool h_sync_polarity;
- bool v_sync_polarity;
- bool interlaced;
-
- enum color_space color_space;
- enum dynamic_range dynamic_range;
- enum color_coefficient ycbcr_coeff;
- enum color_depth color_depth;
-
- enum link_rate_type link_rate;
- enum link_lane_count_type lane_count;
-};
-
-struct exynos_dp_platdata {
- struct video_info *video_info;
-
- void (*phy_init)(void);
- void (*phy_exit)(void);
-};
-
-#endif /* _EXYNOS_DP_H */
--
1.7.10.4
From: Jingoo Han <[email protected]>
Add a PHY provider driver for the Samsung Exynos SoC Display Port PHY.
Signed-off-by: Jingoo Han <[email protected]>
Reviewed-by: Tomasz Figa <[email protected]>
Cc: Sylwester Nawrocki <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
---
.../devicetree/bindings/phy/samsung-phy.txt | 8 ++
drivers/phy/Kconfig | 6 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-exynos-dp-video.c | 111 ++++++++++++++++++++
4 files changed, 126 insertions(+)
create mode 100644 drivers/phy/phy-exynos-dp-video.c
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 5ff208c..c0fccaa 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -12,3 +12,11 @@ the PHY specifier identifies the PHY and its meaning is as follows:
1 - MIPI DSIM 0,
2 - MIPI CSIS 1,
3 - MIPI DSIM 1.
+
+Samsung EXYNOS SoC series Display Port PHY
+-------------------------------------------------
+
+Required properties:
+- compatible : should be "samsung,exynos5250-dp-video-phy";
+- reg : offset and length of the Display Port PHY register set;
+- #phy-cells : from the generic PHY bindings, must be 0;
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 6f446d0..ed0b1b8 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -19,4 +19,10 @@ config PHY_EXYNOS_MIPI_VIDEO
help
Support for MIPI CSI-2 and MIPI DSI DPHY found on Samsung
S5P and EXYNOS SoCs.
+
+config PHY_EXYNOS_DP_VIDEO
+ tristate "EXYNOS SoC series Display Port PHY driver"
+ depends on OF
+ help
+ Support for Display Port PHY found on Samsung EXYNOS SoCs.
endif
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 71d8841..0fd1340 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -4,3 +4,4 @@
obj-$(CONFIG_GENERIC_PHY) += phy-core.o
obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o
+obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
new file mode 100644
index 0000000..3c8e247
--- /dev/null
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -0,0 +1,111 @@
+/*
+ * Samsung EXYNOS SoC series Display Port PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Jingoo Han <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+/* DPTX_PHY_CONTROL register */
+#define EXYNOS_DPTX_PHY_ENABLE (1 << 0)
+
+struct exynos_dp_video_phy {
+ void __iomem *regs;
+};
+
+static int __set_phy_state(struct exynos_dp_video_phy *state, unsigned int on)
+{
+ u32 reg;
+
+ reg = readl(state->regs);
+ if (on)
+ reg |= EXYNOS_DPTX_PHY_ENABLE;
+ else
+ reg &= ~EXYNOS_DPTX_PHY_ENABLE;
+ writel(reg, state->regs);
+
+ return 0;
+}
+
+static int exynos_dp_video_phy_power_on(struct phy *phy)
+{
+ struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+ return __set_phy_state(state, 1);
+}
+
+static int exynos_dp_video_phy_power_off(struct phy *phy)
+{
+ struct exynos_dp_video_phy *state = phy_get_drvdata(phy);
+
+ return __set_phy_state(state, 0);
+}
+
+static struct phy_ops exynos_dp_video_phy_ops = {
+ .power_on = exynos_dp_video_phy_power_on,
+ .power_off = exynos_dp_video_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int exynos_dp_video_phy_probe(struct platform_device *pdev)
+{
+ struct exynos_dp_video_phy *state;
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ struct phy_provider *phy_provider;
+ struct phy *phy;
+
+ state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
+ if (!state)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ state->regs = devm_ioremap_resource(dev, res);
+ if (IS_ERR(state->regs))
+ return PTR_ERR(state->regs);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ phy = devm_phy_create(dev, 0, &exynos_dp_video_phy_ops, NULL);
+ if (IS_ERR(phy)) {
+ dev_err(dev, "failed to create Display Port PHY\n");
+ return PTR_ERR(phy);
+ }
+ phy_set_drvdata(phy, state);
+
+ return 0;
+}
+
+static const struct of_device_id exynos_dp_video_phy_of_match[] = {
+ { .compatible = "samsung,exynos5250-dp-video-phy" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match);
+
+static struct platform_driver exynos_dp_video_phy_driver = {
+ .probe = exynos_dp_video_phy_probe,
+ .driver = {
+ .name = "exynos-dp-video-phy",
+ .owner = THIS_MODULE,
+ .of_match_table = exynos_dp_video_phy_of_match,
+ }
+};
+module_platform_driver(exynos_dp_video_phy_driver);
+
+MODULE_AUTHOR("Jingoo Han <[email protected]>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
--
1.7.10.4
Now that twl4030-usb is adapted to the new generic PHY framework,
*set_suspend* and *phy_init* ops can be removed from twl4030-usb driver.
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
Reviewed-by: Sylwester Nawrocki <[email protected]>
---
drivers/usb/phy/phy-twl4030-usb.c | 57 +++++++++----------------------------
1 file changed, 13 insertions(+), 44 deletions(-)
diff --git a/drivers/usb/phy/phy-twl4030-usb.c b/drivers/usb/phy/phy-twl4030-usb.c
index 9051756..44f8b1b 100644
--- a/drivers/usb/phy/phy-twl4030-usb.c
+++ b/drivers/usb/phy/phy-twl4030-usb.c
@@ -422,25 +422,20 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on)
}
}
-static void twl4030_phy_suspend(struct twl4030_usb *twl, int controller_off)
+static int twl4030_phy_power_off(struct phy *phy)
{
+ struct twl4030_usb *twl = phy_get_drvdata(phy);
+
if (twl->asleep)
- return;
+ return 0;
twl4030_phy_power(twl, 0);
twl->asleep = 1;
dev_dbg(twl->dev, "%s\n", __func__);
-}
-
-static int twl4030_phy_power_off(struct phy *phy)
-{
- struct twl4030_usb *twl = phy_get_drvdata(phy);
-
- twl4030_phy_suspend(twl, 0);
return 0;
}
-static void __twl4030_phy_resume(struct twl4030_usb *twl)
+static void __twl4030_phy_power_on(struct twl4030_usb *twl)
{
twl4030_phy_power(twl, 1);
twl4030_i2c_access(twl, 1);
@@ -449,11 +444,13 @@ static void __twl4030_phy_resume(struct twl4030_usb *twl)
twl4030_i2c_access(twl, 0);
}
-static void twl4030_phy_resume(struct twl4030_usb *twl)
+static int twl4030_phy_power_on(struct phy *phy)
{
+ struct twl4030_usb *twl = phy_get_drvdata(phy);
+
if (!twl->asleep)
- return;
- __twl4030_phy_resume(twl);
+ return 0;
+ __twl4030_phy_power_on(twl);
twl->asleep = 0;
dev_dbg(twl->dev, "%s\n", __func__);
@@ -466,13 +463,6 @@ static void twl4030_phy_resume(struct twl4030_usb *twl)
cancel_delayed_work(&twl->id_workaround_work);
schedule_delayed_work(&twl->id_workaround_work, HZ);
}
-}
-
-static int twl4030_phy_power_on(struct phy *phy)
-{
- struct twl4030_usb *twl = phy_get_drvdata(phy);
-
- twl4030_phy_resume(twl);
return 0;
}
@@ -604,9 +594,9 @@ static void twl4030_id_workaround_work(struct work_struct *work)
}
}
-static int twl4030_usb_phy_init(struct usb_phy *phy)
+static int twl4030_phy_init(struct phy *phy)
{
- struct twl4030_usb *twl = phy_to_twl(phy);
+ struct twl4030_usb *twl = phy_get_drvdata(phy);
enum omap_musb_vbus_id_status status;
/*
@@ -621,32 +611,13 @@ static int twl4030_usb_phy_init(struct usb_phy *phy)
if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) {
omap_musb_mailbox(twl->linkstat);
- twl4030_phy_resume(twl);
+ twl4030_phy_power_on(phy);
}
sysfs_notify(&twl->dev->kobj, NULL, "vbus");
return 0;
}
-static int twl4030_phy_init(struct phy *phy)
-{
- struct twl4030_usb *twl = phy_get_drvdata(phy);
-
- return twl4030_usb_phy_init(&twl->phy);
-}
-
-static int twl4030_set_suspend(struct usb_phy *x, int suspend)
-{
- struct twl4030_usb *twl = phy_to_twl(x);
-
- if (suspend)
- twl4030_phy_suspend(twl, 1);
- else
- twl4030_phy_resume(twl);
-
- return 0;
-}
-
static int twl4030_set_peripheral(struct usb_otg *otg,
struct usb_gadget *gadget)
{
@@ -717,8 +688,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
twl->phy.label = "twl4030";
twl->phy.otg = otg;
twl->phy.type = USB_PHY_TYPE_USB2;
- twl->phy.set_suspend = twl4030_set_suspend;
- twl->phy.init = twl4030_usb_phy_init;
otg->phy = &twl->phy;
otg->set_host = twl4030_set_host;
--
1.7.10.4
Used the generic PHY framework API to create the PHY. Now the power off and
power on are done in omap_usb_power_off and omap_usb_power_on respectively.
However using the old USB PHY library cannot be completely removed
because OTG is intertwined with PHY and moving to the new framework
will break OTG. Once we have a separate OTG state machine, we
can get rid of the USB PHY library.
Signed-off-by: Kishon Vijay Abraham I <[email protected]>
Reviewed-by: Sylwester Nawrocki <[email protected]>
Acked-by: Felipe Balbi <[email protected]>
---
drivers/usb/phy/Kconfig | 1 +
drivers/usb/phy/phy-omap-usb2.c | 45 +++++++++++++++++++++++++++++++++++----
2 files changed, 42 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 3622fff..cc55993 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -75,6 +75,7 @@ config OMAP_CONTROL_USB
config OMAP_USB2
tristate "OMAP USB2 PHY Driver"
depends on ARCH_OMAP2PLUS
+ depends on GENERIC_PHY
select OMAP_CONTROL_USB
help
Enable this to support the transceiver that is part of SOC. This
diff --git a/drivers/usb/phy/phy-omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c
index 844ab68..751b30f 100644
--- a/drivers/usb/phy/phy-omap-usb2.c
+++ b/drivers/usb/phy/phy-omap-usb2.c
@@ -28,6 +28,7 @@
#include <linux/pm_runtime.h>
#include <linux/delay.h>
#include <linux/usb/omap_control_usb.h>
+#include <linux/phy/phy.h>
/**
* omap_usb2_set_comparator - links the comparator present in the sytem with
@@ -119,10 +120,36 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
return 0;
}
+static int omap_usb_power_off(struct phy *x)
+{
+ struct omap_usb *phy = phy_get_drvdata(x);
+
+ omap_control_usb_phy_power(phy->control_dev, 0);
+
+ return 0;
+}
+
+static int omap_usb_power_on(struct phy *x)
+{
+ struct omap_usb *phy = phy_get_drvdata(x);
+
+ omap_control_usb_phy_power(phy->control_dev, 1);
+
+ return 0;
+}
+
+static struct phy_ops ops = {
+ .power_on = omap_usb_power_on,
+ .power_off = omap_usb_power_off,
+ .owner = THIS_MODULE,
+};
+
static int omap_usb2_probe(struct platform_device *pdev)
{
struct omap_usb *phy;
+ struct phy *generic_phy;
struct usb_otg *otg;
+ struct phy_provider *phy_provider;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy) {
@@ -144,6 +171,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
phy->phy.otg = otg;
phy->phy.type = USB_PHY_TYPE_USB2;
+ phy_provider = devm_of_phy_provider_register(phy->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
phy->control_dev = omap_get_control_dev();
if (IS_ERR(phy->control_dev)) {
dev_dbg(&pdev->dev, "Failed to get control device\n");
@@ -159,6 +191,15 @@ static int omap_usb2_probe(struct platform_device *pdev)
otg->start_srp = omap_usb_start_srp;
otg->phy = &phy->phy;
+ platform_set_drvdata(pdev, phy);
+ pm_runtime_enable(phy->dev);
+
+ generic_phy = devm_phy_create(phy->dev, 0, &ops, "omap-usb2");
+ if (IS_ERR(generic_phy))
+ return PTR_ERR(generic_phy);
+
+ phy_set_drvdata(generic_phy, phy);
+
phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
if (IS_ERR(phy->wkupclk)) {
dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
@@ -174,10 +215,6 @@ static int omap_usb2_probe(struct platform_device *pdev)
usb_add_phy_dev(&phy->phy);
- platform_set_drvdata(pdev, phy);
-
- pm_runtime_enable(phy->dev);
-
return 0;
}
--
1.7.10.4
* Kishon Vijay Abraham I <[email protected]> [130717 23:53]:
> In order for controllers to get PHY in case of non dt boot, the phy
> binding information (phy device name) should be added in the platform
> data of the controller.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> Reviewed-by: Sylwester Nawrocki <[email protected]>
> Acked-by: Felipe Balbi <[email protected]>
> ---
> arch/arm/mach-omap2/usb-musb.c | 3 +++
> include/linux/usb/musb.h | 3 +++
> 2 files changed, 6 insertions(+)
>
> diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
> index 8c4de27..6aa7cbf 100644
> --- a/arch/arm/mach-omap2/usb-musb.c
> +++ b/arch/arm/mach-omap2/usb-musb.c
> @@ -85,6 +85,9 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data)
> musb_plat.mode = board_data->mode;
> musb_plat.extvbus = board_data->extvbus;
>
> + if (cpu_is_omap34xx())
> + musb_plat.phy_label = "twl4030";
> +
> if (soc_is_am35xx()) {
> oh_name = "am35x_otg_hs";
> name = "musb-am35x";
I don't think there's a USB PHY on non-twl4030 chips, so this should
be OK:
Acked-by: Tony Lindgren <[email protected]>
> diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h
> index 053c268..596f8c8 100644
> --- a/include/linux/usb/musb.h
> +++ b/include/linux/usb/musb.h
> @@ -104,6 +104,9 @@ struct musb_hdrc_platform_data {
> /* for clk_get() */
> const char *clock;
>
> + /* phy label */
> + const char *phy_label;
> +
> /* (HOST or OTG) switch VBUS on/off */
> int (*set_vbus)(struct device *dev, int is_on);
>
> --
> 1.7.10.4
>
* Kishon Vijay Abraham I <[email protected]> [130717 23:53]:
> Updated the usb_otg_hs dt data to include the *phy* and *phy-names*
> binding in order for the driver to use the new generic PHY framework.
> Also updated the Documentation to include the binding information.
> The PHY binding information can be found at
> Documentation/devicetree/bindings/phy/phy-bindings.txt
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> Acked-by: Felipe Balbi <[email protected]>
> Reviewed-by: Sylwester Nawrocki <[email protected]>
In general the .dts changes should be separate to avoid pointless
merge conflicts. But sounds like things will stop working for
USB unless we do it like this so:
Acked-by: Tony Lindgren <[email protected]>
> ---
> Documentation/devicetree/bindings/usb/omap-usb.txt | 5 +++++
> Documentation/devicetree/bindings/usb/usb-phy.txt | 6 ++++++
> arch/arm/boot/dts/omap3-beagle-xm.dts | 2 ++
> arch/arm/boot/dts/omap3-evm.dts | 2 ++
> arch/arm/boot/dts/omap3-overo.dtsi | 2 ++
> arch/arm/boot/dts/omap4.dtsi | 3 +++
> arch/arm/boot/dts/twl4030.dtsi | 1 +
> 7 files changed, 21 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt
> index 57e71f6..825790d 100644
> --- a/Documentation/devicetree/bindings/usb/omap-usb.txt
> +++ b/Documentation/devicetree/bindings/usb/omap-usb.txt
> @@ -19,6 +19,9 @@ OMAP MUSB GLUE
> - power : Should be "50". This signifies the controller can supply up to
> 100mA when operating in host mode.
> - usb-phy : the phandle for the PHY device
> + - phys : the phandle for the PHY device (used by generic PHY framework)
> + - phy-names : the names of the PHY corresponding to the PHYs present in the
> + *phy* phandle.
>
> Optional properties:
> - ctrl-module : phandle of the control module this glue uses to write to
> @@ -33,6 +36,8 @@ usb_otg_hs: usb_otg_hs@4a0ab000 {
> num-eps = <16>;
> ram-bits = <12>;
> ctrl-module = <&omap_control_usb>;
> + phys = <&usb2_phy>;
> + phy-names = "usb2-phy";
> };
>
> Board specific device node entry
> diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt
> index 61496f5..c0245c8 100644
> --- a/Documentation/devicetree/bindings/usb/usb-phy.txt
> +++ b/Documentation/devicetree/bindings/usb/usb-phy.txt
> @@ -5,6 +5,8 @@ OMAP USB2 PHY
> Required properties:
> - compatible: Should be "ti,omap-usb2"
> - reg : Address and length of the register set for the device.
> + - #phy-cells: determine the number of cells that should be given in the
> + phandle while referencing this phy.
>
> Optional properties:
> - ctrl-module : phandle of the control module used by PHY driver to power on
> @@ -16,6 +18,7 @@ usb2phy@4a0ad080 {
> compatible = "ti,omap-usb2";
> reg = <0x4a0ad080 0x58>;
> ctrl-module = <&omap_control_usb>;
> + #phy-cells = <0>;
> };
>
> OMAP USB3 PHY
> @@ -25,6 +28,8 @@ Required properties:
> - reg : Address and length of the register set for the device.
> - reg-names: The names of the register addresses corresponding to the registers
> filled in "reg".
> + - #phy-cells: determine the number of cells that should be given in the
> + phandle while referencing this phy.
>
> Optional properties:
> - ctrl-module : phandle of the control module used by PHY driver to power on
> @@ -39,4 +44,5 @@ usb3phy@4a084400 {
> <0x4a084c00 0x40>;
> reg-names = "phy_rx", "phy_tx", "pll_ctrl";
> ctrl-module = <&omap_control_usb>;
> + #phy-cells = <0>;
> };
> diff --git a/arch/arm/boot/dts/omap3-beagle-xm.dts b/arch/arm/boot/dts/omap3-beagle-xm.dts
> index afdb164..533b2da 100644
> --- a/arch/arm/boot/dts/omap3-beagle-xm.dts
> +++ b/arch/arm/boot/dts/omap3-beagle-xm.dts
> @@ -144,6 +144,8 @@
> &usb_otg_hs {
> interface-type = <0>;
> usb-phy = <&usb2_phy>;
> + phys = <&usb2_phy>;
> + phy-names = "usb2-phy";
> mode = <3>;
> power = <50>;
> };
> diff --git a/arch/arm/boot/dts/omap3-evm.dts b/arch/arm/boot/dts/omap3-evm.dts
> index 7d4329d..4134dd0 100644
> --- a/arch/arm/boot/dts/omap3-evm.dts
> +++ b/arch/arm/boot/dts/omap3-evm.dts
> @@ -70,6 +70,8 @@
> &usb_otg_hs {
> interface-type = <0>;
> usb-phy = <&usb2_phy>;
> + phys = <&usb2_phy>;
> + phy-names = "usb2-phy";
> mode = <3>;
> power = <50>;
> };
> diff --git a/arch/arm/boot/dts/omap3-overo.dtsi b/arch/arm/boot/dts/omap3-overo.dtsi
> index 8f1abec..a461d2f 100644
> --- a/arch/arm/boot/dts/omap3-overo.dtsi
> +++ b/arch/arm/boot/dts/omap3-overo.dtsi
> @@ -76,6 +76,8 @@
> &usb_otg_hs {
> interface-type = <0>;
> usb-phy = <&usb2_phy>;
> + phys = <&usb2_phy>;
> + phy-names = "usb2-phy";
> mode = <3>;
> power = <50>;
> };
> diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi
> index 22d9f2b..1e8e2fe 100644
> --- a/arch/arm/boot/dts/omap4.dtsi
> +++ b/arch/arm/boot/dts/omap4.dtsi
> @@ -520,6 +520,7 @@
> compatible = "ti,omap-usb2";
> reg = <0x4a0ad080 0x58>;
> ctrl-module = <&omap_control_usb>;
> + #phy-cells = <0>;
> };
> };
>
> @@ -658,6 +659,8 @@
> interrupt-names = "mc", "dma";
> ti,hwmods = "usb_otg_hs";
> usb-phy = <&usb2_phy>;
> + phys = <&usb2_phy>;
> + phy-names = "usb2-phy";
> multipoint = <1>;
> num-eps = <16>;
> ram-bits = <12>;
> diff --git a/arch/arm/boot/dts/twl4030.dtsi b/arch/arm/boot/dts/twl4030.dtsi
> index b3034da..ce4cd6f 100644
> --- a/arch/arm/boot/dts/twl4030.dtsi
> +++ b/arch/arm/boot/dts/twl4030.dtsi
> @@ -80,6 +80,7 @@
> usb1v8-supply = <&vusb1v8>;
> usb3v1-supply = <&vusb3v1>;
> usb_mode = <1>;
> + #phy-cells = <0>;
> };
>
> twl_pwm: pwm {
> --
> 1.7.10.4
>
On Thu, Jul 18, 2013 at 12:16:10PM +0530, Kishon Vijay Abraham I wrote:
> +struct phy_provider *__of_phy_provider_register(struct device *dev,
> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
> + struct of_phandle_args *args));
> +struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
> + struct of_phandle_args *args))
> +
> +__of_phy_provider_register and __devm_of_phy_provider_register can be used to
> +register the phy_provider and it takes device, owner and of_xlate as
> +arguments. For the dt boot case, all PHY providers should use one of the above
> +2 APIs to register the PHY provider.
Why do you have __ for the prefix of a public function? Is that really
the way that OF handles this type of thing?
> --- /dev/null
> +++ b/drivers/phy/Kconfig
> @@ -0,0 +1,13 @@
> +#
> +# PHY
> +#
> +
> +menuconfig GENERIC_PHY
> + tristate "PHY Subsystem"
> + help
> + Generic PHY support.
> +
> + This framework is designed to provide a generic interface for PHY
> + devices present in the kernel. This layer will have the generic
> + API by which phy drivers can create PHY using the phy framework and
> + phy users can obtain reference to the PHY.
Again, please reverse this. The drivers that use it should select it,
not depend on it, which will then enable this option. I will never know
if I need to enable it, and based on your follow-on patches, if I don't,
drivers that were working just fine, now disappeared from my build,
which isn't nice, and a pain to notice and fix up.
> +/**
> + * phy_create() - create a new phy
> + * @dev: device that is creating the new phy
> + * @id: id of the phy
> + * @ops: function pointers for performing phy operations
> + * @label: label given to the phy
> + *
> + * Called to create a phy using phy framework.
> + */
> +struct phy *phy_create(struct device *dev, u8 id, const struct phy_ops *ops,
> + const char *label)
> +{
> + int ret;
> + struct phy *phy;
> +
> + if (!dev) {
> + dev_WARN(dev, "no device provided for PHY\n");
> + ret = -EINVAL;
> + goto err0;
> + }
> +
> + phy = kzalloc(sizeof(*phy), GFP_KERNEL);
> + if (!phy) {
> + ret = -ENOMEM;
> + goto err0;
> + }
> +
> + device_initialize(&phy->dev);
> + mutex_init(&phy->mutex);
> +
> + phy->dev.class = phy_class;
> + phy->dev.parent = dev;
> + phy->dev.of_node = dev->of_node;
> + phy->id = id;
> + phy->ops = ops;
> + phy->label = kstrdup(label, GFP_KERNEL);
> +
> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
Your naming is odd, no "phy" anywhere in it? You rely on the sender to
never send a duplicate name.id pair? Why not create your own ids based
on the number of phys in the system, like almost all other classes and
subsystems do?
> +static inline int phy_pm_runtime_get(struct phy *phy)
> +{
> + if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
> + return -EINVAL;
Why would phy ever not be valid and a error pointer? And why dump the
stack if that happens, that seems really extreme.
> +
> + if (!pm_runtime_enabled(&phy->dev))
> + return -ENOTSUPP;
> +
> + return pm_runtime_get(&phy->dev);
> +}
This, and the other inline functions in this .h file seem huge, why are
they inline and not in the .c file? There's no speed issues, and it
should save space overall in the .c file. Please move them.
> +static inline int phy_init(struct phy *phy)
> +{
> + int ret;
> +
> + ret = phy_pm_runtime_get_sync(phy);
> + if (ret < 0 && ret != -ENOTSUPP)
> + return ret;
> +
> + mutex_lock(&phy->mutex);
> + if (phy->init_count++ == 0 && phy->ops->init) {
> + ret = phy->ops->init(phy);
> + if (ret < 0) {
> + dev_err(&phy->dev, "phy init failed --> %d\n", ret);
> + goto out;
> + }
> + }
> +
> +out:
> + mutex_unlock(&phy->mutex);
> + phy_pm_runtime_put(phy);
> + return ret;
> +}
> +
> +static inline int phy_exit(struct phy *phy)
> +{
> + int ret;
> +
> + ret = phy_pm_runtime_get_sync(phy);
> + if (ret < 0 && ret != -ENOTSUPP)
> + return ret;
> +
> + mutex_lock(&phy->mutex);
> + if (--phy->init_count == 0 && phy->ops->exit) {
> + ret = phy->ops->exit(phy);
> + if (ret < 0) {
> + dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
> + goto out;
> + }
> + }
> +
> +out:
> + mutex_unlock(&phy->mutex);
> + phy_pm_runtime_put(phy);
> + return ret;
> +}
> +
> +static inline int phy_power_on(struct phy *phy)
> +{
> + int ret = -ENOTSUPP;
> +
> + ret = phy_pm_runtime_get_sync(phy);
> + if (ret < 0 && ret != -ENOTSUPP)
> + return ret;
> +
> + mutex_lock(&phy->mutex);
> + if (phy->power_count++ == 0 && phy->ops->power_on) {
> + ret = phy->ops->power_on(phy);
> + if (ret < 0) {
> + dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
> + goto out;
> + }
> + }
> +
> +out:
> + mutex_unlock(&phy->mutex);
> +
> + return ret;
> +}
> +
> +static inline int phy_power_off(struct phy *phy)
> +{
> + int ret = -ENOTSUPP;
> +
> + mutex_lock(&phy->mutex);
> + if (--phy->power_count == 0 && phy->ops->power_off) {
> + ret = phy->ops->power_off(phy);
> + if (ret < 0) {
> + dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
> + goto out;
> + }
> + }
> +
> +out:
> + mutex_unlock(&phy->mutex);
> + phy_pm_runtime_put(phy);
> +
> + return ret;
> +}
Look at those 3 functions, they are all "real" and not an inline
function at all, please move them.
thanks,
greg k-h
On Thu, Jul 18, 2013 at 12:16:11PM +0530, Kishon Vijay Abraham I wrote:
> Used the generic PHY framework API to create the PHY. Now the power off and
> power on are done in omap_usb_power_off and omap_usb_power_on respectively.
>
> However using the old USB PHY library cannot be completely removed
> because OTG is intertwined with PHY and moving to the new framework
> will break OTG. Once we have a separate OTG state machine, we
> can get rid of the USB PHY library.
>
> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
> Reviewed-by: Sylwester Nawrocki <[email protected]>
> Acked-by: Felipe Balbi <[email protected]>
> ---
> drivers/usb/phy/Kconfig | 1 +
> drivers/usb/phy/phy-omap-usb2.c | 45 +++++++++++++++++++++++++++++++++++----
> 2 files changed, 42 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> index 3622fff..cc55993 100644
> --- a/drivers/usb/phy/Kconfig
> +++ b/drivers/usb/phy/Kconfig
> @@ -75,6 +75,7 @@ config OMAP_CONTROL_USB
> config OMAP_USB2
> tristate "OMAP USB2 PHY Driver"
> depends on ARCH_OMAP2PLUS
> + depends on GENERIC_PHY
> select OMAP_CONTROL_USB
> help
> Enable this to support the transceiver that is part of SOC. This
> diff --git a/drivers/usb/phy/phy-omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c
> index 844ab68..751b30f 100644
> --- a/drivers/usb/phy/phy-omap-usb2.c
> +++ b/drivers/usb/phy/phy-omap-usb2.c
> @@ -28,6 +28,7 @@
> #include <linux/pm_runtime.h>
> #include <linux/delay.h>
> #include <linux/usb/omap_control_usb.h>
> +#include <linux/phy/phy.h>
>
> /**
> * omap_usb2_set_comparator - links the comparator present in the sytem with
> @@ -119,10 +120,36 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
> return 0;
> }
>
> +static int omap_usb_power_off(struct phy *x)
> +{
> + struct omap_usb *phy = phy_get_drvdata(x);
> +
> + omap_control_usb_phy_power(phy->control_dev, 0);
> +
> + return 0;
> +}
> +
> +static int omap_usb_power_on(struct phy *x)
> +{
> + struct omap_usb *phy = phy_get_drvdata(x);
> +
> + omap_control_usb_phy_power(phy->control_dev, 1);
> +
> + return 0;
> +}
> +
> +static struct phy_ops ops = {
> + .power_on = omap_usb_power_on,
> + .power_off = omap_usb_power_off,
> + .owner = THIS_MODULE,
> +};
> +
> static int omap_usb2_probe(struct platform_device *pdev)
> {
> struct omap_usb *phy;
> + struct phy *generic_phy;
> struct usb_otg *otg;
> + struct phy_provider *phy_provider;
>
> phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
> if (!phy) {
> @@ -144,6 +171,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
> phy->phy.otg = otg;
> phy->phy.type = USB_PHY_TYPE_USB2;
>
> + phy_provider = devm_of_phy_provider_register(phy->dev,
> + of_phy_simple_xlate);
> + if (IS_ERR(phy_provider))
> + return PTR_ERR(phy_provider);
> +
> phy->control_dev = omap_get_control_dev();
> if (IS_ERR(phy->control_dev)) {
> dev_dbg(&pdev->dev, "Failed to get control device\n");
> @@ -159,6 +191,15 @@ static int omap_usb2_probe(struct platform_device *pdev)
> otg->start_srp = omap_usb_start_srp;
> otg->phy = &phy->phy;
>
> + platform_set_drvdata(pdev, phy);
> + pm_runtime_enable(phy->dev);
> +
> + generic_phy = devm_phy_create(phy->dev, 0, &ops, "omap-usb2");
> + if (IS_ERR(generic_phy))
> + return PTR_ERR(generic_phy);
So, if I have two of these controllers in my system, I can't create the
second phy because the name for it will be identical to the first?
That's why the phy core should handle the id, and not rely on the
drivers to set it, as they have no idea how many they have in the
system.
thanks,
greg k-h
Hi,
On Thursday 18 July 2013 12:50 PM, Greg KH wrote:
> On Thu, Jul 18, 2013 at 12:16:10PM +0530, Kishon Vijay Abraham I wrote:
>> +struct phy_provider *__of_phy_provider_register(struct device *dev,
>> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
>> + struct of_phandle_args *args));
>> +struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
>> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
>> + struct of_phandle_args *args))
>> +
>> +__of_phy_provider_register and __devm_of_phy_provider_register can be used to
>> +register the phy_provider and it takes device, owner and of_xlate as
>> +arguments. For the dt boot case, all PHY providers should use one of the above
>> +2 APIs to register the PHY provider.
>
> Why do you have __ for the prefix of a public function? Is that really
> the way that OF handles this type of thing?
I have a macro of_phy_provider_register/devm_of_phy_provider_register that
calls these functions and should be used by the PHY drivers. Probably I should
make a mention of it in the Documentation.
>
>> --- /dev/null
>> +++ b/drivers/phy/Kconfig
>> @@ -0,0 +1,13 @@
>> +#
>> +# PHY
>> +#
>> +
>> +menuconfig GENERIC_PHY
>> + tristate "PHY Subsystem"
>> + help
>> + Generic PHY support.
>> +
>> + This framework is designed to provide a generic interface for PHY
>> + devices present in the kernel. This layer will have the generic
>> + API by which phy drivers can create PHY using the phy framework and
>> + phy users can obtain reference to the PHY.
>
> Again, please reverse this. The drivers that use it should select it,
> not depend on it, which will then enable this option. I will never know
> if I need to enable it, and based on your follow-on patches, if I don't,
> drivers that were working just fine, now disappeared from my build,
> which isn't nice, and a pain to notice and fix up.
ok.
>
>> +/**
>> + * phy_create() - create a new phy
>> + * @dev: device that is creating the new phy
>> + * @id: id of the phy
>> + * @ops: function pointers for performing phy operations
>> + * @label: label given to the phy
>> + *
>> + * Called to create a phy using phy framework.
>> + */
>> +struct phy *phy_create(struct device *dev, u8 id, const struct phy_ops *ops,
>> + const char *label)
>> +{
>> + int ret;
>> + struct phy *phy;
>> +
>> + if (!dev) {
>> + dev_WARN(dev, "no device provided for PHY\n");
>> + ret = -EINVAL;
>> + goto err0;
>> + }
>> +
>> + phy = kzalloc(sizeof(*phy), GFP_KERNEL);
>> + if (!phy) {
>> + ret = -ENOMEM;
>> + goto err0;
>> + }
>> +
>> + device_initialize(&phy->dev);
>> + mutex_init(&phy->mutex);
>> +
>> + phy->dev.class = phy_class;
>> + phy->dev.parent = dev;
>> + phy->dev.of_node = dev->of_node;
>> + phy->id = id;
>> + phy->ops = ops;
>> + phy->label = kstrdup(label, GFP_KERNEL);
>> +
>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
>
> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
> never send a duplicate name.id pair? Why not create your own ids based
> on the number of phys in the system, like almost all other classes and
> subsystems do?
hmm.. some PHY drivers use the id they provide to perform some of their
internal operation as in [1] (This is used only if a single PHY provider
implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
to give the PHY drivers an option to use auto id.
[1] ->
http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
>
>> +static inline int phy_pm_runtime_get(struct phy *phy)
>> +{
>> + if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
>> + return -EINVAL;
>
> Why would phy ever not be valid and a error pointer? And why dump the
> stack if that happens, that seems really extreme.
hmm.. there might be cases where the same controller in one soc needs PHY
control and in some other soc does not need PHY control. In such cases, we
might get error pointer here.
I'll change WARN to dev_err.
>
>> +
>> + if (!pm_runtime_enabled(&phy->dev))
>> + return -ENOTSUPP;
>> +
>> + return pm_runtime_get(&phy->dev);
>> +}
>
> This, and the other inline functions in this .h file seem huge, why are
> they inline and not in the .c file? There's no speed issues, and it
> should save space overall in the .c file. Please move them.
ok
>
>
>> +static inline int phy_init(struct phy *phy)
>> +{
>> + int ret;
>> +
>> + ret = phy_pm_runtime_get_sync(phy);
>> + if (ret < 0 && ret != -ENOTSUPP)
>> + return ret;
>> +
>> + mutex_lock(&phy->mutex);
>> + if (phy->init_count++ == 0 && phy->ops->init) {
>> + ret = phy->ops->init(phy);
>> + if (ret < 0) {
>> + dev_err(&phy->dev, "phy init failed --> %d\n", ret);
>> + goto out;
>> + }
>> + }
>> +
>> +out:
>> + mutex_unlock(&phy->mutex);
>> + phy_pm_runtime_put(phy);
>> + return ret;
>> +}
>> +
>> +static inline int phy_exit(struct phy *phy)
>> +{
>> + int ret;
>> +
>> + ret = phy_pm_runtime_get_sync(phy);
>> + if (ret < 0 && ret != -ENOTSUPP)
>> + return ret;
>> +
>> + mutex_lock(&phy->mutex);
>> + if (--phy->init_count == 0 && phy->ops->exit) {
>> + ret = phy->ops->exit(phy);
>> + if (ret < 0) {
>> + dev_err(&phy->dev, "phy exit failed --> %d\n", ret);
>> + goto out;
>> + }
>> + }
>> +
>> +out:
>> + mutex_unlock(&phy->mutex);
>> + phy_pm_runtime_put(phy);
>> + return ret;
>> +}
>> +
>> +static inline int phy_power_on(struct phy *phy)
>> +{
>> + int ret = -ENOTSUPP;
>> +
>> + ret = phy_pm_runtime_get_sync(phy);
>> + if (ret < 0 && ret != -ENOTSUPP)
>> + return ret;
>> +
>> + mutex_lock(&phy->mutex);
>> + if (phy->power_count++ == 0 && phy->ops->power_on) {
>> + ret = phy->ops->power_on(phy);
>> + if (ret < 0) {
>> + dev_err(&phy->dev, "phy poweron failed --> %d\n", ret);
>> + goto out;
>> + }
>> + }
>> +
>> +out:
>> + mutex_unlock(&phy->mutex);
>> +
>> + return ret;
>> +}
>> +
>> +static inline int phy_power_off(struct phy *phy)
>> +{
>> + int ret = -ENOTSUPP;
>> +
>> + mutex_lock(&phy->mutex);
>> + if (--phy->power_count == 0 && phy->ops->power_off) {
>> + ret = phy->ops->power_off(phy);
>> + if (ret < 0) {
>> + dev_err(&phy->dev, "phy poweroff failed --> %d\n", ret);
>> + goto out;
>> + }
>> + }
>> +
>> +out:
>> + mutex_unlock(&phy->mutex);
>> + phy_pm_runtime_put(phy);
>> +
>> + return ret;
>> +}
>
> Look at those 3 functions, they are all "real" and not an inline
> function at all, please move them.
Alright.
Thanks
Kishon
On Thursday 18 July 2013 12:51 PM, Greg KH wrote:
> On Thu, Jul 18, 2013 at 12:16:11PM +0530, Kishon Vijay Abraham I wrote:
>> Used the generic PHY framework API to create the PHY. Now the power off and
>> power on are done in omap_usb_power_off and omap_usb_power_on respectively.
>>
>> However using the old USB PHY library cannot be completely removed
>> because OTG is intertwined with PHY and moving to the new framework
>> will break OTG. Once we have a separate OTG state machine, we
>> can get rid of the USB PHY library.
>>
>> Signed-off-by: Kishon Vijay Abraham I <[email protected]>
>> Reviewed-by: Sylwester Nawrocki <[email protected]>
>> Acked-by: Felipe Balbi <[email protected]>
>> ---
>> drivers/usb/phy/Kconfig | 1 +
>> drivers/usb/phy/phy-omap-usb2.c | 45 +++++++++++++++++++++++++++++++++++----
>> 2 files changed, 42 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
>> index 3622fff..cc55993 100644
>> --- a/drivers/usb/phy/Kconfig
>> +++ b/drivers/usb/phy/Kconfig
>> @@ -75,6 +75,7 @@ config OMAP_CONTROL_USB
>> config OMAP_USB2
>> tristate "OMAP USB2 PHY Driver"
>> depends on ARCH_OMAP2PLUS
>> + depends on GENERIC_PHY
>> select OMAP_CONTROL_USB
>> help
>> Enable this to support the transceiver that is part of SOC. This
>> diff --git a/drivers/usb/phy/phy-omap-usb2.c b/drivers/usb/phy/phy-omap-usb2.c
>> index 844ab68..751b30f 100644
>> --- a/drivers/usb/phy/phy-omap-usb2.c
>> +++ b/drivers/usb/phy/phy-omap-usb2.c
>> @@ -28,6 +28,7 @@
>> #include <linux/pm_runtime.h>
>> #include <linux/delay.h>
>> #include <linux/usb/omap_control_usb.h>
>> +#include <linux/phy/phy.h>
>>
>> /**
>> * omap_usb2_set_comparator - links the comparator present in the sytem with
>> @@ -119,10 +120,36 @@ static int omap_usb2_suspend(struct usb_phy *x, int suspend)
>> return 0;
>> }
>>
>> +static int omap_usb_power_off(struct phy *x)
>> +{
>> + struct omap_usb *phy = phy_get_drvdata(x);
>> +
>> + omap_control_usb_phy_power(phy->control_dev, 0);
>> +
>> + return 0;
>> +}
>> +
>> +static int omap_usb_power_on(struct phy *x)
>> +{
>> + struct omap_usb *phy = phy_get_drvdata(x);
>> +
>> + omap_control_usb_phy_power(phy->control_dev, 1);
>> +
>> + return 0;
>> +}
>> +
>> +static struct phy_ops ops = {
>> + .power_on = omap_usb_power_on,
>> + .power_off = omap_usb_power_off,
>> + .owner = THIS_MODULE,
>> +};
>> +
>> static int omap_usb2_probe(struct platform_device *pdev)
>> {
>> struct omap_usb *phy;
>> + struct phy *generic_phy;
>> struct usb_otg *otg;
>> + struct phy_provider *phy_provider;
>>
>> phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
>> if (!phy) {
>> @@ -144,6 +171,11 @@ static int omap_usb2_probe(struct platform_device *pdev)
>> phy->phy.otg = otg;
>> phy->phy.type = USB_PHY_TYPE_USB2;
>>
>> + phy_provider = devm_of_phy_provider_register(phy->dev,
>> + of_phy_simple_xlate);
>> + if (IS_ERR(phy_provider))
>> + return PTR_ERR(phy_provider);
>> +
>> phy->control_dev = omap_get_control_dev();
>> if (IS_ERR(phy->control_dev)) {
>> dev_dbg(&pdev->dev, "Failed to get control device\n");
>> @@ -159,6 +191,15 @@ static int omap_usb2_probe(struct platform_device *pdev)
>> otg->start_srp = omap_usb_start_srp;
>> otg->phy = &phy->phy;
>>
>> + platform_set_drvdata(pdev, phy);
>> + pm_runtime_enable(phy->dev);
>> +
>> + generic_phy = devm_phy_create(phy->dev, 0, &ops, "omap-usb2");
>> + if (IS_ERR(generic_phy))
>> + return PTR_ERR(generic_phy);
>
> So, if I have two of these controllers in my system, I can't create the
> second phy because the name for it will be identical to the first?
> That's why the phy core should handle the id, and not rely on the
> drivers to set it, as they have no idea how many they have in the
> system.
hmm.. for such cases I'll have something like PLATFORM_DEVID_AUTO.
Thanks
Kishon
On Thu, Jul 18, 2013 at 02:29:52PM +0530, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Thursday 18 July 2013 12:50 PM, Greg KH wrote:
> > On Thu, Jul 18, 2013 at 12:16:10PM +0530, Kishon Vijay Abraham I wrote:
> >> +struct phy_provider *__of_phy_provider_register(struct device *dev,
> >> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
> >> + struct of_phandle_args *args));
> >> +struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
> >> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
> >> + struct of_phandle_args *args))
> >> +
> >> +__of_phy_provider_register and __devm_of_phy_provider_register can be used to
> >> +register the phy_provider and it takes device, owner and of_xlate as
> >> +arguments. For the dt boot case, all PHY providers should use one of the above
> >> +2 APIs to register the PHY provider.
> >
> > Why do you have __ for the prefix of a public function? Is that really
> > the way that OF handles this type of thing?
>
> I have a macro of_phy_provider_register/devm_of_phy_provider_register that
> calls these functions and should be used by the PHY drivers. Probably I should
> make a mention of it in the Documentation.
Yes, mention those as you never want to be calling __* functions
directly, right?
> >> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
> >
> > Your naming is odd, no "phy" anywhere in it? You rely on the sender to
> > never send a duplicate name.id pair? Why not create your own ids based
> > on the number of phys in the system, like almost all other classes and
> > subsystems do?
>
> hmm.. some PHY drivers use the id they provide to perform some of their
> internal operation as in [1] (This is used only if a single PHY provider
> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
> to give the PHY drivers an option to use auto id.
>
> [1] ->
> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
No, who cares about the id? No one outside of the phy core ever should,
because you pass back the only pointer that they really do care about,
if they need to do anything with the device. Use that, and then you can
rip out all of the "search for a phy by a string" logic, as that's not
needed either. Just stick to the pointer, it's easier, and safer that
way.
> >> +static inline int phy_pm_runtime_get(struct phy *phy)
> >> +{
> >> + if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
> >> + return -EINVAL;
> >
> > Why would phy ever not be valid and a error pointer? And why dump the
> > stack if that happens, that seems really extreme.
>
> hmm.. there might be cases where the same controller in one soc needs PHY
> control and in some other soc does not need PHY control. In such cases, we
> might get error pointer here.
> I'll change WARN to dev_err.
I still don't understand. You have control over the code that calls
these functions, just ensure that they pass in a valid pointer, it's
that simple. Or am I missing something?
thanks,
greg k-h
Hi,
On Thursday 18 July 2013 09:19 PM, Greg KH wrote:
> On Thu, Jul 18, 2013 at 02:29:52PM +0530, Kishon Vijay Abraham I wrote:
>> Hi,
>>
>> On Thursday 18 July 2013 12:50 PM, Greg KH wrote:
>>> On Thu, Jul 18, 2013 at 12:16:10PM +0530, Kishon Vijay Abraham I wrote:
>>>> +struct phy_provider *__of_phy_provider_register(struct device *dev,
>>>> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
>>>> + struct of_phandle_args *args));
>>>> +struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
>>>> + struct module *owner, struct phy * (*of_xlate)(struct device *dev,
>>>> + struct of_phandle_args *args))
>>>> +
>>>> +__of_phy_provider_register and __devm_of_phy_provider_register can be used to
>>>> +register the phy_provider and it takes device, owner and of_xlate as
>>>> +arguments. For the dt boot case, all PHY providers should use one of the above
>>>> +2 APIs to register the PHY provider.
>>>
>>> Why do you have __ for the prefix of a public function? Is that really
>>> the way that OF handles this type of thing?
>>
>> I have a macro of_phy_provider_register/devm_of_phy_provider_register that
>> calls these functions and should be used by the PHY drivers. Probably I should
>> make a mention of it in the Documentation.
>
> Yes, mention those as you never want to be calling __* functions
> directly, right?
correct.
>
>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
>>>
>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
>>> never send a duplicate name.id pair? Why not create your own ids based
>>> on the number of phys in the system, like almost all other classes and
>>> subsystems do?
>>
>> hmm.. some PHY drivers use the id they provide to perform some of their
>> internal operation as in [1] (This is used only if a single PHY provider
>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
>> to give the PHY drivers an option to use auto id.
>>
>> [1] ->
>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
>
> No, who cares about the id? No one outside of the phy core ever should,
> because you pass back the only pointer that they really do care about,
> if they need to do anything with the device. Use that, and then you can
hmm.. ok.
> rip out all of the "search for a phy by a string" logic, as that's not
Actually this is needed for non-dt boot case. In the case of dt boot, we use a
phandle by which the controller can get a reference to the phy. But in the case
of non-dt boot, the controller can get a reference to the phy only by label.
> needed either. Just stick to the pointer, it's easier, and safer that
> way.
>
>>>> +static inline int phy_pm_runtime_get(struct phy *phy)
>>>> +{
>>>> + if (WARN(IS_ERR(phy), "Invalid PHY reference\n"))
>>>> + return -EINVAL;
>>>
>>> Why would phy ever not be valid and a error pointer? And why dump the
>>> stack if that happens, that seems really extreme.
>>
>> hmm.. there might be cases where the same controller in one soc needs PHY
>> control and in some other soc does not need PHY control. In such cases, we
>> might get error pointer here.
>> I'll change WARN to dev_err.
>
> I still don't understand. You have control over the code that calls
> these functions, just ensure that they pass in a valid pointer, it's
> that simple. Or am I missing something?
You are right. Valid pointer check can be done in controller code as well.
Thanks
Kishon
On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
> >>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
> >>>
> >>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
> >>> never send a duplicate name.id pair? Why not create your own ids based
> >>> on the number of phys in the system, like almost all other classes and
> >>> subsystems do?
> >>
> >> hmm.. some PHY drivers use the id they provide to perform some of their
> >> internal operation as in [1] (This is used only if a single PHY provider
> >> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
> >> to give the PHY drivers an option to use auto id.
> >>
> >> [1] ->
> >> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
> >
> > No, who cares about the id? No one outside of the phy core ever should,
> > because you pass back the only pointer that they really do care about,
> > if they need to do anything with the device. Use that, and then you can
>
> hmm.. ok.
>
> > rip out all of the "search for a phy by a string" logic, as that's not
>
> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
> phandle by which the controller can get a reference to the phy. But in the case
> of non-dt boot, the controller can get a reference to the phy only by label.
I don't understand. They registered the phy, and got back a pointer to
it. Why can't they save it in their local structure to use it again
later if needed? They should never have to "ask" for the device, as the
device id might be unknown if there are multiple devices in the system.
Or am I missing something?
thanks,
greg k-h
Hi,
On Friday 19 July 2013 11:13 AM, Greg KH wrote:
> On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
>>>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
>>>>>
>>>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
>>>>> never send a duplicate name.id pair? Why not create your own ids based
>>>>> on the number of phys in the system, like almost all other classes and
>>>>> subsystems do?
>>>>
>>>> hmm.. some PHY drivers use the id they provide to perform some of their
>>>> internal operation as in [1] (This is used only if a single PHY provider
>>>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
>>>> to give the PHY drivers an option to use auto id.
>>>>
>>>> [1] ->
>>>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
>>>
>>> No, who cares about the id? No one outside of the phy core ever should,
>>> because you pass back the only pointer that they really do care about,
>>> if they need to do anything with the device. Use that, and then you can
>>
>> hmm.. ok.
>>
>>> rip out all of the "search for a phy by a string" logic, as that's not
>>
>> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
>> phandle by which the controller can get a reference to the phy. But in the case
>> of non-dt boot, the controller can get a reference to the phy only by label.
>
> I don't understand. They registered the phy, and got back a pointer to
> it. Why can't they save it in their local structure to use it again
> later if needed? They should never have to "ask" for the device, as the
One is a *PHY provider* driver which is a driver for some PHY device. This will
use phy_create to create the phy.
The other is a *PHY consumer* driver which might be any controller driver (can
be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
> device id might be unknown if there are multiple devices in the system.
I agree with you on the device id part. That need not be known to the PHY driver.
Thanks
Kishon
On Fri, Jul 19, 2013 at 11:25:44AM +0530, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Friday 19 July 2013 11:13 AM, Greg KH wrote:
> > On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
> >>>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
> >>>>>
> >>>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
> >>>>> never send a duplicate name.id pair? Why not create your own ids based
> >>>>> on the number of phys in the system, like almost all other classes and
> >>>>> subsystems do?
> >>>>
> >>>> hmm.. some PHY drivers use the id they provide to perform some of their
> >>>> internal operation as in [1] (This is used only if a single PHY provider
> >>>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
> >>>> to give the PHY drivers an option to use auto id.
> >>>>
> >>>> [1] ->
> >>>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
> >>>
> >>> No, who cares about the id? No one outside of the phy core ever should,
> >>> because you pass back the only pointer that they really do care about,
> >>> if they need to do anything with the device. Use that, and then you can
> >>
> >> hmm.. ok.
> >>
> >>> rip out all of the "search for a phy by a string" logic, as that's not
> >>
> >> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
> >> phandle by which the controller can get a reference to the phy. But in the case
> >> of non-dt boot, the controller can get a reference to the phy only by label.
> >
> > I don't understand. They registered the phy, and got back a pointer to
> > it. Why can't they save it in their local structure to use it again
> > later if needed? They should never have to "ask" for the device, as the
>
> One is a *PHY provider* driver which is a driver for some PHY device. This will
> use phy_create to create the phy.
> The other is a *PHY consumer* driver which might be any controller driver (can
> be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
> phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
> > device id might be unknown if there are multiple devices in the system.
>
> I agree with you on the device id part. That need not be known to the PHY driver.
How does a consumer know which "label" to use in a non-dt system if
there are multiple PHYs in the system?
Do you have any drivers that are non-dt using this yet?
greg k-h
Hi,
On Friday 19 July 2013 11:59 AM, Greg KH wrote:
> On Fri, Jul 19, 2013 at 11:25:44AM +0530, Kishon Vijay Abraham I wrote:
>> Hi,
>>
>> On Friday 19 July 2013 11:13 AM, Greg KH wrote:
>>> On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
>>>>>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
>>>>>>>
>>>>>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
>>>>>>> never send a duplicate name.id pair? Why not create your own ids based
>>>>>>> on the number of phys in the system, like almost all other classes and
>>>>>>> subsystems do?
>>>>>>
>>>>>> hmm.. some PHY drivers use the id they provide to perform some of their
>>>>>> internal operation as in [1] (This is used only if a single PHY provider
>>>>>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
>>>>>> to give the PHY drivers an option to use auto id.
>>>>>>
>>>>>> [1] ->
>>>>>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
>>>>>
>>>>> No, who cares about the id? No one outside of the phy core ever should,
>>>>> because you pass back the only pointer that they really do care about,
>>>>> if they need to do anything with the device. Use that, and then you can
>>>>
>>>> hmm.. ok.
>>>>
>>>>> rip out all of the "search for a phy by a string" logic, as that's not
>>>>
>>>> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
>>>> phandle by which the controller can get a reference to the phy. But in the case
>>>> of non-dt boot, the controller can get a reference to the phy only by label.
>>>
>>> I don't understand. They registered the phy, and got back a pointer to
>>> it. Why can't they save it in their local structure to use it again
>>> later if needed? They should never have to "ask" for the device, as the
>>
>> One is a *PHY provider* driver which is a driver for some PHY device. This will
>> use phy_create to create the phy.
>> The other is a *PHY consumer* driver which might be any controller driver (can
>> be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
>> phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
>>> device id might be unknown if there are multiple devices in the system.
>>
>> I agree with you on the device id part. That need not be known to the PHY driver.
>
> How does a consumer know which "label" to use in a non-dt system if
> there are multiple PHYs in the system?
That should be passed using platform data.
>
> Do you have any drivers that are non-dt using this yet?
yes. tw4030 (used in OMAP3) supports non-dt.
[PATCH 04/15] ARM: OMAP: USB: Add phy binding information
[PATCH 06/15] usb: musb: omap2430: use the new generic PHY framework
of this patch series shows how it's used.
Thanks
Kishon
On 07/19/2013 12:36 AM, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Friday 19 July 2013 11:59 AM, Greg KH wrote:
>> On Fri, Jul 19, 2013 at 11:25:44AM +0530, Kishon Vijay Abraham I wrote:
>>> Hi,
>>>
>>> On Friday 19 July 2013 11:13 AM, Greg KH wrote:
>>>> On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
>>>>>>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
>>>>>>>>
>>>>>>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
>>>>>>>> never send a duplicate name.id pair? Why not create your own ids based
>>>>>>>> on the number of phys in the system, like almost all other classes and
>>>>>>>> subsystems do?
>>>>>>>
>>>>>>> hmm.. some PHY drivers use the id they provide to perform some of their
>>>>>>> internal operation as in [1] (This is used only if a single PHY provider
>>>>>>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
>>>>>>> to give the PHY drivers an option to use auto id.
>>>>>>>
>>>>>>> [1] ->
>>>>>>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
>>>>>>
>>>>>> No, who cares about the id? No one outside of the phy core ever should,
>>>>>> because you pass back the only pointer that they really do care about,
>>>>>> if they need to do anything with the device. Use that, and then you can
>>>>>
>>>>> hmm.. ok.
>>>>>
>>>>>> rip out all of the "search for a phy by a string" logic, as that's not
>>>>>
>>>>> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
>>>>> phandle by which the controller can get a reference to the phy. But in the case
>>>>> of non-dt boot, the controller can get a reference to the phy only by label.
>>>>
>>>> I don't understand. They registered the phy, and got back a pointer to
>>>> it. Why can't they save it in their local structure to use it again
>>>> later if needed? They should never have to "ask" for the device, as the
>>>
>>> One is a *PHY provider* driver which is a driver for some PHY device. This will
>>> use phy_create to create the phy.
>>> The other is a *PHY consumer* driver which might be any controller driver (can
>>> be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
>>> phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
>>>> device id might be unknown if there are multiple devices in the system.
>>>
>>> I agree with you on the device id part. That need not be known to the PHY driver.
>>
>> How does a consumer know which "label" to use in a non-dt system if
>> there are multiple PHYs in the system?
>
> That should be passed using platform data.
I don't think that's right. That's just like passing clock names in
platform data, which I believe is frowned upon.
Instead, why not take the approach that e.g. regulators have taken? Each
driver defines the names of the objects that it requires. There is a
table (registered by a board file) that has lookup key (device name,
regulator name), and the output is the regulator device (or global
regulator name).
This is almost the same way that DT works, except that in DT, the table
is represented as properties in the DT. The DT binding defines the names
of those properties, or the strings that must be in the foo-names
properties, just like a driver in non-DT Linux is going to define the
names it expects to be provided with.
That way, you don't need platform data to define the names.
On Fri, Jul 19, 2013 at 12:06:01PM +0530, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Friday 19 July 2013 11:59 AM, Greg KH wrote:
> > On Fri, Jul 19, 2013 at 11:25:44AM +0530, Kishon Vijay Abraham I wrote:
> >> Hi,
> >>
> >> On Friday 19 July 2013 11:13 AM, Greg KH wrote:
> >>> On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
> >>>>>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
> >>>>>>>
> >>>>>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
> >>>>>>> never send a duplicate name.id pair? Why not create your own ids based
> >>>>>>> on the number of phys in the system, like almost all other classes and
> >>>>>>> subsystems do?
> >>>>>>
> >>>>>> hmm.. some PHY drivers use the id they provide to perform some of their
> >>>>>> internal operation as in [1] (This is used only if a single PHY provider
> >>>>>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
> >>>>>> to give the PHY drivers an option to use auto id.
> >>>>>>
> >>>>>> [1] ->
> >>>>>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
> >>>>>
> >>>>> No, who cares about the id? No one outside of the phy core ever should,
> >>>>> because you pass back the only pointer that they really do care about,
> >>>>> if they need to do anything with the device. Use that, and then you can
> >>>>
> >>>> hmm.. ok.
> >>>>
> >>>>> rip out all of the "search for a phy by a string" logic, as that's not
> >>>>
> >>>> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
> >>>> phandle by which the controller can get a reference to the phy. But in the case
> >>>> of non-dt boot, the controller can get a reference to the phy only by label.
> >>>
> >>> I don't understand. They registered the phy, and got back a pointer to
> >>> it. Why can't they save it in their local structure to use it again
> >>> later if needed? They should never have to "ask" for the device, as the
> >>
> >> One is a *PHY provider* driver which is a driver for some PHY device. This will
> >> use phy_create to create the phy.
> >> The other is a *PHY consumer* driver which might be any controller driver (can
> >> be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
> >> phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
> >>> device id might be unknown if there are multiple devices in the system.
> >>
> >> I agree with you on the device id part. That need not be known to the PHY driver.
> >
> > How does a consumer know which "label" to use in a non-dt system if
> > there are multiple PHYs in the system?
>
> That should be passed using platform data.
Ick, don't pass strings around, pass pointers. If you have platform
data you can get to, then put the pointer there, don't use a "name".
thanks,
greg k-h
Hi,
On Friday 19 July 2013 09:24 PM, Stephen Warren wrote:
> On 07/19/2013 12:36 AM, Kishon Vijay Abraham I wrote:
>> Hi,
>>
>> On Friday 19 July 2013 11:59 AM, Greg KH wrote:
>>> On Fri, Jul 19, 2013 at 11:25:44AM +0530, Kishon Vijay Abraham I wrote:
>>>> Hi,
>>>>
>>>> On Friday 19 July 2013 11:13 AM, Greg KH wrote:
>>>>> On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
>>>>>>>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
>>>>>>>>>
>>>>>>>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
>>>>>>>>> never send a duplicate name.id pair? Why not create your own ids based
>>>>>>>>> on the number of phys in the system, like almost all other classes and
>>>>>>>>> subsystems do?
>>>>>>>>
>>>>>>>> hmm.. some PHY drivers use the id they provide to perform some of their
>>>>>>>> internal operation as in [1] (This is used only if a single PHY provider
>>>>>>>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
>>>>>>>> to give the PHY drivers an option to use auto id.
>>>>>>>>
>>>>>>>> [1] ->
>>>>>>>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
>>>>>>>
>>>>>>> No, who cares about the id? No one outside of the phy core ever should,
>>>>>>> because you pass back the only pointer that they really do care about,
>>>>>>> if they need to do anything with the device. Use that, and then you can
>>>>>>
>>>>>> hmm.. ok.
>>>>>>
>>>>>>> rip out all of the "search for a phy by a string" logic, as that's not
>>>>>>
>>>>>> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
>>>>>> phandle by which the controller can get a reference to the phy. But in the case
>>>>>> of non-dt boot, the controller can get a reference to the phy only by label.
>>>>>
>>>>> I don't understand. They registered the phy, and got back a pointer to
>>>>> it. Why can't they save it in their local structure to use it again
>>>>> later if needed? They should never have to "ask" for the device, as the
>>>>
>>>> One is a *PHY provider* driver which is a driver for some PHY device. This will
>>>> use phy_create to create the phy.
>>>> The other is a *PHY consumer* driver which might be any controller driver (can
>>>> be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
>>>> phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
>>>>> device id might be unknown if there are multiple devices in the system.
>>>>
>>>> I agree with you on the device id part. That need not be known to the PHY driver.
>>>
>>> How does a consumer know which "label" to use in a non-dt system if
>>> there are multiple PHYs in the system?
>>
>> That should be passed using platform data.
>
> I don't think that's right. That's just like passing clock names in
> platform data, which I believe is frowned upon.
>
> Instead, why not take the approach that e.g. regulators have taken? Each
> driver defines the names of the objects that it requires. There is a
> table (registered by a board file) that has lookup key (device name,
We were using a similar approach with USB PHY layer but things started
breaking after the device names are created using PLATFORM_DEVID_AUTO.
Now theres no way to reliably know the device names in advance.
Btw I had such device name binding in my v3 of this patch series [1] and
had some discussion with Grant during that time [2].
[1] ->
http://archive.arm.linux.org.uk/lurker/message/20130320.091200.721a6fb5.hu.html
[2] -> https://lkml.org/lkml/2013/4/22/26
Thanks
Kishon
Hi,
On Saturday 20 July 2013 05:20 AM, Greg KH wrote:
> On Fri, Jul 19, 2013 at 12:06:01PM +0530, Kishon Vijay Abraham I wrote:
>> Hi,
>>
>> On Friday 19 July 2013 11:59 AM, Greg KH wrote:
>>> On Fri, Jul 19, 2013 at 11:25:44AM +0530, Kishon Vijay Abraham I wrote:
>>>> Hi,
>>>>
>>>> On Friday 19 July 2013 11:13 AM, Greg KH wrote:
>>>>> On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
>>>>>>>>>> + ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
>>>>>>>>>
>>>>>>>>> Your naming is odd, no "phy" anywhere in it? You rely on the sender to
>>>>>>>>> never send a duplicate name.id pair? Why not create your own ids based
>>>>>>>>> on the number of phys in the system, like almost all other classes and
>>>>>>>>> subsystems do?
>>>>>>>>
>>>>>>>> hmm.. some PHY drivers use the id they provide to perform some of their
>>>>>>>> internal operation as in [1] (This is used only if a single PHY provider
>>>>>>>> implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
>>>>>>>> to give the PHY drivers an option to use auto id.
>>>>>>>>
>>>>>>>> [1] ->
>>>>>>>> http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
>>>>>>>
>>>>>>> No, who cares about the id? No one outside of the phy core ever should,
>>>>>>> because you pass back the only pointer that they really do care about,
>>>>>>> if they need to do anything with the device. Use that, and then you can
>>>>>>
>>>>>> hmm.. ok.
>>>>>>
>>>>>>> rip out all of the "search for a phy by a string" logic, as that's not
>>>>>>
>>>>>> Actually this is needed for non-dt boot case. In the case of dt boot, we use a
>>>>>> phandle by which the controller can get a reference to the phy. But in the case
>>>>>> of non-dt boot, the controller can get a reference to the phy only by label.
>>>>>
>>>>> I don't understand. They registered the phy, and got back a pointer to
>>>>> it. Why can't they save it in their local structure to use it again
>>>>> later if needed? They should never have to "ask" for the device, as the
>>>>
>>>> One is a *PHY provider* driver which is a driver for some PHY device. This will
>>>> use phy_create to create the phy.
>>>> The other is a *PHY consumer* driver which might be any controller driver (can
>>>> be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
>>>> phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
>>>>> device id might be unknown if there are multiple devices in the system.
>>>>
>>>> I agree with you on the device id part. That need not be known to the PHY driver.
>>>
>>> How does a consumer know which "label" to use in a non-dt system if
>>> there are multiple PHYs in the system?
>>
>> That should be passed using platform data.
>
> Ick, don't pass strings around, pass pointers. If you have platform
> data you can get to, then put the pointer there, don't use a "name".
I don't think I understood you here :-s We wont have phy pointer when we
create the device for the controller no?(it'll be done in board file).
Probably I'm missing something.
Thanks
Kishon
On Sat, Jul 20, 2013 at 08:49:32AM +0530, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Saturday 20 July 2013 05:20 AM, Greg KH wrote:
> >On Fri, Jul 19, 2013 at 12:06:01PM +0530, Kishon Vijay Abraham I wrote:
> >>Hi,
> >>
> >>On Friday 19 July 2013 11:59 AM, Greg KH wrote:
> >>>On Fri, Jul 19, 2013 at 11:25:44AM +0530, Kishon Vijay Abraham I wrote:
> >>>>Hi,
> >>>>
> >>>>On Friday 19 July 2013 11:13 AM, Greg KH wrote:
> >>>>>On Fri, Jul 19, 2013 at 11:07:10AM +0530, Kishon Vijay Abraham I wrote:
> >>>>>>>>>>+ ret = dev_set_name(&phy->dev, "%s.%d", dev_name(dev), id);
> >>>>>>>>>
> >>>>>>>>>Your naming is odd, no "phy" anywhere in it? You rely on the sender to
> >>>>>>>>>never send a duplicate name.id pair? Why not create your own ids based
> >>>>>>>>>on the number of phys in the system, like almost all other classes and
> >>>>>>>>>subsystems do?
> >>>>>>>>
> >>>>>>>>hmm.. some PHY drivers use the id they provide to perform some of their
> >>>>>>>>internal operation as in [1] (This is used only if a single PHY provider
> >>>>>>>>implements multiple PHYS). Probably I'll add an option like PLATFORM_DEVID_AUTO
> >>>>>>>>to give the PHY drivers an option to use auto id.
> >>>>>>>>
> >>>>>>>>[1] ->
> >>>>>>>>http://archive.arm.linux.org.uk/lurker/message/20130628.134308.4a8f7668.ca.html
> >>>>>>>
> >>>>>>>No, who cares about the id? No one outside of the phy core ever should,
> >>>>>>>because you pass back the only pointer that they really do care about,
> >>>>>>>if they need to do anything with the device. Use that, and then you can
> >>>>>>
> >>>>>>hmm.. ok.
> >>>>>>
> >>>>>>>rip out all of the "search for a phy by a string" logic, as that's not
> >>>>>>
> >>>>>>Actually this is needed for non-dt boot case. In the case of dt boot, we use a
> >>>>>>phandle by which the controller can get a reference to the phy. But in the case
> >>>>>>of non-dt boot, the controller can get a reference to the phy only by label.
> >>>>>
> >>>>>I don't understand. They registered the phy, and got back a pointer to
> >>>>>it. Why can't they save it in their local structure to use it again
> >>>>>later if needed? They should never have to "ask" for the device, as the
> >>>>
> >>>>One is a *PHY provider* driver which is a driver for some PHY device. This will
> >>>>use phy_create to create the phy.
> >>>>The other is a *PHY consumer* driver which might be any controller driver (can
> >>>>be USB/SATA/PCIE). The PHY consumer will use phy_get to get a reference to the
> >>>>phy (by *phandle* in the case of dt boot and *label* in the case of non-dt boot).
> >>>>>device id might be unknown if there are multiple devices in the system.
> >>>>
> >>>>I agree with you on the device id part. That need not be known to the PHY driver.
> >>>
> >>>How does a consumer know which "label" to use in a non-dt system if
> >>>there are multiple PHYs in the system?
> >>
> >>That should be passed using platform data.
> >
> >Ick, don't pass strings around, pass pointers. If you have platform
> >data you can get to, then put the pointer there, don't use a "name".
>
> I don't think I understood you here :-s We wont have phy pointer
> when we create the device for the controller no?(it'll be done in
> board file). Probably I'm missing something.
Why will you not have that pointer? You can't rely on the "name" as the
device id will not match up, so you should be able to rely on the
pointer being in the structure that the board sets up, right?
Don't use names, especially as ids can, and will, change, that is going
to cause big problems. Use pointers, this is C, we are supposed to be
doing that :)
thanks,
greg k-h
On Sat, 20 Jul 2013, Greg KH wrote:
> > >>That should be passed using platform data.
> > >
> > >Ick, don't pass strings around, pass pointers. If you have platform
> > >data you can get to, then put the pointer there, don't use a "name".
> >
> > I don't think I understood you here :-s We wont have phy pointer
> > when we create the device for the controller no?(it'll be done in
> > board file). Probably I'm missing something.
>
> Why will you not have that pointer? You can't rely on the "name" as the
> device id will not match up, so you should be able to rely on the
> pointer being in the structure that the board sets up, right?
>
> Don't use names, especially as ids can, and will, change, that is going
> to cause big problems. Use pointers, this is C, we are supposed to be
> doing that :)
Kishon, I think what Greg means is this: The name you are using must
be stored somewhere in a data structure constructed by the board file,
right? Or at least, associated with some data structure somehow.
Otherwise the platform code wouldn't know which PHY hardware
corresponded to a particular name.
Greg's suggestion is that you store the address of that data structure
in the platform data instead of storing the name string. Have the
consumer pass the data structure's address when it calls phy_create,
instead of passing the name. Then you don't have to worry about two
PHYs accidentally ending up with the same name or any other similar
problems.
Alan Stern
On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
> On Sat, 20 Jul 2013, Greg KH wrote:
>
> > > >>That should be passed using platform data.
> > > >
> > > >Ick, don't pass strings around, pass pointers. If you have platform
> > > >data you can get to, then put the pointer there, don't use a "name".
> > >
> > > I don't think I understood you here :-s We wont have phy pointer
> > > when we create the device for the controller no?(it'll be done in
> > > board file). Probably I'm missing something.
> >
> > Why will you not have that pointer? You can't rely on the "name" as the
> > device id will not match up, so you should be able to rely on the
> > pointer being in the structure that the board sets up, right?
> >
> > Don't use names, especially as ids can, and will, change, that is going
> > to cause big problems. Use pointers, this is C, we are supposed to be
> > doing that :)
>
> Kishon, I think what Greg means is this: The name you are using must
> be stored somewhere in a data structure constructed by the board file,
> right? Or at least, associated with some data structure somehow.
> Otherwise the platform code wouldn't know which PHY hardware
> corresponded to a particular name.
>
> Greg's suggestion is that you store the address of that data structure
> in the platform data instead of storing the name string. Have the
> consumer pass the data structure's address when it calls phy_create,
> instead of passing the name. Then you don't have to worry about two
> PHYs accidentally ending up with the same name or any other similar
> problems.
Close, but the issue is that whatever returns from phy_create() should
then be used, no need to call any "find" functions, as you can just use
the pointer that phy_create() returns. Much like all other class api
functions in the kernel work.
thanks,
greg k-h
On Sat, Jul 20, 2013 at 07:59:10PM -0700, Greg KH wrote:
> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
> > On Sat, 20 Jul 2013, Greg KH wrote:
> >
> > > > >>That should be passed using platform data.
> > > > >
> > > > >Ick, don't pass strings around, pass pointers. If you have platform
> > > > >data you can get to, then put the pointer there, don't use a "name".
> > > >
> > > > I don't think I understood you here :-s We wont have phy pointer
> > > > when we create the device for the controller no?(it'll be done in
> > > > board file). Probably I'm missing something.
> > >
> > > Why will you not have that pointer? You can't rely on the "name" as the
> > > device id will not match up, so you should be able to rely on the
> > > pointer being in the structure that the board sets up, right?
> > >
> > > Don't use names, especially as ids can, and will, change, that is going
> > > to cause big problems. Use pointers, this is C, we are supposed to be
> > > doing that :)
> >
> > Kishon, I think what Greg means is this: The name you are using must
> > be stored somewhere in a data structure constructed by the board file,
> > right? Or at least, associated with some data structure somehow.
> > Otherwise the platform code wouldn't know which PHY hardware
> > corresponded to a particular name.
> >
> > Greg's suggestion is that you store the address of that data structure
> > in the platform data instead of storing the name string. Have the
> > consumer pass the data structure's address when it calls phy_create,
> > instead of passing the name. Then you don't have to worry about two
> > PHYs accidentally ending up with the same name or any other similar
> > problems.
>
> Close, but the issue is that whatever returns from phy_create() should
> then be used, no need to call any "find" functions, as you can just use
> the pointer that phy_create() returns. Much like all other class api
> functions in the kernel work.
I think the problem here is to connect two from the bus structure
completely independent devices. Several frameworks (ASoC, soc-camera)
had this problem and this wasn't solved until the advent of devicetrees
and their phandles.
phy_create might be called from the probe function of some i2c device
(the phy device) and the resulting pointer is then needed in some other
platform devices (the user of the phy) probe function.
The best solution we have right now is implemented in the clk framework
which uses a string matching of the device names in clk_get() (at least
in the non-dt case).
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Hi,
On Saturday 20 of July 2013 19:59:10 Greg KH wrote:
> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
> > On Sat, 20 Jul 2013, Greg KH wrote:
> > > > >>That should be passed using platform data.
> > > > >
> > > > >Ick, don't pass strings around, pass pointers. If you have
> > > > >platform
> > > > >data you can get to, then put the pointer there, don't use a
> > > > >"name".
> > > >
> > > > I don't think I understood you here :-s We wont have phy pointer
> > > > when we create the device for the controller no?(it'll be done in
> > > > board file). Probably I'm missing something.
> > >
> > > Why will you not have that pointer? You can't rely on the "name" as
> > > the device id will not match up, so you should be able to rely on
> > > the pointer being in the structure that the board sets up, right?
> > >
> > > Don't use names, especially as ids can, and will, change, that is
> > > going
> > > to cause big problems. Use pointers, this is C, we are supposed to
> > > be
> > > doing that :)
> >
> > Kishon, I think what Greg means is this: The name you are using must
> > be stored somewhere in a data structure constructed by the board file,
> > right? Or at least, associated with some data structure somehow.
> > Otherwise the platform code wouldn't know which PHY hardware
> > corresponded to a particular name.
> >
> > Greg's suggestion is that you store the address of that data structure
> > in the platform data instead of storing the name string. Have the
> > consumer pass the data structure's address when it calls phy_create,
> > instead of passing the name. Then you don't have to worry about two
> > PHYs accidentally ending up with the same name or any other similar
> > problems.
>
> Close, but the issue is that whatever returns from phy_create() should
> then be used, no need to call any "find" functions, as you can just use
> the pointer that phy_create() returns. Much like all other class api
> functions in the kernel work.
I think there is a confusion here about who registers the PHYs.
All platform code does is registering a platform/i2c/whatever device,
which causes a driver (located in drivers/phy/) to be instantiated. Such
drivers call phy_create(), usually in their probe() callbacks, so
platform_code has no way (and should have no way, for the sake of
layering) to get what phy_create() returns.
IMHO we need a lookup method for PHYs, just like for clocks, regulators,
PWMs or even i2c busses because there are complex cases when passing just
a name using platform data will not work. I would second what Stephen said
[1] and define a structure doing things in a DT-like way.
Example;
[platform code]
static const struct phy_lookup my_phy_lookup[] = {
PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
/* etc... */
};
static void my_machine_init(void)
{
/* ... */
phy_register_lookup(my_phy_lookup, ARRAY_SIZE(my_phy_lookup));
/* ... */
}
/* Notice nothing stuffed in platform data. */
[provider code - samsung-usbphy driver]
static int samsung_usbphy_probe(...)
{
/* ... */
for (i = 0; i < PHY_COUNT; ++i) {
usbphy->phy[i].name = "phy";
usbphy->phy[i].id = i;
/* ... */
ret = phy_create(&usbphy->phy);
/* err handling */
}
/* ... */
}
[consumer code - s3c-hsotg driver]
static int s3c_hsotg_probe(...)
{
/* ... */
phy = phy_get(&pdev->dev, "otg");
/* ... */
}
[1] http://thread.gmane.org/gmane.linux.ports.arm.kernel/252813
Best regards,
Tomasz
Hi,
On Sunday 21 July 2013 04:01 PM, Tomasz Figa wrote:
> Hi,
>
> On Saturday 20 of July 2013 19:59:10 Greg KH wrote:
>> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
>>> On Sat, 20 Jul 2013, Greg KH wrote:
>>>>>>> That should be passed using platform data.
>>>>>>
>>>>>> Ick, don't pass strings around, pass pointers. If you have
>>>>>> platform
>>>>>> data you can get to, then put the pointer there, don't use a
>>>>>> "name".
>>>>>
>>>>> I don't think I understood you here :-s We wont have phy pointer
>>>>> when we create the device for the controller no?(it'll be done in
>>>>> board file). Probably I'm missing something.
>>>>
>>>> Why will you not have that pointer? You can't rely on the "name" as
>>>> the device id will not match up, so you should be able to rely on
>>>> the pointer being in the structure that the board sets up, right?
>>>>
>>>> Don't use names, especially as ids can, and will, change, that is
>>>> going
>>>> to cause big problems. Use pointers, this is C, we are supposed to
>>>> be
>>>> doing that :)
>>>
>>> Kishon, I think what Greg means is this: The name you are using must
>>> be stored somewhere in a data structure constructed by the board file,
>>> right? Or at least, associated with some data structure somehow.
>>> Otherwise the platform code wouldn't know which PHY hardware
>>> corresponded to a particular name.
>>>
>>> Greg's suggestion is that you store the address of that data structure
>>> in the platform data instead of storing the name string. Have the
>>> consumer pass the data structure's address when it calls phy_create,
>>> instead of passing the name. Then you don't have to worry about two
>>> PHYs accidentally ending up with the same name or any other similar
>>> problems.
>>
>> Close, but the issue is that whatever returns from phy_create() should
>> then be used, no need to call any "find" functions, as you can just use
>> the pointer that phy_create() returns. Much like all other class api
>> functions in the kernel work.
>
> I think there is a confusion here about who registers the PHYs.
>
> All platform code does is registering a platform/i2c/whatever device,
> which causes a driver (located in drivers/phy/) to be instantiated. Such
> drivers call phy_create(), usually in their probe() callbacks, so
> platform_code has no way (and should have no way, for the sake of
> layering) to get what phy_create() returns.
right.
>
> IMHO we need a lookup method for PHYs, just like for clocks, regulators,
> PWMs or even i2c busses because there are complex cases when passing just
> a name using platform data will not work. I would second what Stephen said
> [1] and define a structure doing things in a DT-like way.
>
> Example;
>
> [platform code]
>
> static const struct phy_lookup my_phy_lookup[] = {
> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
The only problem here is that if *PLATFORM_DEVID_AUTO* is used while
creating the device, the ids in the device name would change and
PHY_LOOKUP wont be useful.
Thanks
Kishon
On Sunday 21 of July 2013 16:37:33 Kishon Vijay Abraham I wrote:
> Hi,
>
> On Sunday 21 July 2013 04:01 PM, Tomasz Figa wrote:
> > Hi,
> >
> > On Saturday 20 of July 2013 19:59:10 Greg KH wrote:
> >> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
> >>> On Sat, 20 Jul 2013, Greg KH wrote:
> >>>>>>> That should be passed using platform data.
> >>>>>>
> >>>>>> Ick, don't pass strings around, pass pointers. If you have
> >>>>>> platform
> >>>>>> data you can get to, then put the pointer there, don't use a
> >>>>>> "name".
> >>>>>
> >>>>> I don't think I understood you here :-s We wont have phy pointer
> >>>>> when we create the device for the controller no?(it'll be done in
> >>>>> board file). Probably I'm missing something.
> >>>>
> >>>> Why will you not have that pointer? You can't rely on the "name"
> >>>> as
> >>>> the device id will not match up, so you should be able to rely on
> >>>> the pointer being in the structure that the board sets up, right?
> >>>>
> >>>> Don't use names, especially as ids can, and will, change, that is
> >>>> going
> >>>> to cause big problems. Use pointers, this is C, we are supposed to
> >>>> be
> >>>> doing that :)
> >>>
> >>> Kishon, I think what Greg means is this: The name you are using
> >>> must
> >>> be stored somewhere in a data structure constructed by the board
> >>> file,
> >>> right? Or at least, associated with some data structure somehow.
> >>> Otherwise the platform code wouldn't know which PHY hardware
> >>> corresponded to a particular name.
> >>>
> >>> Greg's suggestion is that you store the address of that data
> >>> structure
> >>> in the platform data instead of storing the name string. Have the
> >>> consumer pass the data structure's address when it calls phy_create,
> >>> instead of passing the name. Then you don't have to worry about two
> >>> PHYs accidentally ending up with the same name or any other similar
> >>> problems.
> >>
> >> Close, but the issue is that whatever returns from phy_create()
> >> should
> >> then be used, no need to call any "find" functions, as you can just
> >> use
> >> the pointer that phy_create() returns. Much like all other class api
> >> functions in the kernel work.
> >
> > I think there is a confusion here about who registers the PHYs.
> >
> > All platform code does is registering a platform/i2c/whatever device,
> > which causes a driver (located in drivers/phy/) to be instantiated.
> > Such drivers call phy_create(), usually in their probe() callbacks,
> > so platform_code has no way (and should have no way, for the sake of
> > layering) to get what phy_create() returns.
>
> right.
>
> > IMHO we need a lookup method for PHYs, just like for clocks,
> > regulators, PWMs or even i2c busses because there are complex cases
> > when passing just a name using platform data will not work. I would
> > second what Stephen said [1] and define a structure doing things in a
> > DT-like way.
> >
> > Example;
> >
> > [platform code]
> >
> > static const struct phy_lookup my_phy_lookup[] = {
> >
> > PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
>
> The only problem here is that if *PLATFORM_DEVID_AUTO* is used while
> creating the device, the ids in the device name would change and
> PHY_LOOKUP wont be useful.
I don't think this is a problem. All the existing lookup methods already
use ID to identify devices (see regulators, clkdev, PWMs, i2c, ...). You
can simply add a requirement that the ID must be assigned manually,
without using PLATFORM_DEVID_AUTO to use PHY lookup.
Best regards,
Tomasz
On Sun, Jul 21, 2013 at 01:12:07PM +0200, Tomasz Figa wrote:
> On Sunday 21 of July 2013 16:37:33 Kishon Vijay Abraham I wrote:
> > Hi,
> >
> > On Sunday 21 July 2013 04:01 PM, Tomasz Figa wrote:
> > > Hi,
> > >
> > > On Saturday 20 of July 2013 19:59:10 Greg KH wrote:
> > >> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
> > >>> On Sat, 20 Jul 2013, Greg KH wrote:
> > >>>>>>> That should be passed using platform data.
> > >>>>>>
> > >>>>>> Ick, don't pass strings around, pass pointers. If you have
> > >>>>>> platform
> > >>>>>> data you can get to, then put the pointer there, don't use a
> > >>>>>> "name".
> > >>>>>
> > >>>>> I don't think I understood you here :-s We wont have phy pointer
> > >>>>> when we create the device for the controller no?(it'll be done in
> > >>>>> board file). Probably I'm missing something.
> > >>>>
> > >>>> Why will you not have that pointer? You can't rely on the "name"
> > >>>> as
> > >>>> the device id will not match up, so you should be able to rely on
> > >>>> the pointer being in the structure that the board sets up, right?
> > >>>>
> > >>>> Don't use names, especially as ids can, and will, change, that is
> > >>>> going
> > >>>> to cause big problems. Use pointers, this is C, we are supposed to
> > >>>> be
> > >>>> doing that :)
> > >>>
> > >>> Kishon, I think what Greg means is this: The name you are using
> > >>> must
> > >>> be stored somewhere in a data structure constructed by the board
> > >>> file,
> > >>> right? Or at least, associated with some data structure somehow.
> > >>> Otherwise the platform code wouldn't know which PHY hardware
> > >>> corresponded to a particular name.
> > >>>
> > >>> Greg's suggestion is that you store the address of that data
> > >>> structure
> > >>> in the platform data instead of storing the name string. Have the
> > >>> consumer pass the data structure's address when it calls phy_create,
> > >>> instead of passing the name. Then you don't have to worry about two
> > >>> PHYs accidentally ending up with the same name or any other similar
> > >>> problems.
> > >>
> > >> Close, but the issue is that whatever returns from phy_create()
> > >> should
> > >> then be used, no need to call any "find" functions, as you can just
> > >> use
> > >> the pointer that phy_create() returns. Much like all other class api
> > >> functions in the kernel work.
> > >
> > > I think there is a confusion here about who registers the PHYs.
> > >
> > > All platform code does is registering a platform/i2c/whatever device,
> > > which causes a driver (located in drivers/phy/) to be instantiated.
> > > Such drivers call phy_create(), usually in their probe() callbacks,
> > > so platform_code has no way (and should have no way, for the sake of
> > > layering) to get what phy_create() returns.
Why not put pointers in the platform data structure that can hold these
pointers? I thought that is why we created those structures in the
first place. If not, what are they there for?
> > > IMHO we need a lookup method for PHYs, just like for clocks,
> > > regulators, PWMs or even i2c busses because there are complex cases
> > > when passing just a name using platform data will not work. I would
> > > second what Stephen said [1] and define a structure doing things in a
> > > DT-like way.
> > >
> > > Example;
> > >
> > > [platform code]
> > >
> > > static const struct phy_lookup my_phy_lookup[] = {
> > >
> > > PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
> >
> > The only problem here is that if *PLATFORM_DEVID_AUTO* is used while
> > creating the device, the ids in the device name would change and
> > PHY_LOOKUP wont be useful.
>
> I don't think this is a problem. All the existing lookup methods already
> use ID to identify devices (see regulators, clkdev, PWMs, i2c, ...). You
> can simply add a requirement that the ID must be assigned manually,
> without using PLATFORM_DEVID_AUTO to use PHY lookup.
And I'm saying that this idea, of using a specific name and id, is
frought with fragility and will break in the future in various ways when
devices get added to systems, making these strings constantly have to be
kept up to date with different board configurations.
People, NEVER, hardcode something like an id. The fact that this
happens today with the clock code, doesn't make it right, it makes the
clock code wrong. Others have already said that this is wrong there as
well, as systems change and dynamic ids get used more and more.
Let's not repeat the same mistakes of the past just because we refuse to
learn from them...
So again, the "find a phy by a string" functions should be removed, the
device id should be automatically created by the phy core just to make
things unique in sysfs, and no driver code should _ever_ be reliant on
the number that is being created, and the pointer to the phy structure
should be used everywhere instead.
With those types of changes, I will consider merging this subsystem, but
without them, sorry, I will not.
thanks,
greg k-h
On Sun, Jul 21, 2013 at 12:22:48PM +0200, Sascha Hauer wrote:
> On Sat, Jul 20, 2013 at 07:59:10PM -0700, Greg KH wrote:
> > On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
> > > On Sat, 20 Jul 2013, Greg KH wrote:
> > >
> > > > > >>That should be passed using platform data.
> > > > > >
> > > > > >Ick, don't pass strings around, pass pointers. If you have platform
> > > > > >data you can get to, then put the pointer there, don't use a "name".
> > > > >
> > > > > I don't think I understood you here :-s We wont have phy pointer
> > > > > when we create the device for the controller no?(it'll be done in
> > > > > board file). Probably I'm missing something.
> > > >
> > > > Why will you not have that pointer? You can't rely on the "name" as the
> > > > device id will not match up, so you should be able to rely on the
> > > > pointer being in the structure that the board sets up, right?
> > > >
> > > > Don't use names, especially as ids can, and will, change, that is going
> > > > to cause big problems. Use pointers, this is C, we are supposed to be
> > > > doing that :)
> > >
> > > Kishon, I think what Greg means is this: The name you are using must
> > > be stored somewhere in a data structure constructed by the board file,
> > > right? Or at least, associated with some data structure somehow.
> > > Otherwise the platform code wouldn't know which PHY hardware
> > > corresponded to a particular name.
> > >
> > > Greg's suggestion is that you store the address of that data structure
> > > in the platform data instead of storing the name string. Have the
> > > consumer pass the data structure's address when it calls phy_create,
> > > instead of passing the name. Then you don't have to worry about two
> > > PHYs accidentally ending up with the same name or any other similar
> > > problems.
> >
> > Close, but the issue is that whatever returns from phy_create() should
> > then be used, no need to call any "find" functions, as you can just use
> > the pointer that phy_create() returns. Much like all other class api
> > functions in the kernel work.
>
> I think the problem here is to connect two from the bus structure
> completely independent devices. Several frameworks (ASoC, soc-camera)
> had this problem and this wasn't solved until the advent of devicetrees
> and their phandles.
> phy_create might be called from the probe function of some i2c device
> (the phy device) and the resulting pointer is then needed in some other
> platform devices (the user of the phy) probe function.
> The best solution we have right now is implemented in the clk framework
> which uses a string matching of the device names in clk_get() (at least
> in the non-dt case).
I would argue that clocks are wrong here as well, as others have already
pointed out.
What's wrong with the platform_data structure, why can't that be used
for this?
Or, if not, we can always add pointers to the platform device structure,
or even the main 'struct device' as well, that's what it is there for.
thanks,
greg k-h
On 07/21/2013 05:48 PM, Greg KH wrote:
> On Sun, Jul 21, 2013 at 12:22:48PM +0200, Sascha Hauer wrote:
>> On Sat, Jul 20, 2013 at 07:59:10PM -0700, Greg KH wrote:
>>> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
>>>> On Sat, 20 Jul 2013, Greg KH wrote:
>>>>
>>>>>>>> That should be passed using platform data.
>>>>>>>
>>>>>>> Ick, don't pass strings around, pass pointers. If you have platform
>>>>>>> data you can get to, then put the pointer there, don't use a "name".
>>>>>>
>>>>>> I don't think I understood you here :-s We wont have phy pointer
>>>>>> when we create the device for the controller no?(it'll be done in
>>>>>> board file). Probably I'm missing something.
>>>>>
>>>>> Why will you not have that pointer? You can't rely on the "name" as the
>>>>> device id will not match up, so you should be able to rely on the
>>>>> pointer being in the structure that the board sets up, right?
>>>>>
>>>>> Don't use names, especially as ids can, and will, change, that is going
>>>>> to cause big problems. Use pointers, this is C, we are supposed to be
>>>>> doing that :)
>>>>
>>>> Kishon, I think what Greg means is this: The name you are using must
>>>> be stored somewhere in a data structure constructed by the board file,
>>>> right? Or at least, associated with some data structure somehow.
>>>> Otherwise the platform code wouldn't know which PHY hardware
>>>> corresponded to a particular name.
>>>>
>>>> Greg's suggestion is that you store the address of that data structure
>>>> in the platform data instead of storing the name string. Have the
>>>> consumer pass the data structure's address when it calls phy_create,
>>>> instead of passing the name. Then you don't have to worry about two
>>>> PHYs accidentally ending up with the same name or any other similar
>>>> problems.
>>>
>>> Close, but the issue is that whatever returns from phy_create() should
>>> then be used, no need to call any "find" functions, as you can just use
>>> the pointer that phy_create() returns. Much like all other class api
>>> functions in the kernel work.
>>
>> I think the problem here is to connect two from the bus structure
>> completely independent devices. Several frameworks (ASoC, soc-camera)
>> had this problem and this wasn't solved until the advent of devicetrees
>> and their phandles.
>> phy_create might be called from the probe function of some i2c device
>> (the phy device) and the resulting pointer is then needed in some other
>> platform devices (the user of the phy) probe function.
>> The best solution we have right now is implemented in the clk framework
>> which uses a string matching of the device names in clk_get() (at least
>> in the non-dt case).
>
> I would argue that clocks are wrong here as well, as others have already
> pointed out.
>
> What's wrong with the platform_data structure, why can't that be used
> for this?
At the point the platform data of some driver is initialized, e.g. in
board setup code the PHY pointer is not known, since the PHY supplier
driver has not initialized yet. Even though we wanted to pass pointer
to a PHY through some notifier call, it would have been not clear
which PHY user driver should match on such notifier. A single PHY
supplier driver can create M PHY objects and this needs to be mapped
to N PHY user drivers. This mapping needs to be defined somewhere by
the system integrator. It works well with device tree, but except that
there seems to be no other reliable infrastructure in the kernel to
define links/dependencies between devices, since device identifiers are
not known in advance in all cases.
What Tomasz proposed seems currently most reasonable to me for non-dt.
> Or, if not, we can always add pointers to the platform device structure,
> or even the main 'struct device' as well, that's what it is there for.
Still we would need to solve a problem which platform device structure
gets which PHY pointer.
--
Regards,
Sylwester
On Sun, 21 Jul 2013, Sylwester Nawrocki wrote:
> > What's wrong with the platform_data structure, why can't that be used
> > for this?
>
> At the point the platform data of some driver is initialized, e.g. in
> board setup code the PHY pointer is not known, since the PHY supplier
> driver has not initialized yet. Even though we wanted to pass pointer
> to a PHY through some notifier call, it would have been not clear
> which PHY user driver should match on such notifier. A single PHY
> supplier driver can create M PHY objects and this needs to be mapped
> to N PHY user drivers. This mapping needs to be defined somewhere by
> the system integrator. It works well with device tree, but except that
> there seems to be no other reliable infrastructure in the kernel to
> define links/dependencies between devices, since device identifiers are
> not known in advance in all cases.
>
> What Tomasz proposed seems currently most reasonable to me for non-dt.
>
> > Or, if not, we can always add pointers to the platform device structure,
> > or even the main 'struct device' as well, that's what it is there for.
>
> Still we would need to solve a problem which platform device structure
> gets which PHY pointer.
Can you explain the issues in more detail? I don't fully understand
the situation.
Here's what I think I know:
The PHY and the controller it is attached to are both physical
devices.
The connection between them is hardwired by the system
manufacturer and cannot be changed by software.
PHYs are generally described by fixed system-specific board
files or by Device Tree information. Are they ever discovered
dynamically?
Is the same true for the controllers attached to the PHYs?
If not -- if both a PHY and a controller are discovered
dynamically -- how does the kernel know whether they are
connected to each other?
The kernel needs to know which controller is attached to which
PHY. Currently this information is represented by name or ID
strings embedded in platform data.
The PHY's driver (the supplier) uses the platform data to
construct a platform_device structure that represents the PHY.
Until this is done, the controller's driver (the client) cannot
use the PHY.
Since there is no parent-child relation between the PHY and the
controller, there is no guarantee that the PHY's driver will be
ready when the controller's driver wants to use it. A deferred
probe may be needed.
The issue (or one of the issues) in this discussion is that
Greg does not like the idea of using names or IDs to associate
PHYs with controllers, because they are too prone to
duplications or other errors. Pointers are more reliable.
But pointers to what? Since the only data known to be
available to both the PHY driver and controller driver is the
platform data, the obvious answer is a pointer to platform data
(either for the PHY or for the controller, or maybe both).
Probably some of the details above are wrong; please indicate where I
have gone astray. Also, I'm not clear about the role played by various
APIs. For example, where does phy_create() fit into this picture?
Alan Stern
Hi,
On Monday 22 July 2013 12:52 AM, Alan Stern wrote:
> On Sun, 21 Jul 2013, Sylwester Nawrocki wrote:
>
>>> What's wrong with the platform_data structure, why can't that be used
>>> for this?
>>
>> At the point the platform data of some driver is initialized, e.g. in
>> board setup code the PHY pointer is not known, since the PHY supplier
>> driver has not initialized yet. Even though we wanted to pass pointer
>> to a PHY through some notifier call, it would have been not clear
>> which PHY user driver should match on such notifier. A single PHY
>> supplier driver can create M PHY objects and this needs to be mapped
>> to N PHY user drivers. This mapping needs to be defined somewhere by
>> the system integrator. It works well with device tree, but except that
>> there seems to be no other reliable infrastructure in the kernel to
>> define links/dependencies between devices, since device identifiers are
>> not known in advance in all cases.
>>
>> What Tomasz proposed seems currently most reasonable to me for non-dt.
>>
>>> Or, if not, we can always add pointers to the platform device structure,
>>> or even the main 'struct device' as well, that's what it is there for.
>>
>> Still we would need to solve a problem which platform device structure
>> gets which PHY pointer.
>
> Can you explain the issues in more detail? I don't fully understand
> the situation.
>
> Here's what I think I know:
>
> The PHY and the controller it is attached to are both physical
> devices.
>
> The connection between them is hardwired by the system
> manufacturer and cannot be changed by software.
>
> PHYs are generally described by fixed system-specific board
> files or by Device Tree information. Are they ever discovered
> dynamically?
No. They are created just like any other platform devices are created.
>
> Is the same true for the controllers attached to the PHYs?
> If not -- if both a PHY and a controller are discovered
> dynamically -- how does the kernel know whether they are
> connected to each other?
No differences here. Both PHY and controller will have dt information or hwmod
data using which platform devices will be created.
>
> The kernel needs to know which controller is attached to which
> PHY. Currently this information is represented by name or ID
> strings embedded in platform data.
right. It's embedded in the platform data of the controller.
>
> The PHY's driver (the supplier) uses the platform data to
> construct a platform_device structure that represents the PHY.
Currently the driver assigns static labels (corresponding to the label used in
the platform data of the controller).
> Until this is done, the controller's driver (the client) cannot
> use the PHY.
right.
>
> Since there is no parent-child relation between the PHY and the
> controller, there is no guarantee that the PHY's driver will be
> ready when the controller's driver wants to use it. A deferred
> probe may be needed.
right.
>
> The issue (or one of the issues) in this discussion is that
> Greg does not like the idea of using names or IDs to associate
> PHYs with controllers, because they are too prone to
> duplications or other errors. Pointers are more reliable.
>
> But pointers to what? Since the only data known to be
> available to both the PHY driver and controller driver is the
> platform data, the obvious answer is a pointer to platform data
> (either for the PHY or for the controller, or maybe both).
hmm.. it's not going to be simple though as the platform device for the PHY and
controller can be created in entirely different places. e.g., in some cases the
PHY device is a child of some mfd core device (the device will be created in
drivers/mfd) and the controller driver (usually) is created in board file. I
guess then we have to come up with something to share a pointer in two
different files.
>
> Probably some of the details above are wrong; please indicate where I
> have gone astray. Also, I'm not clear about the role played by various
> APIs. For example, where does phy_create() fit into this picture?
phy_create is the API by which the PHY's driver (the supplier) hook into the
PHY framework. It's like the controller driver will always interact with the
PHY driver through the PHY framework.
Thanks
Kishon
On Mon, 22 Jul 2013, Kishon Vijay Abraham I wrote:
> > The PHY and the controller it is attached to are both physical
> > devices.
> >
> > The connection between them is hardwired by the system
> > manufacturer and cannot be changed by software.
> >
> > PHYs are generally described by fixed system-specific board
> > files or by Device Tree information. Are they ever discovered
> > dynamically?
>
> No. They are created just like any other platform devices are created.
Okay. Are PHYs _always_ platform devices?
> > Is the same true for the controllers attached to the PHYs?
> > If not -- if both a PHY and a controller are discovered
> > dynamically -- how does the kernel know whether they are
> > connected to each other?
>
> No differences here. Both PHY and controller will have dt information or hwmod
> data using which platform devices will be created.
> >
> > The kernel needs to know which controller is attached to which
> > PHY. Currently this information is represented by name or ID
> > strings embedded in platform data.
>
> right. It's embedded in the platform data of the controller.
It must also be embedded in the PHY's platform data somehow.
Otherwise, how would the kernel know which PHY to use?
> > The PHY's driver (the supplier) uses the platform data to
> > construct a platform_device structure that represents the PHY.
>
> Currently the driver assigns static labels (corresponding to the label used in
> the platform data of the controller).
> > Until this is done, the controller's driver (the client) cannot
> > use the PHY.
>
> right.
> >
> > Since there is no parent-child relation between the PHY and the
> > controller, there is no guarantee that the PHY's driver will be
> > ready when the controller's driver wants to use it. A deferred
> > probe may be needed.
>
> right.
> >
> > The issue (or one of the issues) in this discussion is that
> > Greg does not like the idea of using names or IDs to associate
> > PHYs with controllers, because they are too prone to
> > duplications or other errors. Pointers are more reliable.
> >
> > But pointers to what? Since the only data known to be
> > available to both the PHY driver and controller driver is the
> > platform data, the obvious answer is a pointer to platform data
> > (either for the PHY or for the controller, or maybe both).
>
> hmm.. it's not going to be simple though as the platform device for the PHY and
> controller can be created in entirely different places. e.g., in some cases the
> PHY device is a child of some mfd core device (the device will be created in
> drivers/mfd) and the controller driver (usually) is created in board file. I
> guess then we have to come up with something to share a pointer in two
> different files.
The ability for two different source files to share a pointer to a data
item defined in a third source file has been around since long before
the C language was invented. :-)
In this case, it doesn't matter where the platform_device structures
are created or where the driver source code is. Let's take a simple
example. Suppose the system design includes a PHY named "foo". Then
the board file could contain:
struct phy_info { ... } phy_foo;
EXPORT_SYMBOL_GPL(phy_foo);
and a header file would contain:
extern struct phy_info phy_foo;
The PHY supplier could then call phy_create(&phy_foo), and the PHY
client could call phy_find(&phy_foo). Or something like that; make up
your own structure tags and function names.
It's still possible to have conflicts, but now two PHYs with the same
name (or a misspelled name somewhere) will cause an error at link time.
> > Probably some of the details above are wrong; please indicate where I
> > have gone astray. Also, I'm not clear about the role played by various
> > APIs. For example, where does phy_create() fit into this picture?
>
> phy_create is the API by which the PHY's driver (the supplier) hook into the
> PHY framework. It's like the controller driver will always interact with the
> PHY driver through the PHY framework.
Alan Stern
On Mon, Jul 22, 2013 at 12:55:18PM +0530, Kishon Vijay Abraham I wrote:
> > The issue (or one of the issues) in this discussion is that
> > Greg does not like the idea of using names or IDs to associate
> > PHYs with controllers, because they are too prone to
> > duplications or other errors. Pointers are more reliable.
> >
> > But pointers to what? Since the only data known to be
> > available to both the PHY driver and controller driver is the
> > platform data, the obvious answer is a pointer to platform data
> > (either for the PHY or for the controller, or maybe both).
>
> hmm.. it's not going to be simple though as the platform device for the PHY and
> controller can be created in entirely different places. e.g., in some cases the
> PHY device is a child of some mfd core device (the device will be created in
> drivers/mfd) and the controller driver (usually) is created in board file. I
> guess then we have to come up with something to share a pointer in two
> different files.
What's wrong with using the platform_data structure that is unique to
all boards (see include/platform_data/ for examples)? Isn't that what
this structure is there for?
greg k-h
Hi,
On Monday 22 July 2013 08:34 PM, Greg KH wrote:
> On Mon, Jul 22, 2013 at 12:55:18PM +0530, Kishon Vijay Abraham I wrote:
>>> The issue (or one of the issues) in this discussion is that
>>> Greg does not like the idea of using names or IDs to associate
>>> PHYs with controllers, because they are too prone to
>>> duplications or other errors. Pointers are more reliable.
>>>
>>> But pointers to what? Since the only data known to be
>>> available to both the PHY driver and controller driver is the
>>> platform data, the obvious answer is a pointer to platform data
>>> (either for the PHY or for the controller, or maybe both).
>>
>> hmm.. it's not going to be simple though as the platform device for the PHY and
>> controller can be created in entirely different places. e.g., in some cases the
>> PHY device is a child of some mfd core device (the device will be created in
>> drivers/mfd) and the controller driver (usually) is created in board file. I
>> guess then we have to come up with something to share a pointer in two
>> different files.
>
> What's wrong with using the platform_data structure that is unique to
> all boards (see include/platform_data/ for examples)? Isn't that what
> this structure is there for?
Alright. I got some ideas from Alan Stern. I'll use it with platform_data and
repost the series.
Thanks
Kishon
Hi,
On Monday 22 July 2013 08:14 PM, Alan Stern wrote:
> On Mon, 22 Jul 2013, Kishon Vijay Abraham I wrote:
>
>>> The PHY and the controller it is attached to are both physical
>>> devices.
>>>
>>> The connection between them is hardwired by the system
>>> manufacturer and cannot be changed by software.
>>>
>>> PHYs are generally described by fixed system-specific board
>>> files or by Device Tree information. Are they ever discovered
>>> dynamically?
>>
>> No. They are created just like any other platform devices are created.
>
> Okay. Are PHYs _always_ platform devices?
Not always. It can be any other device also.
>
>>> Is the same true for the controllers attached to the PHYs?
>>> If not -- if both a PHY and a controller are discovered
>>> dynamically -- how does the kernel know whether they are
>>> connected to each other?
>>
>> No differences here. Both PHY and controller will have dt information or hwmod
>> data using which platform devices will be created.
>>>
>>> The kernel needs to know which controller is attached to which
>>> PHY. Currently this information is represented by name or ID
>>> strings embedded in platform data.
>>
>> right. It's embedded in the platform data of the controller.
>
> It must also be embedded in the PHY's platform data somehow.
> Otherwise, how would the kernel know which PHY to use?
>
>>> The PHY's driver (the supplier) uses the platform data to
>>> construct a platform_device structure that represents the PHY.
>>
>> Currently the driver assigns static labels (corresponding to the label used in
>> the platform data of the controller).
>>> Until this is done, the controller's driver (the client) cannot
>>> use the PHY.
>>
>> right.
>>>
>>> Since there is no parent-child relation between the PHY and the
>>> controller, there is no guarantee that the PHY's driver will be
>>> ready when the controller's driver wants to use it. A deferred
>>> probe may be needed.
>>
>> right.
>>>
>>> The issue (or one of the issues) in this discussion is that
>>> Greg does not like the idea of using names or IDs to associate
>>> PHYs with controllers, because they are too prone to
>>> duplications or other errors. Pointers are more reliable.
>>>
>>> But pointers to what? Since the only data known to be
>>> available to both the PHY driver and controller driver is the
>>> platform data, the obvious answer is a pointer to platform data
>>> (either for the PHY or for the controller, or maybe both).
>>
>> hmm.. it's not going to be simple though as the platform device for the PHY and
>> controller can be created in entirely different places. e.g., in some cases the
>> PHY device is a child of some mfd core device (the device will be created in
>> drivers/mfd) and the controller driver (usually) is created in board file. I
>> guess then we have to come up with something to share a pointer in two
>> different files.
>
> The ability for two different source files to share a pointer to a data
> item defined in a third source file has been around since long before
> the C language was invented. :-)
>
> In this case, it doesn't matter where the platform_device structures
> are created or where the driver source code is. Let's take a simple
> example. Suppose the system design includes a PHY named "foo". Then
> the board file could contain:
>
> struct phy_info { ... } phy_foo;
> EXPORT_SYMBOL_GPL(phy_foo);
>
> and a header file would contain:
>
> extern struct phy_info phy_foo;
>
> The PHY supplier could then call phy_create(&phy_foo), and the PHY
> client could call phy_find(&phy_foo). Or something like that; make up
> your own structure tags and function names.
Alright. Thanks for the hint :-)
Thanks
Kishon
Hi Alan,
On Monday 22 of July 2013 10:44:39 Alan Stern wrote:
> On Mon, 22 Jul 2013, Kishon Vijay Abraham I wrote:
> > > The PHY and the controller it is attached to are both physical
> > > devices.
> > >
> > > The connection between them is hardwired by the system
> > > manufacturer and cannot be changed by software.
> > >
> > > PHYs are generally described by fixed system-specific board
> > > files or by Device Tree information. Are they ever discovered
> > > dynamically?
> >
> > No. They are created just like any other platform devices are created.
>
> Okay. Are PHYs _always_ platform devices?
They can be i2c, spi or any other device types as well.
> > > Is the same true for the controllers attached to the PHYs?
> > > If not -- if both a PHY and a controller are discovered
> > > dynamically -- how does the kernel know whether they are
> > > connected to each other?
> >
> > No differences here. Both PHY and controller will have dt information
> > or hwmod data using which platform devices will be created.
> >
> > > The kernel needs to know which controller is attached to which
> > > PHY. Currently this information is represented by name or ID
> > > strings embedded in platform data.
> >
> > right. It's embedded in the platform data of the controller.
>
> It must also be embedded in the PHY's platform data somehow.
> Otherwise, how would the kernel know which PHY to use?
By using a PHY lookup as Stephen and I suggested in our previous replies.
Without any extra data in platform data. (I have even posted a code
example.)
> > > The PHY's driver (the supplier) uses the platform data to
> > > construct a platform_device structure that represents the PHY.
> >
> > Currently the driver assigns static labels (corresponding to the label
> > used in the platform data of the controller).
> >
> > > Until this is done, the controller's driver (the client) cannot
> > > use the PHY.
> >
> > right.
> >
> > > Since there is no parent-child relation between the PHY and the
> > > controller, there is no guarantee that the PHY's driver will be
> > > ready when the controller's driver wants to use it. A deferred
> > > probe may be needed.
> >
> > right.
> >
> > > The issue (or one of the issues) in this discussion is that
> > > Greg does not like the idea of using names or IDs to associate
> > > PHYs with controllers, because they are too prone to
> > > duplications or other errors. Pointers are more reliable.
> > >
> > > But pointers to what? Since the only data known to be
> > > available to both the PHY driver and controller driver is the
> > > platform data, the obvious answer is a pointer to platform data
> > > (either for the PHY or for the controller, or maybe both).
> >
> > hmm.. it's not going to be simple though as the platform device for
> > the PHY and controller can be created in entirely different places.
> > e.g., in some cases the PHY device is a child of some mfd core device
> > (the device will be created in drivers/mfd) and the controller driver
> > (usually) is created in board file. I guess then we have to come up
> > with something to share a pointer in two different files.
>
> The ability for two different source files to share a pointer to a data
> item defined in a third source file has been around since long before
> the C language was invented. :-)
>
> In this case, it doesn't matter where the platform_device structures
> are created or where the driver source code is. Let's take a simple
> example. Suppose the system design includes a PHY named "foo". Then
> the board file could contain:
>
> struct phy_info { ... } phy_foo;
> EXPORT_SYMBOL_GPL(phy_foo);
>
> and a header file would contain:
>
> extern struct phy_info phy_foo;
>
> The PHY supplier could then call phy_create(&phy_foo), and the PHY
> client could call phy_find(&phy_foo). Or something like that; make up
> your own structure tags and function names.
>
> It's still possible to have conflicts, but now two PHYs with the same
> name (or a misspelled name somewhere) will cause an error at link time.
This is incorrect, sorry. First of all it's a layering violation - you
export random driver-specific symbols from one driver to another. Then
imagine 4 SoCs - A, B, C, D. There are two PHY types PHY1 and PHY2 and
there are two types of consumer drivers (e.g. USB host controllers). Now
consider following mapping:
SoC PHY consumer
A PHY1 HOST1
B PHY1 HOST2
C PHY2 HOST1
D PHY2 HOST2
So we have to be able to use any of the PHYs with any of the host drivers.
This means you would have to export symbol with the same name from both
PHY drivers, which obviously would not work in this case, because having
both drivers enabled (in a multiplatform aware configuration) would lead
to linking conflict.
Best regards,
Tomasz
[Fixed address of devicetree mailing list and added more people on CC.]
For reference, full thread can be found under following link:
http://thread.gmane.org/gmane.linux.ports.arm.kernel/252813
Best regards,
Tomasz
On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
> Hi Alan,
>
> On Monday 22 of July 2013 10:44:39 Alan Stern wrote:
> > On Mon, 22 Jul 2013, Kishon Vijay Abraham I wrote:
> > > > The PHY and the controller it is attached to are both
physical
> > > > devices.
> > > >
> > > > The connection between them is hardwired by the system
> > > > manufacturer and cannot be changed by software.
> > > >
> > > > PHYs are generally described by fixed system-specific
board
> > > > files or by Device Tree information. Are they ever
discovered
> > > > dynamically?
> > >
> > > No. They are created just like any other platform devices are
> > > created.
> >
> > Okay. Are PHYs _always_ platform devices?
>
> They can be i2c, spi or any other device types as well.
>
> > > > Is the same true for the controllers attached to the PHYs?
> > > > If not -- if both a PHY and a controller are discovered
> > > > dynamically -- how does the kernel know whether they are
> > > > connected to each other?
> > >
> > > No differences here. Both PHY and controller will have dt
> > > information
> > > or hwmod data using which platform devices will be created.
> > >
> > > > The kernel needs to know which controller is attached to
which
> > > > PHY. Currently this information is represented by name or
ID
> > > > strings embedded in platform data.
> > >
> > > right. It's embedded in the platform data of the controller.
> >
> > It must also be embedded in the PHY's platform data somehow.
> > Otherwise, how would the kernel know which PHY to use?
>
> By using a PHY lookup as Stephen and I suggested in our previous
> replies. Without any extra data in platform data. (I have even posted a
> code example.)
>
> > > > The PHY's driver (the supplier) uses the platform data to
> > > > construct a platform_device structure that represents the
PHY.
> > >
> > > Currently the driver assigns static labels (corresponding to the
> > > label
> > > used in the platform data of the controller).
> > >
> > > > Until this is done, the controller's driver (the client)
cannot
> > > > use the PHY.
> > >
> > > right.
> > >
> > > > Since there is no parent-child relation between the PHY
and the
> > > > controller, there is no guarantee that the PHY's driver
will be
> > > > ready when the controller's driver wants to use it. A
deferred
> > > > probe may be needed.
> > >
> > > right.
> > >
> > > > The issue (or one of the issues) in this discussion is
that
> > > > Greg does not like the idea of using names or IDs to
associate
> > > > PHYs with controllers, because they are too prone to
> > > > duplications or other errors. Pointers are more reliable.
> > > >
> > > > But pointers to what? Since the only data known to be
> > > > available to both the PHY driver and controller driver is
the
> > > > platform data, the obvious answer is a pointer to platform
data
> > > > (either for the PHY or for the controller, or maybe both).
> > >
> > > hmm.. it's not going to be simple though as the platform device for
> > > the PHY and controller can be created in entirely different places.
> > > e.g., in some cases the PHY device is a child of some mfd core
> > > device
> > > (the device will be created in drivers/mfd) and the controller
> > > driver
> > > (usually) is created in board file. I guess then we have to come up
> > > with something to share a pointer in two different files.
> >
> > The ability for two different source files to share a pointer to a
> > data
> > item defined in a third source file has been around since long before
> > the C language was invented. :-)
> >
> > In this case, it doesn't matter where the platform_device structures
> > are created or where the driver source code is. Let's take a simple
> > example. Suppose the system design includes a PHY named "foo". Then
> > the board file could contain:
> >
> > struct phy_info { ... } phy_foo;
> > EXPORT_SYMBOL_GPL(phy_foo);
> >
> > and a header file would contain:
> >
> > extern struct phy_info phy_foo;
> >
> > The PHY supplier could then call phy_create(&phy_foo), and the PHY
> > client could call phy_find(&phy_foo). Or something like that; make up
> > your own structure tags and function names.
> >
> > It's still possible to have conflicts, but now two PHYs with the same
> > name (or a misspelled name somewhere) will cause an error at link
> > time.
>
> This is incorrect, sorry. First of all it's a layering violation - you
> export random driver-specific symbols from one driver to another. Then
> imagine 4 SoCs - A, B, C, D. There are two PHY types PHY1 and PHY2 and
> there are two types of consumer drivers (e.g. USB host controllers). Now
> consider following mapping:
>
> SoC PHY consumer
> A PHY1 HOST1
> B PHY1 HOST2
> C PHY2 HOST1
> D PHY2 HOST2
>
> So we have to be able to use any of the PHYs with any of the host
> drivers. This means you would have to export symbol with the same name
> from both PHY drivers, which obviously would not work in this case,
> because having both drivers enabled (in a multiplatform aware
> configuration) would lead to linking conflict.
>
> Best regards,
> Tomasz
On Tue, 23 Jul 2013, Tomasz Figa wrote:
> On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
> > Hi Alan,
Thanks for helping to clarify the issues here.
> > > Okay. Are PHYs _always_ platform devices?
> >
> > They can be i2c, spi or any other device types as well.
In those other cases, presumably there is no platform data associated
with the PHY since it isn't a platform device. Then how does the
kernel know which controller is attached to the PHY? Is this spelled
out in platform data associated with the PHY's i2c/spi/whatever parent?
> > > > > PHY. Currently this information is represented by name or
> ID
> > > > > strings embedded in platform data.
> > > >
> > > > right. It's embedded in the platform data of the controller.
> > >
> > > It must also be embedded in the PHY's platform data somehow.
> > > Otherwise, how would the kernel know which PHY to use?
> >
> > By using a PHY lookup as Stephen and I suggested in our previous
> > replies. Without any extra data in platform data. (I have even posted a
> > code example.)
I don't understand, because I don't know what "a PHY lookup" does.
> > > In this case, it doesn't matter where the platform_device structures
> > > are created or where the driver source code is. Let's take a simple
> > > example. Suppose the system design includes a PHY named "foo". Then
> > > the board file could contain:
> > >
> > > struct phy_info { ... } phy_foo;
> > > EXPORT_SYMBOL_GPL(phy_foo);
> > >
> > > and a header file would contain:
> > >
> > > extern struct phy_info phy_foo;
> > >
> > > The PHY supplier could then call phy_create(&phy_foo), and the PHY
> > > client could call phy_find(&phy_foo). Or something like that; make up
> > > your own structure tags and function names.
> > >
> > > It's still possible to have conflicts, but now two PHYs with the same
> > > name (or a misspelled name somewhere) will cause an error at link
> > > time.
> >
> > This is incorrect, sorry. First of all it's a layering violation - you
> > export random driver-specific symbols from one driver to another. Then
No, that's not what I said. Neither the PHY driver nor the controller
driver exports anything to the other. Instead, both drivers use data
exported by the board file.
> > imagine 4 SoCs - A, B, C, D. There are two PHY types PHY1 and PHY2 and
> > there are two types of consumer drivers (e.g. USB host controllers). Now
> > consider following mapping:
> >
> > SoC PHY consumer
> > A PHY1 HOST1
> > B PHY1 HOST2
> > C PHY2 HOST1
> > D PHY2 HOST2
> >
> > So we have to be able to use any of the PHYs with any of the host
> > drivers. This means you would have to export symbol with the same name
> > from both PHY drivers, which obviously would not work in this case,
> > because having both drivers enabled (in a multiplatform aware
> > configuration) would lead to linking conflict.
You're right; the scheme was too simple. Instead, the board file must
export two types of data structures, one for PHYs and one for
controllers. Like this:
struct phy_info {
/* Info for the controller attached to this PHY */
struct controller_info *hinfo;
};
struct controller_info {
/* Info for the PHY which this controller is attached to */
struct phy_info *pinfo;
};
The board file for SoC A would contain:
struct phy_info phy1 = {&host1);
EXPORT_SYMBOL(phy1);
struct controller_info host1 = {&phy1};
EXPORT_SYMBOL(host1);
The board file for SoC B would contain:
struct phy_info phy1 = {&host2);
EXPORT_SYMBOL(phy1);
struct controller_info host2 = {&phy1};
EXPORT_SYMBOL(host2);
And so on. This explicitly gives the connection between PHYs and
controllers. The PHY providers would use &phy1 or &phy2, and the PHY
consumers would use &host1 or &host2.
Alan Stern
On Tuesday 23 of July 2013 10:37:05 Alan Stern wrote:
> On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
> > > Hi Alan,
>
> Thanks for helping to clarify the issues here.
>
> > > > Okay. Are PHYs _always_ platform devices?
> > >
> > > They can be i2c, spi or any other device types as well.
>
> In those other cases, presumably there is no platform data associated
> with the PHY since it isn't a platform device. Then how does the
> kernel know which controller is attached to the PHY? Is this spelled
> out in platform data associated with the PHY's i2c/spi/whatever parent?
>
> > > > > > PHY. Currently this information is represented by name or
> >
> > ID
> >
> > > > > > strings embedded in platform data.
> > > > >
> > > > > right. It's embedded in the platform data of the controller.
> > > >
> > > > It must also be embedded in the PHY's platform data somehow.
> > > > Otherwise, how would the kernel know which PHY to use?
> > >
> > > By using a PHY lookup as Stephen and I suggested in our previous
> > > replies. Without any extra data in platform data. (I have even posted
> > > a
> > > code example.)
>
> I don't understand, because I don't know what "a PHY lookup" does.
I have provided a code example in [1]. Feel free to ask questions about
those code snippets.
[1] http://thread.gmane.org/gmane.linux.ports.arm.kernel/252813/focus=20889
> > > > In this case, it doesn't matter where the platform_device
> > > > structures
> > > > are created or where the driver source code is. Let's take a
> > > > simple
> > > > example. Suppose the system design includes a PHY named "foo".
> > > > Then
> > > > the board file could contain:
> > > >
> > > > struct phy_info { ... } phy_foo;
> > > > EXPORT_SYMBOL_GPL(phy_foo);
> > > >
> > > > and a header file would contain:
> > > >
> > > > extern struct phy_info phy_foo;
> > > >
> > > > The PHY supplier could then call phy_create(&phy_foo), and the PHY
> > > > client could call phy_find(&phy_foo). Or something like that; make
> > > > up
> > > > your own structure tags and function names.
> > > >
> > > > It's still possible to have conflicts, but now two PHYs with the
> > > > same
> > > > name (or a misspelled name somewhere) will cause an error at link
> > > > time.
> > >
> > > This is incorrect, sorry. First of all it's a layering violation -
> > > you
> > > export random driver-specific symbols from one driver to another.
> > > Then
>
> No, that's not what I said. Neither the PHY driver nor the controller
> driver exports anything to the other. Instead, both drivers use data
> exported by the board file.
It's still a random, driver-specific global symbol exported from board file
to drivers.
> > > imagine 4 SoCs - A, B, C, D. There are two PHY types PHY1 and PHY2
> > > and
> > > there are two types of consumer drivers (e.g. USB host controllers).
> > > Now
> > > consider following mapping:
> > >
> > > SoC PHY consumer
> > > A PHY1 HOST1
> > > B PHY1 HOST2
> > > C PHY2 HOST1
> > > D PHY2 HOST2
> > >
> > > So we have to be able to use any of the PHYs with any of the host
> > > drivers. This means you would have to export symbol with the same
> > > name
> > > from both PHY drivers, which obviously would not work in this case,
> > > because having both drivers enabled (in a multiplatform aware
> > > configuration) would lead to linking conflict.
>
> You're right; the scheme was too simple. Instead, the board file must
> export two types of data structures, one for PHYs and one for
> controllers. Like this:
>
> struct phy_info {
> /* Info for the controller attached to this PHY */
> struct controller_info *hinfo;
> };
>
> struct controller_info {
> /* Info for the PHY which this controller is attached to */
> struct phy_info *pinfo;
> };
>
> The board file for SoC A would contain:
>
> struct phy_info phy1 = {&host1);
> EXPORT_SYMBOL(phy1);
> struct controller_info host1 = {&phy1};
> EXPORT_SYMBOL(host1);
>
> The board file for SoC B would contain:
>
> struct phy_info phy1 = {&host2);
> EXPORT_SYMBOL(phy1);
> struct controller_info host2 = {&phy1};
> EXPORT_SYMBOL(host2);
>
> And so on. This explicitly gives the connection between PHYs and
> controllers. The PHY providers would use &phy1 or &phy2, and the PHY
> consumers would use &host1 or &host2.
This could work assuming that only one SoC and one board is supported in
single kernel image. However it's not the case.
We've used to support multiple boards since a long time already and now for
selected platforms we even support multiplatform, i.e. multiple SoCs in
single zImage. Such solution will not work.
Best regards,
Tomasz
Hi,
On Tuesday 23 July 2013 08:07 PM, Alan Stern wrote:
> On Tue, 23 Jul 2013, Tomasz Figa wrote:
>
>> On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
>>> Hi Alan,
>
> Thanks for helping to clarify the issues here.
>
>>>> Okay. Are PHYs _always_ platform devices?
>>>
>>> They can be i2c, spi or any other device types as well.
>
> In those other cases, presumably there is no platform data associated
> with the PHY since it isn't a platform device. Then how does the
> kernel know which controller is attached to the PHY? Is this spelled
> out in platform data associated with the PHY's i2c/spi/whatever parent?
Yes. I think we could use i2c_board_info for passing platform data.
>
>>>>>> PHY. Currently this information is represented by name or
>> ID
>>>>>> strings embedded in platform data.
>>>>>
>>>>> right. It's embedded in the platform data of the controller.
>>>>
>>>> It must also be embedded in the PHY's platform data somehow.
>>>> Otherwise, how would the kernel know which PHY to use?
>>>
>>> By using a PHY lookup as Stephen and I suggested in our previous
>>> replies. Without any extra data in platform data. (I have even posted a
>>> code example.)
>
> I don't understand, because I don't know what "a PHY lookup" does.
It is how the PHY framework finds a PHY, when the controller (say USB)requests
a PHY from the PHY framework.
>
>>>> In this case, it doesn't matter where the platform_device structures
>>>> are created or where the driver source code is. Let's take a simple
>>>> example. Suppose the system design includes a PHY named "foo". Then
>>>> the board file could contain:
>>>>
>>>> struct phy_info { ... } phy_foo;
>>>> EXPORT_SYMBOL_GPL(phy_foo);
>>>>
>>>> and a header file would contain:
>>>>
>>>> extern struct phy_info phy_foo;
>>>>
>>>> The PHY supplier could then call phy_create(&phy_foo), and the PHY
>>>> client could call phy_find(&phy_foo). Or something like that; make up
>>>> your own structure tags and function names.
>>>>
>>>> It's still possible to have conflicts, but now two PHYs with the same
>>>> name (or a misspelled name somewhere) will cause an error at link
>>>> time.
>>>
>>> This is incorrect, sorry. First of all it's a layering violation - you
>>> export random driver-specific symbols from one driver to another. Then
>
> No, that's not what I said. Neither the PHY driver nor the controller
> driver exports anything to the other. Instead, both drivers use data
> exported by the board file.
I think instead we can use the same data while creating the platform data of
the controller and the PHY.
The PHY driver while creating the PHY (using PHY framework) will also pass the
*data* it actually got from the platform data to the framework.
The PHY user driver (USB), while requesting for the PHY (from the PHY
framework) will pass the *data* it got from its platform data.
The PHY framework can do a comparison of the *data* pointers it has and return
the appropriate PHY to the controller.
>
>>> imagine 4 SoCs - A, B, C, D. There are two PHY types PHY1 and PHY2 and
>>> there are two types of consumer drivers (e.g. USB host controllers). Now
>>> consider following mapping:
>>>
>>> SoC PHY consumer
>>> A PHY1 HOST1
>>> B PHY1 HOST2
>>> C PHY2 HOST1
>>> D PHY2 HOST2
>>>
>>> So we have to be able to use any of the PHYs with any of the host
>>> drivers. This means you would have to export symbol with the same name
>>> from both PHY drivers, which obviously would not work in this case,
>>> because having both drivers enabled (in a multiplatform aware
>>> configuration) would lead to linking conflict.
>
> You're right; the scheme was too simple. Instead, the board file must
> export two types of data structures, one for PHYs and one for
> controllers. Like this:
>
> struct phy_info {
> /* Info for the controller attached to this PHY */
> struct controller_info *hinfo;
> };
>
> struct controller_info {
> /* Info for the PHY which this controller is attached to */
> struct phy_info *pinfo;
> };
>
> The board file for SoC A would contain:
>
> struct phy_info phy1 = {&host1);
> EXPORT_SYMBOL(phy1);
> struct controller_info host1 = {&phy1};
> EXPORT_SYMBOL(host1);
>
> The board file for SoC B would contain:
>
> struct phy_info phy1 = {&host2);
> EXPORT_SYMBOL(phy1);
> struct controller_info host2 = {&phy1};
> EXPORT_SYMBOL(host2);
I meant something like this
struct phy_info {
const char *name;
};
struct phy_platform_data {
.
.
struct phy_info *info;
};
struct usb_controller_platform_data {
.
.
struct phy_info *info;
};
struct phy_info phy_info;
While creating the phy device
struct phy_platform_data phy_data;
phy_data.info = &info;
platform_device_add_data(pdev, &phy_data, sizeof(*phy_data))
platform_device_add();
While creating the controller device
struct usb_controller_platform_data controller_data;
controller_data.info = &info;
platform_device_add_data(pdev, &controller_data, sizeof(*controller_data))
platform_device_add();
Then modify PHY framework API phy create
phy_create((struct device *dev, const struct phy_ops *ops,
void *priv) {//API changed to take void pointer instead of label
. //existing implementation
.
phy->priv = priv;
}
struct phy *phy_get(struct device *dev, const char *string, void *priv) {
//API changed to take an additional pointer
phy_lookup(priv)
}
static struct phy *phy_lookup(void *priv) {
.
.
if (phy->priv==priv) //instead of string comparison, we'll use pointer
return phy;
}
PHY driver should be like
phy_create((dev, ops, pdata->info);
The controller driver would do
phy_get(dev, NULL, pdata->info);
Now the PHY framework will check for a match of *priv* pointer and return the PHY.
I think this should be possible?
Thanks
Kishon
On Tue, Jul 23, 2013 at 08:48:24PM +0530, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Tuesday 23 July 2013 08:07 PM, Alan Stern wrote:
> > On Tue, 23 Jul 2013, Tomasz Figa wrote:
> >
> >> On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
> >>> Hi Alan,
> >
> > Thanks for helping to clarify the issues here.
> >
> >>>> Okay. Are PHYs _always_ platform devices?
> >>>
> >>> They can be i2c, spi or any other device types as well.
> >
> > In those other cases, presumably there is no platform data associated
> > with the PHY since it isn't a platform device. Then how does the
> > kernel know which controller is attached to the PHY? Is this spelled
> > out in platform data associated with the PHY's i2c/spi/whatever parent?
>
> Yes. I think we could use i2c_board_info for passing platform data.
> >
> >>>>>> PHY. Currently this information is represented by name or
> >> ID
> >>>>>> strings embedded in platform data.
> >>>>>
> >>>>> right. It's embedded in the platform data of the controller.
> >>>>
> >>>> It must also be embedded in the PHY's platform data somehow.
> >>>> Otherwise, how would the kernel know which PHY to use?
> >>>
> >>> By using a PHY lookup as Stephen and I suggested in our previous
> >>> replies. Without any extra data in platform data. (I have even posted a
> >>> code example.)
> >
> > I don't understand, because I don't know what "a PHY lookup" does.
>
> It is how the PHY framework finds a PHY, when the controller (say USB)requests
> a PHY from the PHY framework.
> >
> >>>> In this case, it doesn't matter where the platform_device structures
> >>>> are created or where the driver source code is. Let's take a simple
> >>>> example. Suppose the system design includes a PHY named "foo". Then
> >>>> the board file could contain:
> >>>>
> >>>> struct phy_info { ... } phy_foo;
> >>>> EXPORT_SYMBOL_GPL(phy_foo);
> >>>>
> >>>> and a header file would contain:
> >>>>
> >>>> extern struct phy_info phy_foo;
> >>>>
> >>>> The PHY supplier could then call phy_create(&phy_foo), and the PHY
> >>>> client could call phy_find(&phy_foo). Or something like that; make up
> >>>> your own structure tags and function names.
> >>>>
> >>>> It's still possible to have conflicts, but now two PHYs with the same
> >>>> name (or a misspelled name somewhere) will cause an error at link
> >>>> time.
> >>>
> >>> This is incorrect, sorry. First of all it's a layering violation - you
> >>> export random driver-specific symbols from one driver to another. Then
> >
> > No, that's not what I said. Neither the PHY driver nor the controller
> > driver exports anything to the other. Instead, both drivers use data
> > exported by the board file.
>
> I think instead we can use the same data while creating the platform data of
> the controller and the PHY.
> The PHY driver while creating the PHY (using PHY framework) will also pass the
> *data* it actually got from the platform data to the framework.
> The PHY user driver (USB), while requesting for the PHY (from the PHY
> framework) will pass the *data* it got from its platform data.
> The PHY framework can do a comparison of the *data* pointers it has and return
> the appropriate PHY to the controller.
> >
> >>> imagine 4 SoCs - A, B, C, D. There are two PHY types PHY1 and PHY2 and
> >>> there are two types of consumer drivers (e.g. USB host controllers). Now
> >>> consider following mapping:
> >>>
> >>> SoC PHY consumer
> >>> A PHY1 HOST1
> >>> B PHY1 HOST2
> >>> C PHY2 HOST1
> >>> D PHY2 HOST2
> >>>
> >>> So we have to be able to use any of the PHYs with any of the host
> >>> drivers. This means you would have to export symbol with the same name
> >>> from both PHY drivers, which obviously would not work in this case,
> >>> because having both drivers enabled (in a multiplatform aware
> >>> configuration) would lead to linking conflict.
> >
> > You're right; the scheme was too simple. Instead, the board file must
> > export two types of data structures, one for PHYs and one for
> > controllers. Like this:
> >
> > struct phy_info {
> > /* Info for the controller attached to this PHY */
> > struct controller_info *hinfo;
> > };
> >
> > struct controller_info {
> > /* Info for the PHY which this controller is attached to */
> > struct phy_info *pinfo;
> > };
> >
> > The board file for SoC A would contain:
> >
> > struct phy_info phy1 = {&host1);
> > EXPORT_SYMBOL(phy1);
> > struct controller_info host1 = {&phy1};
> > EXPORT_SYMBOL(host1);
> >
> > The board file for SoC B would contain:
> >
> > struct phy_info phy1 = {&host2);
> > EXPORT_SYMBOL(phy1);
> > struct controller_info host2 = {&phy1};
> > EXPORT_SYMBOL(host2);
>
> I meant something like this
> struct phy_info {
> const char *name;
> };
>
> struct phy_platform_data {
> .
> .
> struct phy_info *info;
> };
>
> struct usb_controller_platform_data {
> .
> .
> struct phy_info *info;
> };
>
> struct phy_info phy_info;
>
> While creating the phy device
> struct phy_platform_data phy_data;
> phy_data.info = &info;
> platform_device_add_data(pdev, &phy_data, sizeof(*phy_data))
> platform_device_add();
>
> While creating the controller device
> struct usb_controller_platform_data controller_data;
> controller_data.info = &info;
> platform_device_add_data(pdev, &controller_data, sizeof(*controller_data))
> platform_device_add();
>
> Then modify PHY framework API phy create
> phy_create((struct device *dev, const struct phy_ops *ops,
> void *priv) {//API changed to take void pointer instead of label
> . //existing implementation
> .
> phy->priv = priv;
> }
>
> struct phy *phy_get(struct device *dev, const char *string, void *priv) {
> //API changed to take an additional pointer
> phy_lookup(priv)
> }
>
> static struct phy *phy_lookup(void *priv) {
> .
> .
> if (phy->priv==priv) //instead of string comparison, we'll use pointer
> return phy;
> }
>
> PHY driver should be like
> phy_create((dev, ops, pdata->info);
>
> The controller driver would do
> phy_get(dev, NULL, pdata->info);
>
> Now the PHY framework will check for a match of *priv* pointer and return the PHY.
>
> I think this should be possible?
Ick, no. Why can't you just pass the pointer to the phy itself? If you
had a "priv" pointer to search from, then you could have just passed the
original phy pointer in the first place, right?
The issue is that a string "name" is not going to scale at all, as it
requires hard-coded information that will change over time (as the
existing clock interface is already showing.)
Please just pass the real "phy" pointer around, that's what it is there
for. Your "board binding" logic/code should be able to handle this, as
it somehow was going to do the same thing with a "name".
thanks,
greg k-h
Hi Greg,
On Tuesday 23 July 2013 09:48 PM, Greg KH wrote:
> On Tue, Jul 23, 2013 at 08:48:24PM +0530, Kishon Vijay Abraham I wrote:
>> Hi,
>>
>> On Tuesday 23 July 2013 08:07 PM, Alan Stern wrote:
>>> On Tue, 23 Jul 2013, Tomasz Figa wrote:
>>>
>>>> On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
>>>>> Hi Alan,
>>>
>>> Thanks for helping to clarify the issues here.
>>>
>>>>>> Okay. Are PHYs _always_ platform devices?
>>>>>
>>>>> They can be i2c, spi or any other device types as well.
>>>
>>> In those other cases, presumably there is no platform data associated
>>> with the PHY since it isn't a platform device. Then how does the
>>> kernel know which controller is attached to the PHY? Is this spelled
>>> out in platform data associated with the PHY's i2c/spi/whatever parent?
.
.
<snip>
.
.
>>
>> static struct phy *phy_lookup(void *priv) {
>> .
>> .
>> if (phy->priv==priv) //instead of string comparison, we'll use pointer
>> return phy;
>> }
>>
>> PHY driver should be like
>> phy_create((dev, ops, pdata->info);
>>
>> The controller driver would do
>> phy_get(dev, NULL, pdata->info);
>>
>> Now the PHY framework will check for a match of *priv* pointer and return the PHY.
>>
>> I think this should be possible?
>
> Ick, no. Why can't you just pass the pointer to the phy itself? If you
> had a "priv" pointer to search from, then you could have just passed the
> original phy pointer in the first place, right?
>
> The issue is that a string "name" is not going to scale at all, as it
> requires hard-coded information that will change over time (as the
> existing clock interface is already showing.)
>
> Please just pass the real "phy" pointer around, that's what it is there
> for. Your "board binding" logic/code should be able to handle this, as
> it somehow was going to do the same thing with a "name".
The problem is the board file won't have the *phy* pointer. *phy* pointer is
created at a much later time when the phy driver is probed.
Thanks
Kishon
On Tue, Jul 23, 2013 at 09:58:34PM +0530, Kishon Vijay Abraham I wrote:
> Hi Greg,
>
> On Tuesday 23 July 2013 09:48 PM, Greg KH wrote:
> > On Tue, Jul 23, 2013 at 08:48:24PM +0530, Kishon Vijay Abraham I wrote:
> >> Hi,
> >>
> >> On Tuesday 23 July 2013 08:07 PM, Alan Stern wrote:
> >>> On Tue, 23 Jul 2013, Tomasz Figa wrote:
> >>>
> >>>> On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
> >>>>> Hi Alan,
> >>>
> >>> Thanks for helping to clarify the issues here.
> >>>
> >>>>>> Okay. Are PHYs _always_ platform devices?
> >>>>>
> >>>>> They can be i2c, spi or any other device types as well.
> >>>
> >>> In those other cases, presumably there is no platform data associated
> >>> with the PHY since it isn't a platform device. Then how does the
> >>> kernel know which controller is attached to the PHY? Is this spelled
> >>> out in platform data associated with the PHY's i2c/spi/whatever parent?
> .
> .
> <snip>
> .
> .
> >>
> >> static struct phy *phy_lookup(void *priv) {
> >> .
> >> .
> >> if (phy->priv==priv) //instead of string comparison, we'll use pointer
> >> return phy;
> >> }
> >>
> >> PHY driver should be like
> >> phy_create((dev, ops, pdata->info);
> >>
> >> The controller driver would do
> >> phy_get(dev, NULL, pdata->info);
> >>
> >> Now the PHY framework will check for a match of *priv* pointer and return the PHY.
> >>
> >> I think this should be possible?
> >
> > Ick, no. Why can't you just pass the pointer to the phy itself? If you
> > had a "priv" pointer to search from, then you could have just passed the
> > original phy pointer in the first place, right?
> >
> > The issue is that a string "name" is not going to scale at all, as it
> > requires hard-coded information that will change over time (as the
> > existing clock interface is already showing.)
> >
> > Please just pass the real "phy" pointer around, that's what it is there
> > for. Your "board binding" logic/code should be able to handle this, as
> > it somehow was going to do the same thing with a "name".
>
> The problem is the board file won't have the *phy* pointer. *phy* pointer is
> created at a much later time when the phy driver is probed.
Ok, then save it then, as no one could have used it before then, right?
All I don't want to see is any "get by name/void *" functions in the
api, as that way is fragile and will break, as people have already
shown.
Just pass the real pointer around. If that is somehow a problem, then
something larger is a problem with how board devices are tied together :)
thanks,
greg k-h
On Tuesday 23 of July 2013 09:18:46 Greg KH wrote:
> On Tue, Jul 23, 2013 at 08:48:24PM +0530, Kishon Vijay Abraham I wrote:
> > Hi,
> >
> > On Tuesday 23 July 2013 08:07 PM, Alan Stern wrote:
> > > On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > >> On Tuesday 23 of July 2013 09:29:32 Tomasz Figa wrote:
> > >>> Hi Alan,
> > >
> > > Thanks for helping to clarify the issues here.
> > >
> > >>>> Okay. Are PHYs _always_ platform devices?
> > >>>
> > >>> They can be i2c, spi or any other device types as well.
> > >
> > > In those other cases, presumably there is no platform data associated
> > > with the PHY since it isn't a platform device. Then how does the
> > > kernel know which controller is attached to the PHY? Is this spelled
> > > out in platform data associated with the PHY's i2c/spi/whatever
> > > parent?
> >
> > Yes. I think we could use i2c_board_info for passing platform data.
> >
> > >>>>>> PHY. Currently this information is represented by name or
> > >>
> > >> ID
> > >>
> > >>>>>> strings embedded in platform data.
> > >>>>>
> > >>>>> right. It's embedded in the platform data of the controller.
> > >>>>
> > >>>> It must also be embedded in the PHY's platform data somehow.
> > >>>> Otherwise, how would the kernel know which PHY to use?
> > >>>
> > >>> By using a PHY lookup as Stephen and I suggested in our previous
> > >>> replies. Without any extra data in platform data. (I have even
> > >>> posted a
> > >>> code example.)
> > >
> > > I don't understand, because I don't know what "a PHY lookup" does.
> >
> > It is how the PHY framework finds a PHY, when the controller (say
> > USB)requests a PHY from the PHY framework.
> >
> > >>>> In this case, it doesn't matter where the platform_device
> > >>>> structures
> > >>>> are created or where the driver source code is. Let's take a
> > >>>> simple
> > >>>> example. Suppose the system design includes a PHY named "foo".
> > >>>> Then
> > >>>> the board file could contain:
> > >>>>
> > >>>> struct phy_info { ... } phy_foo;
> > >>>> EXPORT_SYMBOL_GPL(phy_foo);
> > >>>>
> > >>>> and a header file would contain:
> > >>>>
> > >>>> extern struct phy_info phy_foo;
> > >>>>
> > >>>> The PHY supplier could then call phy_create(&phy_foo), and the PHY
> > >>>> client could call phy_find(&phy_foo). Or something like that;
> > >>>> make up
> > >>>> your own structure tags and function names.
> > >>>>
> > >>>> It's still possible to have conflicts, but now two PHYs with the
> > >>>> same
> > >>>> name (or a misspelled name somewhere) will cause an error at link
> > >>>> time.
> > >>>
> > >>> This is incorrect, sorry. First of all it's a layering violation -
> > >>> you
> > >>> export random driver-specific symbols from one driver to another.
> > >>> Then
> > >
> > > No, that's not what I said. Neither the PHY driver nor the
> > > controller
> > > driver exports anything to the other. Instead, both drivers use data
> > > exported by the board file.
> >
> > I think instead we can use the same data while creating the platform
> > data of the controller and the PHY.
> > The PHY driver while creating the PHY (using PHY framework) will also
> > pass the *data* it actually got from the platform data to the
> > framework. The PHY user driver (USB), while requesting for the PHY
> > (from the PHY framework) will pass the *data* it got from its platform
> > data.
> > The PHY framework can do a comparison of the *data* pointers it has and
> > return the appropriate PHY to the controller.
> >
> > >>> imagine 4 SoCs - A, B, C, D. There are two PHY types PHY1 and PHY2
> > >>> and
> > >>> there are two types of consumer drivers (e.g. USB host
> > >>> controllers). Now
> > >>> consider following mapping:
> > >>>
> > >>> SoC PHY consumer
> > >>> A PHY1 HOST1
> > >>> B PHY1 HOST2
> > >>> C PHY2 HOST1
> > >>> D PHY2 HOST2
> > >>>
> > >>> So we have to be able to use any of the PHYs with any of the host
> > >>> drivers. This means you would have to export symbol with the same
> > >>> name
> > >>> from both PHY drivers, which obviously would not work in this case,
> > >>> because having both drivers enabled (in a multiplatform aware
> > >>> configuration) would lead to linking conflict.
> > >
> > > You're right; the scheme was too simple. Instead, the board file
> > > must
> > > export two types of data structures, one for PHYs and one for
> > > controllers. Like this:
> > >
> > > struct phy_info {
> > >
> > > /* Info for the controller attached to this PHY */
> > > struct controller_info *hinfo;
> > >
> > > };
> > >
> > > struct controller_info {
> > >
> > > /* Info for the PHY which this controller is attached to */
> > > struct phy_info *pinfo;
> > >
> > > };
> > >
> > > The board file for SoC A would contain:
> > >
> > > struct phy_info phy1 = {&host1);
> > > EXPORT_SYMBOL(phy1);
> > > struct controller_info host1 = {&phy1};
> > > EXPORT_SYMBOL(host1);
> > >
> > > The board file for SoC B would contain:
> > >
> > > struct phy_info phy1 = {&host2);
> > > EXPORT_SYMBOL(phy1);
> > > struct controller_info host2 = {&phy1};
> > > EXPORT_SYMBOL(host2);
> >
> > I meant something like this
> > struct phy_info {
> >
> > const char *name;
> >
> > };
> >
> > struct phy_platform_data {
> >
> > .
> > .
> > struct phy_info *info;
> >
> > };
> >
> > struct usb_controller_platform_data {
> >
> > .
> > .
> > struct phy_info *info;
> >
> > };
> >
> > struct phy_info phy_info;
> >
> > While creating the phy device
> >
> > struct phy_platform_data phy_data;
> > phy_data.info = &info;
> > platform_device_add_data(pdev, &phy_data, sizeof(*phy_data))
> > platform_device_add();
> >
> > While creating the controller device
> >
> > struct usb_controller_platform_data controller_data;
> > controller_data.info = &info;
> > platform_device_add_data(pdev, &controller_data,
> > sizeof(*controller_data)) platform_device_add();
> >
> > Then modify PHY framework API phy create
> >
> > phy_create((struct device *dev, const struct phy_ops *ops,
> >
> > void *priv) {//API changed to take void pointer instead of
> > label
> >
> > . //existing implementation
> > .
> > phy->priv = priv;
> >
> > }
> >
> > struct phy *phy_get(struct device *dev, const char *string, void
> > *priv) {>
> > //API changed to take an additional pointer
> >
> > phy_lookup(priv)
> >
> > }
> >
> > static struct phy *phy_lookup(void *priv) {
> >
> > .
> > .
> > if (phy->priv==priv) //instead of string comparison, we'll use
> > pointer
> >
> > return phy;
> >
> > }
> >
> > PHY driver should be like
> >
> > phy_create((dev, ops, pdata->info);
> >
> > The controller driver would do
> >
> > phy_get(dev, NULL, pdata->info);
> >
> > Now the PHY framework will check for a match of *priv* pointer and
> > return the PHY.
> >
> > I think this should be possible?
>
> Ick, no. Why can't you just pass the pointer to the phy itself? If you
> had a "priv" pointer to search from, then you could have just passed the
> original phy pointer in the first place, right?
IMHO it would be better if you provided some code example, but let's try to
check if I understood you correctly.
8><------------------------------------------------------------------------
[Board file]
static struct phy my_phy;
static struct platform_device phy_pdev = {
/* ... */
.platform_data = &my_phy;
/* ... */
};
static struct platform_device phy_pdev = {
/* ... */
.platform_data = &my_phy;
/* ... */
};
[Provider driver]
struct phy *phy = pdev->dev.platform_data;
ret = phy_create(phy);
[Consumer driver]
struct phy *phy = pdev->dev.platform_data;
ret = phy_get(&pdev->dev, phy);
------------------------------------------------------------------------><8
Is this what you mean?
> The issue is that a string "name" is not going to scale at all, as it
> requires hard-coded information that will change over time (as the
> existing clock interface is already showing.)
I fully agree that a simple, single string will not scale even in some, not
so uncommon cases, but there is already a lot of existing lookup solutions
over the kernel and so there is no point in introducing another one.
> Please just pass the real "phy" pointer around, that's what it is there
> for. Your "board binding" logic/code should be able to handle this, as
> it somehow was going to do the same thing with a "name".
It's technically correct, but quality of this solution isn't really nice,
because it's a layering violation (at least if I understood what you mean).
This is because you need to have full definition of struct phy in board file
and a structure that is used as private data in PHY core comes from
platform code.
Best regards,
Tomasz
On Tue, Jul 23, 2013 at 06:50:29PM +0200, Tomasz Figa wrote:
> > Ick, no. Why can't you just pass the pointer to the phy itself? If you
> > had a "priv" pointer to search from, then you could have just passed the
> > original phy pointer in the first place, right?
>
> IMHO it would be better if you provided some code example, but let's try to
> check if I understood you correctly.
It's not my code that I want to have added, so I don't have to write
examples, I just get to complain about the existing stuff :)
> 8><------------------------------------------------------------------------
>
> [Board file]
>
> static struct phy my_phy;
>
> static struct platform_device phy_pdev = {
> /* ... */
> .platform_data = &my_phy;
> /* ... */
> };
>
> static struct platform_device phy_pdev = {
> /* ... */
> .platform_data = &my_phy;
> /* ... */
> };
>
> [Provider driver]
>
> struct phy *phy = pdev->dev.platform_data;
>
> ret = phy_create(phy);
>
> [Consumer driver]
>
> struct phy *phy = pdev->dev.platform_data;
>
> ret = phy_get(&pdev->dev, phy);
>
> ------------------------------------------------------------------------><8
>
> Is this what you mean?
No. Well, kind of. What's wrong with using the platform data structure
unique to the board to have the pointer?
For example (just randomly picking one), the ata-pxa driver would change
include/linux/platform_data/ata-pxa.h to have a phy pointer in it:
struct phy;
struct pata_pxa_pdata {
/* PXA DMA DREQ<0:2> pin */
uint32_t dma_dreq;
/* Register shift */
uint32_t reg_shift;
/* IRQ flags */
uint32_t irq_flags;
/* PHY */
struct phy *phy;
};
Then, when you create the platform, set the phy* pointer with a call to
phy_create(). Then you can use that pointer wherever that plaform data
is available (i.e. whereever platform_data is at).
> > The issue is that a string "name" is not going to scale at all, as it
> > requires hard-coded information that will change over time (as the
> > existing clock interface is already showing.)
>
> I fully agree that a simple, single string will not scale even in some, not
> so uncommon cases, but there is already a lot of existing lookup solutions
> over the kernel and so there is no point in introducing another one.
I'm trying to get _rid_ of lookup "solutions" and just use a real
pointer, as you should. I'll go tackle those other ones after this one
is taken care of, to show how the others should be handled as well.
> > Please just pass the real "phy" pointer around, that's what it is there
> > for. Your "board binding" logic/code should be able to handle this, as
> > it somehow was going to do the same thing with a "name".
>
> It's technically correct, but quality of this solution isn't really nice,
> because it's a layering violation (at least if I understood what you mean).
> This is because you need to have full definition of struct phy in board file
> and a structure that is used as private data in PHY core comes from
> platform code.
No, just a pointer, you don't need the "full" structure until you get to
some .c code that actually manipulates the phy itself, for all other
places, you are just dealing with a pointer and a structure you never
reference.
Does that make more sense?
thanks,
greg k-h
On Tue, Jul 23, 2013 at 10:37:05AM -0400, Alan Stern wrote:
> On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > > > Okay. Are PHYs _always_ platform devices?
> > > They can be i2c, spi or any other device types as well.
> In those other cases, presumably there is no platform data associated
> with the PHY since it isn't a platform device. Then how does the
> kernel know which controller is attached to the PHY? Is this spelled
> out in platform data associated with the PHY's i2c/spi/whatever parent?
Platform data is nothing to do with the platform bus - it's board
specific data (ie, data for the platform) and can be done with any
device.
On Tue, Jul 23, 2013 at 10:37:11AM -0700, Greg KH wrote:
> On Tue, Jul 23, 2013 at 06:50:29PM +0200, Tomasz Figa wrote:
> > I fully agree that a simple, single string will not scale even in some, not
> > so uncommon cases, but there is already a lot of existing lookup solutions
> > over the kernel and so there is no point in introducing another one.
> I'm trying to get _rid_ of lookup "solutions" and just use a real
> pointer, as you should. I'll go tackle those other ones after this one
> is taken care of, to show how the others should be handled as well.
What are the problems you are seeing with doing things with lookups?
Having to write platform data for everything gets old fast and the code
duplication is pretty tedious...
On Tuesday 23 of July 2013 10:37:11 Greg KH wrote:
> On Tue, Jul 23, 2013 at 06:50:29PM +0200, Tomasz Figa wrote:
> > > Ick, no. Why can't you just pass the pointer to the phy itself? If
> > > you
> > > had a "priv" pointer to search from, then you could have just passed
> > > the
> > > original phy pointer in the first place, right?
> >
> > IMHO it would be better if you provided some code example, but let's
> > try to check if I understood you correctly.
>
> It's not my code that I want to have added, so I don't have to write
> examples, I just get to complain about the existing stuff :)
Still, I think that some small code snippets illustrating the idea are
really helpful.
> > 8><--------------------------------------------------------------------
> > ----
> >
> > [Board file]
> >
> > static struct phy my_phy;
> >
> > static struct platform_device phy_pdev = {
> >
> > /* ... */
> > .platform_data = &my_phy;
> > /* ... */
> >
> > };
> >
> > static struct platform_device phy_pdev = {
> >
> > /* ... */
> > .platform_data = &my_phy;
> > /* ... */
> >
> > };
> >
> > [Provider driver]
> >
> > struct phy *phy = pdev->dev.platform_data;
> >
> > ret = phy_create(phy);
> >
> > [Consumer driver]
> >
> > struct phy *phy = pdev->dev.platform_data;
> >
> > ret = phy_get(&pdev->dev, phy);
> >
> > -----------------------------------------------------------------------
> > -><8
> >
> > Is this what you mean?
>
> No. Well, kind of. What's wrong with using the platform data structure
> unique to the board to have the pointer?
>
> For example (just randomly picking one), the ata-pxa driver would change
> include/linux/platform_data/ata-pxa.h to have a phy pointer in it:
>
> struct phy;
>
> struct pata_pxa_pdata {
> /* PXA DMA DREQ<0:2> pin */
> uint32_t dma_dreq;
> /* Register shift */
> uint32_t reg_shift;
> /* IRQ flags */
> uint32_t irq_flags;
> /* PHY */
> struct phy *phy;
> };
>
> Then, when you create the platform, set the phy* pointer with a call to
> phy_create(). Then you can use that pointer wherever that plaform data
> is available (i.e. whereever platform_data is at).
Hmm? So, do you suggest to call phy_create() from board file? What phy_ops
struct and other hardware parameters would it take?
> > > The issue is that a string "name" is not going to scale at all, as it
> > > requires hard-coded information that will change over time (as the
> > > existing clock interface is already showing.)
> >
> > I fully agree that a simple, single string will not scale even in some,
> > not so uncommon cases, but there is already a lot of existing lookup
> > solutions over the kernel and so there is no point in introducing
> > another one.
> I'm trying to get _rid_ of lookup "solutions" and just use a real
> pointer, as you should. I'll go tackle those other ones after this one
> is taken care of, to show how the others should be handled as well.
There was a reason for introducing lookup solutions. The reason was that in
board file there is no way to get a pointer to something that is going to be
created much later in time. We don't do time travel ;-).
> > > Please just pass the real "phy" pointer around, that's what it is
> > > there
> > > for. Your "board binding" logic/code should be able to handle this,
> > > as
> > > it somehow was going to do the same thing with a "name".
> >
> > It's technically correct, but quality of this solution isn't really
> > nice, because it's a layering violation (at least if I understood what
> > you mean). This is because you need to have full definition of struct
> > phy in board file and a structure that is used as private data in PHY
> > core comes from platform code.
>
> No, just a pointer, you don't need the "full" structure until you get to
> some .c code that actually manipulates the phy itself, for all other
> places, you are just dealing with a pointer and a structure you never
> reference.
>
> Does that make more sense?
Well, to the point that I think I now understood your suggestion.
Unfortunately the suggestion alone isn't really something that can be done,
considering how driver core and generic frameworks work.
Best regards,
Tomasz
On Tue, Jul 23, 2013 at 06:44:56PM +0100, Mark Brown wrote:
> On Tue, Jul 23, 2013 at 10:37:11AM -0700, Greg KH wrote:
> > On Tue, Jul 23, 2013 at 06:50:29PM +0200, Tomasz Figa wrote:
>
> > > I fully agree that a simple, single string will not scale even in some, not
> > > so uncommon cases, but there is already a lot of existing lookup solutions
> > > over the kernel and so there is no point in introducing another one.
>
> > I'm trying to get _rid_ of lookup "solutions" and just use a real
> > pointer, as you should. I'll go tackle those other ones after this one
> > is taken care of, to show how the others should be handled as well.
>
> What are the problems you are seeing with doing things with lookups?
You don't "know" the id of the device you are looking up, due to
multiple devices being in the system (dynamic ids, look back earlier in
this thread for details about that.)
> Having to write platform data for everything gets old fast and the code
> duplication is pretty tedious...
Adding a single pointer is "tedious"? Where is the "name" that you are
going to lookup going to come from? That code doesn't write itself...
thanks,
greg k-h
On Tue, Jul 23, 2013 at 07:48:11PM +0200, Tomasz Figa wrote:
> On Tuesday 23 of July 2013 10:37:11 Greg KH wrote:
> > On Tue, Jul 23, 2013 at 06:50:29PM +0200, Tomasz Figa wrote:
> > > > Ick, no. Why can't you just pass the pointer to the phy itself? If
> > > > you
> > > > had a "priv" pointer to search from, then you could have just passed
> > > > the
> > > > original phy pointer in the first place, right?
> > >
> > > IMHO it would be better if you provided some code example, but let's
> > > try to check if I understood you correctly.
> >
> > It's not my code that I want to have added, so I don't have to write
> > examples, I just get to complain about the existing stuff :)
>
> Still, I think that some small code snippets illustrating the idea are
> really helpful.
>
> > > 8><--------------------------------------------------------------------
> > > ----
> > >
> > > [Board file]
> > >
> > > static struct phy my_phy;
> > >
> > > static struct platform_device phy_pdev = {
> > >
> > > /* ... */
> > > .platform_data = &my_phy;
> > > /* ... */
> > >
> > > };
> > >
> > > static struct platform_device phy_pdev = {
> > >
> > > /* ... */
> > > .platform_data = &my_phy;
> > > /* ... */
> > >
> > > };
> > >
> > > [Provider driver]
> > >
> > > struct phy *phy = pdev->dev.platform_data;
> > >
> > > ret = phy_create(phy);
> > >
> > > [Consumer driver]
> > >
> > > struct phy *phy = pdev->dev.platform_data;
> > >
> > > ret = phy_get(&pdev->dev, phy);
> > >
> > > -----------------------------------------------------------------------
> > > -><8
> > >
> > > Is this what you mean?
> >
> > No. Well, kind of. What's wrong with using the platform data structure
> > unique to the board to have the pointer?
> >
> > For example (just randomly picking one), the ata-pxa driver would change
> > include/linux/platform_data/ata-pxa.h to have a phy pointer in it:
> >
> > struct phy;
> >
> > struct pata_pxa_pdata {
> > /* PXA DMA DREQ<0:2> pin */
> > uint32_t dma_dreq;
> > /* Register shift */
> > uint32_t reg_shift;
> > /* IRQ flags */
> > uint32_t irq_flags;
> > /* PHY */
> > struct phy *phy;
> > };
> >
> > Then, when you create the platform, set the phy* pointer with a call to
> > phy_create(). Then you can use that pointer wherever that plaform data
> > is available (i.e. whereever platform_data is at).
>
> Hmm? So, do you suggest to call phy_create() from board file? What phy_ops
> struct and other hardware parameters would it take?
>
> > > > The issue is that a string "name" is not going to scale at all, as it
> > > > requires hard-coded information that will change over time (as the
> > > > existing clock interface is already showing.)
> > >
> > > I fully agree that a simple, single string will not scale even in some,
> > > not so uncommon cases, but there is already a lot of existing lookup
> > > solutions over the kernel and so there is no point in introducing
> > > another one.
> > I'm trying to get _rid_ of lookup "solutions" and just use a real
> > pointer, as you should. I'll go tackle those other ones after this one
> > is taken care of, to show how the others should be handled as well.
>
> There was a reason for introducing lookup solutions. The reason was that in
> board file there is no way to get a pointer to something that is going to be
> created much later in time. We don't do time travel ;-).
>
> > > > Please just pass the real "phy" pointer around, that's what it is
> > > > there
> > > > for. Your "board binding" logic/code should be able to handle this,
> > > > as
> > > > it somehow was going to do the same thing with a "name".
> > >
> > > It's technically correct, but quality of this solution isn't really
> > > nice, because it's a layering violation (at least if I understood what
> > > you mean). This is because you need to have full definition of struct
> > > phy in board file and a structure that is used as private data in PHY
> > > core comes from platform code.
> >
> > No, just a pointer, you don't need the "full" structure until you get to
> > some .c code that actually manipulates the phy itself, for all other
> > places, you are just dealing with a pointer and a structure you never
> > reference.
> >
> > Does that make more sense?
>
> Well, to the point that I think I now understood your suggestion.
> Unfortunately the suggestion alone isn't really something that can be done,
> considering how driver core and generic frameworks work.
Ok, given that I seem to be totally confused as to exactly how the
board-specific frameworks work, I'll take your word for it.
But again, I will not accept "lookup by name" type solutions, when the
"name" is dynamic and will change. Because you are using a "name", you
can deal with a pointer, putting it _somewhere_ in your board-specific
data structures, as you are going to need to store it anyway (hint, you
had to get that "name" from somewhere, right?)
And maybe the way that these "generic frameworks" are created is wrong,
given that you don't feel that a generic pointer can be passed to the
needed devices. That seems like a huge problem, one that has already
been pointed out is causing issues with other subsystems.
So maybe they need to be fixed?
thanks,
greg k-h
On Tue, Jul 23, 2013 at 11:01:10AM -0700, Greg KH wrote:
> On Tue, Jul 23, 2013 at 06:44:56PM +0100, Mark Brown wrote:
> > What are the problems you are seeing with doing things with lookups?
> You don't "know" the id of the device you are looking up, due to
> multiple devices being in the system (dynamic ids, look back earlier in
> this thread for details about that.)
I got copied in very late so don't have most of the thread I'm afraid,
I did try looking at web archives but didn't see a clear problem
statement. In any case this is why the APIs doing lookups do the
lookups in the context of the requesting device - devices ask for
whatever name they use locally.
> > Having to write platform data for everything gets old fast and the code
> > duplication is pretty tedious...
> Adding a single pointer is "tedious"? Where is the "name" that you are
> going to lookup going to come from? That code doesn't write itself...
It's adding platform data in the first place that gets tedious - and of
course there's also DT and ACPI to worry about, it's not just a case of
platform data and then you're done. Pushing the lookup into library
code means that drivers don't have to worry about any of this stuff.
For most of the APIs doing this there is a clear and unambiguous name in
the hardware that can be used (and for hardware process reasons is
unlikely to get changed). The major exception to this is the clock API
since it is relatively rare to have clear, segregated IP level
information for IPs baked into larger chips. The other APIs tend to be
establishing chip to chip links.
On Tue, 23 Jul 2013, Tomasz Figa wrote:
> IMHO it would be better if you provided some code example, but let's try to
> check if I understood you correctly.
>
> 8><------------------------------------------------------------------------
>
> [Board file]
>
> static struct phy my_phy;
>
> static struct platform_device phy_pdev = {
> /* ... */
> .platform_data = &my_phy;
> /* ... */
> };
>
> static struct platform_device phy_pdev = {
This should be controller_pdev, not phy_pdev, yes?
> /* ... */
> .platform_data = &my_phy;
> /* ... */
> };
>
> [Provider driver]
>
> struct phy *phy = pdev->dev.platform_data;
>
> ret = phy_create(phy);
>
> [Consumer driver]
>
> struct phy *phy = pdev->dev.platform_data;
>
> ret = phy_get(&pdev->dev, phy);
Or even just phy_get(&pdev->dev), because phy_get() could be smart
enough to to set phy = dev->platform_data.
> ------------------------------------------------------------------------><8
>
> Is this what you mean?
That's what I was going to suggest too. The struct phy is defined in
the board file, which already knows about all the PHYs that exist in
the system. (Or perhaps it is allocated dynamically, so that when many
board files are present in the same kernel, only the entries listed in
the board file for the current system get created.) Then the
structure's address is stored in the platform data and made available
to both the provider and the consumer.
Even though the struct phy is defined (or allocated) in the board file,
its contents don't get filled in until the PHY driver provides the
details.
> It's technically correct, but quality of this solution isn't really nice,
> because it's a layering violation (at least if I understood what you mean).
> This is because you need to have full definition of struct phy in board file
> and a structure that is used as private data in PHY core comes from
> platform code.
You don't have to have a full definition in the board file. Just a
partial definition -- most of the contents can be filled in later, when
the PHY driver is ready to store the private data.
It's not a layering violation for one region of the kernel to store
private data in a structure defined by another part of the kernel.
This happens all the time (e.g., dev_set_drvdata).
Alan Stern
On Tue, Jul 23, 2013 at 08:31:05PM +0100, Mark Brown wrote:
> > You don't "know" the id of the device you are looking up, due to
> > multiple devices being in the system (dynamic ids, look back earlier in
> > this thread for details about that.)
>
> I got copied in very late so don't have most of the thread I'm afraid,
> I did try looking at web archives but didn't see a clear problem
> statement. In any case this is why the APIs doing lookups do the
> lookups in the context of the requesting device - devices ask for
> whatever name they use locally.
What do you mean by "locally"?
The problem with the api was that the phy core wanted a id and a name to
create a phy, and then later other code was doing a "lookup" based on
the name and id (mushed together), because it "knew" that this device
was the one it wanted.
Just like the clock api, which, for multiple devices, has proven to
cause problems. I don't want to see us accept an api that we know has
issues in it now, I'd rather us fix it up properly.
Subsystems should be able to create ids how ever they want to, and not
rely on the code calling them to specify the names of the devices that
way, otherwise the api is just too fragile.
I think, that if you create a device, then just carry around the pointer
to that device (in this case a phy) and pass it to whatever other code
needs it. No need to do lookups on "known names" or anything else, just
normal pointers, with no problems for multiple devices, busses, or
naming issues.
> > > Having to write platform data for everything gets old fast and the code
> > > duplication is pretty tedious...
>
> > Adding a single pointer is "tedious"? Where is the "name" that you are
> > going to lookup going to come from? That code doesn't write itself...
>
> It's adding platform data in the first place that gets tedious - and of
> course there's also DT and ACPI to worry about, it's not just a case of
> platform data and then you're done. Pushing the lookup into library
> code means that drivers don't have to worry about any of this stuff.
I agree, so just pass around the pointer to the phy and all is good. No
need to worry about DT or ACPI or anything else.
> For most of the APIs doing this there is a clear and unambiguous name in
> the hardware that can be used (and for hardware process reasons is
> unlikely to get changed). The major exception to this is the clock API
> since it is relatively rare to have clear, segregated IP level
> information for IPs baked into larger chips. The other APIs tend to be
> establishing chip to chip links.
The clock api is having problems with multiple "names" due to dynamic
devices from what I was told. I want to prevent the PHY interface from
having that same issue.
thanks,
greg k-h
On Tuesday 23 of July 2013 12:44:23 Greg KH wrote:
> On Tue, Jul 23, 2013 at 08:31:05PM +0100, Mark Brown wrote:
> > > You don't "know" the id of the device you are looking up, due to
> > > multiple devices being in the system (dynamic ids, look back earlier
> > > in
> > > this thread for details about that.)
> >
> > I got copied in very late so don't have most of the thread I'm afraid,
> > I did try looking at web archives but didn't see a clear problem
> > statement. In any case this is why the APIs doing lookups do the
> > lookups in the context of the requesting device - devices ask for
> > whatever name they use locally.
>
> What do you mean by "locally"?
>
> The problem with the api was that the phy core wanted a id and a name to
> create a phy, and then later other code was doing a "lookup" based on
> the name and id (mushed together), because it "knew" that this device
> was the one it wanted.
>
> Just like the clock api, which, for multiple devices, has proven to
> cause problems. I don't want to see us accept an api that we know has
> issues in it now, I'd rather us fix it up properly.
>
> Subsystems should be able to create ids how ever they want to, and not
> rely on the code calling them to specify the names of the devices that
> way, otherwise the api is just too fragile.
>
> I think, that if you create a device, then just carry around the pointer
> to that device (in this case a phy) and pass it to whatever other code
> needs it. No need to do lookups on "known names" or anything else,
> just normal pointers, with no problems for multiple devices, busses, or
> naming issues.
PHY object is not a device, it is something that a device driver creates
(one or more instances of) when it is being probed. You don't have a clean
way to export this PHY object to other driver, other than keeping this PHY
on a list inside PHY core with some well-known ID (e.g. device name +
consumer port name/index, like in regulator core) and then to use this
well-known ID inside consumer driver as a lookup key passed to phy_get();
Actually I think for PHY case, exactly the same way as used for regulators
might be completely fine:
1. Each PHY would have some kind of platform, non-unique name, that is
just used to print some messages (like the platform/board name of a
regulator).
2. Each PHY would have an array of consumers. Consumer specifier would
consist of consumer device name and consumer port name - just like in
regulator subsystem.
3. PHY driver receives an array of, let's say, phy_init_data inside its
platform data that it would use to register its PHYs.
4. Consumer drivers would have constant consumer port names and wouldn't
receive any information about PHYs from platform code.
Code example:
[Board file]
static const struct phy_consumer_data usb_20_phy0_consumers[] = {
{
.devname = "foo-ehci",
.port = "usbphy",
},
};
static const struct phy_consumer_data usb_20_phy1_consumers[] = {
{
.devname = "foo-otg",
.port = "otgphy",
},
};
static const struct phy_init_data my_phys[] = {
{
.name = "USB 2.0 PHY 0",
.consumers = usb_20_phy0_consumers,
.num_consumers = ARRAY_SIZE(usb_20_phy0_consumers),
},
{
.name = "USB 2.0 PHY 1",
.consumers = usb_20_phy1_consumers,
.num_consumers = ARRAY_SIZE(usb_20_phy1_consumers),
},
{ }
};
static const struct platform_device usb_phy_pdev = {
.name = "foo-usbphy",
.id = -1,
.dev = {
.platform_data = my_phys,
},
};
[PHY driver]
static int foo_usbphy_probe(pdev)
{
struct foo_usbphy *foo;
struct phy_init_data *init_data = pdev->dev.platform_data;
/* ... */
// for each PHY in init_data {
phy_register(&foo->phy[i], &init_data[i]);
// }
/* ... */
}
[EHCI driver]
static int foo_ehci_probe(pdev)
{
struct phy *phy;
/* ... */
phy = phy_get(&pdev->dev, "usbphy");
/* ... */
}
[OTG driver]
static int foo_otg_probe(pdev)
{
struct phy *phy;
/* ... */
phy = phy_get(&pdev->dev, "otgphy");
/* ... */
}
> > > > Having to write platform data for everything gets old fast and the
> > > > code
> > > > duplication is pretty tedious...
> > >
> > > Adding a single pointer is "tedious"? Where is the "name" that you
> > > are
> > > going to lookup going to come from? That code doesn't write
> > > itself...
> >
> > It's adding platform data in the first place that gets tedious - and
> > of
> > course there's also DT and ACPI to worry about, it's not just a case
> > of
> > platform data and then you're done. Pushing the lookup into library
> > code means that drivers don't have to worry about any of this stuff.
>
> I agree, so just pass around the pointer to the phy and all is good. No
> need to worry about DT or ACPI or anything else.
With Device Tree we don't have board files anymore. How would you pass any
pointers between provider and consumer drivers in this case?
> > For most of the APIs doing this there is a clear and unambiguous name
> > in the hardware that can be used (and for hardware process reasons is
> > unlikely to get changed). The major exception to this is the clock
> > API since it is relatively rare to have clear, segregated IP level
> > information for IPs baked into larger chips. The other APIs tend to
> > be establishing chip to chip links.
>
> The clock api is having problems with multiple "names" due to dynamic
> devices from what I was told. I want to prevent the PHY interface from
> having that same issue.
Yes, the clock API has a problem related to the clock namespace being
global for all registered clock controllers. This is not a problem with
lookup in general, but with wrong lookup key chosen.
Best regards,
Tomasz
On Tuesday 23 of July 2013 15:36:00 Alan Stern wrote:
> On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > IMHO it would be better if you provided some code example, but let's
> > try to check if I understood you correctly.
> >
> > 8><-------------------------------------------------------------------
> > -----
> >
> > [Board file]
> >
> > static struct phy my_phy;
> >
> > static struct platform_device phy_pdev = {
> >
> > /* ... */
> > .platform_data = &my_phy;
> > /* ... */
> >
> > };
> >
> > static struct platform_device phy_pdev = {
>
> This should be controller_pdev, not phy_pdev, yes?
Right. A copy-pasto.
>
> > /* ... */
> > .platform_data = &my_phy;
> > /* ... */
> >
> > };
> >
> > [Provider driver]
> >
> > struct phy *phy = pdev->dev.platform_data;
> >
> > ret = phy_create(phy);
> >
> > [Consumer driver]
> >
> > struct phy *phy = pdev->dev.platform_data;
> >
> > ret = phy_get(&pdev->dev, phy);
>
> Or even just phy_get(&pdev->dev), because phy_get() could be smart
> enough to to set phy = dev->platform_data.
Unless you need more than one PHY in this driver...
>
> > ----------------------------------------------------------------------
> > --><8
> >
> > Is this what you mean?
>
> That's what I was going to suggest too. The struct phy is defined in
> the board file, which already knows about all the PHYs that exist in
> the system. (Or perhaps it is allocated dynamically, so that when many
> board files are present in the same kernel, only the entries listed in
> the board file for the current system get created.)
Well, such dynamic allocation is a must. We don't accept non-multiplatform
aware code anymore, not even saying about multiboard.
> Then the
> structure's address is stored in the platform data and made available
> to both the provider and the consumer.
Yes, technically this can work. You would still have to perform some kind
of synchronization to make sure that the PHY bound to this structure is
actually present. This is again technically doable (e.g. a list of
registered struct phys inside PHY core).
> Even though the struct phy is defined (or allocated) in the board file,
> its contents don't get filled in until the PHY driver provides the
> details.
You can't assure this. Board file is free to do whatever it wants with
this struct. A clean solution would prevent this.
> > It's technically correct, but quality of this solution isn't really
> > nice, because it's a layering violation (at least if I understood
> > what you mean). This is because you need to have full definition of
> > struct phy in board file and a structure that is used as private data
> > in PHY core comes from platform code.
>
> You don't have to have a full definition in the board file. Just a
> partial definition -- most of the contents can be filled in later, when
> the PHY driver is ready to store the private data.
>
> It's not a layering violation for one region of the kernel to store
> private data in a structure defined by another part of the kernel.
> This happens all the time (e.g., dev_set_drvdata).
Not really. The phy struct is something that _is_ private data of PHY
subsystem, not something that can store private data of PHY subsystem
(sure it can store private data of particular PHY driver, but that's
another story) and only PHY subsystem should have access to its contents.
By the way, we need to consider other cases here as well, for example it
would be nice to have a single phy_get() function that works for both non-
DT and DT cases to make the consumer driver not have to worry whether it's
being probed from DT or not.
I'd suggest simply reusing the lookup method of regulator framework, just
as I suggested here:
http://thread.gmane.org/gmane.linux.ports.arm.kernel/252813/focus=101661
Best regards,
Tomasz
On Tuesday 23 of July 2013 11:04:14 Greg KH wrote:
> On Tue, Jul 23, 2013 at 07:48:11PM +0200, Tomasz Figa wrote:
> > On Tuesday 23 of July 2013 10:37:11 Greg KH wrote:
> > > On Tue, Jul 23, 2013 at 06:50:29PM +0200, Tomasz Figa wrote:
> > > > > Ick, no. Why can't you just pass the pointer to the phy itself?
> > > > > If
> > > > > you
> > > > > had a "priv" pointer to search from, then you could have just
> > > > > passed
> > > > > the
> > > > > original phy pointer in the first place, right?
> > > >
> > > > IMHO it would be better if you provided some code example, but
> > > > let's
> > > > try to check if I understood you correctly.
> > >
> > > It's not my code that I want to have added, so I don't have to write
> > > examples, I just get to complain about the existing stuff :)
> >
> > Still, I think that some small code snippets illustrating the idea are
> > really helpful.
> >
> > > > 8><---------------------------------------------------------------
> > > > -----
> > > > ----
> > > >
> > > > [Board file]
> > > >
> > > > static struct phy my_phy;
> > > >
> > > > static struct platform_device phy_pdev = {
> > > >
> > > > /* ... */
> > > > .platform_data = &my_phy;
> > > > /* ... */
> > > >
> > > > };
> > > >
> > > > static struct platform_device phy_pdev = {
> > > >
> > > > /* ... */
> > > > .platform_data = &my_phy;
> > > > /* ... */
> > > >
> > > > };
> > > >
> > > > [Provider driver]
> > > >
> > > > struct phy *phy = pdev->dev.platform_data;
> > > >
> > > > ret = phy_create(phy);
> > > >
> > > > [Consumer driver]
> > > >
> > > > struct phy *phy = pdev->dev.platform_data;
> > > >
> > > > ret = phy_get(&pdev->dev, phy);
> > > >
> > > > ------------------------------------------------------------------
> > > > -----
> > > > -><8
> > > >
> > > > Is this what you mean?
> > >
> > > No. Well, kind of. What's wrong with using the platform data
> > > structure unique to the board to have the pointer?
> > >
> > > For example (just randomly picking one), the ata-pxa driver would
> > > change include/linux/platform_data/ata-pxa.h to have a phy pointer
> > > in it:
> > >
> > > struct phy;
> > >
> > > struct pata_pxa_pdata {
> > >
> > > /* PXA DMA DREQ<0:2> pin */
> > > uint32_t dma_dreq;
> > > /* Register shift */
> > > uint32_t reg_shift;
> > > /* IRQ flags */
> > > uint32_t irq_flags;
> > > /* PHY */
> > > struct phy *phy;
> > >
> > > };
> > >
> > > Then, when you create the platform, set the phy* pointer with a call
> > > to
> > > phy_create(). Then you can use that pointer wherever that plaform
> > > data
> > > is available (i.e. whereever platform_data is at).
> >
> > Hmm? So, do you suggest to call phy_create() from board file? What
> > phy_ops struct and other hardware parameters would it take?
> >
> > > > > The issue is that a string "name" is not going to scale at all,
> > > > > as it
> > > > > requires hard-coded information that will change over time (as
> > > > > the
> > > > > existing clock interface is already showing.)
> > > >
> > > > I fully agree that a simple, single string will not scale even in
> > > > some,
> > > > not so uncommon cases, but there is already a lot of existing
> > > > lookup
> > > > solutions over the kernel and so there is no point in introducing
> > > > another one.
> > >
> > > I'm trying to get _rid_ of lookup "solutions" and just use a real
> > > pointer, as you should. I'll go tackle those other ones after this
> > > one
> > > is taken care of, to show how the others should be handled as well.
> >
> > There was a reason for introducing lookup solutions. The reason was
> > that in board file there is no way to get a pointer to something that
> > is going to be created much later in time. We don't do time travel
> > ;-).
> >
> > > > > Please just pass the real "phy" pointer around, that's what it
> > > > > is
> > > > > there
> > > > > for. Your "board binding" logic/code should be able to handle
> > > > > this,
> > > > > as
> > > > > it somehow was going to do the same thing with a "name".
> > > >
> > > > It's technically correct, but quality of this solution isn't
> > > > really
> > > > nice, because it's a layering violation (at least if I understood
> > > > what
> > > > you mean). This is because you need to have full definition of
> > > > struct
> > > > phy in board file and a structure that is used as private data in
> > > > PHY
> > > > core comes from platform code.
> > >
> > > No, just a pointer, you don't need the "full" structure until you
> > > get to some .c code that actually manipulates the phy itself, for
> > > all other places, you are just dealing with a pointer and a
> > > structure you never reference.
> > >
> > > Does that make more sense?
> >
> > Well, to the point that I think I now understood your suggestion.
> > Unfortunately the suggestion alone isn't really something that can be
> > done, considering how driver core and generic frameworks work.
>
> Ok, given that I seem to be totally confused as to exactly how the
> board-specific frameworks work, I'll take your word for it.
Well, they are working in a way that keeps separation of layers, making
things clean. Platform code should not (well, there might exist some in
tree hacks, but this should not be propagated) used to exchange data
between drivers, but rather to specify board specific parameters for
generic drivers. If drivers need to cooperate, there must be a dedicated
interface for this, like the PHY framework Kishon is introducing here.
Sure, with platform code you can do a lot of hacky things, for example you
can simply provide PHY callbacks inside platform_data, like it was being
done historically, but that's just ugly.
Anyway, board files should now be rather considered a historical thing. We
are moving towards full DT-based description on ARM systems and so board
files and related things, like name-based lookups, statically registered
platform devices and so one are going away. Device Tree handles such
provider-consumer links automatically using specifiers with phandles and
lookup by node + provider-specific specifier args, so all the problems
with binding things together just go away.
> But again, I will not accept "lookup by name" type solutions, when the
> "name" is dynamic and will change. Because you are using a "name", you
> can deal with a pointer, putting it _somewhere_ in your board-specific
> data structures, as you are going to need to store it anyway (hint, you
> had to get that "name" from somewhere, right?)
Yes. This kind of artificial names passed to both provider and consumer
isn't really a good way of lookup. This is just an example of bad lookup
key, though. IMHO for a good example of lookup you should see regulator
framework.
> And maybe the way that these "generic frameworks" are created is wrong,
> given that you don't feel that a generic pointer can be passed to the
> needed devices. That seems like a huge problem, one that has already
> been pointed out is causing issues with other subsystems.
What problem are you talking about here? AFAIK frameworks using correctly
designed lookup do work fine for most, if not all, people. See the
regulator framework.
> So maybe they need to be fixed?
I don't really think anything is broken here, so there is nothing to fix.
Best regards,
Tomasz
On Tue, Jul 23, 2013 at 10:07:52PM +0200, Tomasz Figa wrote:
> On Tuesday 23 of July 2013 12:44:23 Greg KH wrote:
> > On Tue, Jul 23, 2013 at 08:31:05PM +0100, Mark Brown wrote:
> > > > You don't "know" the id of the device you are looking up, due to
> > > > multiple devices being in the system (dynamic ids, look back earlier
> > > > in
> > > > this thread for details about that.)
> > >
> > > I got copied in very late so don't have most of the thread I'm afraid,
> > > I did try looking at web archives but didn't see a clear problem
> > > statement. In any case this is why the APIs doing lookups do the
> > > lookups in the context of the requesting device - devices ask for
> > > whatever name they use locally.
> >
> > What do you mean by "locally"?
> >
> > The problem with the api was that the phy core wanted a id and a name to
> > create a phy, and then later other code was doing a "lookup" based on
> > the name and id (mushed together), because it "knew" that this device
> > was the one it wanted.
> >
> > Just like the clock api, which, for multiple devices, has proven to
> > cause problems. I don't want to see us accept an api that we know has
> > issues in it now, I'd rather us fix it up properly.
> >
> > Subsystems should be able to create ids how ever they want to, and not
> > rely on the code calling them to specify the names of the devices that
> > way, otherwise the api is just too fragile.
> >
> > I think, that if you create a device, then just carry around the pointer
> > to that device (in this case a phy) and pass it to whatever other code
> > needs it. No need to do lookups on "known names" or anything else,
> > just normal pointers, with no problems for multiple devices, busses, or
> > naming issues.
>
> PHY object is not a device, it is something that a device driver creates
> (one or more instances of) when it is being probed.
But you created a 'struct device' for it, so I think of it as a "device"
be it "virtual" or "real" :)
> You don't have a clean way to export this PHY object to other driver,
> other than keeping this PHY on a list inside PHY core with some
> well-known ID (e.g. device name + consumer port name/index, like in
> regulator core) and then to use this well-known ID inside consumer
> driver as a lookup key passed to phy_get();
>
> Actually I think for PHY case, exactly the same way as used for
> regulators might be completely fine:
>
> 1. Each PHY would have some kind of platform, non-unique name, that is
> just used to print some messages (like the platform/board name of a
> regulator).
> 2. Each PHY would have an array of consumers. Consumer specifier would
> consist of consumer device name and consumer port name - just like in
> regulator subsystem.
> 3. PHY driver receives an array of, let's say, phy_init_data inside its
> platform data that it would use to register its PHYs.
> 4. Consumer drivers would have constant consumer port names and wouldn't
> receive any information about PHYs from platform code.
>
> Code example:
>
> [Board file]
>
> static const struct phy_consumer_data usb_20_phy0_consumers[] = {
> {
> .devname = "foo-ehci",
> .port = "usbphy",
> },
> };
>
> static const struct phy_consumer_data usb_20_phy1_consumers[] = {
> {
> .devname = "foo-otg",
> .port = "otgphy",
> },
> };
>
> static const struct phy_init_data my_phys[] = {
> {
> .name = "USB 2.0 PHY 0",
> .consumers = usb_20_phy0_consumers,
> .num_consumers = ARRAY_SIZE(usb_20_phy0_consumers),
> },
> {
> .name = "USB 2.0 PHY 1",
> .consumers = usb_20_phy1_consumers,
> .num_consumers = ARRAY_SIZE(usb_20_phy1_consumers),
> },
> { }
> };
>
> static const struct platform_device usb_phy_pdev = {
> .name = "foo-usbphy",
> .id = -1,
> .dev = {
> .platform_data = my_phys,
> },
> };
>
> [PHY driver]
>
> static int foo_usbphy_probe(pdev)
> {
> struct foo_usbphy *foo;
> struct phy_init_data *init_data = pdev->dev.platform_data;
> /* ... */
> // for each PHY in init_data {
> phy_register(&foo->phy[i], &init_data[i]);
> // }
> /* ... */
> }
>
> [EHCI driver]
>
> static int foo_ehci_probe(pdev)
> {
> struct phy *phy;
> /* ... */
> phy = phy_get(&pdev->dev, "usbphy");
> /* ... */
> }
>
> [OTG driver]
>
> static int foo_otg_probe(pdev)
> {
> struct phy *phy;
> /* ... */
> phy = phy_get(&pdev->dev, "otgphy");
> /* ... */
> }
That's not so bad, as long as you let the phy core use whatever name it
wants for the device when it registers it with sysfs. Use the name you
are requesting as a "tag" or some such "hint" as to what the phy can be
looked up by.
Good luck handling duplicate "tags" :)
thanks,
greg k-h
On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > That's what I was going to suggest too. The struct phy is defined in
> > the board file, which already knows about all the PHYs that exist in
> > the system. (Or perhaps it is allocated dynamically, so that when many
> > board files are present in the same kernel, only the entries listed in
> > the board file for the current system get created.)
>
> Well, such dynamic allocation is a must. We don't accept non-multiplatform
> aware code anymore, not even saying about multiboard.
>
> > Then the
> > structure's address is stored in the platform data and made available
> > to both the provider and the consumer.
>
> Yes, technically this can work. You would still have to perform some kind
> of synchronization to make sure that the PHY bound to this structure is
> actually present. This is again technically doable (e.g. a list of
> registered struct phys inside PHY core).
The synchronization takes place inside phy_get. If phy_create hasn't
been called for this structure by the time phy_get runs, phy_get will
return an error.
> > Even though the struct phy is defined (or allocated) in the board file,
> > its contents don't get filled in until the PHY driver provides the
> > details.
>
> You can't assure this. Board file is free to do whatever it wants with
> this struct. A clean solution would prevent this.
I'm not sure what you mean here. Of course I can't prevent a board
file from messing up a data structure. I can't prevent it from causing
memory access violations either; in fact, I can't prevent any bugs in
other people's code.
Besides, why do you say the board file is free to do whatever it wants
with the struct phy? Currently the struct phy is created by the PHY
provider and the PHY core, right? It's not even mentioned in the board
file.
> > > It's technically correct, but quality of this solution isn't really
> > > nice, because it's a layering violation (at least if I understood
> > > what you mean). This is because you need to have full definition of
> > > struct phy in board file and a structure that is used as private data
> > > in PHY core comes from platform code.
> >
> > You don't have to have a full definition in the board file. Just a
> > partial definition -- most of the contents can be filled in later, when
> > the PHY driver is ready to store the private data.
> >
> > It's not a layering violation for one region of the kernel to store
> > private data in a structure defined by another part of the kernel.
> > This happens all the time (e.g., dev_set_drvdata).
>
> Not really. The phy struct is something that _is_ private data of PHY
> subsystem, not something that can store private data of PHY subsystem
> (sure it can store private data of particular PHY driver, but that's
> another story) and only PHY subsystem should have access to its contents.
If you want to keep the phy struct completely separate from the board
file, there's an easy way to do it. Let's say the board file knows
about N different PHYs in the system. Then you define an array of N
pointers to phys:
struct phy *(phy_address[N]);
In the platform data for both PHY j and its controller, store
&phy_address[j]. The PHY provider passes this cookie to phy_create:
cookie = pdev->dev.platform_data;
ret = phy_create(phy, cookie);
and phy_create simply stores: *cookie = phy. The PHY consumer does
much the same the same thing:
cookie = pdev->dev.platform_data;
phy = phy_get(cookie);
phy_get returns *cookie if it isn't NULL, or an ERR_PTR otherwise.
> By the way, we need to consider other cases here as well, for example it
> would be nice to have a single phy_get() function that works for both non-
> DT and DT cases to make the consumer driver not have to worry whether it's
> being probed from DT or not.
You ought to be able to adapt this scheme to work with DT. Maybe by
having multiple "phy_address" arrays.
Alan Stern
On Tuesday 23 of July 2013 16:53:55 Alan Stern wrote:
> On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > > That's what I was going to suggest too. The struct phy is defined
> > > in
> > > the board file, which already knows about all the PHYs that exist in
> > > the system. (Or perhaps it is allocated dynamically, so that when
> > > many
> > > board files are present in the same kernel, only the entries listed
> > > in
> > > the board file for the current system get created.)
> >
> > Well, such dynamic allocation is a must. We don't accept
> > non-multiplatform aware code anymore, not even saying about
> > multiboard.
> >
> > > Then the
> > > structure's address is stored in the platform data and made
> > > available
> > > to both the provider and the consumer.
> >
> > Yes, technically this can work. You would still have to perform some
> > kind of synchronization to make sure that the PHY bound to this
> > structure is actually present. This is again technically doable (e.g.
> > a list of registered struct phys inside PHY core).
>
> The synchronization takes place inside phy_get. If phy_create hasn't
> been called for this structure by the time phy_get runs, phy_get will
> return an error.
Yes, this is the solution that I had in mind when saying that this is
doable.
> > > Even though the struct phy is defined (or allocated) in the board
> > > file,
> > > its contents don't get filled in until the PHY driver provides the
> > > details.
> >
> > You can't assure this. Board file is free to do whatever it wants with
> > this struct. A clean solution would prevent this.
>
> I'm not sure what you mean here. Of course I can't prevent a board
> file from messing up a data structure. I can't prevent it from causing
> memory access violations either; in fact, I can't prevent any bugs in
> other people's code.
>
> Besides, why do you say the board file is free to do whatever it wants
> with the struct phy? Currently the struct phy is created by the PHY
> provider and the PHY core, right? It's not even mentioned in the board
> file.
I mean, if you have a struct type of which full declaration is available
for some code, this code can access any memeber of it without any hacks,
which is not something that we want to have in board files. The phy struct
should be opaque for them.
> > > > It's technically correct, but quality of this solution isn't
> > > > really
> > > > nice, because it's a layering violation (at least if I understood
> > > > what you mean). This is because you need to have full definition
> > > > of
> > > > struct phy in board file and a structure that is used as private
> > > > data
> > > > in PHY core comes from platform code.
> > >
> > > You don't have to have a full definition in the board file. Just a
> > > partial definition -- most of the contents can be filled in later,
> > > when
> > > the PHY driver is ready to store the private data.
> > >
> > > It's not a layering violation for one region of the kernel to store
> > > private data in a structure defined by another part of the kernel.
> > > This happens all the time (e.g., dev_set_drvdata).
> >
> > Not really. The phy struct is something that _is_ private data of PHY
> > subsystem, not something that can store private data of PHY subsystem
> > (sure it can store private data of particular PHY driver, but that's
> > another story) and only PHY subsystem should have access to its
> > contents.
> If you want to keep the phy struct completely separate from the board
> file, there's an easy way to do it. Let's say the board file knows
> about N different PHYs in the system. Then you define an array of N
> pointers to phys:
>
> struct phy *(phy_address[N]);
>
> In the platform data for both PHY j and its controller, store
> &phy_address[j]. The PHY provider passes this cookie to phy_create:
>
> cookie = pdev->dev.platform_data;
> ret = phy_create(phy, cookie);
>
> and phy_create simply stores: *cookie = phy. The PHY consumer does
> much the same the same thing:
>
> cookie = pdev->dev.platform_data;
> phy = phy_get(cookie);
>
> phy_get returns *cookie if it isn't NULL, or an ERR_PTR otherwise.
OK, this can work. Again, just technically, because it's rather ugly.
> > By the way, we need to consider other cases here as well, for example
> > it would be nice to have a single phy_get() function that works for
> > both non- DT and DT cases to make the consumer driver not have to
> > worry whether it's being probed from DT or not.
>
> You ought to be able to adapt this scheme to work with DT. Maybe by
> having multiple "phy_address" arrays.
Where would you want to have those phy_address arrays stored? There are no
board files when booting with DT. Not even saying that you don't need to
use any hacky schemes like this when you have DT that nicely specifies
relations between devices.
Anyway, board file should not be considered as a method to exchange data
between drivers. It should be used only to pass data from it to drivers,
not the other way. Ideally all data in a board file should be marked as
const and __init and dropped after system initialization.
Best regards,
Tomasz
On Tuesday 23 of July 2013 13:50:07 Greg KH wrote:
> On Tue, Jul 23, 2013 at 10:07:52PM +0200, Tomasz Figa wrote:
> > On Tuesday 23 of July 2013 12:44:23 Greg KH wrote:
> > > On Tue, Jul 23, 2013 at 08:31:05PM +0100, Mark Brown wrote:
> > > > > You don't "know" the id of the device you are looking up, due to
> > > > > multiple devices being in the system (dynamic ids, look back
> > > > > earlier
> > > > > in
> > > > > this thread for details about that.)
> > > >
> > > > I got copied in very late so don't have most of the thread I'm
> > > > afraid,
> > > > I did try looking at web archives but didn't see a clear problem
> > > > statement. In any case this is why the APIs doing lookups do the
> > > > lookups in the context of the requesting device - devices ask for
> > > > whatever name they use locally.
> > >
> > > What do you mean by "locally"?
> > >
> > > The problem with the api was that the phy core wanted a id and a
> > > name to create a phy, and then later other code was doing a
> > > "lookup" based on the name and id (mushed together), because it
> > > "knew" that this device was the one it wanted.
> > >
> > > Just like the clock api, which, for multiple devices, has proven to
> > > cause problems. I don't want to see us accept an api that we know
> > > has
> > > issues in it now, I'd rather us fix it up properly.
> > >
> > > Subsystems should be able to create ids how ever they want to, and
> > > not
> > > rely on the code calling them to specify the names of the devices
> > > that
> > > way, otherwise the api is just too fragile.
> > >
> > > I think, that if you create a device, then just carry around the
> > > pointer to that device (in this case a phy) and pass it to whatever
> > > other code needs it. No need to do lookups on "known names" or
> > > anything else, just normal pointers, with no problems for multiple
> > > devices, busses, or naming issues.
> >
> > PHY object is not a device, it is something that a device driver
> > creates (one or more instances of) when it is being probed.
>
> But you created a 'struct device' for it, so I think of it as a "device"
> be it "virtual" or "real" :)
Keep in mind that those virtual devices are created by PHY driver bound to
a real device and one real device can have multiple virtual devices behind
it.
> > You don't have a clean way to export this PHY object to other driver,
> > other than keeping this PHY on a list inside PHY core with some
> > well-known ID (e.g. device name + consumer port name/index, like in
> > regulator core) and then to use this well-known ID inside consumer
> > driver as a lookup key passed to phy_get();
> >
> > Actually I think for PHY case, exactly the same way as used for
> > regulators might be completely fine:
> >
> > 1. Each PHY would have some kind of platform, non-unique name, that is
> > just used to print some messages (like the platform/board name of a
> > regulator).
> > 2. Each PHY would have an array of consumers. Consumer specifier would
> > consist of consumer device name and consumer port name - just like in
> > regulator subsystem.
> > 3. PHY driver receives an array of, let's say, phy_init_data inside
> > its
> > platform data that it would use to register its PHYs.
> > 4. Consumer drivers would have constant consumer port names and
> > wouldn't receive any information about PHYs from platform code.
> >
> > Code example:
> >
> > [Board file]
> >
> > static const struct phy_consumer_data usb_20_phy0_consumers[] = {
> >
> > {
> >
> > .devname = "foo-ehci",
> > .port = "usbphy",
> >
> > },
> >
> > };
> >
> > static const struct phy_consumer_data usb_20_phy1_consumers[] = {
> >
> > {
> >
> > .devname = "foo-otg",
> > .port = "otgphy",
> >
> > },
> >
> > };
> >
> > static const struct phy_init_data my_phys[] = {
> >
> > {
> >
> > .name = "USB 2.0 PHY 0",
> > .consumers = usb_20_phy0_consumers,
> > .num_consumers = ARRAY_SIZE(usb_20_phy0_consumers),
> >
> > },
> > {
> >
> > .name = "USB 2.0 PHY 1",
> > .consumers = usb_20_phy1_consumers,
> > .num_consumers = ARRAY_SIZE(usb_20_phy1_consumers),
> >
> > },
> > { }
> >
> > };
> >
> > static const struct platform_device usb_phy_pdev = {
> >
> > .name = "foo-usbphy",
> > .id = -1,
> > .dev = {
> >
> > .platform_data = my_phys,
> >
> > },
> >
> > };
> >
> > [PHY driver]
> >
> > static int foo_usbphy_probe(pdev)
> > {
> >
> > struct foo_usbphy *foo;
> > struct phy_init_data *init_data = pdev->dev.platform_data;
> > /* ... */
> > // for each PHY in init_data {
> >
> > phy_register(&foo->phy[i], &init_data[i]);
> >
> > // }
> > /* ... */
> >
> > }
> >
> > [EHCI driver]
> >
> > static int foo_ehci_probe(pdev)
> > {
> >
> > struct phy *phy;
> > /* ... */
> > phy = phy_get(&pdev->dev, "usbphy");
> > /* ... */
> >
> > }
> >
> > [OTG driver]
> >
> > static int foo_otg_probe(pdev)
> > {
> >
> > struct phy *phy;
> > /* ... */
> > phy = phy_get(&pdev->dev, "otgphy");
> > /* ... */
> >
> > }
>
> That's not so bad, as long as you let the phy core use whatever name it
> wants for the device when it registers it with sysfs.
Yes, in regulator core consumer names are completely separated from this.
Regulator core simply assigns a sequential integer ID to each regulator
and registers /sys/class/regulator/regulator.ID for each regulator.
> Use the name you
> are requesting as a "tag" or some such "hint" as to what the phy can be
> looked up by.
>
> Good luck handling duplicate "tags" :)
The tag alone is not a key. Lookup key consists of two components,
consumer device name and consumer tag. What kind of duplicate tags can be
a problem here?
Best regards,
Tomasz
On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > If you want to keep the phy struct completely separate from the board
> > file, there's an easy way to do it. Let's say the board file knows
> > about N different PHYs in the system. Then you define an array of N
> > pointers to phys:
> >
> > struct phy *(phy_address[N]);
> >
> > In the platform data for both PHY j and its controller, store
> > &phy_address[j]. The PHY provider passes this cookie to phy_create:
> >
> > cookie = pdev->dev.platform_data;
> > ret = phy_create(phy, cookie);
> >
> > and phy_create simply stores: *cookie = phy. The PHY consumer does
> > much the same the same thing:
> >
> > cookie = pdev->dev.platform_data;
> > phy = phy_get(cookie);
> >
> > phy_get returns *cookie if it isn't NULL, or an ERR_PTR otherwise.
>
> OK, this can work. Again, just technically, because it's rather ugly.
There's no reason the phy_address things have to be arrays. A separate
individual pointer for each PHY would work just as well.
> Where would you want to have those phy_address arrays stored? There are no
> board files when booting with DT. Not even saying that you don't need to
> use any hacky schemes like this when you have DT that nicely specifies
> relations between devices.
If everybody agrees DT has a nice scheme for specifying relations
between devices, why not use that same scheme in the PHY core?
> Anyway, board file should not be considered as a method to exchange data
> between drivers. It should be used only to pass data from it to drivers,
> not the other way. Ideally all data in a board file should be marked as
> const and __init and dropped after system initialization.
The phy_address things don't have to be defined or allocated in the
board file; they could be set up along with the platform data.
In any case, this was simply meant to be a suggestion to show that it
is relatively easy to do what you need without using name or ID
strings.
Alan Stern
On Tue, Jul 23, 2013 at 11:05:48PM +0200, Tomasz Figa wrote:
> > That's not so bad, as long as you let the phy core use whatever name it
> > wants for the device when it registers it with sysfs.
>
> Yes, in regulator core consumer names are completely separated from this.
> Regulator core simply assigns a sequential integer ID to each regulator
> and registers /sys/class/regulator/regulator.ID for each regulator.
Yes, that's fine.
> > Use the name you
> > are requesting as a "tag" or some such "hint" as to what the phy can be
> > looked up by.
> >
> > Good luck handling duplicate "tags" :)
>
> The tag alone is not a key. Lookup key consists of two components,
> consumer device name and consumer tag. What kind of duplicate tags can be
> a problem here?
Ok, I didn't realize it looked at both parts, that makes sense, thanks.
greg k-h
On Tuesday 23 of July 2013 17:14:20 Alan Stern wrote:
> On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > > If you want to keep the phy struct completely separate from the
> > > board
> > > file, there's an easy way to do it. Let's say the board file knows
> > > about N different PHYs in the system. Then you define an array of N
> > > pointers to phys:
> > >
> > > struct phy *(phy_address[N]);
> > >
> > > In the platform data for both PHY j and its controller, store
> > >
> > > &phy_address[j]. The PHY provider passes this cookie to phy_create:
> > > cookie = pdev->dev.platform_data;
> > > ret = phy_create(phy, cookie);
> > >
> > > and phy_create simply stores: *cookie = phy. The PHY consumer does
> > >
> > > much the same the same thing:
> > > cookie = pdev->dev.platform_data;
> > > phy = phy_get(cookie);
> > >
> > > phy_get returns *cookie if it isn't NULL, or an ERR_PTR otherwise.
> >
> > OK, this can work. Again, just technically, because it's rather ugly.
>
> There's no reason the phy_address things have to be arrays. A separate
> individual pointer for each PHY would work just as well.
>
> > Where would you want to have those phy_address arrays stored? There
> > are no board files when booting with DT. Not even saying that you
> > don't need to use any hacky schemes like this when you have DT that
> > nicely specifies relations between devices.
>
> If everybody agrees DT has a nice scheme for specifying relations
> between devices, why not use that same scheme in the PHY core?
It is already used, for cases when consumer device has a DT node attached.
In non-DT case this kind lookup translates loosely to something that is
being done in regulator framework - you can't bind devices by pointers,
because you don't have those pointers, so you need to use device names.
> > Anyway, board file should not be considered as a method to exchange
> > data between drivers. It should be used only to pass data from it to
> > drivers, not the other way. Ideally all data in a board file should
> > be marked as const and __init and dropped after system
> > initialization.
>
> The phy_address things don't have to be defined or allocated in the
> board file; they could be set up along with the platform data.
There is no platform data when booting with DT.
> In any case, this was simply meant to be a suggestion to show that it
> is relatively easy to do what you need without using name or ID
> strings.
Sure. It's good to have different options discussed as well.
Best regards,
Tomasz
On Tue, Jul 23, 2013 at 12:44:23PM -0700, Greg KH wrote:
> On Tue, Jul 23, 2013 at 08:31:05PM +0100, Mark Brown wrote:
> > statement. In any case this is why the APIs doing lookups do the
> > lookups in the context of the requesting device - devices ask for
> > whatever name they use locally.
> What do you mean by "locally"?
Within themselves - for example a regulator consumer asks for a given
supply on the device in terms of the supply names the device has.
> The problem with the api was that the phy core wanted a id and a name to
> create a phy, and then later other code was doing a "lookup" based on
> the name and id (mushed together), because it "knew" that this device
> was the one it wanted.
Ah, that sounds like the API is missing a component to link things
together. But I could be wrong. What I would expect to see is that the
consumer says "I want the PHY called X" and the PHY driver says "I
provide this set of PHYs" with a layer in between that plugs those
together. This would normally involve talking about the parent device
rather than the PHY itself.
> I think, that if you create a device, then just carry around the pointer
> to that device (in this case a phy) and pass it to whatever other code
> needs it. No need to do lookups on "known names" or anything else, just
> normal pointers, with no problems for multiple devices, busses, or
> naming issues.
I think you're not really talking about the lookup API at all here but
rather about one way in which the matching code can be written. What
everything *really* wants to do is work in terms of resources namespaced
within struct devices since every bit of hardware in the system should
have one of those it can use and if you have a struct device you can do
useful things like call dev_printk() and find the device tree data to do
device tree based lookups.
Unfortunately for a number of buses even when statically registering the
struct device doesn't get allocated until the device is probed so what
everyone fell back on doing was using dev_name() in cases where the
struct device wasn't there yet, or just always using it for consistency
since for most of the affected buses dev_name() is fixed for human
interface reasons. I think this is the issue you're concerned about
here since if the dev_name() is dynamically allocated this breaks down.
This only affects board files, DT and ACPI can both use their own data
structures to do the mapping.
I had thought you were talking about picking the names that the
consumers use (which isn't actually that big a deal, it's just a bit
annoying for the clock API).
> > It's adding platform data in the first place that gets tedious - and of
> > course there's also DT and ACPI to worry about, it's not just a case of
> > platform data and then you're done. Pushing the lookup into library
> > code means that drivers don't have to worry about any of this stuff.
> I agree, so just pass around the pointer to the phy and all is good. No
> need to worry about DT or ACPI or anything else.
No, in practice passing around the pointer gets tricky if you're using
something other than board files (or even are doing any kind of dynamic
stuff with board files) since the two devices need to find each other
and if you're using platform data then the code doing the matching has
to know about the platform data for every device it might need to match
which is just miserable.
Something would need to do something like allocate the PHY objects and
then arrange for them to be passed to both provider and consumer devices
prior to those being registered, knowing where to place the pointers in
the platform data for each device. This is straightforward with board
files but not otherwise, people have tried this before.
> > For most of the APIs doing this there is a clear and unambiguous name in
> > the hardware that can be used (and for hardware process reasons is
> > unlikely to get changed). The major exception to this is the clock API
> > since it is relatively rare to have clear, segregated IP level
> > information for IPs baked into larger chips. The other APIs tend to be
> > establishing chip to chip links.
> The clock api is having problems with multiple "names" due to dynamic
> devices from what I was told. I want to prevent the PHY interface from
> having that same issue.
I think the underlying issue here is that we don't have a good enough
general way for board files (or other C code but mostly them) to talk
about devices prior to their being registered - rather than have the
pointer you're talking about be the PHY object itself have the pointer
be something which allows us to match the struct device when it's
created. This should be transparent to drivers and would be usable by
all the existing APIs.
On Tuesday 23 July 2013, Tomasz Figa wrote:
> On Tuesday 23 of July 2013 17:14:20 Alan Stern wrote:
> > On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > > Where would you want to have those phy_address arrays stored? There
> > > are no board files when booting with DT. Not even saying that you
> > > don't need to use any hacky schemes like this when you have DT that
> > > nicely specifies relations between devices.
> >
> > If everybody agrees DT has a nice scheme for specifying relations
> > between devices, why not use that same scheme in the PHY core?
>
> It is already used, for cases when consumer device has a DT node attached.
> In non-DT case this kind lookup translates loosely to something that is
> being done in regulator framework - you can't bind devices by pointers,
> because you don't have those pointers, so you need to use device names.
>
Sorry for jumping in to the middle of the discussion, but why does a *new*
framework even bother defining an interface for board files?
Can't we just drop any interfaces for platform data passing in the phy
framework and put the burden of adding those to anyone who actually needs
them? All the platforms we are concerned with here (exynos and omap,
plus new platforms) can be booted using DT anyway.
Arnd
On Thursday 25 July 2013, Kishon Vijay Abraham I wrote:
> On Thursday 25 July 2013 12:02 AM, Arnd Bergmann wrote:
> > On Tuesday 23 July 2013, Tomasz Figa wrote:
> >> On Tuesday 23 of July 2013 17:14:20 Alan Stern wrote:
> >>> On Tue, 23 Jul 2013, Tomasz Figa wrote:
> >>>> Where would you want to have those phy_address arrays stored? There
> >>>> are no board files when booting with DT. Not even saying that you
> >>>> don't need to use any hacky schemes like this when you have DT that
> >>>> nicely specifies relations between devices.
> >>>
> >>> If everybody agrees DT has a nice scheme for specifying relations
> >>> between devices, why not use that same scheme in the PHY core?
> >>
> >> It is already used, for cases when consumer device has a DT node attached.
> >> In non-DT case this kind lookup translates loosely to something that is
> >> being done in regulator framework - you can't bind devices by pointers,
> >> because you don't have those pointers, so you need to use device names.
> >>
> >
> > Sorry for jumping in to the middle of the discussion, but why does a new
> > framework even bother defining an interface for board files?
> >
> > Can't we just drop any interfaces for platform data passing in the phy
> > framework and put the burden of adding those to anyone who actually needs
> > them? All the platforms we are concerned with here (exynos and omap,
> > plus new platforms) can be booted using DT anyway.
>
> The OMAP3 platforms still needs to be supported for non-dt :-s
Can't you leave the existing PHY handling for legacy OMAP3 USB PHY
until they are all converted? I don't expect that to take a long time
now that the OMAP4 board files have been removed. Are there still
drivers without DT bindings that hold up the removal of the OMAP3
board files?
Otherwise I'd suggest delaying the phy subsystem by another merge window,
until that is resolved.
Arnd
On Wed, Jul 24, 2013 at 08:32:03PM +0200, Arnd Bergmann wrote:
> Sorry for jumping in to the middle of the discussion, but why does a *new*
> framework even bother defining an interface for board files?
> Can't we just drop any interfaces for platform data passing in the phy
> framework and put the burden of adding those to anyone who actually needs
> them? All the platforms we are concerned with here (exynos and omap,
> plus new platforms) can be booted using DT anyway.
There's a bunch of non-DT architectures that are in active use (blackfin
for example) and I'd really hope that this is useful for some of them.
The pushback here was about the fact that the subsystem was doing odd
things with selecting device names which is odd in itself, I don't know
if that had bled over into the DT bindings but it sounded like it
might've done so.
On 07/24/2013 08:32 PM, Arnd Bergmann wrote:
> On Tuesday 23 July 2013, Tomasz Figa wrote:
>> On Tuesday 23 of July 2013 17:14:20 Alan Stern wrote:
>>> On Tue, 23 Jul 2013, Tomasz Figa wrote:
>>>> Where would you want to have those phy_address arrays stored? There
>>>> are no board files when booting with DT. Not even saying that you
>>>> don't need to use any hacky schemes like this when you have DT that
>>>> nicely specifies relations between devices.
>>>
>>> If everybody agrees DT has a nice scheme for specifying relations
>>> between devices, why not use that same scheme in the PHY core?
>>
>> It is already used, for cases when consumer device has a DT node attached.
>> In non-DT case this kind lookup translates loosely to something that is
>> being done in regulator framework - you can't bind devices by pointers,
>> because you don't have those pointers, so you need to use device names.
>>
>
> Sorry for jumping in to the middle of the discussion, but why does a *new*
> framework even bother defining an interface for board files?
>
> Can't we just drop any interfaces for platform data passing in the phy
> framework and put the burden of adding those to anyone who actually needs
> them? All the platforms we are concerned with here (exynos and omap,
> plus new platforms) can be booted using DT anyway.
Indeed, I was also a bit surprised we still need non-dt support, since
migration to this generic PHY framework in case of exynos was solely
part of migration of the whole platform to DT.
Two of the drivers that are being converted are also used on s5pv210,
but there is currently no boards in mainline that would use devices
covered by those drivers and s5pv210 will very likely get DT support
in v3.13 anyway.
But it seems omap still needs non-dt support in the PHY framework.
---
Thanks,
Sylwester
Hi Arnd,
On Wednesday 24 July 2013 20:32:03 Arnd Bergmann wrote:
> On Tuesday 23 July 2013, Tomasz Figa wrote:
> > On Tuesday 23 of July 2013 17:14:20 Alan Stern wrote:
> > > On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > > > Where would you want to have those phy_address arrays stored? There
> > > > are no board files when booting with DT. Not even saying that you
> > > > don't need to use any hacky schemes like this when you have DT that
> > > > nicely specifies relations between devices.
> > >
> > > If everybody agrees DT has a nice scheme for specifying relations
> > > between devices, why not use that same scheme in the PHY core?
> >
> > It is already used, for cases when consumer device has a DT node attached.
> > In non-DT case this kind lookup translates loosely to something that is
> > being done in regulator framework - you can't bind devices by pointers,
> > because you don't have those pointers, so you need to use device names.
>
> Sorry for jumping in to the middle of the discussion, but why does a *new*
> framework even bother defining an interface for board files?
>
> Can't we just drop any interfaces for platform data passing in the phy
> framework and put the burden of adding those to anyone who actually needs
> them? All the platforms we are concerned with here (exynos and omap, plus
> new platforms) can be booted using DT anyway.
What about non-DT architectures such as MIPS (still widely used in consumer
networking equipments from what I've heard) ?
--
Regards,
Laurent Pinchart
On Thursday 25 July 2013, Laurent Pinchart wrote:
> On Wednesday 24 July 2013 20:32:03 Arnd Bergmann wrote:
> > On Tuesday 23 July 2013, Tomasz Figa wrote:
> > > On Tuesday 23 of July 2013 17:14:20 Alan Stern wrote:
> > > > On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > > > > Where would you want to have those phy_address arrays stored? There
> > > > > are no board files when booting with DT. Not even saying that you
> > > > > don't need to use any hacky schemes like this when you have DT that
> > > > > nicely specifies relations between devices.
> > > >
> > > > If everybody agrees DT has a nice scheme for specifying relations
> > > > between devices, why not use that same scheme in the PHY core?
> > >
> > > It is already used, for cases when consumer device has a DT node attached.
> > > In non-DT case this kind lookup translates loosely to something that is
> > > being done in regulator framework - you can't bind devices by pointers,
> > > because you don't have those pointers, so you need to use device names.
> >
> > Sorry for jumping in to the middle of the discussion, but why does a new
> > framework even bother defining an interface for board files?
> >
> > Can't we just drop any interfaces for platform data passing in the phy
> > framework and put the burden of adding those to anyone who actually needs
> > them? All the platforms we are concerned with here (exynos and omap, plus
> > new platforms) can be booted using DT anyway.
>
> What about non-DT architectures such as MIPS (still widely used in consumer
> networking equipments from what I've heard) ?
* Vendors of such equipment have started moving on to ARM (e.g. Broadcom bcm47xx)
* Some of the modern MIPS platforms are now using DT
* Legacy platforms probably won't migrate to either DT or the generic PHY framework
I'm not saying that we can't support legacy board files with the common
PHY framework, but I'd expect things to be much easier if we focus on those
platforms that are actively being worked on for now, to bring an end to the
pointless API discussion.
Arnd
Hi Arnd,
On Thursday 25 July 2013 13:00:49 Arnd Bergmann wrote:
> On Thursday 25 July 2013, Laurent Pinchart wrote:
> > On Wednesday 24 July 2013 20:32:03 Arnd Bergmann wrote:
> > > On Tuesday 23 July 2013, Tomasz Figa wrote:
> > > > On Tuesday 23 of July 2013 17:14:20 Alan Stern wrote:
> > > > > On Tue, 23 Jul 2013, Tomasz Figa wrote:
> > > > > > Where would you want to have those phy_address arrays stored?
> > > > > > There are no board files when booting with DT. Not even saying
> > > > > > that you don't need to use any hacky schemes like this when you
> > > > > > have DT that nicely specifies relations between devices.
> > > > >
> > > > > If everybody agrees DT has a nice scheme for specifying relations
> > > > > between devices, why not use that same scheme in the PHY core?
> > > >
> > > > It is already used, for cases when consumer device has a DT node
> > > > attached. In non-DT case this kind lookup translates loosely to
> > > > something that is being done in regulator framework - you can't bind
> > > > devices by pointers, because you don't have those pointers, so you
> > > > need to use device names.
> > >
> > > Sorry for jumping in to the middle of the discussion, but why does a new
> > > framework even bother defining an interface for board files?
> > >
> > > Can't we just drop any interfaces for platform data passing in the phy
> > > framework and put the burden of adding those to anyone who actually
> > > needs them? All the platforms we are concerned with here (exynos and
> > > omap, plus new platforms) can be booted using DT anyway.
> >
> > What about non-DT architectures such as MIPS (still widely used in
> > consumer networking equipments from what I've heard) ?
>
> * Vendors of such equipment have started moving on to ARM (e.g. Broadcom
> bcm47xx)
> * Some of the modern MIPS platforms are now using DT
> * Legacy platforms probably won't migrate to either DT or the generic PHY
> framework
>
> I'm not saying that we can't support legacy board files with the common PHY
> framework, but I'd expect things to be much easier if we focus on those
> platforms that are actively being worked on for now, to bring an end to the
> pointless API discussion.
Fair enough :-)
--
Regards,
Laurent Pinchart
On Thu, Jul 25, 2013 at 01:00:49PM +0200, Arnd Bergmann wrote:
> I'm not saying that we can't support legacy board files with the common
> PHY framework, but I'd expect things to be much easier if we focus on those
> platforms that are actively being worked on for now, to bring an end to the
> pointless API discussion.
Well, it seemed like Greg's concerns had already been addressed anyway.
On Sun, Jul 21, 2013 at 08:46:53AM -0700, Greg KH wrote:
> On Sun, Jul 21, 2013 at 01:12:07PM +0200, Tomasz Figa wrote:
> > On Sunday 21 of July 2013 16:37:33 Kishon Vijay Abraham I wrote:
> > > Hi,
> > >
> > > On Sunday 21 July 2013 04:01 PM, Tomasz Figa wrote:
> > > > Hi,
> > > >
> > > > On Saturday 20 of July 2013 19:59:10 Greg KH wrote:
> > > >> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
> > > >>> On Sat, 20 Jul 2013, Greg KH wrote:
> > > >>>>>>> That should be passed using platform data.
> > > >>>>>>
> > > >>>>>> Ick, don't pass strings around, pass pointers. If you have
> > > >>>>>> platform
> > > >>>>>> data you can get to, then put the pointer there, don't use a
> > > >>>>>> "name".
> > > >>>>>
> > > >>>>> I don't think I understood you here :-s We wont have phy pointer
> > > >>>>> when we create the device for the controller no?(it'll be done in
> > > >>>>> board file). Probably I'm missing something.
> > > >>>>
> > > >>>> Why will you not have that pointer? You can't rely on the "name"
> > > >>>> as
> > > >>>> the device id will not match up, so you should be able to rely on
> > > >>>> the pointer being in the structure that the board sets up, right?
> > > >>>>
> > > >>>> Don't use names, especially as ids can, and will, change, that is
> > > >>>> going
> > > >>>> to cause big problems. Use pointers, this is C, we are supposed to
> > > >>>> be
> > > >>>> doing that :)
> > > >>>
> > > >>> Kishon, I think what Greg means is this: The name you are using
> > > >>> must
> > > >>> be stored somewhere in a data structure constructed by the board
> > > >>> file,
> > > >>> right? Or at least, associated with some data structure somehow.
> > > >>> Otherwise the platform code wouldn't know which PHY hardware
> > > >>> corresponded to a particular name.
> > > >>>
> > > >>> Greg's suggestion is that you store the address of that data
> > > >>> structure
> > > >>> in the platform data instead of storing the name string. Have the
> > > >>> consumer pass the data structure's address when it calls phy_create,
> > > >>> instead of passing the name. Then you don't have to worry about two
> > > >>> PHYs accidentally ending up with the same name or any other similar
> > > >>> problems.
> > > >>
> > > >> Close, but the issue is that whatever returns from phy_create()
> > > >> should
> > > >> then be used, no need to call any "find" functions, as you can just
> > > >> use
> > > >> the pointer that phy_create() returns. Much like all other class api
> > > >> functions in the kernel work.
> > > >
> > > > I think there is a confusion here about who registers the PHYs.
> > > >
> > > > All platform code does is registering a platform/i2c/whatever device,
> > > > which causes a driver (located in drivers/phy/) to be instantiated.
> > > > Such drivers call phy_create(), usually in their probe() callbacks,
> > > > so platform_code has no way (and should have no way, for the sake of
> > > > layering) to get what phy_create() returns.
>
> Why not put pointers in the platform data structure that can hold these
> pointers? I thought that is why we created those structures in the
> first place. If not, what are they there for?
heh, IMO we shouldn't pass pointers of any kind through platform_data,
we want to pass data :-)
Allowing to pass pointers through that, is one of the reasons which got
us in such a big mess in ARM land, well it was much easier for a
board-file/driver writer to pass a function pointer then to create a
generic framework :-)
> > > > IMHO we need a lookup method for PHYs, just like for clocks,
> > > > regulators, PWMs or even i2c busses because there are complex cases
> > > > when passing just a name using platform data will not work. I would
> > > > second what Stephen said [1] and define a structure doing things in a
> > > > DT-like way.
> > > >
> > > > Example;
> > > >
> > > > [platform code]
> > > >
> > > > static const struct phy_lookup my_phy_lookup[] = {
> > > >
> > > > PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
> > >
> > > The only problem here is that if *PLATFORM_DEVID_AUTO* is used while
> > > creating the device, the ids in the device name would change and
> > > PHY_LOOKUP wont be useful.
> >
> > I don't think this is a problem. All the existing lookup methods already
> > use ID to identify devices (see regulators, clkdev, PWMs, i2c, ...). You
> > can simply add a requirement that the ID must be assigned manually,
> > without using PLATFORM_DEVID_AUTO to use PHY lookup.
>
> And I'm saying that this idea, of using a specific name and id, is
> frought with fragility and will break in the future in various ways when
> devices get added to systems, making these strings constantly have to be
> kept up to date with different board configurations.
>
> People, NEVER, hardcode something like an id. The fact that this
> happens today with the clock code, doesn't make it right, it makes the
> clock code wrong. Others have already said that this is wrong there as
> well, as systems change and dynamic ids get used more and more.
>
> Let's not repeat the same mistakes of the past just because we refuse to
> learn from them...
>
> So again, the "find a phy by a string" functions should be removed, the
> device id should be automatically created by the phy core just to make
> things unique in sysfs, and no driver code should _ever_ be reliant on
> the number that is being created, and the pointer to the phy structure
> should be used everywhere instead.
>
> With those types of changes, I will consider merging this subsystem, but
> without them, sorry, I will not.
I'll agree with Greg here, the very fact that we see people trying to
add a requirement of *NOT* using PLATFORM_DEVID_AUTO already points to a
big problem in the framework.
The fact is that if we don't allow PLATFORM_DEVID_AUTO we will end up
adding similar infrastructure to the driver themselves to make sure we
don't end up with duplicate names in sysfs in case we have multiple
instances of the same IP in the SoC (or several of the same PCIe card).
I really don't want to go back to that.
--
balbi
Hi,
On Tuesday 30 July 2013 12:41 PM, Felipe Balbi wrote:
> On Sun, Jul 21, 2013 at 08:46:53AM -0700, Greg KH wrote:
>> On Sun, Jul 21, 2013 at 01:12:07PM +0200, Tomasz Figa wrote:
>>> On Sunday 21 of July 2013 16:37:33 Kishon Vijay Abraham I wrote:
>>>> Hi,
>>>>
>>>> On Sunday 21 July 2013 04:01 PM, Tomasz Figa wrote:
>>>>> Hi,
>>>>>
>>>>> On Saturday 20 of July 2013 19:59:10 Greg KH wrote:
>>>>>> On Sat, Jul 20, 2013 at 10:32:26PM -0400, Alan Stern wrote:
>>>>>>> On Sat, 20 Jul 2013, Greg KH wrote:
>>>>>>>>>>> That should be passed using platform data.
>>>>>>>>>>
>>>>>>>>>> Ick, don't pass strings around, pass pointers. If you have
>>>>>>>>>> platform
>>>>>>>>>> data you can get to, then put the pointer there, don't use a
>>>>>>>>>> "name".
>>>>>>>>>
>>>>>>>>> I don't think I understood you here :-s We wont have phy pointer
>>>>>>>>> when we create the device for the controller no?(it'll be done in
>>>>>>>>> board file). Probably I'm missing something.
>>>>>>>>
>>>>>>>> Why will you not have that pointer? You can't rely on the "name"
>>>>>>>> as
>>>>>>>> the device id will not match up, so you should be able to rely on
>>>>>>>> the pointer being in the structure that the board sets up, right?
>>>>>>>>
>>>>>>>> Don't use names, especially as ids can, and will, change, that is
>>>>>>>> going
>>>>>>>> to cause big problems. Use pointers, this is C, we are supposed to
>>>>>>>> be
>>>>>>>> doing that :)
>>>>>>>
>>>>>>> Kishon, I think what Greg means is this: The name you are using
>>>>>>> must
>>>>>>> be stored somewhere in a data structure constructed by the board
>>>>>>> file,
>>>>>>> right? Or at least, associated with some data structure somehow.
>>>>>>> Otherwise the platform code wouldn't know which PHY hardware
>>>>>>> corresponded to a particular name.
>>>>>>>
>>>>>>> Greg's suggestion is that you store the address of that data
>>>>>>> structure
>>>>>>> in the platform data instead of storing the name string. Have the
>>>>>>> consumer pass the data structure's address when it calls phy_create,
>>>>>>> instead of passing the name. Then you don't have to worry about two
>>>>>>> PHYs accidentally ending up with the same name or any other similar
>>>>>>> problems.
>>>>>>
>>>>>> Close, but the issue is that whatever returns from phy_create()
>>>>>> should
>>>>>> then be used, no need to call any "find" functions, as you can just
>>>>>> use
>>>>>> the pointer that phy_create() returns. Much like all other class api
>>>>>> functions in the kernel work.
>>>>>
>>>>> I think there is a confusion here about who registers the PHYs.
>>>>>
>>>>> All platform code does is registering a platform/i2c/whatever device,
>>>>> which causes a driver (located in drivers/phy/) to be instantiated.
>>>>> Such drivers call phy_create(), usually in their probe() callbacks,
>>>>> so platform_code has no way (and should have no way, for the sake of
>>>>> layering) to get what phy_create() returns.
>>
>> Why not put pointers in the platform data structure that can hold these
>> pointers? I thought that is why we created those structures in the
>> first place. If not, what are they there for?
>
> heh, IMO we shouldn't pass pointers of any kind through platform_data,
> we want to pass data :-)
>
> Allowing to pass pointers through that, is one of the reasons which got
> us in such a big mess in ARM land, well it was much easier for a
> board-file/driver writer to pass a function pointer then to create a
> generic framework :-)
>
>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
>>>>> regulators, PWMs or even i2c busses because there are complex cases
>>>>> when passing just a name using platform data will not work. I would
>>>>> second what Stephen said [1] and define a structure doing things in a
>>>>> DT-like way.
>>>>>
>>>>> Example;
>>>>>
>>>>> [platform code]
>>>>>
>>>>> static const struct phy_lookup my_phy_lookup[] = {
>>>>>
>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
>>>>
>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used while
>>>> creating the device, the ids in the device name would change and
>>>> PHY_LOOKUP wont be useful.
>>>
>>> I don't think this is a problem. All the existing lookup methods already
>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c, ...). You
>>> can simply add a requirement that the ID must be assigned manually,
>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
>>
>> And I'm saying that this idea, of using a specific name and id, is
>> frought with fragility and will break in the future in various ways when
>> devices get added to systems, making these strings constantly have to be
>> kept up to date with different board configurations.
>>
>> People, NEVER, hardcode something like an id. The fact that this
>> happens today with the clock code, doesn't make it right, it makes the
>> clock code wrong. Others have already said that this is wrong there as
>> well, as systems change and dynamic ids get used more and more.
>>
>> Let's not repeat the same mistakes of the past just because we refuse to
>> learn from them...
>>
>> So again, the "find a phy by a string" functions should be removed, the
>> device id should be automatically created by the phy core just to make
>> things unique in sysfs, and no driver code should _ever_ be reliant on
>> the number that is being created, and the pointer to the phy structure
>> should be used everywhere instead.
>>
>> With those types of changes, I will consider merging this subsystem, but
>> without them, sorry, I will not.
>
> I'll agree with Greg here, the very fact that we see people trying to
> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already points to a
> big problem in the framework.
>
> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will end up
> adding similar infrastructure to the driver themselves to make sure we
> don't end up with duplicate names in sysfs in case we have multiple
> instances of the same IP in the SoC (or several of the same PCIe card).
> I really don't want to go back to that.
If we are using PLATFORM_DEVID_AUTO, then I dont see any way we can give the
correct binding information to the PHY framework. I think we can drop having
this non-dt support in PHY framework? I see only one platform (OMAP3) going to
be needing this non-dt support and we can use the USB PHY library for it.
Thanks
Kishon
Hi,
On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I wrote:
> >>>>> IMHO we need a lookup method for PHYs, just like for clocks,
> >>>>> regulators, PWMs or even i2c busses because there are complex cases
> >>>>> when passing just a name using platform data will not work. I would
> >>>>> second what Stephen said [1] and define a structure doing things in a
> >>>>> DT-like way.
> >>>>>
> >>>>> Example;
> >>>>>
> >>>>> [platform code]
> >>>>>
> >>>>> static const struct phy_lookup my_phy_lookup[] = {
> >>>>>
> >>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
> >>>>
> >>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used while
> >>>> creating the device, the ids in the device name would change and
> >>>> PHY_LOOKUP wont be useful.
> >>>
> >>> I don't think this is a problem. All the existing lookup methods already
> >>> use ID to identify devices (see regulators, clkdev, PWMs, i2c, ...). You
> >>> can simply add a requirement that the ID must be assigned manually,
> >>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
> >>
> >> And I'm saying that this idea, of using a specific name and id, is
> >> frought with fragility and will break in the future in various ways when
> >> devices get added to systems, making these strings constantly have to be
> >> kept up to date with different board configurations.
> >>
> >> People, NEVER, hardcode something like an id. The fact that this
> >> happens today with the clock code, doesn't make it right, it makes the
> >> clock code wrong. Others have already said that this is wrong there as
> >> well, as systems change and dynamic ids get used more and more.
> >>
> >> Let's not repeat the same mistakes of the past just because we refuse to
> >> learn from them...
> >>
> >> So again, the "find a phy by a string" functions should be removed, the
> >> device id should be automatically created by the phy core just to make
> >> things unique in sysfs, and no driver code should _ever_ be reliant on
> >> the number that is being created, and the pointer to the phy structure
> >> should be used everywhere instead.
> >>
> >> With those types of changes, I will consider merging this subsystem, but
> >> without them, sorry, I will not.
> >
> > I'll agree with Greg here, the very fact that we see people trying to
> > add a requirement of *NOT* using PLATFORM_DEVID_AUTO already points to a
> > big problem in the framework.
> >
> > The fact is that if we don't allow PLATFORM_DEVID_AUTO we will end up
> > adding similar infrastructure to the driver themselves to make sure we
> > don't end up with duplicate names in sysfs in case we have multiple
> > instances of the same IP in the SoC (or several of the same PCIe card).
> > I really don't want to go back to that.
>
> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we can give the
> correct binding information to the PHY framework. I think we can drop having
> this non-dt support in PHY framework? I see only one platform (OMAP3) going to
> be needing this non-dt support and we can use the USB PHY library for it.
you shouldn't drop support for non-DT platform, in any case we lived
without DT (and still do) for years. Gotta find a better way ;-)
--
balbi
Hi,
On Wednesday 31 July 2013 11:45 AM, Felipe Balbi wrote:
> Hi,
>
> On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I wrote:
>>>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
>>>>>>> regulators, PWMs or even i2c busses because there are complex cases
>>>>>>> when passing just a name using platform data will not work. I would
>>>>>>> second what Stephen said [1] and define a structure doing things in a
>>>>>>> DT-like way.
>>>>>>>
>>>>>>> Example;
>>>>>>>
>>>>>>> [platform code]
>>>>>>>
>>>>>>> static const struct phy_lookup my_phy_lookup[] = {
>>>>>>>
>>>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
>>>>>>
>>>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used while
>>>>>> creating the device, the ids in the device name would change and
>>>>>> PHY_LOOKUP wont be useful.
>>>>>
>>>>> I don't think this is a problem. All the existing lookup methods already
>>>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c, ...). You
>>>>> can simply add a requirement that the ID must be assigned manually,
>>>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
>>>>
>>>> And I'm saying that this idea, of using a specific name and id, is
>>>> frought with fragility and will break in the future in various ways when
>>>> devices get added to systems, making these strings constantly have to be
>>>> kept up to date with different board configurations.
>>>>
>>>> People, NEVER, hardcode something like an id. The fact that this
>>>> happens today with the clock code, doesn't make it right, it makes the
>>>> clock code wrong. Others have already said that this is wrong there as
>>>> well, as systems change and dynamic ids get used more and more.
>>>>
>>>> Let's not repeat the same mistakes of the past just because we refuse to
>>>> learn from them...
>>>>
>>>> So again, the "find a phy by a string" functions should be removed, the
>>>> device id should be automatically created by the phy core just to make
>>>> things unique in sysfs, and no driver code should _ever_ be reliant on
>>>> the number that is being created, and the pointer to the phy structure
>>>> should be used everywhere instead.
>>>>
>>>> With those types of changes, I will consider merging this subsystem, but
>>>> without them, sorry, I will not.
>>>
>>> I'll agree with Greg here, the very fact that we see people trying to
>>> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already points to a
>>> big problem in the framework.
>>>
>>> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will end up
>>> adding similar infrastructure to the driver themselves to make sure we
>>> don't end up with duplicate names in sysfs in case we have multiple
>>> instances of the same IP in the SoC (or several of the same PCIe card).
>>> I really don't want to go back to that.
>>
>> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we can give the
>> correct binding information to the PHY framework. I think we can drop having
>> this non-dt support in PHY framework? I see only one platform (OMAP3) going to
>> be needing this non-dt support and we can use the USB PHY library for it.
>
> you shouldn't drop support for non-DT platform, in any case we lived
> without DT (and still do) for years. Gotta find a better way ;-)
hmm..
how about passing the device names of PHY in platform data of the controller?
It should be deterministic as the PHY framework assigns its own id and we
*don't* want to add any requirement that the ID must be assigned manually
without using PLATFORM_DEVID_AUTO. We can get rid of *phy_init_data* in the v10
patch series.
Thanks
Kishon
>
On Tuesday 13 of August 2013 16:14:44 Kishon Vijay Abraham I wrote:
> Hi,
>
> On Wednesday 31 July 2013 11:45 AM, Felipe Balbi wrote:
> > Hi,
> >
> > On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I wrote:
> >>>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
> >>>>>>> regulators, PWMs or even i2c busses because there are complex
> >>>>>>> cases
> >>>>>>> when passing just a name using platform data will not work. I
> >>>>>>> would
> >>>>>>> second what Stephen said [1] and define a structure doing things
> >>>>>>> in a
> >>>>>>> DT-like way.
> >>>>>>>
> >>>>>>> Example;
> >>>>>>>
> >>>>>>> [platform code]
> >>>>>>>
> >>>>>>> static const struct phy_lookup my_phy_lookup[] = {
> >>>>>>>
> >>>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
> >>>>>>
> >>>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used
> >>>>>> while
> >>>>>> creating the device, the ids in the device name would change and
> >>>>>> PHY_LOOKUP wont be useful.
> >>>>>
> >>>>> I don't think this is a problem. All the existing lookup methods
> >>>>> already
> >>>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c,
> >>>>> ...). You
> >>>>> can simply add a requirement that the ID must be assigned manually,
> >>>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
> >>>>
> >>>> And I'm saying that this idea, of using a specific name and id, is
> >>>> frought with fragility and will break in the future in various ways
> >>>> when
> >>>> devices get added to systems, making these strings constantly have
> >>>> to be
> >>>> kept up to date with different board configurations.
> >>>>
> >>>> People, NEVER, hardcode something like an id. The fact that this
> >>>> happens today with the clock code, doesn't make it right, it makes
> >>>> the
> >>>> clock code wrong. Others have already said that this is wrong there
> >>>> as
> >>>> well, as systems change and dynamic ids get used more and more.
> >>>>
> >>>> Let's not repeat the same mistakes of the past just because we
> >>>> refuse to
> >>>> learn from them...
> >>>>
> >>>> So again, the "find a phy by a string" functions should be removed,
> >>>> the
> >>>> device id should be automatically created by the phy core just to
> >>>> make
> >>>> things unique in sysfs, and no driver code should _ever_ be reliant
> >>>> on
> >>>> the number that is being created, and the pointer to the phy
> >>>> structure
> >>>> should be used everywhere instead.
> >>>>
> >>>> With those types of changes, I will consider merging this subsystem,
> >>>> but
> >>>> without them, sorry, I will not.
> >>>
> >>> I'll agree with Greg here, the very fact that we see people trying to
> >>> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already points
> >>> to a
> >>> big problem in the framework.
> >>>
> >>> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will end up
> >>> adding similar infrastructure to the driver themselves to make sure
> >>> we
> >>> don't end up with duplicate names in sysfs in case we have multiple
> >>> instances of the same IP in the SoC (or several of the same PCIe
> >>> card).
> >>> I really don't want to go back to that.
> >>
> >> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we can
> >> give the correct binding information to the PHY framework. I think we
> >> can drop having this non-dt support in PHY framework? I see only one
> >> platform (OMAP3) going to be needing this non-dt support and we can
> >> use the USB PHY library for it.>
> > you shouldn't drop support for non-DT platform, in any case we lived
> > without DT (and still do) for years. Gotta find a better way ;-)
>
> hmm..
>
> how about passing the device names of PHY in platform data of the
> controller? It should be deterministic as the PHY framework assigns its
> own id and we *don't* want to add any requirement that the ID must be
> assigned manually without using PLATFORM_DEVID_AUTO. We can get rid of
> *phy_init_data* in the v10 patch series.
What about slightly altering the concept of v9 to pass a pointer to struct
device instead of device name inside phy_init_data?
Best regards,
Tomasz
On Tuesday 13 August 2013 05:07 PM, Tomasz Figa wrote:
> On Tuesday 13 of August 2013 16:14:44 Kishon Vijay Abraham I wrote:
>> Hi,
>>
>> On Wednesday 31 July 2013 11:45 AM, Felipe Balbi wrote:
>>> Hi,
>>>
>>> On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I wrote:
>>>>>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
>>>>>>>>> regulators, PWMs or even i2c busses because there are complex
>>>>>>>>> cases
>>>>>>>>> when passing just a name using platform data will not work. I
>>>>>>>>> would
>>>>>>>>> second what Stephen said [1] and define a structure doing things
>>>>>>>>> in a
>>>>>>>>> DT-like way.
>>>>>>>>>
>>>>>>>>> Example;
>>>>>>>>>
>>>>>>>>> [platform code]
>>>>>>>>>
>>>>>>>>> static const struct phy_lookup my_phy_lookup[] = {
>>>>>>>>>
>>>>>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
>>>>>>>>
>>>>>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used
>>>>>>>> while
>>>>>>>> creating the device, the ids in the device name would change and
>>>>>>>> PHY_LOOKUP wont be useful.
>>>>>>>
>>>>>>> I don't think this is a problem. All the existing lookup methods
>>>>>>> already
>>>>>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c,
>>>>>>> ...). You
>>>>>>> can simply add a requirement that the ID must be assigned manually,
>>>>>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
>>>>>>
>>>>>> And I'm saying that this idea, of using a specific name and id, is
>>>>>> frought with fragility and will break in the future in various ways
>>>>>> when
>>>>>> devices get added to systems, making these strings constantly have
>>>>>> to be
>>>>>> kept up to date with different board configurations.
>>>>>>
>>>>>> People, NEVER, hardcode something like an id. The fact that this
>>>>>> happens today with the clock code, doesn't make it right, it makes
>>>>>> the
>>>>>> clock code wrong. Others have already said that this is wrong there
>>>>>> as
>>>>>> well, as systems change and dynamic ids get used more and more.
>>>>>>
>>>>>> Let's not repeat the same mistakes of the past just because we
>>>>>> refuse to
>>>>>> learn from them...
>>>>>>
>>>>>> So again, the "find a phy by a string" functions should be removed,
>>>>>> the
>>>>>> device id should be automatically created by the phy core just to
>>>>>> make
>>>>>> things unique in sysfs, and no driver code should _ever_ be reliant
>>>>>> on
>>>>>> the number that is being created, and the pointer to the phy
>>>>>> structure
>>>>>> should be used everywhere instead.
>>>>>>
>>>>>> With those types of changes, I will consider merging this subsystem,
>>>>>> but
>>>>>> without them, sorry, I will not.
>>>>>
>>>>> I'll agree with Greg here, the very fact that we see people trying to
>>>>> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already points
>>>>> to a
>>>>> big problem in the framework.
>>>>>
>>>>> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will end up
>>>>> adding similar infrastructure to the driver themselves to make sure
>>>>> we
>>>>> don't end up with duplicate names in sysfs in case we have multiple
>>>>> instances of the same IP in the SoC (or several of the same PCIe
>>>>> card).
>>>>> I really don't want to go back to that.
>>>>
>>>> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we can
>>>> give the correct binding information to the PHY framework. I think we
>>>> can drop having this non-dt support in PHY framework? I see only one
>>>> platform (OMAP3) going to be needing this non-dt support and we can
>>>> use the USB PHY library for it.>
>>> you shouldn't drop support for non-DT platform, in any case we lived
>>> without DT (and still do) for years. Gotta find a better way ;-)
>>
>> hmm..
>>
>> how about passing the device names of PHY in platform data of the
>> controller? It should be deterministic as the PHY framework assigns its
>> own id and we *don't* want to add any requirement that the ID must be
>> assigned manually without using PLATFORM_DEVID_AUTO. We can get rid of
>> *phy_init_data* in the v10 patch series.
>
> What about slightly altering the concept of v9 to pass a pointer to struct
> device instead of device name inside phy_init_data?
The problem is device might be created very late. (For example in omap4, usb2
phy device gets created when ocp2scp bus is probed). And we have to pass the
init data in board file.
Thanks
Kishon
W dniu 2013-08-13 14:05, Kishon Vijay Abraham I pisze:
> On Tuesday 13 August 2013 05:07 PM, Tomasz Figa wrote:
>> On Tuesday 13 of August 2013 16:14:44 Kishon Vijay Abraham I wrote:
>>> On Wednesday 31 July 2013 11:45 AM, Felipe Balbi wrote:
>>>> On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I wrote:
>>>>>>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
>>>>>>>>>> regulators, PWMs or even i2c busses because there are complex
>>>>>>>>>> cases
>>>>>>>>>> when passing just a name using platform data will not work. I
>>>>>>>>>> would
>>>>>>>>>> second what Stephen said [1] and define a structure doing things
>>>>>>>>>> in a
>>>>>>>>>> DT-like way.
>>>>>>>>>>
>>>>>>>>>> Example;
>>>>>>>>>>
>>>>>>>>>> [platform code]
>>>>>>>>>>
>>>>>>>>>> static const struct phy_lookup my_phy_lookup[] = {
>>>>>>>>>>
>>>>>>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1", "phy.2"),
>>>>>>>>>
>>>>>>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used
>>>>>>>>> while
>>>>>>>>> creating the device, the ids in the device name would change and
>>>>>>>>> PHY_LOOKUP wont be useful.
>>>>>>>>
>>>>>>>> I don't think this is a problem. All the existing lookup methods
>>>>>>>> already
>>>>>>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c,
>>>>>>>> ...). You
>>>>>>>> can simply add a requirement that the ID must be assigned manually,
>>>>>>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
>>>>>>>
>>>>>>> And I'm saying that this idea, of using a specific name and id, is
>>>>>>> frought with fragility and will break in the future in various ways
>>>>>>> when
>>>>>>> devices get added to systems, making these strings constantly have
>>>>>>> to be
>>>>>>> kept up to date with different board configurations.
>>>>>>>
>>>>>>> People, NEVER, hardcode something like an id. The fact that this
>>>>>>> happens today with the clock code, doesn't make it right, it makes
>>>>>>> the
>>>>>>> clock code wrong. Others have already said that this is wrong there
>>>>>>> as
>>>>>>> well, as systems change and dynamic ids get used more and more.
>>>>>>>
>>>>>>> Let's not repeat the same mistakes of the past just because we
>>>>>>> refuse to
>>>>>>> learn from them...
>>>>>>>
>>>>>>> So again, the "find a phy by a string" functions should be removed,
>>>>>>> the
>>>>>>> device id should be automatically created by the phy core just to
>>>>>>> make
>>>>>>> things unique in sysfs, and no driver code should _ever_ be reliant
>>>>>>> on
>>>>>>> the number that is being created, and the pointer to the phy
>>>>>>> structure
>>>>>>> should be used everywhere instead.
>>>>>>>
>>>>>>> With those types of changes, I will consider merging this subsystem,
>>>>>>> but
>>>>>>> without them, sorry, I will not.
>>>>>>
>>>>>> I'll agree with Greg here, the very fact that we see people trying to
>>>>>> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already points
>>>>>> to a big problem in the framework.
>>>>>>
>>>>>> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will end up
>>>>>> adding similar infrastructure to the driver themselves to make sure
>>>>>> we
>>>>>> don't end up with duplicate names in sysfs in case we have multiple
>>>>>> instances of the same IP in the SoC (or several of the same PCIe
>>>>>> card).
>>>>>> I really don't want to go back to that.
>>>>>
>>>>> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we can
>>>>> give the correct binding information to the PHY framework. I think we
>>>>> can drop having this non-dt support in PHY framework? I see only one
>>>>> platform (OMAP3) going to be needing this non-dt support and we can
>>>>> use the USB PHY library for it.>
>>>> you shouldn't drop support for non-DT platform, in any case we lived
>>>> without DT (and still do) for years. Gotta find a better way ;-)
>>>
>>> hmm..
>>>
>>> how about passing the device names of PHY in platform data of the
>>> controller? It should be deterministic as the PHY framework assigns its
>>> own id and we *don't* want to add any requirement that the ID must be
>>> assigned manually without using PLATFORM_DEVID_AUTO. We can get rid of
>>> *phy_init_data* in the v10 patch series.
OK, so the PHY device name would have a fixed part, passed as
platform data of the controller and a variable part appended
by the PHY core, depending on the number of registered PHYs ?
Then same PHY names would be passed as the PHY provider driver's
platform data ?
Then if there are 2 instances of the above (same names in platform
data) how would be determined which PHY controller is linked to
which PHY supplier ?
I guess you want each device instance to have different PHY device
names already in platform data ? That might work. We probably will
be focused mostly on DT anyway. It seem without DT we are trying
to find some layer that would allow us to couple relevant devices
and overcome driver core inconvenience that it provides to means
to identify specific devices in advance. :) Your proposal sounds
reasonable, however I might be missing some details or corner cases.
>> What about slightly altering the concept of v9 to pass a pointer to struct
>> device instead of device name inside phy_init_data?
As Felipe said, we don't want to pass pointers in platform_data
to/from random subsystems. We pass data, passing pointers would
be a total mess IMHO.
> The problem is device might be created very late. (For example in omap4, usb2
> phy device gets created when ocp2scp bus is probed). And we have to pass the
> init data in board file.
Regards,
Sylwester
On Wednesday 14 of August 2013 00:19:28 Sylwester Nawrocki wrote:
> W dniu 2013-08-13 14:05, Kishon Vijay Abraham I pisze:
> > On Tuesday 13 August 2013 05:07 PM, Tomasz Figa wrote:
> >> On Tuesday 13 of August 2013 16:14:44 Kishon Vijay Abraham I wrote:
> >>> On Wednesday 31 July 2013 11:45 AM, Felipe Balbi wrote:
> >>>> On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I
wrote:
> >>>>>>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
> >>>>>>>>>> regulators, PWMs or even i2c busses because there are complex
> >>>>>>>>>> cases
> >>>>>>>>>> when passing just a name using platform data will not work. I
> >>>>>>>>>> would
> >>>>>>>>>> second what Stephen said [1] and define a structure doing
> >>>>>>>>>> things
> >>>>>>>>>> in a
> >>>>>>>>>> DT-like way.
> >>>>>>>>>>
> >>>>>>>>>> Example;
> >>>>>>>>>>
> >>>>>>>>>> [platform code]
> >>>>>>>>>>
> >>>>>>>>>> static const struct phy_lookup my_phy_lookup[] = {
> >>>>>>>>>>
> >>>>>>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1",
> >>>>>>>>>> "phy.2"),
> >>>>>>>>>
> >>>>>>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used
> >>>>>>>>> while
> >>>>>>>>> creating the device, the ids in the device name would change
> >>>>>>>>> and
> >>>>>>>>> PHY_LOOKUP wont be useful.
> >>>>>>>>
> >>>>>>>> I don't think this is a problem. All the existing lookup
> >>>>>>>> methods
> >>>>>>>> already
> >>>>>>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c,
> >>>>>>>> ...). You
> >>>>>>>> can simply add a requirement that the ID must be assigned
> >>>>>>>> manually,
> >>>>>>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
> >>>>>>>
> >>>>>>> And I'm saying that this idea, of using a specific name and id,
> >>>>>>> is
> >>>>>>> frought with fragility and will break in the future in various
> >>>>>>> ways
> >>>>>>> when
> >>>>>>> devices get added to systems, making these strings constantly
> >>>>>>> have
> >>>>>>> to be
> >>>>>>> kept up to date with different board configurations.
> >>>>>>>
> >>>>>>> People, NEVER, hardcode something like an id. The fact that
> >>>>>>> this
> >>>>>>> happens today with the clock code, doesn't make it right, it
> >>>>>>> makes
> >>>>>>> the
> >>>>>>> clock code wrong. Others have already said that this is wrong
> >>>>>>> there
> >>>>>>> as
> >>>>>>> well, as systems change and dynamic ids get used more and more.
> >>>>>>>
> >>>>>>> Let's not repeat the same mistakes of the past just because we
> >>>>>>> refuse to
> >>>>>>> learn from them...
> >>>>>>>
> >>>>>>> So again, the "find a phy by a string" functions should be
> >>>>>>> removed,
> >>>>>>> the
> >>>>>>> device id should be automatically created by the phy core just
> >>>>>>> to
> >>>>>>> make
> >>>>>>> things unique in sysfs, and no driver code should _ever_ be
> >>>>>>> reliant
> >>>>>>> on
> >>>>>>> the number that is being created, and the pointer to the phy
> >>>>>>> structure
> >>>>>>> should be used everywhere instead.
> >>>>>>>
> >>>>>>> With those types of changes, I will consider merging this
> >>>>>>> subsystem,
> >>>>>>> but
> >>>>>>> without them, sorry, I will not.
> >>>>>>
> >>>>>> I'll agree with Greg here, the very fact that we see people
> >>>>>> trying to
> >>>>>> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already
> >>>>>> points
> >>>>>> to a big problem in the framework.
> >>>>>>
> >>>>>> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will
> >>>>>> end up
> >>>>>> adding similar infrastructure to the driver themselves to make
> >>>>>> sure
> >>>>>> we
> >>>>>> don't end up with duplicate names in sysfs in case we have
> >>>>>> multiple
> >>>>>> instances of the same IP in the SoC (or several of the same PCIe
> >>>>>> card).
> >>>>>> I really don't want to go back to that.
> >>>>>
> >>>>> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we
> >>>>> can
> >>>>> give the correct binding information to the PHY framework. I think
> >>>>> we
> >>>>> can drop having this non-dt support in PHY framework? I see only
> >>>>> one
> >>>>> platform (OMAP3) going to be needing this non-dt support and we
> >>>>> can
> >>>>> use the USB PHY library for it.>
> >>>>
> >>>> you shouldn't drop support for non-DT platform, in any case we
> >>>> lived
> >>>> without DT (and still do) for years. Gotta find a better way ;-)
> >>>
> >>> hmm..
> >>>
> >>> how about passing the device names of PHY in platform data of the
> >>> controller? It should be deterministic as the PHY framework assigns
> >>> its
> >>> own id and we *don't* want to add any requirement that the ID must
> >>> be
> >>> assigned manually without using PLATFORM_DEVID_AUTO. We can get rid
> >>> of
> >>> *phy_init_data* in the v10 patch series.
>
> OK, so the PHY device name would have a fixed part, passed as
> platform data of the controller and a variable part appended
> by the PHY core, depending on the number of registered PHYs ?
>
> Then same PHY names would be passed as the PHY provider driver's
> platform data ?
>
> Then if there are 2 instances of the above (same names in platform
> data) how would be determined which PHY controller is linked to
> which PHY supplier ?
>
> I guess you want each device instance to have different PHY device
> names already in platform data ? That might work. We probably will
> be focused mostly on DT anyway. It seem without DT we are trying
> to find some layer that would allow us to couple relevant devices
> and overcome driver core inconvenience that it provides to means
> to identify specific devices in advance. :) Your proposal sounds
> reasonable, however I might be missing some details or corner cases.
>
> >> What about slightly altering the concept of v9 to pass a pointer to
> >> struct device instead of device name inside phy_init_data?
>
> As Felipe said, we don't want to pass pointers in platform_data
> to/from random subsystems. We pass data, passing pointers would
> be a total mess IMHO.
Well, this is a total mess anyway... I don't really get the point of using
PLATFORM_DEVID_AUTO. The only thing that comes to my mind is that you can
use it if you don't care about the ID and so it can be assigned
automatically.
However my understanding of the device ID is that it was supposed to
provide a way to identify multiple instances of identical devices in a
reliable way, to solve problems like the one we are trying to solve
here...
So maybe let's stop solving an already solved problem and just state that
you need to explicitly assign device ID to use this framework?
Best regards,
Tomasz
Hi,
On Wednesday 14 August 2013 04:34 AM, Tomasz Figa wrote:
> On Wednesday 14 of August 2013 00:19:28 Sylwester Nawrocki wrote:
>> W dniu 2013-08-13 14:05, Kishon Vijay Abraham I pisze:
>>> On Tuesday 13 August 2013 05:07 PM, Tomasz Figa wrote:
>>>> On Tuesday 13 of August 2013 16:14:44 Kishon Vijay Abraham I wrote:
>>>>> On Wednesday 31 July 2013 11:45 AM, Felipe Balbi wrote:
>>>>>> On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I
> wrote:
>>>>>>>>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
>>>>>>>>>>>> regulators, PWMs or even i2c busses because there are complex
>>>>>>>>>>>> cases
>>>>>>>>>>>> when passing just a name using platform data will not work. I
>>>>>>>>>>>> would
>>>>>>>>>>>> second what Stephen said [1] and define a structure doing
>>>>>>>>>>>> things
>>>>>>>>>>>> in a
>>>>>>>>>>>> DT-like way.
>>>>>>>>>>>>
>>>>>>>>>>>> Example;
>>>>>>>>>>>>
>>>>>>>>>>>> [platform code]
>>>>>>>>>>>>
>>>>>>>>>>>> static const struct phy_lookup my_phy_lookup[] = {
>>>>>>>>>>>>
>>>>>>>>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1",
>>>>>>>>>>>> "phy.2"),
>>>>>>>>>>>
>>>>>>>>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used
>>>>>>>>>>> while
>>>>>>>>>>> creating the device, the ids in the device name would change
>>>>>>>>>>> and
>>>>>>>>>>> PHY_LOOKUP wont be useful.
>>>>>>>>>>
>>>>>>>>>> I don't think this is a problem. All the existing lookup
>>>>>>>>>> methods
>>>>>>>>>> already
>>>>>>>>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c,
>>>>>>>>>> ...). You
>>>>>>>>>> can simply add a requirement that the ID must be assigned
>>>>>>>>>> manually,
>>>>>>>>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
>>>>>>>>>
>>>>>>>>> And I'm saying that this idea, of using a specific name and id,
>>>>>>>>> is
>>>>>>>>> frought with fragility and will break in the future in various
>>>>>>>>> ways
>>>>>>>>> when
>>>>>>>>> devices get added to systems, making these strings constantly
>>>>>>>>> have
>>>>>>>>> to be
>>>>>>>>> kept up to date with different board configurations.
>>>>>>>>>
>>>>>>>>> People, NEVER, hardcode something like an id. The fact that
>>>>>>>>> this
>>>>>>>>> happens today with the clock code, doesn't make it right, it
>>>>>>>>> makes
>>>>>>>>> the
>>>>>>>>> clock code wrong. Others have already said that this is wrong
>>>>>>>>> there
>>>>>>>>> as
>>>>>>>>> well, as systems change and dynamic ids get used more and more.
>>>>>>>>>
>>>>>>>>> Let's not repeat the same mistakes of the past just because we
>>>>>>>>> refuse to
>>>>>>>>> learn from them...
>>>>>>>>>
>>>>>>>>> So again, the "find a phy by a string" functions should be
>>>>>>>>> removed,
>>>>>>>>> the
>>>>>>>>> device id should be automatically created by the phy core just
>>>>>>>>> to
>>>>>>>>> make
>>>>>>>>> things unique in sysfs, and no driver code should _ever_ be
>>>>>>>>> reliant
>>>>>>>>> on
>>>>>>>>> the number that is being created, and the pointer to the phy
>>>>>>>>> structure
>>>>>>>>> should be used everywhere instead.
>>>>>>>>>
>>>>>>>>> With those types of changes, I will consider merging this
>>>>>>>>> subsystem,
>>>>>>>>> but
>>>>>>>>> without them, sorry, I will not.
>>>>>>>>
>>>>>>>> I'll agree with Greg here, the very fact that we see people
>>>>>>>> trying to
>>>>>>>> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already
>>>>>>>> points
>>>>>>>> to a big problem in the framework.
>>>>>>>>
>>>>>>>> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will
>>>>>>>> end up
>>>>>>>> adding similar infrastructure to the driver themselves to make
>>>>>>>> sure
>>>>>>>> we
>>>>>>>> don't end up with duplicate names in sysfs in case we have
>>>>>>>> multiple
>>>>>>>> instances of the same IP in the SoC (or several of the same PCIe
>>>>>>>> card).
>>>>>>>> I really don't want to go back to that.
>>>>>>>
>>>>>>> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we
>>>>>>> can
>>>>>>> give the correct binding information to the PHY framework. I think
>>>>>>> we
>>>>>>> can drop having this non-dt support in PHY framework? I see only
>>>>>>> one
>>>>>>> platform (OMAP3) going to be needing this non-dt support and we
>>>>>>> can
>>>>>>> use the USB PHY library for it.>
>>>>>>
>>>>>> you shouldn't drop support for non-DT platform, in any case we
>>>>>> lived
>>>>>> without DT (and still do) for years. Gotta find a better way ;-)
>>>>>
>>>>> hmm..
>>>>>
>>>>> how about passing the device names of PHY in platform data of the
>>>>> controller? It should be deterministic as the PHY framework assigns
>>>>> its
>>>>> own id and we *don't* want to add any requirement that the ID must
>>>>> be
>>>>> assigned manually without using PLATFORM_DEVID_AUTO. We can get rid
>>>>> of
>>>>> *phy_init_data* in the v10 patch series.
>>
>> OK, so the PHY device name would have a fixed part, passed as
>> platform data of the controller and a variable part appended
>> by the PHY core, depending on the number of registered PHYs ?
>>
>> Then same PHY names would be passed as the PHY provider driver's
>> platform data ?
>>
>> Then if there are 2 instances of the above (same names in platform
>> data) how would be determined which PHY controller is linked to
>> which PHY supplier ?
>>
>> I guess you want each device instance to have different PHY device
>> names already in platform data ? That might work. We probably will
>> be focused mostly on DT anyway. It seem without DT we are trying
>> to find some layer that would allow us to couple relevant devices
>> and overcome driver core inconvenience that it provides to means
>> to identify specific devices in advance. :) Your proposal sounds
>> reasonable, however I might be missing some details or corner cases.
>>
>>>> What about slightly altering the concept of v9 to pass a pointer to
>>>> struct device instead of device name inside phy_init_data?
>>
>> As Felipe said, we don't want to pass pointers in platform_data
>> to/from random subsystems. We pass data, passing pointers would
>> be a total mess IMHO.
>
> Well, this is a total mess anyway... I don't really get the point of using
> PLATFORM_DEVID_AUTO. The only thing that comes to my mind is that you can
> use it if you don't care about the ID and so it can be assigned
> automatically.
>
> However my understanding of the device ID is that it was supposed to
> provide a way to identify multiple instances of identical devices in a
> reliable way, to solve problems like the one we are trying to solve
> here...
>
> So maybe let's stop solving an already solved problem and just state that
> you need to explicitly assign device ID to use this framework?
Felipe,
Can we have it the way I had in my v10 patch series till we find a better way?
I think this *non-dt* stuff shouldn't be blocking as most of the users are dt only?
Thanks
Kishon
Felipe,
ping..
On Wednesday 14 August 2013 08:35 PM, Kishon Vijay Abraham I wrote:
> Hi,
>
> On Wednesday 14 August 2013 04:34 AM, Tomasz Figa wrote:
>> On Wednesday 14 of August 2013 00:19:28 Sylwester Nawrocki wrote:
>>> W dniu 2013-08-13 14:05, Kishon Vijay Abraham I pisze:
>>>> On Tuesday 13 August 2013 05:07 PM, Tomasz Figa wrote:
>>>>> On Tuesday 13 of August 2013 16:14:44 Kishon Vijay Abraham I wrote:
>>>>>> On Wednesday 31 July 2013 11:45 AM, Felipe Balbi wrote:
>>>>>>> On Wed, Jul 31, 2013 at 11:14:32AM +0530, Kishon Vijay Abraham I
>> wrote:
>>>>>>>>>>>>> IMHO we need a lookup method for PHYs, just like for clocks,
>>>>>>>>>>>>> regulators, PWMs or even i2c busses because there are complex
>>>>>>>>>>>>> cases
>>>>>>>>>>>>> when passing just a name using platform data will not work. I
>>>>>>>>>>>>> would
>>>>>>>>>>>>> second what Stephen said [1] and define a structure doing
>>>>>>>>>>>>> things
>>>>>>>>>>>>> in a
>>>>>>>>>>>>> DT-like way.
>>>>>>>>>>>>>
>>>>>>>>>>>>> Example;
>>>>>>>>>>>>>
>>>>>>>>>>>>> [platform code]
>>>>>>>>>>>>>
>>>>>>>>>>>>> static const struct phy_lookup my_phy_lookup[] = {
>>>>>>>>>>>>>
>>>>>>>>>>>>> PHY_LOOKUP("s3c-hsotg.0", "otg", "samsung-usbphy.1",
>>>>>>>>>>>>> "phy.2"),
>>>>>>>>>>>>
>>>>>>>>>>>> The only problem here is that if *PLATFORM_DEVID_AUTO* is used
>>>>>>>>>>>> while
>>>>>>>>>>>> creating the device, the ids in the device name would change
>>>>>>>>>>>> and
>>>>>>>>>>>> PHY_LOOKUP wont be useful.
>>>>>>>>>>>
>>>>>>>>>>> I don't think this is a problem. All the existing lookup
>>>>>>>>>>> methods
>>>>>>>>>>> already
>>>>>>>>>>> use ID to identify devices (see regulators, clkdev, PWMs, i2c,
>>>>>>>>>>> ...). You
>>>>>>>>>>> can simply add a requirement that the ID must be assigned
>>>>>>>>>>> manually,
>>>>>>>>>>> without using PLATFORM_DEVID_AUTO to use PHY lookup.
>>>>>>>>>>
>>>>>>>>>> And I'm saying that this idea, of using a specific name and id,
>>>>>>>>>> is
>>>>>>>>>> frought with fragility and will break in the future in various
>>>>>>>>>> ways
>>>>>>>>>> when
>>>>>>>>>> devices get added to systems, making these strings constantly
>>>>>>>>>> have
>>>>>>>>>> to be
>>>>>>>>>> kept up to date with different board configurations.
>>>>>>>>>>
>>>>>>>>>> People, NEVER, hardcode something like an id. The fact that
>>>>>>>>>> this
>>>>>>>>>> happens today with the clock code, doesn't make it right, it
>>>>>>>>>> makes
>>>>>>>>>> the
>>>>>>>>>> clock code wrong. Others have already said that this is wrong
>>>>>>>>>> there
>>>>>>>>>> as
>>>>>>>>>> well, as systems change and dynamic ids get used more and more.
>>>>>>>>>>
>>>>>>>>>> Let's not repeat the same mistakes of the past just because we
>>>>>>>>>> refuse to
>>>>>>>>>> learn from them...
>>>>>>>>>>
>>>>>>>>>> So again, the "find a phy by a string" functions should be
>>>>>>>>>> removed,
>>>>>>>>>> the
>>>>>>>>>> device id should be automatically created by the phy core just
>>>>>>>>>> to
>>>>>>>>>> make
>>>>>>>>>> things unique in sysfs, and no driver code should _ever_ be
>>>>>>>>>> reliant
>>>>>>>>>> on
>>>>>>>>>> the number that is being created, and the pointer to the phy
>>>>>>>>>> structure
>>>>>>>>>> should be used everywhere instead.
>>>>>>>>>>
>>>>>>>>>> With those types of changes, I will consider merging this
>>>>>>>>>> subsystem,
>>>>>>>>>> but
>>>>>>>>>> without them, sorry, I will not.
>>>>>>>>>
>>>>>>>>> I'll agree with Greg here, the very fact that we see people
>>>>>>>>> trying to
>>>>>>>>> add a requirement of *NOT* using PLATFORM_DEVID_AUTO already
>>>>>>>>> points
>>>>>>>>> to a big problem in the framework.
>>>>>>>>>
>>>>>>>>> The fact is that if we don't allow PLATFORM_DEVID_AUTO we will
>>>>>>>>> end up
>>>>>>>>> adding similar infrastructure to the driver themselves to make
>>>>>>>>> sure
>>>>>>>>> we
>>>>>>>>> don't end up with duplicate names in sysfs in case we have
>>>>>>>>> multiple
>>>>>>>>> instances of the same IP in the SoC (or several of the same PCIe
>>>>>>>>> card).
>>>>>>>>> I really don't want to go back to that.
>>>>>>>>
>>>>>>>> If we are using PLATFORM_DEVID_AUTO, then I dont see any way we
>>>>>>>> can
>>>>>>>> give the correct binding information to the PHY framework. I think
>>>>>>>> we
>>>>>>>> can drop having this non-dt support in PHY framework? I see only
>>>>>>>> one
>>>>>>>> platform (OMAP3) going to be needing this non-dt support and we
>>>>>>>> can
>>>>>>>> use the USB PHY library for it.>
>>>>>>>
>>>>>>> you shouldn't drop support for non-DT platform, in any case we
>>>>>>> lived
>>>>>>> without DT (and still do) for years. Gotta find a better way ;-)
>>>>>>
>>>>>> hmm..
>>>>>>
>>>>>> how about passing the device names of PHY in platform data of the
>>>>>> controller? It should be deterministic as the PHY framework assigns
>>>>>> its
>>>>>> own id and we *don't* want to add any requirement that the ID must
>>>>>> be
>>>>>> assigned manually without using PLATFORM_DEVID_AUTO. We can get rid
>>>>>> of
>>>>>> *phy_init_data* in the v10 patch series.
>>>
>>> OK, so the PHY device name would have a fixed part, passed as
>>> platform data of the controller and a variable part appended
>>> by the PHY core, depending on the number of registered PHYs ?
>>>
>>> Then same PHY names would be passed as the PHY provider driver's
>>> platform data ?
>>>
>>> Then if there are 2 instances of the above (same names in platform
>>> data) how would be determined which PHY controller is linked to
>>> which PHY supplier ?
>>>
>>> I guess you want each device instance to have different PHY device
>>> names already in platform data ? That might work. We probably will
>>> be focused mostly on DT anyway. It seem without DT we are trying
>>> to find some layer that would allow us to couple relevant devices
>>> and overcome driver core inconvenience that it provides to means
>>> to identify specific devices in advance. :) Your proposal sounds
>>> reasonable, however I might be missing some details or corner cases.
>>>
>>>>> What about slightly altering the concept of v9 to pass a pointer to
>>>>> struct device instead of device name inside phy_init_data?
>>>
>>> As Felipe said, we don't want to pass pointers in platform_data
>>> to/from random subsystems. We pass data, passing pointers would
>>> be a total mess IMHO.
>>
>> Well, this is a total mess anyway... I don't really get the point of using
>> PLATFORM_DEVID_AUTO. The only thing that comes to my mind is that you can
>> use it if you don't care about the ID and so it can be assigned
>> automatically.
>>
>> However my understanding of the device ID is that it was supposed to
>> provide a way to identify multiple instances of identical devices in a
>> reliable way, to solve problems like the one we are trying to solve
>> here...
>>
>> So maybe let's stop solving an already solved problem and just state that
>> you need to explicitly assign device ID to use this framework?
>
> Felipe,
> Can we have it the way I had in my v10 patch series till we find a better way?
> I think this *non-dt* stuff shouldn't be blocking as most of the users are dt only?
>
> Thanks
> Kishon
>
Hi,
On Mon, Aug 19, 2013 at 10:58:09AM +0530, Kishon Vijay Abraham I wrote:
> >> So maybe let's stop solving an already solved problem and just state that
> >> you need to explicitly assign device ID to use this framework?
> >
> > Felipe,
> > Can we have it the way I had in my v10 patch series till we find a better way?
> > I think this *non-dt* stuff shouldn't be blocking as most of the users are dt only?
I don't have a lot of things against it, but preventing driver authors
to use PLATFORM_DEVID_AUTO just to use the framework is likely going to
piss some people off.
Perhaps we can start with this approach and fix things later ? At least
it ungates all the PHY drivers which are depending on this framework
(quite a few already). If everybody agrees with this approach, I'd be ok
with it too.
cheers
--
balbi