* [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver
@ 2014-03-05 15:28 Kamil Debski
2014-03-05 15:28 ` [PATCH v9 1/4] phy: core: Add an exported of_phy_get function Kamil Debski
` (4 more replies)
0 siblings, 5 replies; 20+ messages in thread
From: Kamil Debski @ 2014-03-05 15:28 UTC (permalink / raw)
To: linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, k.debski, tjakobi, stern, sander
Hi,
This is the ninth version of this patchset. First and most significant change
since v6 is that this patchset includes only patches touching the Generic PHY
Framework. Patches to the USB controllers were stripped as they require
additional work. S5PV210 support is also omitted - it requires more testing.
Since v7 this patch includes fixes for checkpath errors and was rebased onto
Kishon's next branch. v9 brings whitespace corrections compared to v8.
Best wishes,
Kamil Debski
--------------
Changes from v8:
1) phy: core: Add an exported of_phy_get function
- No changes since v8.
2) phy: core: Add devm_of_phy_get to phy-core
- No changes since v8.
3) phy: Add new Exynos USB 2.0 PHY driver
- Fix empty blank line at EOF errors
4) phy: Add Exynos 5250 support to the Exynos USB 2.0 PHY
- Fix empty blank line at EOF error
--------------
Changes from v7:
1) phy: core: Add an exported of_phy_get function
- No changes since v7.
2) phy: core: Add devm_of_phy_get to phy-core
- No changes since v7.
3) phy: Add new Exynos USB 2.0 PHY driver
- Fix checkpatch errors with code indentation and corrected whitespace.
4) phy: Add Exynos 5250 support to the Exynos USB 2.0 PHY
- Fix checkpatch errors with code indentation and corrected whitespace.
--------------
Changes from v6: (not including the change that controller patches were removed
form this patchset, also this patchset excludes S5PV210 support - it needs more
testing)
1) phy: core: Add an exported of_phy_get function
- No changes since v6.
2) phy: core: Add devm_of_phy_get to phy-core
- No changes since v6.
3) phy: Add new Exynos USB 2.0 PHY driver
- Changed the way clocks are supplied to the driver. Prior to version v7
there were reference clocks for every phy instance, now a single "ref"
clock was introduced.
- Updated documentation to match the aforementioned change.
- Add offset EXYNOS_*_UPHYCLK_PHYFSEL_OFFSET to the clock register content
defines.
- Corrected way clock register is modified. Instead of a simple write, a
proper read, modify, write sequence was introduced.
- Important stability fix - added udelay after PHY reset. This fixes a bug
causing instability in USB LAN adapters. Without the delay the DMA burst
mode was could not be enabled.
4) phy: Add Exynos 5250 support to the Exynos USB 2.0 PHY
- Changed handling of clocks to use a single "ref" clock.
----------------
Changes from v5:
1) phy: core: Add an exported of_phy_get function
- corrected behaviour of the modification when GENERIC_PHY is not enabled
by adding a stub of the of_phy_get function
2) phy: core: Add devm_of_phy_get to phy-core
- corrected behaviour of the modification when GENERIC_PHY is not enabled
by adding a stub of the devm_of_phy_get function
3) dts: Add usb2phy to Exynos 4
- no change
4) dts: Add usb2phy to Exynos 5250
- in the previous version, this patch included some phy-exynos5250-usb2.c code
by mistake, the code has been remove and added to the proper patch
5) phy: Add new Exynos USB PHY driver
- changed strings from Exynos 4212 to Exynos 4x12, as the Exynos 4212 driver is
actually a driver for the whole Exynos 4x12 family
- added documentation to the Exynos USB 2.0 PHY driver adaptaion layer
- corrected strings HSCI -> HSIC
- fixed a problem introduced by previous change - on Exynos 4x12 the HSIC did
not work on its own
- mode switch support was added to Exynos 4x12 (same io pins are used by host
and device)
- support for phy_set_bus_width introduced by Matt Porter was added
6) phy: Add support for S5PV210 to the Exynos USB PHY
- setting of clk register was fixed
7) phy: Add Exynos 5250 support to the Exynos USB 2.0 PHY
- supoprt was added for HSIC and device
8) usb: ehci-exynos: Change to use phy provided by the generic phy framework
- DT documentation was moved from usb-ehci.txt to exynos-usb.txt
----------------
Changes from v4:
1) phy: core: Add an exported of_phy_get function
- the new exported function of_phy_get was changed to take the phy's name as a
parameter instead of the index
2) phy: core: Add devm_of_phy_get to phy-core
- fixes made in the comments to devm_of_phy_get
3) phy: Add new Exynos USB PHY driver
- move the documentation from a new to an existing file - samsung-phy.txt
- fix typos and uppercase hex addresses
- add more explanations to Kconfig (checkpatch still complains, but I find it
hard to think what else could I add)
- add selects MFD_SYSCON as the driver needs it (Thank you, Tobias!)
- cleanup included headers in both *.c and .h files
- use BIT(x) macro instead of (1 << x)
- replaced HOST and DEV with PHY0 and PHY1 in phy-exynos4212-usb2.c, the
registers are described as PHYx in the documentation hence the decision to
leave the PHYx naming
- fixed typo in exynos4210_rate_to_clk reg -> *reg
- change hax_mode_switch and enabled type to bool
4) usb: ehci-s5p: Change to use phy provided by the generic phy framework
- Put the issue of phy->otg in order - since the new phy driver does not provide
this field. With the new driver the switch between host and device is done in
power_on of the respective host and device phys.
5) usb: s3c-hsotg: Use the new Exynos USB phy driver with the generic phy
framework
- fixed the example in the documentation
6) phy: Add support for S5PV210 to the Exynos USB PHY driver
- include files cleanup
- use BIT(x) macro instead of (1 << x)
7) phy: Add Exynos 5250 support to the Exynos USB 2.0 PHY driver
- include files cleanup
- use BIT(x) macro instead of (1 << x)
8) dts: Add usb2phy to Exynos 4
- no changes
9) dts: Add usb2phy to Exynos 5250
- no changes
----------------
Changes from v3:
- using PMU and system registers indirectly via syscon
- change labelling
- change Kconfig name
- fixed typos/stray whitespace
- move of_phy_provider_register() to the end of probe
- add a regular error return code to the rate_to_clk functions
- cleanup code and remove unused code
- change struct names to avoid collisions
- add mechanism to support multiple phys by the ehci driver
----------------
Changes from v2:
- rebase all patches to the usb-next branch
- fixes in the documentation file
- remove wrong entries in the phy node (ranges, and #address- & #size-cells)
- add clocks and clock-names as required properites
- rephrase a few sentences
- fixes in the ehci-exynos.c file
- move phy_name variable next to phy in exynos_ehci_hcd
- remove otg from exynos_ehci_hcd as it was no longer used
- move devm_phy_get after the Exynos5440 skip_phy check
- fixes in the s3c-hsotg.c file
- cosmetic fixes (remove empty line that was wrongfully added)
- fixes in the main driver
- remove cpu_type in favour for a boolean flag matched with the compatible
value
- rename files, structures, variables and Kconfig entires - change from simple
"uphy" to "usb2_phy"
- fix multiline comments style
- simplify #ifdefs in of_device_id
- fix Kconfig description
- change dev_info to dev_dbg where reasonable
- cosmetic changes (remove wrongful blank lines)
- remove unnecessary reference counting
----------------
Changes from v1:
- the changes include minor fixes of the hardware initialization of the PHY
module
- some other minor fixes were introduced
----------------------
Original cover letter:
Hi,
This patch adds a new drive for USB PHYs for Samsung SoCs. The driver is
using the Generic PHY Framework created by Kishon Vijay Abrahan I. It
can be found here https://lkml.org/lkml/2013/8/21/29. This patch adds
support to Exynos4 family of SoCs. Support for Exynos3 and Exynos5 is
planned to be added in the near future.
I welcome your comments.
----------------------
Kamil Debski (4):
phy: core: Add an exported of_phy_get function
phy: core: Add devm_of_phy_get to phy-core
phy: Add new Exynos USB 2.0 PHY driver
phy: Add Exynos 5250 support to the Exynos USB 2.0 PHY driver
.../devicetree/bindings/phy/samsung-phy.txt | 54 +++
Documentation/phy/samsung-usb2.txt | 134 +++++++
drivers/phy/Kconfig | 40 ++
drivers/phy/Makefile | 4 +
drivers/phy/phy-core.c | 76 +++-
drivers/phy/phy-exynos4210-usb2.c | 261 +++++++++++++
drivers/phy/phy-exynos4x12-usb2.c | 328 ++++++++++++++++
drivers/phy/phy-exynos5250-usb2.c | 404 ++++++++++++++++++++
drivers/phy/phy-samsung-usb2.c | 228 +++++++++++
drivers/phy/phy-samsung-usb2.h | 67 ++++
include/linux/phy/phy.h | 14 +
11 files changed, 1601 insertions(+), 9 deletions(-)
create mode 100644 Documentation/phy/samsung-usb2.txt
create mode 100644 drivers/phy/phy-exynos4210-usb2.c
create mode 100644 drivers/phy/phy-exynos4x12-usb2.c
create mode 100644 drivers/phy/phy-exynos5250-usb2.c
create mode 100644 drivers/phy/phy-samsung-usb2.c
create mode 100644 drivers/phy/phy-samsung-usb2.h
--
1.7.9.5
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v9 1/4] phy: core: Add an exported of_phy_get function
2014-03-05 15:28 [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
@ 2014-03-05 15:28 ` Kamil Debski
2014-03-05 16:03 ` Tomasz Figa
2014-03-05 15:28 ` [PATCH v9 2/4] phy: core: Add devm_of_phy_get to phy-core Kamil Debski
` (3 subsequent siblings)
4 siblings, 1 reply; 20+ messages in thread
From: Kamil Debski @ 2014-03-05 15:28 UTC (permalink / raw)
To: linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, k.debski, tjakobi, stern, sander
Previously the of_phy_get function took a struct device * and
was declared static. It was impossible to call it from
another driver and thus it was impossible to get phy defined
for a given node. The old function was renamed to _of_phy_get
and was left for internal use. of_phy_get function was added
and it was exported. The function enables to get a phy for
a given device tree node.
Signed-off-by: Kamil Debski <k.debski@samsung.com>
---
drivers/phy/phy-core.c | 45 ++++++++++++++++++++++++++++++++++++---------
include/linux/phy/phy.h | 6 ++++++
2 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 6c73837..7c1b0e1 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -274,8 +274,8 @@ int phy_power_off(struct phy *phy)
EXPORT_SYMBOL_GPL(phy_power_off);
/**
- * of_phy_get() - lookup and obtain a reference to a phy by phandle
- * @dev: device that requests this phy
+ * _of_phy_get() - lookup and obtain a reference to a phy by phandle
+ * @np: device_node for which to get the phy
* @index: the index of the phy
*
* Returns the phy associated with the given phandle value,
@@ -284,20 +284,17 @@ EXPORT_SYMBOL_GPL(phy_power_off);
* 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)
+static struct phy *_of_phy_get(struct device_node *np, 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",
+ ret = of_parse_phandle_with_args(np, "phys", "#phy-cells",
index, &args);
- if (ret) {
- dev_dbg(dev, "failed to get phy in %s node\n",
- dev->of_node->full_name);
+ if (ret)
return ERR_PTR(-ENODEV);
- }
mutex_lock(&phy_provider_mutex);
phy_provider = of_phy_provider_lookup(args.np);
@@ -317,6 +314,36 @@ err0:
}
/**
+ * of_phy_get() - lookup and obtain a reference to a phy using a device_node.
+ * @np: device_node for which to get the phy
+ * @con_id: name of the phy from device's point of view
+ *
+ * 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 *of_phy_get(struct device_node *np, const char *con_id)
+{
+ struct phy *phy = NULL;
+ int index = 0;
+
+ if (con_id)
+ index = of_property_match_string(np, "phy-names", con_id);
+
+ phy = _of_phy_get(np, index);
+ if (IS_ERR(phy))
+ return phy;
+
+ if (!try_module_get(phy->ops->owner))
+ return ERR_PTR(-EPROBE_DEFER);
+
+ get_device(&phy->dev);
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(of_phy_get);
+
+/**
* phy_put() - release the PHY
* @phy: the phy returned by phy_get()
*
@@ -407,7 +434,7 @@ struct phy *phy_get(struct device *dev, const char *string)
if (dev->of_node) {
index = of_property_match_string(dev->of_node, "phy-names",
string);
- phy = of_phy_get(dev, index);
+ phy = _of_phy_get(dev->of_node, index);
} else {
phy = phy_lookup(dev, string);
}
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 3f83459..2fe3194 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -151,6 +151,7 @@ struct phy *devm_phy_get(struct device *dev, const char *string);
struct phy *devm_phy_optional_get(struct device *dev, const char *string);
void phy_put(struct phy *phy);
void devm_phy_put(struct device *dev, struct phy *phy);
+struct phy *of_phy_get(struct device_node *np, const char *con_id);
struct phy *of_phy_simple_xlate(struct device *dev,
struct of_phandle_args *args);
struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
@@ -259,6 +260,11 @@ static inline void devm_phy_put(struct device *dev, struct phy *phy)
{
}
+struct phy *of_phy_get(struct device_node *np, const char *con_id)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
static inline struct phy *of_phy_simple_xlate(struct device *dev,
struct of_phandle_args *args)
{
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v9 2/4] phy: core: Add devm_of_phy_get to phy-core
2014-03-05 15:28 [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
2014-03-05 15:28 ` [PATCH v9 1/4] phy: core: Add an exported of_phy_get function Kamil Debski
@ 2014-03-05 15:28 ` Kamil Debski
2014-03-05 16:04 ` Tomasz Figa
2014-03-05 15:28 ` [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
` (2 subsequent siblings)
4 siblings, 1 reply; 20+ messages in thread
From: Kamil Debski @ 2014-03-05 15:28 UTC (permalink / raw)
To: linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, k.debski, tjakobi, stern, sander
Adding devm_of_phy_get will allow to get phys by supplying a
pointer to the struct device_node instead of struct device.
Signed-off-by: Kamil Debski <k.debski@samsung.com>
---
drivers/phy/phy-core.c | 31 +++++++++++++++++++++++++++++++
include/linux/phy/phy.h | 8 ++++++++
2 files changed, 39 insertions(+)
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 7c1b0e1..623b71c 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -526,6 +526,37 @@ struct phy *devm_phy_optional_get(struct device *dev, const char *string)
EXPORT_SYMBOL_GPL(devm_phy_optional_get);
/**
+ * devm_of_phy_get() - lookup and obtain a reference to a phy.
+ * @dev: device that requests this phy
+ * @np: node containing the phy
+ * @con_id: name of the phy from device's point of view
+ *
+ * Gets the phy using of_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_of_phy_get(struct device *dev, struct device_node *np,
+ const char *con_id)
+{
+ struct phy **ptr, *phy;
+
+ ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return ERR_PTR(-ENOMEM);
+
+ phy = of_phy_get(np, con_id);
+ if (!IS_ERR(phy)) {
+ *ptr = phy;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
+
+ return phy;
+}
+EXPORT_SYMBOL_GPL(devm_of_phy_get);
+
+/**
* phy_create() - create a new phy
* @dev: device that is creating the new phy
* @ops: function pointers for performing phy operations
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 2fe3194..bcbf96c 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -149,6 +149,8 @@ struct phy *phy_get(struct device *dev, const char *string);
struct phy *phy_optional_get(struct device *dev, const char *string);
struct phy *devm_phy_get(struct device *dev, const char *string);
struct phy *devm_phy_optional_get(struct device *dev, const char *string);
+struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
+ const char *con_id);
void phy_put(struct phy *phy);
void devm_phy_put(struct device *dev, struct phy *phy);
struct phy *of_phy_get(struct device_node *np, const char *con_id);
@@ -252,6 +254,12 @@ static inline struct phy *devm_phy_optional_get(struct device *dev,
return ERR_PTR(-ENOSYS);
}
+struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
+ const char *con_id)
+{
+ return ERR_PTR(-ENOSYS);
+}
+
static inline void phy_put(struct phy *phy)
{
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-05 15:28 [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
2014-03-05 15:28 ` [PATCH v9 1/4] phy: core: Add an exported of_phy_get function Kamil Debski
2014-03-05 15:28 ` [PATCH v9 2/4] phy: core: Add devm_of_phy_get to phy-core Kamil Debski
@ 2014-03-05 15:28 ` Kamil Debski
2014-03-05 16:04 ` Tomasz Figa
2014-03-06 8:26 ` Anton Tikhomirov
2014-03-05 15:28 ` [PATCH v9 4/4] phy: Add Exynos 5250 support to the " Kamil Debski
[not found] ` <1394033288-5551-1-git-send-email-k.debski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
4 siblings, 2 replies; 20+ messages in thread
From: Kamil Debski @ 2014-03-05 15:28 UTC (permalink / raw)
To: linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, k.debski, tjakobi, stern, sander
Add a new driver for the Exynos USB 2.0 PHY. The new driver uses the generic
PHY framework. The driver includes support for the Exynos 4x10 and 4x12
SoC families.
Signed-off-by: Kamil Debski <k.debski@samsung.com>
---
.../devicetree/bindings/phy/samsung-phy.txt | 53 ++++
Documentation/phy/samsung-usb2.txt | 134 ++++++++
drivers/phy/Kconfig | 29 ++
drivers/phy/Makefile | 3 +
drivers/phy/phy-exynos4210-usb2.c | 261 ++++++++++++++++
drivers/phy/phy-exynos4x12-usb2.c | 328 ++++++++++++++++++++
drivers/phy/phy-samsung-usb2.c | 222 +++++++++++++
drivers/phy/phy-samsung-usb2.h | 66 ++++
8 files changed, 1096 insertions(+)
create mode 100644 Documentation/phy/samsung-usb2.txt
create mode 100644 drivers/phy/phy-exynos4210-usb2.c
create mode 100644 drivers/phy/phy-exynos4x12-usb2.c
create mode 100644 drivers/phy/phy-samsung-usb2.c
create mode 100644 drivers/phy/phy-samsung-usb2.h
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index c0fccaa..bf955ab 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -20,3 +20,56 @@ 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;
+
+Samsung S5P/EXYNOS SoC series USB PHY
+-------------------------------------------------
+
+Required properties:
+- compatible : should be one of the listed compatibles:
+ - "samsung,exynos4210-usb2-phy"
+ - "samsung,exynos4x12-usb2-phy"
+- reg : a list of registers used by phy driver
+ - first and obligatory is the location of phy modules registers
+- samsung,sysreg-phandle - handle to syscon used to control the system registers
+- samsung,pmureg-phandle - handle to syscon used to control PMU registers
+- #phy-cells : from the generic phy bindings, must be 1;
+- clocks and clock-names:
+ - the "phy" clock is required by the phy module, used as a gate
+ - the "ref" clock is used to get the rate of the clock provided to the
+ PHY module
+
+The first phandle argument in the PHY specifier identifies the PHY, its
+meaning is compatible dependent. For the currently supported SoCs (Exynos 4210
+and Exynos 4212) it is as follows:
+ 0 - USB device ("device"),
+ 1 - USB host ("host"),
+ 2 - HSIC0 ("hsic0"),
+ 3 - HSIC1 ("hsic1"),
+
+Exynos 4210 and Exynos 4212 use mode switching and require that mode switch
+register is supplied.
+
+Example:
+
+For Exynos 4412 (compatible with Exynos 4212):
+
+usbphy: phy@125b0000 {
+ compatible = "samsung,exynos4x12-usb2-phy";
+ reg = <0x125b0000 0x100>;
+ clocks = <&clock 305>, <&clock 2>;
+ clock-names = "phy", "ref";
+ status = "okay";
+ #phy-cells = <1>;
+ samsung,sysreg-phandle = <&sys_reg>;
+ samsung,pmureg-phandle = <&pmu_reg>;
+};
+
+Then the PHY can be used in other nodes such as:
+
+phy-consumer@12340000 {
+ phys = <&usbphy 2>;
+ phy-names = "phy";
+};
+
+Refer to DT bindings documentation of particular PHY consumer devices for more
+information about required PHYs and the way of specification.
diff --git a/Documentation/phy/samsung-usb2.txt b/Documentation/phy/samsung-usb2.txt
new file mode 100644
index 0000000..0c8e260
--- /dev/null
+++ b/Documentation/phy/samsung-usb2.txt
@@ -0,0 +1,134 @@
+.------------------------------------------------------------------------------+
+| Samsung USB 2.0 PHY adaptation layer |
++-----------------------------------------------------------------------------+'
+
+| 1. Description
++----------------
+
+The architecture of the USB 2.0 PHY module in Samsung SoCs is similar
+among many SoCs. In spite of the similarities it proved difficult to
+create a one driver that would fit all these PHY controllers. Often
+the differences were minor and were found in particular bits of the
+registers of the PHY. In some rare cases the order of register writes or
+the PHY powering up process had to be altered. This adaptation layer is
+a compromise between having separate drivers and having a single driver
+with added support for many special cases.
+
+| 2. Files description
++----------------------
+
+- phy-samsung-usb2.c
+ This is the main file of the adaptation layer. This file contains
+ the probe function and provides two callbacks to the Generic PHY
+ Framework. This two callbacks are used to power on and power off the
+ phy. They carry out the common work that has to be done on all version
+ of the PHY module. Depending on which SoC was chosen they execute SoC
+ specific callbacks. The specific SoC version is selected by choosing
+ the appropriate compatible string. In addition, this file contains
+ struct of_device_id definitions for particular SoCs.
+
+- phy-samsung-usb2.h
+ This is the include file. It declares the structures used by this
+ driver. In addition it should contain extern declarations for
+ structures that describe particular SoCs.
+
+| 3. Supporting SoCs
++--------------------
+
+To support a new SoC a new file should be added to the drivers/phy
+directory. Each SoC's configuration is stored in an instance of the
+struct samsung_usb2_phy_config.
+
+struct samsung_usb2_phy_config {
+ const struct samsung_usb2_common_phy *phys;
+ unsigned int num_phys;
+ bool has_mode_switch;
+};
+
+The num_phys is the number of phys handled by the driver. *phys is an
+array that contains the configuration for each phy. The has_mode_switch
+property is a boolean flag that determines whether the SoC has USB host
+and device on a single pair of pins. If so, a special register has to
+be modified to change the internal routing of these pins between a USB
+device or host module.
+
+For example the configuration for Exynos 4210 is following:
+
+const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = {
+ .has_mode_switch = 0,
+ .num_phys = EXYNOS4210_NUM_PHYS,
+ .phys = exynos4210_phys,
+ .rate_to_clk = exynos4210_rate_to_clk,
+}
+
+- int (*rate_to_clk)(unsigned long, u32 *)
+ The rate_to_clk callback is to convert the rate of the clock
+ used as the reference clock for the PHY module to the value
+ that should be written in the hardware register.
+
+The exynos4210_phys configuration array is as follows:
+
+static const struct samsung_usb2_common_phy exynos4210_phys[] = {
+ {
+ .label = "device",
+ .id = EXYNOS4210_DEVICE,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {
+ .label = "host",
+ .id = EXYNOS4210_HOST,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {
+ .label = "hsic0",
+ .id = EXYNOS4210_HSIC0,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {
+ .label = "hsic1",
+ .id = EXYNOS4210_HSIC1,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {},
+};
+
+- int (*power_on)(struct samsung_usb2_phy_instance *);
+- int (*power_off)(struct samsung_usb2_phy_instance *);
+ These two callbacks are used to power on and power off the phy
+ by modifying appropriate registers.
+
+Final change to the driver is adding appropriate compatible value to the
+phy-samsung-usb2.c file. In case of Exynos 4210 the following lines were
+added to the struct of_device_id samsung_usb2_phy_of_match[] array:
+
+#ifdef CONFIG_PHY_EXYNOS4210_USB2
+ {
+ .compatible = "samsung,exynos4210-usb2-phy",
+ .data = &exynos4210_usb2_phy_config,
+ },
+#endif
+
+To add further flexibility to the driver the Kconfig file enables to
+include support for selected SoCs in the compiled driver. The Kconfig
+entry for Exynos 4210 is following:
+
+config PHY_EXYNOS4210_USB2
+ bool "Support for Exynos 4210"
+ depends on PHY_SAMSUNG_USB2
+ depends on CPU_EXYNOS4210
+ help
+ Enable USB PHY support for Exynos 4210. This option requires that
+ Samsung USB 2.0 PHY driver is enabled and means that support for this
+ particular SoC is compiled in the driver. In case of Exynos 4210 four
+ phys are available - device, host, HSCI0 and HSCI1.
+
+The newly created file that supports the new SoC has to be also added to the
+Makefile. In case of Exynos 4210 the added line is following:
+
+obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
+
+After completing these steps the support for the new SoC should be ready.
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index dc1756c..fc5a44a 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -96,4 +96,33 @@ config PHY_SUN4I_USB
This driver controls the entire USB PHY block, both the USB OTG
parts, as well as the 2 regular USB 2 host PHYs.
+config PHY_SAMSUNG_USB2
+ tristate "Samsung USB 2.0 PHY driver"
+ select GENERIC_PHY
+ select MFD_SYSCON
+ help
+ Enable this to support the Samsung USB 2.0 PHY driver for Samsung
+ SoCs. This driver provides the interface for USB 2.0 PHY. Support for
+ particular SoCs has to be enabled in addition to this driver. Number
+ and type of supported phys depends on the SoC.
+
+config PHY_EXYNOS4210_USB2
+ bool "Support for Exynos 4210"
+ depends on PHY_SAMSUNG_USB2
+ depends on CPU_EXYNOS4210
+ help
+ Enable USB PHY support for Exynos 4210. This option requires that
+ Samsung USB 2.0 PHY driver is enabled and means that support for this
+ particular SoC is compiled in the driver. In case of Exynos 4210 four
+ phys are available - device, host, HSIC0 and HSIC1.
+
+config PHY_EXYNOS4X12_USB2
+ bool "Support for Exynos 4x12"
+ depends on PHY_SAMSUNG_USB2
+ depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412)
+ help
+ Enable USB PHY support for Exynos 4x12. This option requires that
+ Samsung USB 2.0 PHY driver is enabled and means that support for this
+ particular SoC is compiled in the driver. In case of Exynos 4x12 four
+ phys are available - device, host, HSIC0 and HSIC1.
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 5d0b59e..0ea36ff 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -11,3 +11,6 @@ obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o
obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
+obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-samsung-usb2.o
+obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
+obj-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
diff --git a/drivers/phy/phy-exynos4210-usb2.c b/drivers/phy/phy-exynos4210-usb2.c
new file mode 100644
index 0000000..236a52a
--- /dev/null
+++ b/drivers/phy/phy-exynos4210-usb2.c
@@ -0,0 +1,261 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4210 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@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/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define EXYNOS_4210_UPHYPWR 0x0
+
+#define EXYNOS_4210_UPHYPWR_PHY0_SUSPEND BIT(0)
+#define EXYNOS_4210_UPHYPWR_PHY0_PWR BIT(3)
+#define EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR BIT(4)
+#define EXYNOS_4210_UPHYPWR_PHY0_SLEEP BIT(5)
+#define EXYNOS_4210_UPHYPWR_PHY0 ( \
+ EXYNOS_4210_UPHYPWR_PHY0_SUSPEND | \
+ EXYNOS_4210_UPHYPWR_PHY0_PWR | \
+ EXYNOS_4210_UPHYPWR_PHY0_OTG_PWR | \
+ EXYNOS_4210_UPHYPWR_PHY0_SLEEP)
+
+#define EXYNOS_4210_UPHYPWR_PHY1_SUSPEND BIT(6)
+#define EXYNOS_4210_UPHYPWR_PHY1_PWR BIT(7)
+#define EXYNOS_4210_UPHYPWR_PHY1_SLEEP BIT(8)
+#define EXYNOS_4210_UPHYPWR_PHY1 ( \
+ EXYNOS_4210_UPHYPWR_PHY1_SUSPEND | \
+ EXYNOS_4210_UPHYPWR_PHY1_PWR | \
+ EXYNOS_4210_UPHYPWR_PHY1_SLEEP)
+
+#define EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND BIT(9)
+#define EXYNOS_4210_UPHYPWR_HSIC0_SLEEP BIT(10)
+#define EXYNOS_4210_UPHYPWR_HSIC0 ( \
+ EXYNOS_4210_UPHYPWR_HSIC0_SUSPEND | \
+ EXYNOS_4210_UPHYPWR_HSIC0_SLEEP)
+
+#define EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND BIT(11)
+#define EXYNOS_4210_UPHYPWR_HSIC1_SLEEP BIT(12)
+#define EXYNOS_4210_UPHYPWR_HSIC1 ( \
+ EXYNOS_4210_UPHYPWR_HSIC1_SUSPEND | \
+ EXYNOS_4210_UPHYPWR_HSIC1_SLEEP)
+
+/* PHY clock control */
+#define EXYNOS_4210_UPHYCLK 0x4
+
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_MASK (0x3 << 0)
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET 0
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ (0x0 << 0)
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ (0x3 << 0)
+#define EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
+
+#define EXYNOS_4210_UPHYCLK_PHY0_ID_PULLUP BIT(2)
+#define EXYNOS_4210_UPHYCLK_PHY0_COMMON_ON BIT(4)
+#define EXYNOS_4210_UPHYCLK_PHY1_COMMON_ON BIT(7)
+
+/* PHY reset control */
+#define EXYNOS_4210_UPHYRST 0x8
+
+#define EXYNOS_4210_URSTCON_PHY0 BIT(0)
+#define EXYNOS_4210_URSTCON_OTG_HLINK BIT(1)
+#define EXYNOS_4210_URSTCON_OTG_PHYLINK BIT(2)
+#define EXYNOS_4210_URSTCON_PHY1_ALL BIT(3)
+#define EXYNOS_4210_URSTCON_PHY1_P0 BIT(4)
+#define EXYNOS_4210_URSTCON_PHY1_P1P2 BIT(5)
+#define EXYNOS_4210_URSTCON_HOST_LINK_ALL BIT(6)
+#define EXYNOS_4210_URSTCON_HOST_LINK_P0 BIT(7)
+#define EXYNOS_4210_URSTCON_HOST_LINK_P1 BIT(8)
+#define EXYNOS_4210_URSTCON_HOST_LINK_P2 BIT(9)
+
+/* Isolation, configured in the power management unit */
+#define EXYNOS_4210_USB_ISOL_DEVICE_OFFSET 0x704
+#define EXYNOS_4210_USB_ISOL_DEVICE BIT(0)
+#define EXYNOS_4210_USB_ISOL_HOST_OFFSET 0x708
+#define EXYNOS_4210_USB_ISOL_HOST BIT(0)
+
+/* USBYPHY1 Floating prevention */
+#define EXYNOS_4210_UPHY1CON 0x34
+#define EXYNOS_4210_UPHY1CON_FLOAT_PREVENTION 0x1
+
+/* Mode switching SUB Device <-> Host */
+#define EXYNOS_4210_MODE_SWITCH_OFFSET 0x21c
+#define EXYNOS_4210_MODE_SWITCH_MASK 1
+#define EXYNOS_4210_MODE_SWITCH_DEVICE 0
+#define EXYNOS_4210_MODE_SWITCH_HOST 1
+
+enum exynos4210_phy_id {
+ EXYNOS4210_DEVICE,
+ EXYNOS4210_HOST,
+ EXYNOS4210_HSIC0,
+ EXYNOS4210_HSIC1,
+ EXYNOS4210_NUM_PHYS,
+};
+
+/*
+ * exynos4210_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int exynos4210_rate_to_clk(unsigned long rate, u32 *reg)
+{
+ switch (rate) {
+ case 12 * MHZ:
+ *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_12MHZ;
+ break;
+ case 24 * MHZ:
+ *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_24MHZ;
+ break;
+ case 48 * MHZ:
+ *reg = EXYNOS_4210_UPHYCLK_PHYFSEL_48MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void exynos4210_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 offset;
+ u32 mask;
+
+ switch (inst->cfg->id) {
+ case EXYNOS4210_DEVICE:
+ offset = EXYNOS_4210_USB_ISOL_DEVICE_OFFSET;
+ mask = EXYNOS_4210_USB_ISOL_DEVICE;
+ break;
+ case EXYNOS4210_HOST:
+ offset = EXYNOS_4210_USB_ISOL_HOST_OFFSET;
+ mask = EXYNOS_4210_USB_ISOL_HOST;
+ break;
+ default:
+ return;
+ };
+
+ regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
+}
+
+static void exynos4210_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 rstbits = 0;
+ u32 phypwr = 0;
+ u32 rst;
+ u32 pwr;
+ u32 clk;
+
+ switch (inst->cfg->id) {
+ case EXYNOS4210_DEVICE:
+ phypwr = EXYNOS_4210_UPHYPWR_PHY0;
+ rstbits = EXYNOS_4210_URSTCON_PHY0;
+ break;
+ case EXYNOS4210_HOST:
+ phypwr = EXYNOS_4210_UPHYPWR_PHY1;
+ rstbits = EXYNOS_4210_URSTCON_PHY1_ALL |
+ EXYNOS_4210_URSTCON_PHY1_P0 |
+ EXYNOS_4210_URSTCON_PHY1_P1P2 |
+ EXYNOS_4210_URSTCON_HOST_LINK_ALL |
+ EXYNOS_4210_URSTCON_HOST_LINK_P0;
+ writel(on, drv->reg_phy + EXYNOS_4210_UPHY1CON);
+ break;
+ case EXYNOS4210_HSIC0:
+ phypwr = EXYNOS_4210_UPHYPWR_HSIC0;
+ rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 |
+ EXYNOS_4210_URSTCON_HOST_LINK_P1;
+ break;
+ case EXYNOS4210_HSIC1:
+ phypwr = EXYNOS_4210_UPHYPWR_HSIC1;
+ rstbits = EXYNOS_4210_URSTCON_PHY1_P1P2 |
+ EXYNOS_4210_URSTCON_HOST_LINK_P2;
+ break;
+ };
+
+ if (on) {
+ clk = readl(drv->reg_phy + EXYNOS_4210_UPHYCLK);
+ clk &= ~EXYNOS_4210_UPHYCLK_PHYFSEL_MASK;
+ clk |= drv->ref_reg_val << EXYNOS_4210_UPHYCLK_PHYFSEL_OFFSET;
+ writel(clk, drv->reg_phy + EXYNOS_4210_UPHYCLK);
+
+ pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
+ pwr &= ~phypwr;
+ writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
+
+ rst = readl(drv->reg_phy + EXYNOS_4210_UPHYRST);
+ rst |= rstbits;
+ writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
+ udelay(10);
+ rst &= ~rstbits;
+ writel(rst, drv->reg_phy + EXYNOS_4210_UPHYRST);
+ /* The following delay is necessary for the reset sequence to be
+ * completed */
+ udelay(80);
+ } else {
+ pwr = readl(drv->reg_phy + EXYNOS_4210_UPHYPWR);
+ pwr |= phypwr;
+ writel(pwr, drv->reg_phy + EXYNOS_4210_UPHYPWR);
+ }
+}
+
+static int exynos4210_power_on(struct samsung_usb2_phy_instance *inst)
+{
+ /* Order of initialisation is important - first power then isolation */
+ exynos4210_phy_pwr(inst, 1);
+ exynos4210_isol(inst, 0);
+
+ return 0;
+}
+
+static int exynos4210_power_off(struct samsung_usb2_phy_instance *inst)
+{
+ exynos4210_isol(inst, 1);
+ exynos4210_phy_pwr(inst, 0);
+
+ return 0;
+}
+
+
+static const struct samsung_usb2_common_phy exynos4210_phys[] = {
+ {
+ .label = "device",
+ .id = EXYNOS4210_DEVICE,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {
+ .label = "host",
+ .id = EXYNOS4210_HOST,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {
+ .label = "hsic0",
+ .id = EXYNOS4210_HSIC0,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {
+ .label = "hsic1",
+ .id = EXYNOS4210_HSIC1,
+ .power_on = exynos4210_power_on,
+ .power_off = exynos4210_power_off,
+ },
+ {},
+};
+
+const struct samsung_usb2_phy_config exynos4210_usb2_phy_config = {
+ .has_mode_switch = 0,
+ .num_phys = EXYNOS4210_NUM_PHYS,
+ .phys = exynos4210_phys,
+ .rate_to_clk = exynos4210_rate_to_clk,
+};
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
new file mode 100644
index 0000000..d92a7cc
--- /dev/null
+++ b/drivers/phy/phy-exynos4x12-usb2.c
@@ -0,0 +1,328 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 4x12 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@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/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+
+/* PHY power control */
+#define EXYNOS_4x12_UPHYPWR 0x0
+
+#define EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND BIT(0)
+#define EXYNOS_4x12_UPHYPWR_PHY0_PWR BIT(3)
+#define EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR BIT(4)
+#define EXYNOS_4x12_UPHYPWR_PHY0_SLEEP BIT(5)
+#define EXYNOS_4x12_UPHYPWR_PHY0 ( \
+ EXYNOS_4x12_UPHYPWR_PHY0_SUSPEND | \
+ EXYNOS_4x12_UPHYPWR_PHY0_PWR | \
+ EXYNOS_4x12_UPHYPWR_PHY0_OTG_PWR | \
+ EXYNOS_4x12_UPHYPWR_PHY0_SLEEP)
+
+#define EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND BIT(6)
+#define EXYNOS_4x12_UPHYPWR_PHY1_PWR BIT(7)
+#define EXYNOS_4x12_UPHYPWR_PHY1_SLEEP BIT(8)
+#define EXYNOS_4x12_UPHYPWR_PHY1 ( \
+ EXYNOS_4x12_UPHYPWR_PHY1_SUSPEND | \
+ EXYNOS_4x12_UPHYPWR_PHY1_PWR | \
+ EXYNOS_4x12_UPHYPWR_PHY1_SLEEP)
+
+#define EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND BIT(9)
+#define EXYNOS_4x12_UPHYPWR_HSIC0_PWR BIT(10)
+#define EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP BIT(11)
+#define EXYNOS_4x12_UPHYPWR_HSIC0 ( \
+ EXYNOS_4x12_UPHYPWR_HSIC0_SUSPEND | \
+ EXYNOS_4x12_UPHYPWR_HSIC0_PWR | \
+ EXYNOS_4x12_UPHYPWR_HSIC0_SLEEP)
+
+#define EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND BIT(12)
+#define EXYNOS_4x12_UPHYPWR_HSIC1_PWR BIT(13)
+#define EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP BIT(14)
+#define EXYNOS_4x12_UPHYPWR_HSIC1 ( \
+ EXYNOS_4x12_UPHYPWR_HSIC1_SUSPEND | \
+ EXYNOS_4x12_UPHYPWR_HSIC1_PWR | \
+ EXYNOS_4x12_UPHYPWR_HSIC1_SLEEP)
+
+/* PHY clock control */
+#define EXYNOS_4x12_UPHYCLK 0x4
+
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK (0x7 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET 0
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6 (0x0 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ (0x1 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ (0x2 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2 (0x3 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ (0x4 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ (0x5 << 0)
+#define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ (0x7 << 0)
+
+#define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP BIT(3)
+#define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON BIT(4)
+#define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON BIT(7)
+
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_MASK (0x7f << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_OFFSET 10
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_12MHZ (0x24 << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_15MHZ (0x1c << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_16MHZ (0x1a << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_19MHZ2 (0x15 << 10)
+#define EXYNOS_4x12_UPHYCLK_HSIC_REFCLK_20MHZ (0x14 << 10)
+
+/* PHY reset control */
+#define EXYNOS_4x12_UPHYRST 0x8
+
+#define EXYNOS_4x12_URSTCON_PHY0 BIT(0)
+#define EXYNOS_4x12_URSTCON_OTG_HLINK BIT(1)
+#define EXYNOS_4x12_URSTCON_OTG_PHYLINK BIT(2)
+#define EXYNOS_4x12_URSTCON_HOST_PHY BIT(3)
+#define EXYNOS_4x12_URSTCON_PHY1 BIT(4)
+#define EXYNOS_4x12_URSTCON_HSIC0 BIT(5)
+#define EXYNOS_4x12_URSTCON_HSIC1 BIT(6)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_ALL BIT(7)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P0 BIT(8)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P1 BIT(9)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P2 BIT(10)
+
+/* Isolation, configured in the power management unit */
+#define EXYNOS_4x12_USB_ISOL_OFFSET 0x704
+#define EXYNOS_4x12_USB_ISOL_OTG BIT(0)
+#define EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET 0x708
+#define EXYNOS_4x12_USB_ISOL_HSIC0 BIT(0)
+#define EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET 0x70c
+#define EXYNOS_4x12_USB_ISOL_HSIC1 BIT(0)
+
+/* Mode switching SUB Device <-> Host */
+#define EXYNOS_4x12_MODE_SWITCH_OFFSET 0x21c
+#define EXYNOS_4x12_MODE_SWITCH_MASK 1
+#define EXYNOS_4x12_MODE_SWITCH_DEVICE 0
+#define EXYNOS_4x12_MODE_SWITCH_HOST 1
+
+enum exynos4x12_phy_id {
+ EXYNOS4x12_DEVICE,
+ EXYNOS4x12_HOST,
+ EXYNOS4x12_HSIC0,
+ EXYNOS4x12_HSIC1,
+ EXYNOS4x12_NUM_PHYS,
+};
+
+/*
+ * exynos4x12_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int exynos4x12_rate_to_clk(unsigned long rate, u32 *reg)
+{
+ /* EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK */
+
+ switch (rate) {
+ case 9600 * KHZ:
+ *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_9MHZ6;
+ break;
+ case 10 * MHZ:
+ *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_10MHZ;
+ break;
+ case 12 * MHZ:
+ *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_12MHZ;
+ break;
+ case 19200 * KHZ:
+ *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_19MHZ2;
+ break;
+ case 20 * MHZ:
+ *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_20MHZ;
+ break;
+ case 24 * MHZ:
+ *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ;
+ break;
+ case 50 * MHZ:
+ *reg = EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void exynos4x12_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 offset;
+ u32 mask;
+
+ switch (inst->cfg->id) {
+ case EXYNOS4x12_DEVICE:
+ case EXYNOS4x12_HOST:
+ offset = EXYNOS_4x12_USB_ISOL_OFFSET;
+ mask = EXYNOS_4x12_USB_ISOL_OTG;
+ break;
+ case EXYNOS4x12_HSIC0:
+ offset = EXYNOS_4x12_USB_ISOL_HSIC0_OFFSET;
+ mask = EXYNOS_4x12_USB_ISOL_HSIC0;
+ break;
+ case EXYNOS4x12_HSIC1:
+ offset = EXYNOS_4x12_USB_ISOL_HSIC1_OFFSET;
+ mask = EXYNOS_4x12_USB_ISOL_HSIC1;
+ break;
+ default:
+ return;
+ };
+
+ regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
+}
+
+static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 clk;
+
+ clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
+ clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
+ clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
+ writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
+}
+
+static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 rstbits = 0;
+ u32 phypwr = 0;
+ u32 rst;
+ u32 pwr;
+ u32 mode = 0;
+ u32 switch_mode = 0;
+
+ switch (inst->cfg->id) {
+ case EXYNOS4x12_DEVICE:
+ phypwr = EXYNOS_4x12_UPHYPWR_PHY0;
+ rstbits = EXYNOS_4x12_URSTCON_PHY0;
+ mode = EXYNOS_4x12_MODE_SWITCH_DEVICE;
+ switch_mode = 1;
+ break;
+ case EXYNOS4x12_HOST:
+ phypwr = EXYNOS_4x12_UPHYPWR_PHY1;
+ rstbits = EXYNOS_4x12_URSTCON_HOST_PHY;
+ mode = EXYNOS_4x12_MODE_SWITCH_HOST;
+ switch_mode = 1;
+ break;
+ case EXYNOS4x12_HSIC0:
+ phypwr = EXYNOS_4x12_UPHYPWR_HSIC0;
+ rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
+ EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
+ EXYNOS_4x12_URSTCON_HOST_PHY;
+ break;
+ case EXYNOS4x12_HSIC1:
+ phypwr = EXYNOS_4x12_UPHYPWR_HSIC1;
+ rstbits = EXYNOS_4x12_URSTCON_HSIC1 |
+ EXYNOS_4x12_URSTCON_HOST_LINK_P1;
+ break;
+ };
+
+ if (on) {
+ if (switch_mode)
+ regmap_update_bits(drv->reg_sys,
+ EXYNOS_4x12_MODE_SWITCH_OFFSET,
+ EXYNOS_4x12_MODE_SWITCH_MASK, mode);
+
+ pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+ pwr &= ~phypwr;
+ writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+
+ rst = readl(drv->reg_phy + EXYNOS_4x12_UPHYRST);
+ rst |= rstbits;
+ writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
+ udelay(10);
+ rst &= ~rstbits;
+ writel(rst, drv->reg_phy + EXYNOS_4x12_UPHYRST);
+ /* The following delay is necessary for the reset sequence to be
+ * completed */
+ udelay(80);
+ } else {
+ pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+ pwr |= phypwr;
+ writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
+ }
+}
+
+static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+
+ inst->enabled = 1;
+ exynos4x12_setup_clk(inst);
+ exynos4x12_phy_pwr(inst, 1);
+ exynos4x12_isol(inst, 0);
+
+ /* Power on the device, as it is necessary for HSIC to work */
+ if (inst->cfg->id == EXYNOS4x12_HSIC0) {
+ struct samsung_usb2_phy_instance *device =
+ &drv->instances[EXYNOS4x12_DEVICE];
+ exynos4x12_phy_pwr(device, 1);
+ exynos4x12_isol(device, 0);
+ }
+
+ return 0;
+}
+
+static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ struct samsung_usb2_phy_instance *device =
+ &drv->instances[EXYNOS4x12_DEVICE];
+
+ inst->enabled = 0;
+ exynos4x12_isol(inst, 1);
+ exynos4x12_phy_pwr(inst, 0);
+
+ if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) {
+ exynos4x12_isol(device, 1);
+ exynos4x12_phy_pwr(device, 0);
+ }
+
+ return 0;
+}
+
+
+static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
+ {
+ .label = "device",
+ .id = EXYNOS4x12_DEVICE,
+ .power_on = exynos4x12_power_on,
+ .power_off = exynos4x12_power_off,
+ },
+ {
+ .label = "host",
+ .id = EXYNOS4x12_HOST,
+ .power_on = exynos4x12_power_on,
+ .power_off = exynos4x12_power_off,
+ },
+ {
+ .label = "hsic0",
+ .id = EXYNOS4x12_HSIC0,
+ .power_on = exynos4x12_power_on,
+ .power_off = exynos4x12_power_off,
+ },
+ {
+ .label = "hsic1",
+ .id = EXYNOS4x12_HSIC1,
+ .power_on = exynos4x12_power_on,
+ .power_off = exynos4x12_power_off,
+ },
+ {},
+};
+
+const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
+ .has_mode_switch = 1,
+ .num_phys = EXYNOS4x12_NUM_PHYS,
+ .phys = exynos4x12_phys,
+ .rate_to_clk = exynos4x12_rate_to_clk,
+};
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
new file mode 100644
index 0000000..c3b7719
--- /dev/null
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -0,0 +1,222 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@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/clk.h>
+#include <linux/mfd/syscon.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>
+#include "phy-samsung-usb2.h"
+
+static int samsung_usb2_phy_power_on(struct phy *phy)
+{
+ struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ int ret;
+
+ dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
+ inst->cfg->label);
+ ret = clk_prepare_enable(drv->clk);
+ if (ret)
+ goto err_main_clk;
+ ret = clk_prepare_enable(drv->ref_clk);
+ if (ret)
+ goto err_instance_clk;
+ if (inst->cfg->power_on) {
+ spin_lock(&drv->lock);
+ ret = inst->cfg->power_on(inst);
+ spin_unlock(&drv->lock);
+ }
+
+ return 0;
+
+err_instance_clk:
+ clk_disable_unprepare(drv->clk);
+err_main_clk:
+ return ret;
+}
+
+static int samsung_usb2_phy_power_off(struct phy *phy)
+{
+ struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ int ret = 0;
+
+ dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
+ inst->cfg->label);
+ if (inst->cfg->power_off) {
+ spin_lock(&drv->lock);
+ ret = inst->cfg->power_off(inst);
+ spin_unlock(&drv->lock);
+ }
+ clk_disable_unprepare(drv->ref_clk);
+ clk_disable_unprepare(drv->clk);
+ return ret;
+}
+
+static struct phy_ops samsung_usb2_phy_ops = {
+ .power_on = samsung_usb2_phy_power_on,
+ .power_off = samsung_usb2_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static struct phy *samsung_usb2_phy_xlate(struct device *dev,
+ struct of_phandle_args *args)
+{
+ struct samsung_usb2_phy_driver *drv;
+
+ drv = dev_get_drvdata(dev);
+ if (!drv)
+ return ERR_PTR(-EINVAL);
+
+ if (WARN_ON(args->args[0] >= drv->cfg->num_phys))
+ return ERR_PTR(-ENODEV);
+
+ return drv->instances[args->args[0]].phy;
+}
+
+static const struct of_device_id samsung_usb2_phy_of_match[] = {
+#ifdef CONFIG_PHY_EXYNOS4210_USB2
+ {
+ .compatible = "samsung,exynos4210-usb2-phy",
+ .data = &exynos4210_usb2_phy_config,
+ },
+#endif
+#ifdef CONFIG_PHY_EXYNOS4X12_USB2
+ {
+ .compatible = "samsung,exynos4x12-usb2-phy",
+ .data = &exynos4x12_usb2_phy_config,
+ },
+#endif
+ { },
+};
+
+static int samsung_usb2_phy_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ const struct samsung_usb2_phy_config *cfg;
+ struct device *dev = &pdev->dev;
+ struct phy_provider *phy_provider;
+ struct resource *mem;
+ struct samsung_usb2_phy_driver *drv;
+ int i, ret;
+
+ if (!pdev->dev.of_node) {
+ dev_err(dev, "This driver is required to be instantiated from device tree\n");
+ return -EINVAL;
+ }
+
+ match = of_match_node(samsung_usb2_phy_of_match, pdev->dev.of_node);
+ if (!match) {
+ dev_err(dev, "of_match_node() failed\n");
+ return -EINVAL;
+ }
+ cfg = match->data;
+
+ drv = devm_kzalloc(dev, sizeof(struct samsung_usb2_phy_driver) +
+ cfg->num_phys * sizeof(struct samsung_usb2_phy_instance),
+ GFP_KERNEL);
+ if (!drv)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, drv);
+ spin_lock_init(&drv->lock);
+
+ drv->cfg = cfg;
+ drv->dev = dev;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ drv->reg_phy = devm_ioremap_resource(dev, mem);
+ if (IS_ERR(drv->reg_phy)) {
+ dev_err(dev, "Failed to map register memory (phy)\n");
+ return PTR_ERR(drv->reg_phy);
+ }
+
+ drv->reg_pmu = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+ "samsung,pmureg-phandle");
+ if (IS_ERR(drv->reg_pmu)) {
+ dev_err(dev, "Failed to map PMU registers (via syscon)\n");
+ return PTR_ERR(drv->reg_pmu);
+ }
+
+ if (drv->cfg->has_mode_switch) {
+ drv->reg_sys = syscon_regmap_lookup_by_phandle(
+ pdev->dev.of_node, "samsung,sysreg-phandle");
+ if (IS_ERR(drv->reg_sys)) {
+ dev_err(dev, "Failed to map system registers (via syscon)\n");
+ return PTR_ERR(drv->reg_sys);
+ }
+ }
+
+ drv->clk = devm_clk_get(dev, "phy");
+ if (IS_ERR(drv->clk)) {
+ dev_err(dev, "Failed to get clock of phy controller\n");
+ return PTR_ERR(drv->clk);
+ }
+
+ drv->ref_clk = devm_clk_get(dev, "ref");
+ if (IS_ERR(drv->ref_clk)) {
+ dev_err(dev, "Failed to get reference clock for the phy controller\n");
+ return PTR_ERR(drv->ref_clk);
+ }
+
+ drv->ref_rate = clk_get_rate(drv->ref_clk);
+ if (drv->cfg->rate_to_clk) {
+ ret = drv->cfg->rate_to_clk(drv->ref_rate, &drv->ref_reg_val);
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; i < drv->cfg->num_phys; i++) {
+ char *label = drv->cfg->phys[i].label;
+ struct samsung_usb2_phy_instance *p = &drv->instances[i];
+
+ dev_dbg(dev, "Creating phy \"%s\"\n", label);
+ p->phy = devm_phy_create(dev, &samsung_usb2_phy_ops, NULL);
+ if (IS_ERR(p->phy)) {
+ dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
+ label);
+ return PTR_ERR(p->phy);
+ }
+
+ p->cfg = &drv->cfg->phys[i];
+ p->drv = drv;
+ phy_set_bus_width(p->phy, 8);
+ phy_set_drvdata(p->phy, p);
+ }
+
+ phy_provider = devm_of_phy_provider_register(dev,
+ samsung_usb2_phy_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(drv->dev, "Failed to register phy provider\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ return 0;
+}
+
+static struct platform_driver samsung_usb2_phy_driver = {
+ .probe = samsung_usb2_phy_probe,
+ .driver = {
+ .of_match_table = samsung_usb2_phy_of_match,
+ .name = "samsung-usb2-phy",
+ .owner = THIS_MODULE,
+ }
+};
+
+module_platform_driver(samsung_usb2_phy_driver);
+MODULE_DESCRIPTION("Samsung S5P/EXYNOS SoC USB PHY driver");
+MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:samsung-usb2-phy");
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
new file mode 100644
index 0000000..51a1601
--- /dev/null
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -0,0 +1,66 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@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 _PHY_EXYNOS_USB2_H
+#define _PHY_EXYNOS_USB2_H
+
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/device.h>
+#include <linux/regmap.h>
+#include <linux/spinlock.h>
+
+#define KHZ 1000
+#define MHZ (KHZ * KHZ)
+
+struct samsung_usb2_phy_driver;
+struct samsung_usb2_phy_instance;
+struct samsung_usb2_phy_config;
+
+struct samsung_usb2_phy_instance {
+ const struct samsung_usb2_common_phy *cfg;
+ struct phy *phy;
+ struct samsung_usb2_phy_driver *drv;
+ bool enabled;
+};
+
+struct samsung_usb2_phy_driver {
+ const struct samsung_usb2_phy_config *cfg;
+ struct clk *clk;
+ struct clk *ref_clk;
+ unsigned long ref_rate;
+ u32 ref_reg_val;
+ struct device *dev;
+ void __iomem *reg_phy;
+ struct regmap *reg_pmu;
+ struct regmap *reg_sys;
+ spinlock_t lock;
+ struct samsung_usb2_phy_instance instances[0];
+};
+
+struct samsung_usb2_common_phy {
+ int (*power_on)(struct samsung_usb2_phy_instance *);
+ int (*power_off)(struct samsung_usb2_phy_instance *);
+ unsigned int id;
+ char *label;
+};
+
+
+struct samsung_usb2_phy_config {
+ const struct samsung_usb2_common_phy *phys;
+ int (*rate_to_clk)(unsigned long, u32 *);
+ unsigned int num_phys;
+ bool has_mode_switch;
+};
+
+extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
+extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
+#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [PATCH v9 4/4] phy: Add Exynos 5250 support to the Exynos USB 2.0 PHY driver
2014-03-05 15:28 [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
` (2 preceding siblings ...)
2014-03-05 15:28 ` [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
@ 2014-03-05 15:28 ` Kamil Debski
[not found] ` <1394033288-5551-1-git-send-email-k.debski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
4 siblings, 0 replies; 20+ messages in thread
From: Kamil Debski @ 2014-03-05 15:28 UTC (permalink / raw)
To: linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, k.debski, tjakobi, stern, sander
Add support for Exynos 5250. This driver is to replace the old
USB 2.0 PHY driver.
Signed-off-by: Kamil Debski <k.debski@samsung.com>
---
.../devicetree/bindings/phy/samsung-phy.txt | 1 +
drivers/phy/Kconfig | 11 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-exynos5250-usb2.c | 404 ++++++++++++++++++++
drivers/phy/phy-samsung-usb2.c | 6 +
drivers/phy/phy-samsung-usb2.h | 1 +
6 files changed, 424 insertions(+)
create mode 100644 drivers/phy/phy-exynos5250-usb2.c
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index bf955ab..28f9edb 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -28,6 +28,7 @@ Required properties:
- compatible : should be one of the listed compatibles:
- "samsung,exynos4210-usb2-phy"
- "samsung,exynos4x12-usb2-phy"
+ - "samsung,exynos5250-usb2-phy"
- reg : a list of registers used by phy driver
- first and obligatory is the location of phy modules registers
- samsung,sysreg-phandle - handle to syscon used to control the system registers
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index fc5a44a..c206e25 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -125,4 +125,15 @@ config PHY_EXYNOS4X12_USB2
Samsung USB 2.0 PHY driver is enabled and means that support for this
particular SoC is compiled in the driver. In case of Exynos 4x12 four
phys are available - device, host, HSIC0 and HSIC1.
+
+config PHY_EXYNOS5250_USB2
+ bool "Support for Exynos 5250"
+ depends on PHY_SAMSUNG_USB2
+ depends on SOC_EXYNOS5250
+ help
+ Enable USB PHY support for Exynos 5250. This option requires that
+ Samsung USB 2.0 PHY driver is enabled and means that support for this
+ particular SoC is compiled in the driver. In case of Exynos 5250 four
+ phys are available - device, host, HSIC0 and HSIC.
+
endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 0ea36ff..f76c239 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -14,3 +14,4 @@ obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-samsung-usb2.o
obj-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
obj-$(CONFIG_PHY_EXYNOS4X12_USB2) += phy-exynos4x12-usb2.o
+obj-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c
new file mode 100644
index 0000000..94179af
--- /dev/null
+++ b/drivers/phy/phy-exynos5250-usb2.c
@@ -0,0 +1,404 @@
+/*
+ * Samsung SoC USB 1.1/2.0 PHY driver - Exynos 5250 support
+ *
+ * Copyright (C) 2013 Samsung Electronics Co., Ltd.
+ * Author: Kamil Debski <k.debski@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/delay.h>
+#include <linux/io.h>
+#include <linux/phy/phy.h>
+#include <linux/regmap.h>
+#include "phy-samsung-usb2.h"
+
+/* Exynos USB PHY registers */
+#define EXYNOS_5250_REFCLKSEL_CRYSTAL 0x0
+#define EXYNOS_5250_REFCLKSEL_XO 0x1
+#define EXYNOS_5250_REFCLKSEL_CLKCORE 0x2
+
+#define EXYNOS_5250_FSEL_9MHZ6 0x0
+#define EXYNOS_5250_FSEL_10MHZ 0x1
+#define EXYNOS_5250_FSEL_12MHZ 0x2
+#define EXYNOS_5250_FSEL_19MHZ2 0x3
+#define EXYNOS_5250_FSEL_20MHZ 0x4
+#define EXYNOS_5250_FSEL_24MHZ 0x5
+#define EXYNOS_5250_FSEL_50MHZ 0x7
+
+/* Normal host */
+#define EXYNOS_5250_HOSTPHYCTRL0 0x0
+
+#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL BIT(31)
+#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT 19
+#define EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_MASK \
+ (0x3 << EXYNOS_5250_HOSTPHYCTRL0_REFCLKSEL_SHIFT)
+#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT 16
+#define EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK \
+ (0x7 << EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT)
+#define EXYNOS_5250_HOSTPHYCTRL0_TESTBURNIN BIT(11)
+#define EXYNOS_5250_HOSTPHYCTRL0_RETENABLE BIT(10)
+#define EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N BIT(9)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_MASK (0x3 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_DUAL (0x0 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ID0 (0x1 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_VATESTENB_ANALOGTEST (0x2 << 7)
+#define EXYNOS_5250_HOSTPHYCTRL0_SIDDQ BIT(6)
+#define EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP BIT(5)
+#define EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND BIT(4)
+#define EXYNOS_5250_HOSTPHYCTRL0_WORDINTERFACE BIT(3)
+#define EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST BIT(2)
+#define EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST BIT(1)
+#define EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST BIT(0)
+
+/* HSIC0 & HSIC1 */
+#define EXYNOS_5250_HSICPHYCTRL1 0x10
+#define EXYNOS_5250_HSICPHYCTRL2 0x20
+
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_MASK (0x3 << 23)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT (0x2 << 23)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_MASK (0x7f << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 (0x24 << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_15 (0x1c << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_16 (0x1a << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_19_2 (0x15 << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_20 (0x14 << 16)
+#define EXYNOS_5250_HSICPHYCTRLX_SIDDQ BIT(6)
+#define EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP BIT(5)
+#define EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND BIT(4)
+#define EXYNOS_5250_HSICPHYCTRLX_WORDINTERFACE BIT(3)
+#define EXYNOS_5250_HSICPHYCTRLX_UTMISWRST BIT(2)
+#define EXYNOS_5250_HSICPHYCTRLX_PHYSWRST BIT(0)
+
+/* EHCI control */
+#define EXYNOS_5250_HOSTEHCICTRL 0x30
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN BIT(29)
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 BIT(28)
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 BIT(27)
+#define EXYNOS_5250_HOSTEHCICTRL_ENAINCR16 BIT(26)
+#define EXYNOS_5250_HOSTEHCICTRL_AUTOPPDONOVRCUREN BIT(25)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT 19
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
+ (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT 13
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_MASK \
+ (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL1_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL2_SHIFT 7
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_MASK \
+ (0x3f << EXYNOS_5250_HOSTEHCICTRL_FLADJVAL0_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT 1
+#define EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_MASK \
+ (0x1 << EXYNOS_5250_HOSTEHCICTRL_FLADJVALHOST_SHIFT)
+#define EXYNOS_5250_HOSTEHCICTRL_SIMULATIONMODE BIT(0)
+
+/* OHCI control */
+#define EXYNOS_5250_HOSTOHCICTRL 0x34
+#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT 1
+#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_MASK \
+ (0x3ff << EXYNOS_5250_HOSTOHCICTRL_FRAMELENVAL_SHIFT)
+#define EXYNOS_5250_HOSTOHCICTRL_FRAMELENVALEN BIT(0)
+
+/* USBOTG */
+#define EXYNOS_5250_USBOTGSYS 0x38
+#define EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET BIT(14)
+#define EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG BIT(13)
+#define EXYNOS_5250_USBOTGSYS_PHY_SW_RST BIT(12)
+#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT 9
+#define EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK \
+ (0x3 << EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT)
+#define EXYNOS_5250_USBOTGSYS_ID_PULLUP BIT(8)
+#define EXYNOS_5250_USBOTGSYS_COMMON_ON BIT(7)
+#define EXYNOS_5250_USBOTGSYS_FSEL_SHIFT 4
+#define EXYNOS_5250_USBOTGSYS_FSEL_MASK \
+ (0x3 << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT)
+#define EXYNOS_5250_USBOTGSYS_FORCE_SLEEP BIT(3)
+#define EXYNOS_5250_USBOTGSYS_OTGDISABLE BIT(2)
+#define EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG BIT(1)
+#define EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND BIT(0)
+
+/* Isolation, configured in the power management unit */
+#define EXYNOS_5250_USB_ISOL_OTG_OFFSET 0x704
+#define EXYNOS_5250_USB_ISOL_OTG BIT(0)
+#define EXYNOS_5250_USB_ISOL_HOST_OFFSET 0x708
+#define EXYNOS_5250_USB_ISOL_HOST BIT(0)
+
+/* Mode swtich register */
+#define EXYNOS_5250_MODE_SWITCH_OFFSET 0x230
+#define EXYNOS_5250_MODE_SWITCH_MASK 1
+#define EXYNOS_5250_MODE_SWITCH_DEVICE 0
+#define EXYNOS_5250_MODE_SWITCH_HOST 1
+
+enum exynos4x12_phy_id {
+ EXYNOS5250_DEVICE,
+ EXYNOS5250_HOST,
+ EXYNOS5250_HSIC0,
+ EXYNOS5250_HSIC1,
+ EXYNOS5250_NUM_PHYS,
+};
+
+/*
+ * exynos5250_rate_to_clk() converts the supplied clock rate to the value that
+ * can be written to the phy register.
+ */
+static int exynos5250_rate_to_clk(unsigned long rate, u32 *reg)
+{
+ /* EXYNOS_5250_FSEL_MASK */
+
+ switch (rate) {
+ case 9600 * KHZ:
+ *reg = EXYNOS_5250_FSEL_9MHZ6;
+ break;
+ case 10 * MHZ:
+ *reg = EXYNOS_5250_FSEL_10MHZ;
+ break;
+ case 12 * MHZ:
+ *reg = EXYNOS_5250_FSEL_12MHZ;
+ break;
+ case 19200 * KHZ:
+ *reg = EXYNOS_5250_FSEL_19MHZ2;
+ break;
+ case 20 * MHZ:
+ *reg = EXYNOS_5250_FSEL_20MHZ;
+ break;
+ case 24 * MHZ:
+ *reg = EXYNOS_5250_FSEL_24MHZ;
+ break;
+ case 50 * MHZ:
+ *reg = EXYNOS_5250_FSEL_50MHZ;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void exynos5250_isol(struct samsung_usb2_phy_instance *inst, bool on)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 offset;
+ u32 mask;
+
+ switch (inst->cfg->id) {
+ case EXYNOS5250_DEVICE:
+ offset = EXYNOS_5250_USB_ISOL_OTG_OFFSET;
+ mask = EXYNOS_5250_USB_ISOL_OTG;
+ break;
+ case EXYNOS5250_HOST:
+ offset = EXYNOS_5250_USB_ISOL_HOST_OFFSET;
+ mask = EXYNOS_5250_USB_ISOL_HOST;
+ break;
+ default:
+ return;
+ };
+
+ regmap_update_bits(drv->reg_pmu, offset, mask, on ? 0 : mask);
+}
+
+static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 ctrl0;
+ u32 otg;
+ u32 ehci;
+ u32 ohci;
+ u32 hsic;
+
+ switch (inst->cfg->id) {
+ case EXYNOS5250_DEVICE:
+ regmap_update_bits(drv->reg_sys,
+ EXYNOS_5250_MODE_SWITCH_OFFSET,
+ EXYNOS_5250_MODE_SWITCH_MASK,
+ EXYNOS_5250_MODE_SWITCH_DEVICE);
+
+ /* OTG configuration */
+ otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+ /* The clock */
+ otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
+ otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
+ /* Reset */
+ otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
+ EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
+ EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
+ otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+ EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
+ EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+ EXYNOS_5250_USBOTGSYS_OTGDISABLE;
+ /* Ref clock */
+ otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
+ otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
+ EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
+ writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+ udelay(100);
+ otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+ EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+ EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
+ EXYNOS_5250_USBOTGSYS_OTGDISABLE);
+ writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+
+
+ break;
+ case EXYNOS5250_HOST:
+ case EXYNOS5250_HSIC0:
+ case EXYNOS5250_HSIC1:
+ /* Host registers configuration */
+ ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+ /* The clock */
+ ctrl0 &= ~EXYNOS_5250_HOSTPHYCTRL0_FSEL_MASK;
+ ctrl0 |= drv->ref_reg_val <<
+ EXYNOS_5250_HOSTPHYCTRL0_FSEL_SHIFT;
+
+ /* Reset */
+ ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
+ EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL |
+ EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
+ EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
+ EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP);
+ ctrl0 |= EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
+ EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST |
+ EXYNOS_5250_HOSTPHYCTRL0_COMMON_ON_N;
+ writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+ udelay(10);
+ ctrl0 &= ~(EXYNOS_5250_HOSTPHYCTRL0_LINKSWRST |
+ EXYNOS_5250_HOSTPHYCTRL0_UTMISWRST);
+ writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+
+ /* OTG configuration */
+ otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+ /* The clock */
+ otg &= ~EXYNOS_5250_USBOTGSYS_FSEL_MASK;
+ otg |= drv->ref_reg_val << EXYNOS_5250_USBOTGSYS_FSEL_SHIFT;
+ /* Reset */
+ otg &= ~(EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
+ EXYNOS_5250_USBOTGSYS_FORCE_SLEEP |
+ EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG);
+ otg |= EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+ EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET |
+ EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+ EXYNOS_5250_USBOTGSYS_OTGDISABLE;
+ /* Ref clock */
+ otg &= ~EXYNOS_5250_USBOTGSYS_REFCLKSEL_MASK;
+ otg |= EXYNOS_5250_REFCLKSEL_CLKCORE <<
+ EXYNOS_5250_USBOTGSYS_REFCLKSEL_SHIFT;
+ writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+ udelay(10);
+ otg &= ~(EXYNOS_5250_USBOTGSYS_PHY_SW_RST |
+ EXYNOS_5250_USBOTGSYS_LINK_SW_RST_UOTG |
+ EXYNOS_5250_USBOTGSYS_PHYLINK_SW_RESET);
+
+ /* HSIC phy configuration */
+ hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
+ EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
+ EXYNOS_5250_HSICPHYCTRLX_PHYSWRST);
+ writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
+ writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
+ udelay(10);
+ hsic &= ~EXYNOS_5250_HSICPHYCTRLX_PHYSWRST;
+ writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
+ writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
+ /* The following delay is necessary for the reset sequence to be
+ * completed */
+ udelay(80);
+
+ /* Enable EHCI DMA burst */
+ ehci = readl(drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
+ ehci |= EXYNOS_5250_HOSTEHCICTRL_ENAINCRXALIGN |
+ EXYNOS_5250_HOSTEHCICTRL_ENAINCR4 |
+ EXYNOS_5250_HOSTEHCICTRL_ENAINCR8 |
+ EXYNOS_5250_HOSTEHCICTRL_ENAINCR16;
+ writel(ehci, drv->reg_phy + EXYNOS_5250_HOSTEHCICTRL);
+
+ /* OHCI settings */
+ ohci = readl(drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
+ /* Following code is based on the old driver */
+ ohci |= 0x1 << 3;
+ writel(ohci, drv->reg_phy + EXYNOS_5250_HOSTOHCICTRL);
+
+ break;
+ }
+ inst->enabled = 1;
+ exynos5250_isol(inst, 0);
+
+ return 0;
+}
+
+static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
+{
+ struct samsung_usb2_phy_driver *drv = inst->drv;
+ u32 ctrl0;
+ u32 otg;
+ u32 hsic;
+
+ inst->enabled = 0;
+ exynos5250_isol(inst, 1);
+
+ switch (inst->cfg->id) {
+ case EXYNOS5250_DEVICE:
+ otg = readl(drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+ otg |= (EXYNOS_5250_USBOTGSYS_FORCE_SUSPEND |
+ EXYNOS_5250_USBOTGSYS_SIDDQ_UOTG |
+ EXYNOS_5250_USBOTGSYS_FORCE_SLEEP);
+ writel(otg, drv->reg_phy + EXYNOS_5250_USBOTGSYS);
+ break;
+ case EXYNOS5250_HOST:
+ ctrl0 = readl(drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+ ctrl0 |= (EXYNOS_5250_HOSTPHYCTRL0_SIDDQ |
+ EXYNOS_5250_HOSTPHYCTRL0_FORCESUSPEND |
+ EXYNOS_5250_HOSTPHYCTRL0_FORCESLEEP |
+ EXYNOS_5250_HOSTPHYCTRL0_PHYSWRST |
+ EXYNOS_5250_HOSTPHYCTRL0_PHYSWRSTALL);
+ writel(ctrl0, drv->reg_phy + EXYNOS_5250_HOSTPHYCTRL0);
+ break;
+ case EXYNOS5250_HSIC0:
+ case EXYNOS5250_HSIC1:
+ hsic = (EXYNOS_5250_HSICPHYCTRLX_REFCLKDIV_12 |
+ EXYNOS_5250_HSICPHYCTRLX_REFCLKSEL_DEFAULT |
+ EXYNOS_5250_HSICPHYCTRLX_SIDDQ |
+ EXYNOS_5250_HSICPHYCTRLX_FORCESLEEP |
+ EXYNOS_5250_HSICPHYCTRLX_FORCESUSPEND
+ );
+ writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL1);
+ writel(hsic, drv->reg_phy + EXYNOS_5250_HSICPHYCTRL2);
+ break;
+ }
+
+ return 0;
+}
+
+
+static const struct samsung_usb2_common_phy exynos5250_phys[] = {
+ {
+ .label = "device",
+ .id = EXYNOS5250_DEVICE,
+ .power_on = exynos5250_power_on,
+ .power_off = exynos5250_power_off,
+ },
+ {
+ .label = "host",
+ .id = EXYNOS5250_HOST,
+ .power_on = exynos5250_power_on,
+ .power_off = exynos5250_power_off,
+ },
+ {
+ .label = "hsic0",
+ .id = EXYNOS5250_HSIC0,
+ .power_on = exynos5250_power_on,
+ .power_off = exynos5250_power_off,
+ },
+ {
+ .label = "hsic1",
+ .id = EXYNOS5250_HSIC1,
+ .power_on = exynos5250_power_on,
+ .power_off = exynos5250_power_off,
+ },
+ {},
+};
+
+const struct samsung_usb2_phy_config exynos5250_usb2_phy_config = {
+ .has_mode_switch = 1,
+ .num_phys = EXYNOS5250_NUM_PHYS,
+ .phys = exynos5250_phys,
+ .rate_to_clk = exynos5250_rate_to_clk,
+};
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index c3b7719..8a8c6bc 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -99,6 +99,12 @@ static const struct of_device_id samsung_usb2_phy_of_match[] = {
.data = &exynos4x12_usb2_phy_config,
},
#endif
+#ifdef CONFIG_PHY_EXYNOS5250_USB2
+ {
+ .compatible = "samsung,exynos5250-usb2-phy",
+ .data = &exynos5250_usb2_phy_config,
+ },
+#endif
{ },
};
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 51a1601..45b3170 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -63,4 +63,5 @@ struct samsung_usb2_phy_config {
extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
+extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
#endif
--
1.7.9.5
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [PATCH v9 1/4] phy: core: Add an exported of_phy_get function
2014-03-05 15:28 ` [PATCH v9 1/4] phy: core: Add an exported of_phy_get function Kamil Debski
@ 2014-03-05 16:03 ` Tomasz Figa
0 siblings, 0 replies; 20+ messages in thread
From: Tomasz Figa @ 2014-03-05 16:03 UTC (permalink / raw)
To: Kamil Debski, linux-kernel, linux-samsung-soc, linux-usb,
devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, tjakobi, stern, sander
On 05.03.2014 16:28, Kamil Debski wrote:
> Previously the of_phy_get function took a struct device * and
> was declared static. It was impossible to call it from
> another driver and thus it was impossible to get phy defined
> for a given node. The old function was renamed to _of_phy_get
> and was left for internal use. of_phy_get function was added
> and it was exported. The function enables to get a phy for
> a given device tree node.
>
> Signed-off-by: Kamil Debski <k.debski@samsung.com>
> ---
> drivers/phy/phy-core.c | 45 ++++++++++++++++++++++++++++++++++++---------
> include/linux/phy/phy.h | 6 ++++++
> 2 files changed, 42 insertions(+), 9 deletions(-)
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v9 2/4] phy: core: Add devm_of_phy_get to phy-core
2014-03-05 15:28 ` [PATCH v9 2/4] phy: core: Add devm_of_phy_get to phy-core Kamil Debski
@ 2014-03-05 16:04 ` Tomasz Figa
0 siblings, 0 replies; 20+ messages in thread
From: Tomasz Figa @ 2014-03-05 16:04 UTC (permalink / raw)
To: Kamil Debski, linux-kernel, linux-samsung-soc, linux-usb,
devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, tjakobi, stern, sander
On 05.03.2014 16:28, Kamil Debski wrote:
> Adding devm_of_phy_get will allow to get phys by supplying a
> pointer to the struct device_node instead of struct device.
>
> Signed-off-by: Kamil Debski <k.debski@samsung.com>
> ---
> drivers/phy/phy-core.c | 31 +++++++++++++++++++++++++++++++
> include/linux/phy/phy.h | 8 ++++++++
> 2 files changed, 39 insertions(+)
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-05 15:28 ` [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
@ 2014-03-05 16:04 ` Tomasz Figa
2014-03-06 8:26 ` Anton Tikhomirov
1 sibling, 0 replies; 20+ messages in thread
From: Tomasz Figa @ 2014-03-05 16:04 UTC (permalink / raw)
To: Kamil Debski, linux-kernel, linux-samsung-soc, linux-usb,
devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, av.tikhomirov,
jg1.han, galak, matt.porter, tjakobi, stern, sander
On 05.03.2014 16:28, Kamil Debski wrote:
> Add a new driver for the Exynos USB 2.0 PHY. The new driver uses the generic
> PHY framework. The driver includes support for the Exynos 4x10 and 4x12
> SoC families.
>
> Signed-off-by: Kamil Debski <k.debski@samsung.com>
> ---
> .../devicetree/bindings/phy/samsung-phy.txt | 53 ++++
> Documentation/phy/samsung-usb2.txt | 134 ++++++++
> drivers/phy/Kconfig | 29 ++
> drivers/phy/Makefile | 3 +
> drivers/phy/phy-exynos4210-usb2.c | 261 ++++++++++++++++
> drivers/phy/phy-exynos4x12-usb2.c | 328 ++++++++++++++++++++
> drivers/phy/phy-samsung-usb2.c | 222 +++++++++++++
> drivers/phy/phy-samsung-usb2.h | 66 ++++
> 8 files changed, 1096 insertions(+)
> create mode 100644 Documentation/phy/samsung-usb2.txt
> create mode 100644 drivers/phy/phy-exynos4210-usb2.c
> create mode 100644 drivers/phy/phy-exynos4x12-usb2.c
> create mode 100644 drivers/phy/phy-samsung-usb2.c
> create mode 100644 drivers/phy/phy-samsung-usb2.h
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Best regards,
Tomasz
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver
[not found] ` <1394033288-5551-1-git-send-email-k.debski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2014-03-05 23:08 ` Tobias Jakobi
2014-03-06 10:25 ` Kamil Debski
0 siblings, 1 reply; 20+ messages in thread
From: Tobias Jakobi @ 2014-03-05 23:08 UTC (permalink / raw)
To: Kamil Debski, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ, kishon-l0cyMroinI0,
t.figa-Sze3O3UU22JBDgjK7y7TUQ, s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ,
mat.krawczuk-Re5JQEeQqe8AvxtiuMwx3w,
yulgon.kim-Sze3O3UU22JBDgjK7y7TUQ,
p.paneri-Sze3O3UU22JBDgjK7y7TUQ,
av.tikhomirov-Sze3O3UU22JBDgjK7y7TUQ,
jg1.han-Sze3O3UU22JBDgjK7y7TUQ, galak-sgV2jX0FEOL9JmXXK+q4OQ,
matt.porter-QSEj5FYQhm4dnm+yROfE0A,
stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz,
sander-7Kwe/DFdFGvR7s880joybQ
Hello Kamil,
this looks very good. I just tested the patchset on my ODROID-X2
(Exynos4412-based board) and the USB stability issues I mentioned to you
before (with the older patchset) seem to be gone.
All devices on the USB behave normally (mass storage, ethernet and
bluetooth).
With best wishes,
Tobias
--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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] 20+ messages in thread
* RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-05 15:28 ` [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
2014-03-05 16:04 ` Tomasz Figa
@ 2014-03-06 8:26 ` Anton Tikhomirov
2014-03-06 8:30 ` Kishon Vijay Abraham I
2014-03-06 10:24 ` Kamil Debski
1 sibling, 2 replies; 20+ messages in thread
From: Anton Tikhomirov @ 2014-03-06 8:26 UTC (permalink / raw)
To: 'Kamil Debski', linux-kernel, linux-samsung-soc,
linux-usb, devicetree
Cc: kyungmin.park, kishon, t.figa, s.nawrocki, m.szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak,
matt.porter, tjakobi, stern, sander
Hi Kamil,
...
> +| 3. Supporting SoCs
> ++--------------------
> +
> +To support a new SoC a new file should be added to the drivers/phy
> +directory. Each SoC's configuration is stored in an instance of the
> +struct samsung_usb2_phy_config.
> +
> +struct samsung_usb2_phy_config {
> + const struct samsung_usb2_common_phy *phys;
> + unsigned int num_phys;
> + bool has_mode_switch;
You missed rate_to_clk here.
> +};
> +
...
> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-
> usb2.c
> new file mode 100644
> index 0000000..c3b7719
> --- /dev/null
> +++ b/drivers/phy/phy-samsung-usb2.c
> @@ -0,0 +1,222 @@
> +/*
> + * Samsung SoC USB 1.1/2.0 PHY driver
> + *
> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> + * Author: Kamil Debski <k.debski@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/clk.h>
> +#include <linux/mfd/syscon.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>
> +#include "phy-samsung-usb2.h"
> +
> +static int samsung_usb2_phy_power_on(struct phy *phy)
> +{
> + struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
> + struct samsung_usb2_phy_driver *drv = inst->drv;
> + int ret;
> +
> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
> + inst->cfg->label);
> + ret = clk_prepare_enable(drv->clk);
clk_prepare_enable() can sleep, and therefore doesn't allow
samusng_usb2_phy_power_on() to be used in atomic context
(e.g. inside spin_lock-ed area), what sometimes may be desirable.
What about to prepare clock in probe, and just enable it here
(note: clk_enable() doesn't sleep).
> + if (ret)
> + goto err_main_clk;
> + ret = clk_prepare_enable(drv->ref_clk);
> + if (ret)
> + goto err_instance_clk;
> + if (inst->cfg->power_on) {
> + spin_lock(&drv->lock);
> + ret = inst->cfg->power_on(inst);
> + spin_unlock(&drv->lock);
> + }
> +
> + return 0;
Thank you
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 8:26 ` Anton Tikhomirov
@ 2014-03-06 8:30 ` Kishon Vijay Abraham I
2014-03-06 8:52 ` Anton Tikhomirov
2014-03-06 10:24 ` Kamil Debski
1 sibling, 1 reply; 20+ messages in thread
From: Kishon Vijay Abraham I @ 2014-03-06 8:30 UTC (permalink / raw)
To: Anton Tikhomirov, 'Kamil Debski', linux-kernel,
linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, t.figa, s.nawrocki, m.szyprowski, gautam.vivek,
mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak, matt.porter,
tjakobi, stern, sander
On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
> Hi Kamil,
>
> ...
>
>> +| 3. Supporting SoCs
>> ++--------------------
>> +
>> +To support a new SoC a new file should be added to the drivers/phy
>> +directory. Each SoC's configuration is stored in an instance of the
>> +struct samsung_usb2_phy_config.
>> +
>> +struct samsung_usb2_phy_config {
>> + const struct samsung_usb2_common_phy *phys;
>> + unsigned int num_phys;
>> + bool has_mode_switch;
>
> You missed rate_to_clk here.
>
>> +};
>> +
>
> ...
>
>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-
>> usb2.c
>> new file mode 100644
>> index 0000000..c3b7719
>> --- /dev/null
>> +++ b/drivers/phy/phy-samsung-usb2.c
>> @@ -0,0 +1,222 @@
>> +/*
>> + * Samsung SoC USB 1.1/2.0 PHY driver
>> + *
>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
>> + * Author: Kamil Debski <k.debski@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/clk.h>
>> +#include <linux/mfd/syscon.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>
>> +#include "phy-samsung-usb2.h"
>> +
>> +static int samsung_usb2_phy_power_on(struct phy *phy)
>> +{
>> + struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
>> + struct samsung_usb2_phy_driver *drv = inst->drv;
>> + int ret;
>> +
>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
>> + inst->cfg->label);
>> + ret = clk_prepare_enable(drv->clk);
>
> clk_prepare_enable() can sleep, and therefore doesn't allow
> samusng_usb2_phy_power_on() to be used in atomic context
> (e.g. inside spin_lock-ed area), what sometimes may be desirable.
> What about to prepare clock in probe, and just enable it here
> (note: clk_enable() doesn't sleep).
The PHY power-on callback is anyway called with mutex held, so I guess
it's fine to have clk_prepare_enable() here.
Thanks
Kishon
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 8:30 ` Kishon Vijay Abraham I
@ 2014-03-06 8:52 ` Anton Tikhomirov
[not found] ` <006201cf3919$5f760750$1e6215f0$%tikhomirov-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
0 siblings, 1 reply; 20+ messages in thread
From: Anton Tikhomirov @ 2014-03-06 8:52 UTC (permalink / raw)
To: 'Kishon Vijay Abraham I', 'Kamil Debski',
linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, t.figa, s.nawrocki, m.szyprowski, gautam.vivek,
mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak, matt.porter,
tjakobi, stern, sander
Hello,
> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>
>
>
> On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
> > Hi Kamil,
> >
> > ...
> >
> >> +| 3. Supporting SoCs
> >> ++--------------------
> >> +
> >> +To support a new SoC a new file should be added to the drivers/phy
> >> +directory. Each SoC's configuration is stored in an instance of the
> >> +struct samsung_usb2_phy_config.
> >> +
> >> +struct samsung_usb2_phy_config {
> >> + const struct samsung_usb2_common_phy *phys;
> >> + unsigned int num_phys;
> >> + bool has_mode_switch;
> >
> > You missed rate_to_clk here.
> >
> >> +};
> >> +
> >
> > ...
> >
> >> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
> samsung-
> >> usb2.c
> >> new file mode 100644
> >> index 0000000..c3b7719
> >> --- /dev/null
> >> +++ b/drivers/phy/phy-samsung-usb2.c
> >> @@ -0,0 +1,222 @@
> >> +/*
> >> + * Samsung SoC USB 1.1/2.0 PHY driver
> >> + *
> >> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> >> + * Author: Kamil Debski <k.debski@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/clk.h>
> >> +#include <linux/mfd/syscon.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>
> >> +#include "phy-samsung-usb2.h"
> >> +
> >> +static int samsung_usb2_phy_power_on(struct phy *phy)
> >> +{
> >> + struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
> >> + struct samsung_usb2_phy_driver *drv = inst->drv;
> >> + int ret;
> >> +
> >> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
> >> + inst->cfg->label);
> >> + ret = clk_prepare_enable(drv->clk);
> >
> > clk_prepare_enable() can sleep, and therefore doesn't allow
> > samusng_usb2_phy_power_on() to be used in atomic context
> > (e.g. inside spin_lock-ed area), what sometimes may be desirable.
> > What about to prepare clock in probe, and just enable it here
> > (note: clk_enable() doesn't sleep).
>
> The PHY power-on callback is anyway called with mutex held, so I guess
> it's fine to have clk_prepare_enable() here.
If we rely totally on generic PHY functions such as phy_power_on()
and friends, why do we need to use locking in callbacks at all.
>
> Thanks
> Kishon
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
[not found] ` <006201cf3919$5f760750$1e6215f0$%tikhomirov-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
@ 2014-03-06 8:56 ` Kishon Vijay Abraham I
2014-03-06 9:02 ` Anton Tikhomirov
0 siblings, 1 reply; 20+ messages in thread
From: Kishon Vijay Abraham I @ 2014-03-06 8:56 UTC (permalink / raw)
To: Anton Tikhomirov, 'Kamil Debski',
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-samsung-soc-u79uwXL29TY76Z2rM5mHXA,
linux-usb-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
Cc: kyungmin.park-Sze3O3UU22JBDgjK7y7TUQ,
t.figa-Sze3O3UU22JBDgjK7y7TUQ, s.nawrocki-Sze3O3UU22JBDgjK7y7TUQ,
m.szyprowski-Sze3O3UU22JBDgjK7y7TUQ,
gautam.vivek-Sze3O3UU22JBDgjK7y7TUQ,
mat.krawczuk-Re5JQEeQqe8AvxtiuMwx3w,
yulgon.kim-Sze3O3UU22JBDgjK7y7TUQ,
p.paneri-Sze3O3UU22JBDgjK7y7TUQ, jg1.han-Sze3O3UU22JBDgjK7y7TUQ,
galak-sgV2jX0FEOL9JmXXK+q4OQ, matt.porter-QSEj5FYQhm4dnm+yROfE0A,
tjakobi-o02PS0xoJP9W0yFyLvAVXMxlOr/tl8fh,
stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz,
sander-7Kwe/DFdFGvR7s880joybQ
Hi,
On Thursday 06 March 2014 02:22 PM, Anton Tikhomirov wrote:
> Hello,
>
>> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>>
>>
>>
>> On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
>>> Hi Kamil,
>>>
>>> ...
>>>
>>>> +| 3. Supporting SoCs
>>>> ++--------------------
>>>> +
>>>> +To support a new SoC a new file should be added to the drivers/phy
>>>> +directory. Each SoC's configuration is stored in an instance of the
>>>> +struct samsung_usb2_phy_config.
>>>> +
>>>> +struct samsung_usb2_phy_config {
>>>> + const struct samsung_usb2_common_phy *phys;
>>>> + unsigned int num_phys;
>>>> + bool has_mode_switch;
>>>
>>> You missed rate_to_clk here.
>>>
>>>> +};
>>>> +
>>>
>>> ...
>>>
>>>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
>> samsung-
>>>> usb2.c
>>>> new file mode 100644
>>>> index 0000000..c3b7719
>>>> --- /dev/null
>>>> +++ b/drivers/phy/phy-samsung-usb2.c
>>>> @@ -0,0 +1,222 @@
>>>> +/*
>>>> + * Samsung SoC USB 1.1/2.0 PHY driver
>>>> + *
>>>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
>>>> + * Author: Kamil Debski <k.debski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
>>>> + *
>>>> + * 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/clk.h>
>>>> +#include <linux/mfd/syscon.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>
>>>> +#include "phy-samsung-usb2.h"
>>>> +
>>>> +static int samsung_usb2_phy_power_on(struct phy *phy)
>>>> +{
>>>> + struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
>>>> + struct samsung_usb2_phy_driver *drv = inst->drv;
>>>> + int ret;
>>>> +
>>>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
>>>> + inst->cfg->label);
>>>> + ret = clk_prepare_enable(drv->clk);
>>>
>>> clk_prepare_enable() can sleep, and therefore doesn't allow
>>> samusng_usb2_phy_power_on() to be used in atomic context
>>> (e.g. inside spin_lock-ed area), what sometimes may be desirable.
>>> What about to prepare clock in probe, and just enable it here
>>> (note: clk_enable() doesn't sleep).
>>
>> The PHY power-on callback is anyway called with mutex held, so I guess
>> it's fine to have clk_prepare_enable() here.
>
> If we rely totally on generic PHY functions such as phy_power_on()
> and friends, why do we need to use locking in callbacks at all.
Didn't get you.. We don't want to invoke power_on when init is getting
executed or you don't want power on or power off to get executed
simultaneously right? So we need to protect it.
Cheers
Kishon
--
To unsubscribe from this list: send the line "unsubscribe devicetree" 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] 20+ messages in thread
* RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 8:56 ` Kishon Vijay Abraham I
@ 2014-03-06 9:02 ` Anton Tikhomirov
2014-03-06 9:19 ` Anton Tikhomirov
0 siblings, 1 reply; 20+ messages in thread
From: Anton Tikhomirov @ 2014-03-06 9:02 UTC (permalink / raw)
To: 'Kishon Vijay Abraham I', 'Kamil Debski',
linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, t.figa, s.nawrocki, m.szyprowski, gautam.vivek,
mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak, matt.porter,
tjakobi, stern, sander
Hi,
> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>
> Hi,
>
> On Thursday 06 March 2014 02:22 PM, Anton Tikhomirov wrote:
> > Hello,
> >
> >> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> >>
> >>
> >>
> >> On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
> >>> Hi Kamil,
> >>>
> >>> ...
> >>>
> >>>> +| 3. Supporting SoCs
> >>>> ++--------------------
> >>>> +
> >>>> +To support a new SoC a new file should be added to the
> drivers/phy
> >>>> +directory. Each SoC's configuration is stored in an instance of
> the
> >>>> +struct samsung_usb2_phy_config.
> >>>> +
> >>>> +struct samsung_usb2_phy_config {
> >>>> + const struct samsung_usb2_common_phy *phys;
> >>>> + unsigned int num_phys;
> >>>> + bool has_mode_switch;
> >>>
> >>> You missed rate_to_clk here.
> >>>
> >>>> +};
> >>>> +
> >>>
> >>> ...
> >>>
> >>>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
> >> samsung-
> >>>> usb2.c
> >>>> new file mode 100644
> >>>> index 0000000..c3b7719
> >>>> --- /dev/null
> >>>> +++ b/drivers/phy/phy-samsung-usb2.c
> >>>> @@ -0,0 +1,222 @@
> >>>> +/*
> >>>> + * Samsung SoC USB 1.1/2.0 PHY driver
> >>>> + *
> >>>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> >>>> + * Author: Kamil Debski <k.debski@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/clk.h>
> >>>> +#include <linux/mfd/syscon.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>
> >>>> +#include "phy-samsung-usb2.h"
> >>>> +
> >>>> +static int samsung_usb2_phy_power_on(struct phy *phy)
> >>>> +{
> >>>> + struct samsung_usb2_phy_instance *inst =
> phy_get_drvdata(phy);
> >>>> + struct samsung_usb2_phy_driver *drv = inst->drv;
> >>>> + int ret;
> >>>> +
> >>>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
> >>>> + inst->cfg->label);
> >>>> + ret = clk_prepare_enable(drv->clk);
> >>>
> >>> clk_prepare_enable() can sleep, and therefore doesn't allow
> >>> samusng_usb2_phy_power_on() to be used in atomic context
> >>> (e.g. inside spin_lock-ed area), what sometimes may be desirable.
> >>> What about to prepare clock in probe, and just enable it here
> >>> (note: clk_enable() doesn't sleep).
> >>
> >> The PHY power-on callback is anyway called with mutex held, so I
> guess
> >> it's fine to have clk_prepare_enable() here.
> >
> > If we rely totally on generic PHY functions such as phy_power_on()
> > and friends, why do we need to use locking in callbacks at all.
>
> Didn't get you.. We don't want to invoke power_on when init is getting
> executed or you don't want power on or power off to get executed
> simultaneously right? So we need to protect it.
I mean callbacks such as samsung_usb2_phy_power_on() which uses spin_lock.
It's already protected by mutex in phy_power_on().
>
> Cheers
> Kishon
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 9:02 ` Anton Tikhomirov
@ 2014-03-06 9:19 ` Anton Tikhomirov
2014-03-06 9:27 ` Kishon Vijay Abraham I
0 siblings, 1 reply; 20+ messages in thread
From: Anton Tikhomirov @ 2014-03-06 9:19 UTC (permalink / raw)
To: 'Anton Tikhomirov', 'Kishon Vijay Abraham I',
'Kamil Debski', linux-kernel, linux-samsung-soc,
linux-usb, devicetree
Cc: kyungmin.park, t.figa, s.nawrocki, m.szyprowski, gautam.vivek,
mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak, matt.porter,
tjakobi, stern, sander
Hi,
> Subject: RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>
> Hi,
>
> > Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> >
> > Hi,
> >
> > On Thursday 06 March 2014 02:22 PM, Anton Tikhomirov wrote:
> > > Hello,
> > >
> > >> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> > >>
> > >>
> > >>
> > >> On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
> > >>> Hi Kamil,
> > >>>
> > >>> ...
> > >>>
> > >>>> +| 3. Supporting SoCs
> > >>>> ++--------------------
> > >>>> +
> > >>>> +To support a new SoC a new file should be added to the
> > drivers/phy
> > >>>> +directory. Each SoC's configuration is stored in an instance of
> > the
> > >>>> +struct samsung_usb2_phy_config.
> > >>>> +
> > >>>> +struct samsung_usb2_phy_config {
> > >>>> + const struct samsung_usb2_common_phy *phys;
> > >>>> + unsigned int num_phys;
> > >>>> + bool has_mode_switch;
> > >>>
> > >>> You missed rate_to_clk here.
> > >>>
> > >>>> +};
> > >>>> +
> > >>>
> > >>> ...
> > >>>
> > >>>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
> > >> samsung-
> > >>>> usb2.c
> > >>>> new file mode 100644
> > >>>> index 0000000..c3b7719
> > >>>> --- /dev/null
> > >>>> +++ b/drivers/phy/phy-samsung-usb2.c
> > >>>> @@ -0,0 +1,222 @@
> > >>>> +/*
> > >>>> + * Samsung SoC USB 1.1/2.0 PHY driver
> > >>>> + *
> > >>>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> > >>>> + * Author: Kamil Debski <k.debski@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/clk.h>
> > >>>> +#include <linux/mfd/syscon.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>
> > >>>> +#include "phy-samsung-usb2.h"
> > >>>> +
> > >>>> +static int samsung_usb2_phy_power_on(struct phy *phy)
> > >>>> +{
> > >>>> + struct samsung_usb2_phy_instance *inst =
> > phy_get_drvdata(phy);
> > >>>> + struct samsung_usb2_phy_driver *drv = inst->drv;
> > >>>> + int ret;
> > >>>> +
> > >>>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
> > >>>> + inst->cfg->label);
> > >>>> + ret = clk_prepare_enable(drv->clk);
> > >>>
> > >>> clk_prepare_enable() can sleep, and therefore doesn't allow
> > >>> samusng_usb2_phy_power_on() to be used in atomic context
> > >>> (e.g. inside spin_lock-ed area), what sometimes may be desirable.
> > >>> What about to prepare clock in probe, and just enable it here
> > >>> (note: clk_enable() doesn't sleep).
> > >>
> > >> The PHY power-on callback is anyway called with mutex held, so I
> > guess
> > >> it's fine to have clk_prepare_enable() here.
> > >
> > > If we rely totally on generic PHY functions such as phy_power_on()
> > > and friends, why do we need to use locking in callbacks at all.
> >
> > Didn't get you.. We don't want to invoke power_on when init is
> getting
> > executed or you don't want power on or power off to get executed
> > simultaneously right? So we need to protect it.
>
> I mean callbacks such as samsung_usb2_phy_power_on() which uses
> spin_lock.
> It's already protected by mutex in phy_power_on().
Well... phy_power_on() uses mutex to protect power_on() callback.
power_on() is samsung_usb2_phy_power_on() in our case.
samsung_usb2_phy_power_on() uses spinlock.
My question is why do we need to use spinlock _inside_ callback
if it is already protected by mutex.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 9:19 ` Anton Tikhomirov
@ 2014-03-06 9:27 ` Kishon Vijay Abraham I
2014-03-07 5:16 ` Anton Tikhomirov
0 siblings, 1 reply; 20+ messages in thread
From: Kishon Vijay Abraham I @ 2014-03-06 9:27 UTC (permalink / raw)
To: Anton Tikhomirov, 'Kamil Debski', linux-kernel,
linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, t.figa, s.nawrocki, m.szyprowski, gautam.vivek,
mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak, matt.porter,
tjakobi, stern, sander
Hi,
On Thursday 06 March 2014 02:49 PM, Anton Tikhomirov wrote:
> Hi,
>
>> Subject: RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>>
>> Hi,
>>
>>> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>>>
>>> Hi,
>>>
>>> On Thursday 06 March 2014 02:22 PM, Anton Tikhomirov wrote:
>>>> Hello,
>>>>
>>>>> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>>>>>
>>>>>
>>>>>
>>>>> On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
>>>>>> Hi Kamil,
>>>>>>
>>>>>> ...
>>>>>>
>>>>>>> +| 3. Supporting SoCs
>>>>>>> ++--------------------
>>>>>>> +
>>>>>>> +To support a new SoC a new file should be added to the
>>> drivers/phy
>>>>>>> +directory. Each SoC's configuration is stored in an instance of
>>> the
>>>>>>> +struct samsung_usb2_phy_config.
>>>>>>> +
>>>>>>> +struct samsung_usb2_phy_config {
>>>>>>> + const struct samsung_usb2_common_phy *phys;
>>>>>>> + unsigned int num_phys;
>>>>>>> + bool has_mode_switch;
>>>>>>
>>>>>> You missed rate_to_clk here.
>>>>>>
>>>>>>> +};
>>>>>>> +
>>>>>>
>>>>>> ...
>>>>>>
>>>>>>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
>>>>> samsung-
>>>>>>> usb2.c
>>>>>>> new file mode 100644
>>>>>>> index 0000000..c3b7719
>>>>>>> --- /dev/null
>>>>>>> +++ b/drivers/phy/phy-samsung-usb2.c
>>>>>>> @@ -0,0 +1,222 @@
>>>>>>> +/*
>>>>>>> + * Samsung SoC USB 1.1/2.0 PHY driver
>>>>>>> + *
>>>>>>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
>>>>>>> + * Author: Kamil Debski <k.debski@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/clk.h>
>>>>>>> +#include <linux/mfd/syscon.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>
>>>>>>> +#include "phy-samsung-usb2.h"
>>>>>>> +
>>>>>>> +static int samsung_usb2_phy_power_on(struct phy *phy)
>>>>>>> +{
>>>>>>> + struct samsung_usb2_phy_instance *inst =
>>> phy_get_drvdata(phy);
>>>>>>> + struct samsung_usb2_phy_driver *drv = inst->drv;
>>>>>>> + int ret;
>>>>>>> +
>>>>>>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
>>>>>>> + inst->cfg->label);
>>>>>>> + ret = clk_prepare_enable(drv->clk);
>>>>>>
>>>>>> clk_prepare_enable() can sleep, and therefore doesn't allow
>>>>>> samusng_usb2_phy_power_on() to be used in atomic context
>>>>>> (e.g. inside spin_lock-ed area), what sometimes may be desirable.
>>>>>> What about to prepare clock in probe, and just enable it here
>>>>>> (note: clk_enable() doesn't sleep).
>>>>>
>>>>> The PHY power-on callback is anyway called with mutex held, so I
>>> guess
>>>>> it's fine to have clk_prepare_enable() here.
>>>>
>>>> If we rely totally on generic PHY functions such as phy_power_on()
>>>> and friends, why do we need to use locking in callbacks at all.
>>>
>>> Didn't get you.. We don't want to invoke power_on when init is
>> getting
>>> executed or you don't want power on or power off to get executed
>>> simultaneously right? So we need to protect it.
>>
>> I mean callbacks such as samsung_usb2_phy_power_on() which uses
>> spin_lock.
>> It's already protected by mutex in phy_power_on().
>
> Well... phy_power_on() uses mutex to protect power_on() callback.
> power_on() is samsung_usb2_phy_power_on() in our case.
> samsung_usb2_phy_power_on() uses spinlock.
> My question is why do we need to use spinlock _inside_ callback
> if it is already protected by mutex.
It is needed when the same PHY provider implements multiple PHYs.
phy-core can protect phy-ops of same PHY. However if the PHY provider
implements multiple PHYs, phy-core won't be able to protect.
Cheers
Kishon
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 8:26 ` Anton Tikhomirov
2014-03-06 8:30 ` Kishon Vijay Abraham I
@ 2014-03-06 10:24 ` Kamil Debski
2014-03-06 10:44 ` Kishon Vijay Abraham I
1 sibling, 1 reply; 20+ messages in thread
From: Kamil Debski @ 2014-03-06 10:24 UTC (permalink / raw)
To: 'Anton Tikhomirov', linux-kernel, linux-samsung-soc,
linux-usb, devicetree
Cc: kyungmin.park, kishon, Tomasz Figa, Sylwester Nawrocki,
Marek Szyprowski, gautam.vivek, mat.krawczuk, yulgon.kim,
p.paneri, jg1.han, galak, matt.porter, tjakobi, stern, sander
Hi Anton, Kishon,
> From: Anton Tikhomirov [mailto:av.tikhomirov@samsung.com]
> Sent: Thursday, March 06, 2014 9:26 AM
>
> Hi Kamil,
>
> ...
>
> > +| 3. Supporting SoCs
> > ++--------------------
> > +
> > +To support a new SoC a new file should be added to the drivers/phy
> > +directory. Each SoC's configuration is stored in an instance of the
> > +struct samsung_usb2_phy_config.
> > +
> > +struct samsung_usb2_phy_config {
> > + const struct samsung_usb2_common_phy *phys;
> > + unsigned int num_phys;
> > + bool has_mode_switch;
>
> You missed rate_to_clk here.
Thank you for spotting this.
Kishon: I am sorry that this omission was made. I am happy to send an
updated patchset. However, I want to give some time for any additional
comments. Do you think that we have for this? Is today evening ok with you?
>
> > +};
> > +
>
> ...
>
> > diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
> samsung-
> > usb2.c new file mode 100644 index 0000000..c3b7719
> > --- /dev/null
> > +++ b/drivers/phy/phy-samsung-usb2.c
> > @@ -0,0 +1,222 @@
> > +/*
> > + * Samsung SoC USB 1.1/2.0 PHY driver
> > + *
> > + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> > + * Author: Kamil Debski <k.debski@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/clk.h>
> > +#include <linux/mfd/syscon.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>
> > +#include "phy-samsung-usb2.h"
> > +
> > +static int samsung_usb2_phy_power_on(struct phy *phy) {
> > + struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
> > + struct samsung_usb2_phy_driver *drv = inst->drv;
> > + int ret;
> > +
> > + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
> > + inst->cfg->label);
> > + ret = clk_prepare_enable(drv->clk);
>
> clk_prepare_enable() can sleep, and therefore doesn't allow
> samusng_usb2_phy_power_on() to be used in atomic context (e.g. inside
> spin_lock-ed area), what sometimes may be desirable.
> What about to prepare clock in probe, and just enable it here
> (note: clk_enable() doesn't sleep).
>From the onward discussion between you and Kishon, I draw the conclusion
that this change is not necessary. Right?
>
> > + if (ret)
> > + goto err_main_clk;
> > + ret = clk_prepare_enable(drv->ref_clk);
> > + if (ret)
> > + goto err_instance_clk;
> > + if (inst->cfg->power_on) {
> > + spin_lock(&drv->lock);
> > + ret = inst->cfg->power_on(inst);
> > + spin_unlock(&drv->lock);
> > + }
> > +
> > + return 0;
>
> Thank you
Best wishes,
--
Kamil Debski
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-05 23:08 ` [PATCH v9 0/4] phy: Add new " Tobias Jakobi
@ 2014-03-06 10:25 ` Kamil Debski
0 siblings, 0 replies; 20+ messages in thread
From: Kamil Debski @ 2014-03-06 10:25 UTC (permalink / raw)
To: 'Tobias Jakobi', linux-kernel, linux-samsung-soc,
linux-usb, devicetree
Cc: kyungmin.park, kishon, Tomasz Figa, Sylwester Nawrocki,
Marek Szyprowski, gautam.vivek, mat.krawczuk, yulgon.kim,
p.paneri, av.tikhomirov, jg1.han, galak, matt.porter, stern,
sander
Hi Tobias,
> From: Tobias Jakobi [mailto:tjakobi@math.uni-bielefeld.de]
> Sent: Thursday, March 06, 2014 12:08 AM
>
> Hello Kamil,
>
> this looks very good. I just tested the patchset on my ODROID-X2
> (Exynos4412-based board) and the USB stability issues I mentioned to
> you before (with the older patchset) seem to be gone.
This problem was related to the reset procedure not being done completely.
It is corrected now.
>
> All devices on the USB behave normally (mass storage, ethernet and
> bluetooth).
Thank you for testing these patches. Would you consider adding a "Tested-by" tag?
I am planning to send v10 soon, which will address comments to v9.
>
> With best wishes,
> Tobias
Best wishes,
--
Kamil Debski
Samsung R&D Institute Poland
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 10:24 ` Kamil Debski
@ 2014-03-06 10:44 ` Kishon Vijay Abraham I
0 siblings, 0 replies; 20+ messages in thread
From: Kishon Vijay Abraham I @ 2014-03-06 10:44 UTC (permalink / raw)
To: Kamil Debski, 'Anton Tikhomirov', linux-kernel,
linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, Tomasz Figa, Sylwester Nawrocki, Marek Szyprowski,
gautam.vivek, mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak,
matt.porter, tjakobi, stern, sander
Hi,
On Thursday 06 March 2014 03:54 PM, Kamil Debski wrote:
> Hi Anton, Kishon,
>
>> From: Anton Tikhomirov [mailto:av.tikhomirov@samsung.com]
>> Sent: Thursday, March 06, 2014 9:26 AM
>>
>> Hi Kamil,
>>
>> ...
>>
>>> +| 3. Supporting SoCs
>>> ++--------------------
>>> +
>>> +To support a new SoC a new file should be added to the drivers/phy
>>> +directory. Each SoC's configuration is stored in an instance of the
>>> +struct samsung_usb2_phy_config.
>>> +
>>> +struct samsung_usb2_phy_config {
>>> + const struct samsung_usb2_common_phy *phys;
>>> + unsigned int num_phys;
>>> + bool has_mode_switch;
>>
>> You missed rate_to_clk here.
>
> Thank you for spotting this.
>
> Kishon: I am sorry that this omission was made. I am happy to send an
> updated patchset. However, I want to give some time for any additional
> comments. Do you think that we have for this? Is today evening ok with you?
Would be great if you can send the patch in 2-3 hrs.. I'd like to give
enough time for auto build to detect any errors.
>>
>>> +};
>>> +
>>
>> ...
>>
>>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
>> samsung-
>>> usb2.c new file mode 100644 index 0000000..c3b7719
>>> --- /dev/null
>>> +++ b/drivers/phy/phy-samsung-usb2.c
>>> @@ -0,0 +1,222 @@
>>> +/*
>>> + * Samsung SoC USB 1.1/2.0 PHY driver
>>> + *
>>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
>>> + * Author: Kamil Debski <k.debski@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/clk.h>
>>> +#include <linux/mfd/syscon.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>
>>> +#include "phy-samsung-usb2.h"
>>> +
>>> +static int samsung_usb2_phy_power_on(struct phy *phy) {
>>> + struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
>>> + struct samsung_usb2_phy_driver *drv = inst->drv;
>>> + int ret;
>>> +
>>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
>>> + inst->cfg->label);
>>> + ret = clk_prepare_enable(drv->clk);
>>
>> clk_prepare_enable() can sleep, and therefore doesn't allow
>> samusng_usb2_phy_power_on() to be used in atomic context (e.g. inside
>> spin_lock-ed area), what sometimes may be desirable.
>> What about to prepare clock in probe, and just enable it here
>> (note: clk_enable() doesn't sleep).
>
> From the onward discussion between you and Kishon, I draw the conclusion
> that this change is not necessary. Right?
right.
Cheers
Kishon
^ permalink raw reply [flat|nested] 20+ messages in thread
* RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
2014-03-06 9:27 ` Kishon Vijay Abraham I
@ 2014-03-07 5:16 ` Anton Tikhomirov
0 siblings, 0 replies; 20+ messages in thread
From: Anton Tikhomirov @ 2014-03-07 5:16 UTC (permalink / raw)
To: 'Kishon Vijay Abraham I', 'Kamil Debski',
linux-kernel, linux-samsung-soc, linux-usb, devicetree
Cc: kyungmin.park, t.figa, s.nawrocki, m.szyprowski, gautam.vivek,
mat.krawczuk, yulgon.kim, p.paneri, jg1.han, galak, matt.porter,
tjakobi, stern, sander
Hi,
> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
>
> Hi,
>
> On Thursday 06 March 2014 02:49 PM, Anton Tikhomirov wrote:
> > Hi,
> >
> >> Subject: RE: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> >>
> >> Hi,
> >>
> >>> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver
> >>>
> >>> Hi,
> >>>
> >>> On Thursday 06 March 2014 02:22 PM, Anton Tikhomirov wrote:
> >>>> Hello,
> >>>>
> >>>>> Subject: Re: [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY
> driver
> >>>>>
> >>>>>
> >>>>>
> >>>>> On Thursday 06 March 2014 01:56 PM, Anton Tikhomirov wrote:
> >>>>>> Hi Kamil,
> >>>>>>
> >>>>>> ...
> >>>>>>
> >>>>>>> +| 3. Supporting SoCs
> >>>>>>> ++--------------------
> >>>>>>> +
> >>>>>>> +To support a new SoC a new file should be added to the
> >>> drivers/phy
> >>>>>>> +directory. Each SoC's configuration is stored in an instance
> of
> >>> the
> >>>>>>> +struct samsung_usb2_phy_config.
> >>>>>>> +
> >>>>>>> +struct samsung_usb2_phy_config {
> >>>>>>> + const struct samsung_usb2_common_phy *phys;
> >>>>>>> + unsigned int num_phys;
> >>>>>>> + bool has_mode_switch;
> >>>>>>
> >>>>>> You missed rate_to_clk here.
> >>>>>>
> >>>>>>> +};
> >>>>>>> +
> >>>>>>
> >>>>>> ...
> >>>>>>
> >>>>>>> diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-
> >>>>> samsung-
> >>>>>>> usb2.c
> >>>>>>> new file mode 100644
> >>>>>>> index 0000000..c3b7719
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/drivers/phy/phy-samsung-usb2.c
> >>>>>>> @@ -0,0 +1,222 @@
> >>>>>>> +/*
> >>>>>>> + * Samsung SoC USB 1.1/2.0 PHY driver
> >>>>>>> + *
> >>>>>>> + * Copyright (C) 2013 Samsung Electronics Co., Ltd.
> >>>>>>> + * Author: Kamil Debski <k.debski@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/clk.h>
> >>>>>>> +#include <linux/mfd/syscon.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>
> >>>>>>> +#include "phy-samsung-usb2.h"
> >>>>>>> +
> >>>>>>> +static int samsung_usb2_phy_power_on(struct phy *phy)
> >>>>>>> +{
> >>>>>>> + struct samsung_usb2_phy_instance *inst =
> >>> phy_get_drvdata(phy);
> >>>>>>> + struct samsung_usb2_phy_driver *drv = inst->drv;
> >>>>>>> + int ret;
> >>>>>>> +
> >>>>>>> + dev_dbg(drv->dev, "Request to power_on \"%s\" usb phy\n",
> >>>>>>> + inst->cfg->label);
> >>>>>>> + ret = clk_prepare_enable(drv->clk);
> >>>>>>
> >>>>>> clk_prepare_enable() can sleep, and therefore doesn't allow
> >>>>>> samusng_usb2_phy_power_on() to be used in atomic context
> >>>>>> (e.g. inside spin_lock-ed area), what sometimes may be desirable.
> >>>>>> What about to prepare clock in probe, and just enable it here
> >>>>>> (note: clk_enable() doesn't sleep).
> >>>>>
> >>>>> The PHY power-on callback is anyway called with mutex held, so I
> >>> guess
> >>>>> it's fine to have clk_prepare_enable() here.
> >>>>
> >>>> If we rely totally on generic PHY functions such as phy_power_on()
> >>>> and friends, why do we need to use locking in callbacks at all.
> >>>
> >>> Didn't get you.. We don't want to invoke power_on when init is
> >> getting
> >>> executed or you don't want power on or power off to get executed
> >>> simultaneously right? So we need to protect it.
> >>
> >> I mean callbacks such as samsung_usb2_phy_power_on() which uses
> >> spin_lock.
> >> It's already protected by mutex in phy_power_on().
> >
> > Well... phy_power_on() uses mutex to protect power_on() callback.
> > power_on() is samsung_usb2_phy_power_on() in our case.
> > samsung_usb2_phy_power_on() uses spinlock.
> > My question is why do we need to use spinlock _inside_ callback
> > if it is already protected by mutex.
>
> It is needed when the same PHY provider implements multiple PHYs.
> phy-core can protect phy-ops of same PHY. However if the PHY provider
> implements multiple PHYs, phy-core won't be able to protect.
Thank you Kishon. Now it's clear.
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2014-03-07 5:16 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-05 15:28 [PATCH v9 0/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
2014-03-05 15:28 ` [PATCH v9 1/4] phy: core: Add an exported of_phy_get function Kamil Debski
2014-03-05 16:03 ` Tomasz Figa
2014-03-05 15:28 ` [PATCH v9 2/4] phy: core: Add devm_of_phy_get to phy-core Kamil Debski
2014-03-05 16:04 ` Tomasz Figa
2014-03-05 15:28 ` [PATCH v9 3/4] phy: Add new Exynos USB 2.0 PHY driver Kamil Debski
2014-03-05 16:04 ` Tomasz Figa
2014-03-06 8:26 ` Anton Tikhomirov
2014-03-06 8:30 ` Kishon Vijay Abraham I
2014-03-06 8:52 ` Anton Tikhomirov
[not found] ` <006201cf3919$5f760750$1e6215f0$%tikhomirov-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2014-03-06 8:56 ` Kishon Vijay Abraham I
2014-03-06 9:02 ` Anton Tikhomirov
2014-03-06 9:19 ` Anton Tikhomirov
2014-03-06 9:27 ` Kishon Vijay Abraham I
2014-03-07 5:16 ` Anton Tikhomirov
2014-03-06 10:24 ` Kamil Debski
2014-03-06 10:44 ` Kishon Vijay Abraham I
2014-03-05 15:28 ` [PATCH v9 4/4] phy: Add Exynos 5250 support to the " Kamil Debski
[not found] ` <1394033288-5551-1-git-send-email-k.debski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2014-03-05 23:08 ` [PATCH v9 0/4] phy: Add new " Tobias Jakobi
2014-03-06 10:25 ` Kamil Debski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).