* [PATCH 00/15] PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 00/15] PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: linux-fbdev, linux-samsung-soc, swarren, balajitk, arnd,
linux-doc, tony, devicetree-discuss, linux-usb, nsekhar,
linux-kernel, grant.likely, akpm, linux-omap, george.cherian,
linux-arm-kernel, linux-media
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 00/15] PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
.../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 <kishon@ti.com>
+
+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 <kishon@ti.com>
+L: linux-kernel@vger.kernel.org
+S: Supported
+F: drivers/phy/
+F: include/linux/phy/
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm@vger.kernel.org
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 <kishon@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.
+ *
+ * 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 <kishon@ti.com>");
+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 <kishon@ti.com>
+ *
+ * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
.../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 <kishon@ti.com>
+
+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 <kishon@ti.com>
+L: linux-kernel@vger.kernel.org
+S: Supported
+F: drivers/phy/
+F: include/linux/phy/
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm@vger.kernel.org
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 <kishon@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.
+ *
+ * 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 <kishon@ti.com>");
+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 <kishon@ti.com>
+ *
+ * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
.../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 at 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 at 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 <kishon@ti.com>
+
+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 <kishon@ti.com>
+L: linux-kernel at vger.kernel.org
+S: Supported
+F: drivers/phy/
+F: include/linux/phy/
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm at vger.kernel.org
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 <kishon@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.
+ *
+ * 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 <kishon@ti.com>");
+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 <kishon@ti.com>
+ *
+ * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, balbi-l0cyMroinI0,
kishon-l0cyMroinI0, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
swarren-DDmLM1+adcrQT0dZR+AlfA, balajitk-l0cyMroinI0,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-usb-u79uwXL29TY76Z2rM5mHXA, nsekhar-l0cyMroinI0,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-omap-u79uwXL29TY76Z2rM5mHXA, george.cherian-l0cyMroinI0,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-media-u79uwXL29TY76Z2rM5mHXA
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 <kishon-l0cyMroinI0@public.gmane.org>
Reviewed-by: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Acked-by: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 03/15] usb: phy: twl4030: use the new generic PHY framework
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 03/15] usb: phy: twl4030: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 03/15] usb: phy: twl4030: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 05/15] ARM: dts: omap: update usb_otg_hs data
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 05/15] ARM: dts: omap: update usb_otg_hs data
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 05/15] ARM: dts: omap: update usb_otg_hs data
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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 at 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 at 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 at 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 06/15] usb: musb: omap2430: use the new generic PHY framework
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 06/15] usb: musb: omap2430: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 06/15] usb: musb: omap2430: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 07/15] usb: phy: omap-usb2: remove *set_suspend* callback from omap-usb2
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 07/15] usb: phy: omap-usb2: remove *set_suspend* callback from omap-usb2
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 07/15] usb: phy: omap-usb2: remove *set_suspend* callback from omap-usb2
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 08/15] usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 08/15] usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, balbi-l0cyMroinI0,
kishon-l0cyMroinI0, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
swarren-DDmLM1+adcrQT0dZR+AlfA, balajitk-l0cyMroinI0,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-usb-u79uwXL29TY76Z2rM5mHXA, nsekhar-l0cyMroinI0,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-omap-u79uwXL29TY76Z2rM5mHXA, george.cherian-l0cyMroinI0,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-media-u79uwXL29TY76Z2rM5mHXA
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 <kishon-l0cyMroinI0@public.gmane.org>
Acked-by: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
Reviewed-by: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 08/15] usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 09/15] phy: Add driver for Exynos MIPI CSIS/DSIM DPHYs
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <s.nawrocki@samsung.com>
+ *
+ * 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 <s.nawrocki@samsung.com>");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 09/15] phy: Add driver for Exynos MIPI CSIS/DSIM DPHYs
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <s.nawrocki@samsung.com>
+ *
+ * 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 <s.nawrocki@samsung.com>");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 09/15] phy: Add driver for Exynos MIPI CSIS/DSIM DPHYs
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <s.nawrocki@samsung.com>
+ *
+ * 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 <s.nawrocki@samsung.com>");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 10/15] video: exynos_mipi_dsim: Use the generic PHY driver
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Donghwa Lee <dh09.lee@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 10/15] video: exynos_mipi_dsim: Use the generic PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Donghwa Lee <dh09.lee@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 10/15] video: exynos_mipi_dsim: Use the generic PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Donghwa Lee <dh09.lee@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 11/15] exynos4-is: Use the generic MIPI CSIS PHY driver
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 11/15] exynos4-is: Use the generic MIPI CSIS PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 11/15] exynos4-is: Use the generic MIPI CSIS PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 12/15] ARM: Samsung: Remove the MIPI PHY setup code
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 12/15] ARM: Samsung: Remove the MIPI PHY setup code
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, balbi-l0cyMroinI0,
kishon-l0cyMroinI0, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ
Cc: grant.likely-QSEj5FYQhm4dnm+yROfE0A, tony-4v6yS6AI5VpBDgjK7y7TUQ,
arnd-r2nGTMty4D4, swarren-DDmLM1+adcrQT0dZR+AlfA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b, balajitk-l0cyMroinI0,
george.cherian-l0cyMroinI0, nsekhar-l0cyMroinI0
From: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
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 <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Kyungmin Park <kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Acked-by: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
Acked-by: Kukjin Kim <kgene.kim-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
Signed-off-by: Kishon Vijay Abraham I <kishon-l0cyMroinI0@public.gmane.org>
---
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);
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 12/15] ARM: Samsung: Remove the MIPI PHY setup code
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 13/15] phy: Add driver for Exynos DP PHY
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Jingoo Han <jg1.han@samsung.com>
Add a PHY provider driver for the Samsung Exynos SoC Display Port PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <jg1.han@samsung.com>
+ *
+ * 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 <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 13/15] phy: Add driver for Exynos DP PHY
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Jingoo Han <jg1.han@samsung.com>
Add a PHY provider driver for the Samsung Exynos SoC Display Port PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <jg1.han@samsung.com>
+ *
+ * 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 <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 13/15] phy: Add driver for Exynos DP PHY
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Jingoo Han <jg1.han@samsung.com>
Add a PHY provider driver for the Samsung Exynos SoC Display Port PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <jg1.han@samsung.com>
+ *
+ * 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 <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 14/15] video: exynos_dp: remove non-DT support for Exynos Display Port
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Jingoo Han <jg1.han@samsung.com>
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 <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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 <jg1.han@samsung.com>
- *
- * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 14/15] video: exynos_dp: remove non-DT support for Exynos Display Port
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Jingoo Han <jg1.han@samsung.com>
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 <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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 <jg1.han@samsung.com>
- *
- * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 14/15] video: exynos_dp: remove non-DT support for Exynos Display Port
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Jingoo Han <jg1.han@samsung.com>
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 <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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 <jg1.han@samsung.com>
- *
- * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 15/15] video: exynos_dp: Use the generic PHY driver
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
(?)
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Jingoo Han <jg1.han@samsung.com>
Use the generic PHY API to control the DP PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 15/15] video: exynos_dp: Use the generic PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: gregkh, kyungmin.park, balbi, kishon, jg1.han, s.nawrocki, kgene.kim
Cc: grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
From: Jingoo Han <jg1.han@samsung.com>
Use the generic PHY API to control the DP PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 15/15] video: exynos_dp: Use the generic PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:46 UTC (permalink / raw)
To: linux-arm-kernel
From: Jingoo Han <jg1.han@samsung.com>
Use the generic PHY API to control the DP PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 00/15] PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Tested-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
.../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 <kishon@ti.com>
+
+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 <kishon@ti.com>
+L: linux-kernel@vger.kernel.org
+S: Supported
+F: drivers/phy/
+F: include/linux/phy/
+
GENERIC UIO DRIVER FOR PCI DEVICES
M: "Michael S. Tsirkin" <mst@redhat.com>
L: kvm@vger.kernel.org
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 <kishon@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.
+ *
+ * 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 <kishon@ti.com>");
+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 <kishon@ti.com>
+ *
+ * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 03/15] usb: phy: twl4030: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 05/15] ARM: dts: omap: update usb_otg_hs data
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 06/15] usb: musb: omap2430: use the new generic PHY framework
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 07/15] usb: phy: omap-usb2: remove *set_suspend* callback from omap-usb2
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 08/15] usb: phy: twl4030-usb: remove *set_suspend* and *phy_init* ops
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 09/15] phy: Add driver for Exynos MIPI CSIS/DSIM DPHYs
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <s.nawrocki@samsung.com>
+ *
+ * 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 <s.nawrocki@samsung.com>");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 10/15] video: exynos_mipi_dsim: Use the generic PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Donghwa Lee <dh09.lee@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 11/15] exynos4-is: Use the generic MIPI CSIS PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 12/15] ARM: Samsung: Remove the MIPI PHY setup code
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Acked-by: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 13/15] phy: Add driver for Exynos DP PHY
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Jingoo Han <jg1.han@samsung.com>
Add a PHY provider driver for the Samsung Exynos SoC Display Port PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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 <jg1.han@samsung.com>
+ *
+ * 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 <jg1.han@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS SoC DP PHY driver");
+MODULE_LICENSE("GPL v2");
--
1.7.10.4
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 14/15] video: exynos_dp: remove non-DT support for Exynos Display Port
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Jingoo Han <jg1.han@samsung.com>
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 <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
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 <jg1.han@samsung.com>
- *
- * 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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* [PATCH 15/15] video: exynos_dp: Use the generic PHY driver
@ 2013-07-18 6:46 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 6:58 UTC (permalink / raw)
To: linux-arm-kernel
From: Jingoo Han <jg1.han@samsung.com>
Use the generic PHY API to control the DP PHY.
Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
.../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
^ permalink raw reply related [flat|nested] 371+ messages in thread
* Re: [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
@ 2013-07-18 7:02 ` Tony Lindgren
0 siblings, 0 replies; 371+ messages in thread
From: Tony Lindgren @ 2013-07-18 7:02 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: gregkh, kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
* Kishon Vijay Abraham I <kishon@ti.com> [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 <kishon@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> ---
> 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 <tony@atomide.com>
> 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
>
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
@ 2013-07-18 7:02 ` Tony Lindgren
0 siblings, 0 replies; 371+ messages in thread
From: Tony Lindgren @ 2013-07-18 7:02 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, balbi-l0cyMroinI0,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-QSEj5FYQhm4dnm+yROfE0A, arnd-r2nGTMty4D4,
swarren-DDmLM1+adcrQT0dZR+AlfA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b, balajitk-l0cyMroinI0,
george.cherian-l0cyMroinI0, nsekhar-l0cyMroinI0
* Kishon Vijay Abraham I <kishon-l0cyMroinI0@public.gmane.org> [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 <kishon-l0cyMroinI0@public.gmane.org>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
> Acked-by: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
> ---
> 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 <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
> 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
>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
@ 2013-07-18 7:02 ` Tony Lindgren
0 siblings, 0 replies; 371+ messages in thread
From: Tony Lindgren @ 2013-07-18 7:02 UTC (permalink / raw)
To: linux-arm-kernel
* Kishon Vijay Abraham I <kishon@ti.com> [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 <kishon@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> ---
> 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 <tony@atomide.com>
> 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
>
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 04/15] ARM: OMAP: USB: Add phy binding information
@ 2013-07-18 7:02 ` Tony Lindgren
0 siblings, 0 replies; 371+ messages in thread
From: Tony Lindgren @ 2013-07-18 7:02 UTC (permalink / raw)
To: linux-arm-kernel
* Kishon Vijay Abraham I <kishon@ti.com> [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 <kishon@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> ---
> 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 <tony@atomide.com>
> 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
>
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 05/15] ARM: dts: omap: update usb_otg_hs data
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
@ 2013-07-18 7:05 ` Tony Lindgren
-1 siblings, 0 replies; 371+ messages in thread
From: Tony Lindgren @ 2013-07-18 7:05 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: gregkh, kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
* Kishon Vijay Abraham I <kishon@ti.com> [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 <kishon@ti.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <tony@atomide.com>
> ---
> 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
>
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 05/15] ARM: dts: omap: update usb_otg_hs data
@ 2013-07-18 7:05 ` Tony Lindgren
0 siblings, 0 replies; 371+ messages in thread
From: Tony Lindgren @ 2013-07-18 7:05 UTC (permalink / raw)
To: linux-arm-kernel
* Kishon Vijay Abraham I <kishon@ti.com> [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 <kishon@ti.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <tony@atomide.com>
> ---
> 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
>
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 05/15] ARM: dts: omap: update usb_otg_hs data
@ 2013-07-18 7:05 ` Tony Lindgren
0 siblings, 0 replies; 371+ messages in thread
From: Tony Lindgren @ 2013-07-18 7:05 UTC (permalink / raw)
To: linux-arm-kernel
* Kishon Vijay Abraham I <kishon@ti.com> [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 <kishon@ti.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
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 <tony@atomide.com>
> ---
> 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 at 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 at 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 at 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
>
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
@ 2013-07-18 7:20 ` Greg KH
-1 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 7:20 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 7:20 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 7:20 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 7:20 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 7:20 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
2013-07-18 6:46 ` Kishon Vijay Abraham I
(?)
@ 2013-07-18 7:21 ` Greg KH
-1 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 7:21 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> ---
> 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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 7:21 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 7:21 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> ---
> 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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 7:21 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 7:21 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> ---
> 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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 8:59 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 8:59 UTC (permalink / raw)
To: Greg KH
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 8:59 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 8:59 UTC (permalink / raw)
To: Greg KH
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, nsekhar-l0cyMroinI0,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, swarren-DDmLM1+adcrQT0dZR+AlfA,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
linux-media-u79uwXL29TY76Z2rM5mHXA, george.cherian-l0cyMroinI0,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
balajitk-l0cyMroinI0, linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 8:59 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 8:59 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 9:00 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 9:00 UTC (permalink / raw)
To: Greg KH
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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 <kishon@ti.com>
>> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
>> Acked-by: Felipe Balbi <balbi@ti.com>
>> ---
>> 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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 9:00 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 9:00 UTC (permalink / raw)
To: Greg KH
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, nsekhar-l0cyMroinI0,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, swarren-DDmLM1+adcrQT0dZR+AlfA,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
linux-media-u79uwXL29TY76Z2rM5mHXA, george.cherian-l0cyMroinI0,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
balajitk-l0cyMroinI0, linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
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 <kishon-l0cyMroinI0@public.gmane.org>
>> Reviewed-by: Sylwester Nawrocki <s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>> Acked-by: Felipe Balbi <balbi-l0cyMroinI0@public.gmane.org>
>> ---
>> 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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 9:00 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 9:00 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
>> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
>> Acked-by: Felipe Balbi <balbi@ti.com>
>> ---
>> 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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 8:59 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 9:11 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 02/15] usb: phy: omap-usb2: use the new generic PHY framework
@ 2013-07-18 9:00 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-18 9:12 UTC (permalink / raw)
To: linux-arm-kernel
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 <kishon@ti.com>
>> Reviewed-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
>> Acked-by: Felipe Balbi <balbi@ti.com>
>> ---
>> 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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-18 8:59 ` Kishon Vijay Abraham I
(?)
@ 2013-07-18 15:49 ` Greg KH
-1 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 15:49 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 15:49 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 15:49 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-18 15:49 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-18 15:49 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-18 15:49 ` Greg KH
(?)
(?)
@ 2013-07-19 5:37 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:37 UTC (permalink / raw)
To: Greg KH
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:37 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:37 UTC (permalink / raw)
To: Greg KH
Cc: linux-fbdev, linux-doc, tony, nsekhar, s.nawrocki, kgene.kim,
swarren, jg1.han, grant.likely, linux-media, george.cherian,
arnd, devicetree-discuss, linux-samsung-soc, linux-omap,
linux-arm-kernel, balajitk, linux-usb, linux-kernel, balbi,
kyungmin.park, akpm
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:37 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:37 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-19 5:37 ` Kishon Vijay Abraham I
(?)
@ 2013-07-19 5:43 ` Greg KH
-1 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 5:43 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:43 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 5:43 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:43 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 5:43 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:37 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:49 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-19 5:43 ` Greg KH
(?)
(?)
@ 2013-07-19 5:55 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:55 UTC (permalink / raw)
To: Greg KH
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:55 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:55 UTC (permalink / raw)
To: Greg KH
Cc: linux-fbdev, linux-doc, tony, nsekhar, s.nawrocki, kgene.kim,
swarren, jg1.han, grant.likely, linux-media, george.cherian,
arnd, devicetree-discuss, linux-samsung-soc, linux-omap,
linux-arm-kernel, balajitk, linux-usb, linux-kernel, balbi,
kyungmin.park, akpm
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:55 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:55 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 5:55 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 5:56 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 6:29 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 6:29 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 6:29 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 6:29 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, balbi-l0cyMroinI0,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-QSEj5FYQhm4dnm+yROfE0A, tony-4v6yS6AI5VpBDgjK7y7TUQ,
arnd-r2nGTMty4D4, swarren-DDmLM1+adcrQT0dZR+AlfA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b, balajitk-l0cyMroinI0,
george.cherian-l0cyMroinI0, nsekhar-l0cyMroinI0
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
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 6:29 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 6:29 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 6:29 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 6:29 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-19 6:29 ` Greg KH
(?)
(?)
@ 2013-07-19 6:36 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 6:36 UTC (permalink / raw)
To: Greg KH
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 6:36 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 6:36 UTC (permalink / raw)
To: Greg KH
Cc: linux-fbdev, linux-doc, tony, nsekhar, s.nawrocki, kgene.kim,
swarren, jg1.han, grant.likely, linux-media, george.cherian,
arnd, devicetree-discuss, linux-samsung-soc, linux-omap,
linux-arm-kernel, balajitk, linux-usb, linux-kernel, balbi,
kyungmin.park, akpm
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 6:36 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 6:36 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 6:36 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-19 6:48 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-19 6:36 ` Kishon Vijay Abraham I
(?)
@ 2013-07-19 15:54 ` Stephen Warren
-1 siblings, 0 replies; 371+ messages in thread
From: Stephen Warren @ 2013-07-19 15:54 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: Greg KH, linux-fbdev, linux-doc, nsekhar, s.nawrocki, kgene.kim,
swarren, jg1.han, grant.likely, linux-media, george.cherian,
devicetree-discuss, linux-samsung-soc, linux-omap,
linux-arm-kernel, balajitk, linux-usb, linux-kernel, balbi,
kyungmin.park, akpm
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.
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 15:54 ` Stephen Warren
0 siblings, 0 replies; 371+ messages in thread
From: Stephen Warren @ 2013-07-19 15:54 UTC (permalink / raw)
To: linux-arm-kernel
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.
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 15:54 ` Stephen Warren
0 siblings, 0 replies; 371+ messages in thread
From: Stephen Warren @ 2013-07-19 15:54 UTC (permalink / raw)
To: linux-arm-kernel
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.
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-19 6:36 ` Kishon Vijay Abraham I
(?)
@ 2013-07-19 23:50 ` Greg KH
-1 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 23:50 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 23:50 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 23:50 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-19 23:50 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-19 23:50 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 3:15 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:15 UTC (permalink / raw)
To: Stephen Warren
Cc: Greg KH, linux-fbdev, linux-doc, nsekhar, s.nawrocki, kgene.kim,
swarren, jg1.han, grant.likely, linux-media, george.cherian,
devicetree-discuss, linux-samsung-soc, linux-omap,
linux-arm-kernel, balajitk, linux-usb, linux-kernel, balbi,
kyungmin.park, akpm
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 3:15 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:15 UTC (permalink / raw)
To: Stephen Warren
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, swarren-DDmLM1+adcrQT0dZR+AlfA,
balajitk-l0cyMroinI0, linux-doc-u79uwXL29TY76Z2rM5mHXA, Greg KH,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ, nsekhar-l0cyMroinI0,
george.cherian-l0cyMroinI0, balbi-l0cyMroinI0,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-media-u79uwXL29TY76Z2rM5mHXA
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 3:15 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:15 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-19 23:50 ` Greg KH
(?)
(?)
@ 2013-07-20 3:19 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:19 UTC (permalink / raw)
To: Greg KH
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 3:19 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:19 UTC (permalink / raw)
To: Greg KH
Cc: linux-fbdev, linux-doc, tony, nsekhar, s.nawrocki, kgene.kim,
swarren, jg1.han, grant.likely, linux-media, george.cherian,
arnd, devicetree-discuss, linux-samsung-soc, linux-omap,
linux-arm-kernel, balajitk, linux-usb, linux-kernel, balbi,
kyungmin.park, akpm
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 3:19 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:19 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 3:15 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:27 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 3:19 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-20 3:31 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 22:00 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-20 22:00 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: kyungmin.park, balbi, jg1.han, s.nawrocki, kgene.kim,
grant.likely, tony, arnd, swarren, devicetree-discuss, linux-doc,
linux-kernel, linux-arm-kernel, linux-samsung-soc, linux-omap,
linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 22:00 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-20 22:00 UTC (permalink / raw)
To: Kishon Vijay Abraham I
Cc: linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
linux-doc-u79uwXL29TY76Z2rM5mHXA, nsekhar-l0cyMroinI0,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ, swarren-DDmLM1+adcrQT0dZR+AlfA,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-QSEj5FYQhm4dnm+yROfE0A,
linux-media-u79uwXL29TY76Z2rM5mHXA, george.cherian-l0cyMroinI0,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
balajitk-l0cyMroinI0, linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, balbi-l0cyMroinI0,
kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 22:00 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-20 22:00 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-20 22:00 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-20 22:00 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 2:32 ` Alan Stern
0 siblings, 0 replies; 371+ messages in thread
From: Alan Stern @ 2013-07-21 2:32 UTC (permalink / raw)
To: Greg KH
Cc: Kishon Vijay Abraham I, kyungmin.park, balbi, jg1.han,
s.nawrocki, kgene.kim, grant.likely, tony, arnd, swarren,
devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
linux-samsung-soc, linux-omap, linux-usb, linux-media,
linux-fbdev, akpm, balajitk, george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 2:32 ` Alan Stern
0 siblings, 0 replies; 371+ messages in thread
From: Alan Stern @ 2013-07-21 2:32 UTC (permalink / raw)
To: Greg KH
Cc: Kishon Vijay Abraham I, kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
balbi-l0cyMroinI0, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
kgene.kim-Sze3O3UU22JBDgjK7y7TUQ,
grant.likely-QSEj5FYQhm4dnm+yROfE0A, tony-4v6yS6AI5VpBDgjK7y7TUQ,
arnd-r2nGTMty4D4, swarren-DDmLM1+adcrQT0dZR+AlfA,
devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
linux-doc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-omap-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-fbdev-u79uwXL29TY76Z2rM5mHXA,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b, balajitk-l0cyMroinI0,
george.cherian-l0cyMroinI0, nsekhar-l0cyMroinI0
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
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 2:32 ` Alan Stern
0 siblings, 0 replies; 371+ messages in thread
From: Alan Stern @ 2013-07-21 2:32 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 2:32 ` Alan Stern
0 siblings, 0 replies; 371+ messages in thread
From: Alan Stern @ 2013-07-21 2:32 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-21 2:32 ` Alan Stern
(?)
@ 2013-07-21 2:59 ` Greg KH
-1 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-21 2:59 UTC (permalink / raw)
To: Alan Stern
Cc: Kishon Vijay Abraham I, kyungmin.park, balbi, jg1.han,
s.nawrocki, kgene.kim, grant.likely, tony, arnd, swarren,
devicetree-discuss, linux-doc, linux-kernel, linux-arm-kernel,
linux-samsung-soc, linux-omap, linux-usb, linux-media,
linux-fbdev, akpm, balajitk, george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 2:59 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-21 2:59 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 2:59 ` Greg KH
0 siblings, 0 replies; 371+ messages in thread
From: Greg KH @ 2013-07-21 2:59 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-21 2:59 ` Greg KH
(?)
@ 2013-07-21 10:22 ` Sascha Hauer
-1 siblings, 0 replies; 371+ messages in thread
From: Sascha Hauer @ 2013-07-21 10:22 UTC (permalink / raw)
To: Greg KH
Cc: Alan Stern, Kishon Vijay Abraham I, kyungmin.park, balbi,
jg1.han, s.nawrocki, kgene.kim, grant.likely, tony, arnd,
swarren, devicetree-discuss, linux-doc, linux-kernel,
linux-arm-kernel, linux-samsung-soc, linux-omap, linux-usb,
linux-media, linux-fbdev, akpm, balajitk, george.cherian,
nsekhar
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 |
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 10:22 ` Sascha Hauer
0 siblings, 0 replies; 371+ messages in thread
From: Sascha Hauer @ 2013-07-21 10:22 UTC (permalink / raw)
To: linux-arm-kernel
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 |
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 10:22 ` Sascha Hauer
0 siblings, 0 replies; 371+ messages in thread
From: Sascha Hauer @ 2013-07-21 10:22 UTC (permalink / raw)
To: linux-arm-kernel
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 |
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-21 2:59 ` Greg KH
(?)
@ 2013-07-21 10:31 ` Tomasz Figa
-1 siblings, 0 replies; 371+ messages in thread
From: Tomasz Figa @ 2013-07-21 10:31 UTC (permalink / raw)
To: Greg KH
Cc: Alan Stern, Kishon Vijay Abraham I, kyungmin.park, balbi,
jg1.han, s.nawrocki, kgene.kim, grant.likely, tony, arnd,
swarren, devicetree-discuss, linux-doc, linux-kernel,
linux-arm-kernel, linux-samsung-soc, linux-omap, linux-usb,
linux-media, linux-fbdev, akpm, balajitk, george.cherian,
nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 10:31 ` Tomasz Figa
0 siblings, 0 replies; 371+ messages in thread
From: Tomasz Figa @ 2013-07-21 10:31 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 10:31 ` Tomasz Figa
0 siblings, 0 replies; 371+ messages in thread
From: Tomasz Figa @ 2013-07-21 10:31 UTC (permalink / raw)
To: linux-arm-kernel
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
2013-07-21 10:31 ` Tomasz Figa
(?)
(?)
@ 2013-07-21 11:07 ` Kishon Vijay Abraham I
-1 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-21 11:07 UTC (permalink / raw)
To: Tomasz Figa
Cc: Greg KH, Alan Stern, kyungmin.park, balbi, jg1.han, s.nawrocki,
kgene.kim, grant.likely, tony, arnd, swarren, devicetree-discuss,
linux-doc, linux-kernel, linux-arm-kernel, linux-samsung-soc,
linux-omap, linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* Re: [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 11:07 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-21 11:07 UTC (permalink / raw)
To: Tomasz Figa
Cc: Greg KH, Alan Stern, kyungmin.park, balbi, jg1.han, s.nawrocki,
kgene.kim, grant.likely, tony, arnd, swarren, devicetree-discuss,
linux-doc, linux-kernel, linux-arm-kernel, linux-samsung-soc,
linux-omap, linux-usb, linux-media, linux-fbdev, akpm, balajitk,
george.cherian, nsekhar
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
^ permalink raw reply [flat|nested] 371+ messages in thread
* [PATCH 01/15] drivers: phy: add generic PHY framework
@ 2013-07-21 11:07 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 371+ messages in thread
From: Kishon Vijay Abraham I @ 2013-07-21 11:07 UTC (permalink / raw)
To: linux-arm-kernel
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:
>>>>>&g