* [PATCH 01/21] of: device: Support loading a module with OF based modalias
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-28 4:17 ` Bjorn Andersson
2016-06-26 7:28 ` [PATCH 02/21] usb: ulpi: Support device discovery via DT Stephen Boyd
` (20 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Rob Herring, devicetree
In the case of ULPI devices, we want to be able to load the
driver before registering the device so that we don't get stuck
in a loop waiting for the phy module to appear and failing usb
controller probe. Currently we request the ulpi module via the
ulpi ids, but in the DT case we might need to request it with the
OF based modalias instead. Add a common function that allows
anyone to request a module with the OF based modalias.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/of/device.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
include/linux/of_device.h | 6 ++++++
2 files changed, 56 insertions(+)
diff --git a/drivers/of/device.c b/drivers/of/device.c
index fd5cfad7c403..f275e5beb736 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -226,6 +226,56 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
return tsize;
}
+static ssize_t of_device_modalias_size(struct device *dev)
+{
+ const char *compat;
+ int cplen, i;
+ ssize_t csize;
+
+ if ((!dev) || (!dev->of_node))
+ return -ENODEV;
+
+ /* Name & Type */
+ csize = 5 + strlen(dev->of_node->name) + strlen(dev->of_node->type);
+
+ /* Get compatible property if any */
+ compat = of_get_property(dev->of_node, "compatible", &cplen);
+ if (!compat)
+ return csize;
+
+ /* Find true end (we tolerate multiple \0 at the end */
+ for (i = (cplen - 1); i >= 0 && !compat[i]; i--)
+ cplen--;
+ if (!cplen)
+ return csize;
+ cplen++;
+
+ /* Check space (need cplen+1 chars including final \0) */
+ return csize + cplen;
+}
+
+int of_device_request_module(struct device *dev)
+{
+ char *str;
+ ssize_t size;
+ int ret;
+
+ size = of_device_modalias_size(dev);
+ if (size < 0)
+ return size;
+
+ str = kmalloc(size + 1, GFP_KERNEL);
+ if (!str)
+ return -ENOMEM;
+
+ of_device_get_modalias(dev, str, size);
+ str[size] = '\0';
+ ret = request_module(str);
+ kfree(str);
+
+ return ret;
+}
+
/**
* of_device_uevent - Display OF related uevent information
*/
diff --git a/include/linux/of_device.h b/include/linux/of_device.h
index cc7dd687a89d..e9afbcc8de12 100644
--- a/include/linux/of_device.h
+++ b/include/linux/of_device.h
@@ -37,6 +37,7 @@ extern const void *of_device_get_match_data(const struct device *dev);
extern ssize_t of_device_get_modalias(struct device *dev,
char *str, ssize_t len);
+extern int of_device_request_module(struct device *dev);
extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env);
extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env);
@@ -78,6 +79,11 @@ static inline int of_device_get_modalias(struct device *dev,
return -ENODEV;
}
+static inline int of_device_request_module(struct device *dev)
+{
+ return -ENODEV;
+}
+
static inline int of_device_uevent_modalias(struct device *dev,
struct kobj_uevent_env *env)
{
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 01/21] of: device: Support loading a module with OF based modalias
2016-06-26 7:28 ` [PATCH 01/21] of: device: Support loading a module with OF based modalias Stephen Boyd
@ 2016-06-28 4:17 ` Bjorn Andersson
0 siblings, 0 replies; 69+ messages in thread
From: Bjorn Andersson @ 2016-06-28 4:17 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Rob Herring, devicetree
On Sun 26 Jun 00:28 PDT 2016, Stephen Boyd wrote:
> In the case of ULPI devices, we want to be able to load the
> driver before registering the device so that we don't get stuck
> in a loop waiting for the phy module to appear and failing usb
> controller probe. Currently we request the ulpi module via the
> ulpi ids, but in the DT case we might need to request it with the
> OF based modalias instead. Add a common function that allows
> anyone to request a module with the OF based modalias.
>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: <devicetree@vger.kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/of/device.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++
> include/linux/of_device.h | 6 ++++++
> 2 files changed, 56 insertions(+)
>
> diff --git a/drivers/of/device.c b/drivers/of/device.c
> index fd5cfad7c403..f275e5beb736 100644
> --- a/drivers/of/device.c
> +++ b/drivers/of/device.c
> @@ -226,6 +226,56 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
> return tsize;
> }
>
> +static ssize_t of_device_modalias_size(struct device *dev)
> +{
> + const char *compat;
> + int cplen, i;
> + ssize_t csize;
> +
> + if ((!dev) || (!dev->of_node))
> + return -ENODEV;
> +
> + /* Name & Type */
> + csize = 5 + strlen(dev->of_node->name) + strlen(dev->of_node->type);
It would be clearer if you replaced 5 with strlen("of:NT"), but...
> +
> + /* Get compatible property if any */
> + compat = of_get_property(dev->of_node, "compatible", &cplen);
> + if (!compat)
> + return csize;
> +
> + /* Find true end (we tolerate multiple \0 at the end */
> + for (i = (cplen - 1); i >= 0 && !compat[i]; i--)
> + cplen--;
> + if (!cplen)
> + return csize;
> + cplen++;
> +
> + /* Check space (need cplen+1 chars including final \0) */
> + return csize + cplen;
> +}
...if I understand of_device_get_modalias() correctly you should be able
to replace this function with:
size = of_device_get_modalias(dev, NULL, 0);
snprintf() will not write to NULL, csize will be larger than 0 so tsize
will be returned before it will memcpy() to the buffer.
> +
> +int of_device_request_module(struct device *dev)
> +{
> + char *str;
> + ssize_t size;
> + int ret;
> +
> + size = of_device_modalias_size(dev);
> + if (size < 0)
> + return size;
> +
> + str = kmalloc(size + 1, GFP_KERNEL);
> + if (!str)
> + return -ENOMEM;
> +
> + of_device_get_modalias(dev, str, size);
> + str[size] = '\0';
> + ret = request_module(str);
> + kfree(str);
> +
> + return ret;
> +}
> +
Regards,
Bjorn
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 02/21] usb: ulpi: Support device discovery via DT
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
2016-06-26 7:28 ` [PATCH 01/21] of: device: Support loading a module with OF based modalias Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-27 4:21 ` kbuild test robot
` (2 more replies)
2016-06-26 7:28 ` [PATCH 03/21] usb: ulpi: Avoid reading/writing in device creation with OF devices Stephen Boyd
` (19 subsequent siblings)
21 siblings, 3 replies; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Greg Kroah-Hartman, Heikki Krogerus, devicetree, Rob Herring
The qcom HSIC ulpi phy doesn't have any bits set in the vendor or
product id ulpi registers. This makes it impossible to make a
ulpi driver match against the id registers. Add support to
discover the ulpi phys via DT to help alleviate this problem.
We'll look for a ulpi bus node underneath the device registering
the ulpi viewport (or the parent of that device to support
chipidea's device layout) and then match up the phy node
underneath that with the ulpi device that's created.
The side benefit of this is that we can use standard DT
properties in the phy node like clks, regulators, gpios, etc.
because we don't have firmware like ACPI to turn these things on
for us. And we can use the DT phy binding to point our phy
consumer to the phy provider.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Cc: <devicetree@vger.kernel.org>
Cc: Rob Herring <robh+dt@kernel.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
Documentation/devicetree/bindings/usb/ulpi.txt | 20 +++++++++
drivers/usb/common/ulpi.c | 56 +++++++++++++++++++++++++-
2 files changed, 74 insertions(+), 2 deletions(-)
create mode 100644 Documentation/devicetree/bindings/usb/ulpi.txt
diff --git a/Documentation/devicetree/bindings/usb/ulpi.txt b/Documentation/devicetree/bindings/usb/ulpi.txt
new file mode 100644
index 000000000000..ca179dc4bd50
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ulpi.txt
@@ -0,0 +1,20 @@
+ULPI bus binding
+----------------
+
+Phys that are behind a ULPI connection can be described with the following
+binding. The host controller shall have a "ulpi" named node as a child, and
+that node shall have one enabled node underneath it representing the ulpi
+device on the bus.
+
+EXAMPLE
+-------
+
+usb {
+ compatible = "vendor,usb-controller";
+
+ ulpi {
+ phy {
+ compatible = "vendor,phy";
+ };
+ };
+};
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index 01c0c0477a9e..980af672bfe3 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -16,6 +16,9 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/acpi.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk/clk-conf.h>
/* -------------------------------------------------------------------------- */
@@ -39,7 +42,10 @@ static int ulpi_match(struct device *dev, struct device_driver *driver)
struct ulpi *ulpi = to_ulpi_dev(dev);
const struct ulpi_device_id *id;
- for (id = drv->id_table; id->vendor; id++)
+ if (of_driver_match_device(dev, driver))
+ return 1;
+
+ for (id = drv->id_table; id && id->vendor; id++)
if (id->vendor == ulpi->id.vendor &&
id->product == ulpi->id.product)
return 1;
@@ -50,6 +56,11 @@ static int ulpi_match(struct device *dev, struct device_driver *driver)
static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env)
{
struct ulpi *ulpi = to_ulpi_dev(dev);
+ int ret;
+
+ ret = of_device_uevent_modalias(dev, env);
+ if (ret != -ENODEV)
+ return ret;
if (add_uevent_var(env, "MODALIAS=ulpi:v%04xp%04x",
ulpi->id.vendor, ulpi->id.product))
@@ -60,6 +71,11 @@ static int ulpi_uevent(struct device *dev, struct kobj_uevent_env *env)
static int ulpi_probe(struct device *dev)
{
struct ulpi_driver *drv = to_ulpi_driver(dev->driver);
+ int ret;
+
+ ret = of_clk_set_defaults(dev->of_node, false);
+ if (ret < 0)
+ return ret;
return drv->probe(to_ulpi_dev(dev));
}
@@ -87,8 +103,13 @@ static struct bus_type ulpi_bus = {
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
+ int len;
struct ulpi *ulpi = to_ulpi_dev(dev);
+ len = of_device_get_modalias(dev, buf, PAGE_SIZE - 1);
+ if (len != -ENODEV)
+ return len;
+
return sprintf(buf, "ulpi:v%04xp%04x\n",
ulpi->id.vendor, ulpi->id.product);
}
@@ -152,6 +173,28 @@ EXPORT_SYMBOL_GPL(ulpi_unregister_driver);
/* -------------------------------------------------------------------------- */
+static int ulpi_of_register(struct ulpi *ulpi)
+{
+ struct device_node *np = NULL, *child;
+
+ /* Find a ulpi bus underneath the parent or the parent of the parent */
+ if (ulpi->dev.parent->of_node)
+ np = of_find_node_by_name(ulpi->dev.parent->of_node, "ulpi");
+ else if (ulpi->dev.parent->parent &&
+ ulpi->dev.parent->parent->of_node)
+ np = of_find_node_by_name(ulpi->dev.parent->parent->of_node, "ulpi");
+ if (!np)
+ return 0;
+
+ child = of_get_next_available_child(np, NULL);
+ if (!child)
+ return -EINVAL;
+
+ ulpi->dev.of_node = child;
+
+ return 0;
+}
+
static int ulpi_register(struct device *dev, struct ulpi *ulpi)
{
int ret;
@@ -181,7 +224,15 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi)
ACPI_COMPANION_SET(&ulpi->dev, ACPI_COMPANION(dev));
- request_module("ulpi:v%04xp%04x", ulpi->id.vendor, ulpi->id.product);
+ if (IS_ENABLED(CONFIG_OF)) {
+ ret = ulpi_of_register(ulpi);
+ if (ret)
+ return ret;
+ }
+
+ if (of_device_request_module(&ulpi->dev))
+ request_module("ulpi:v%04xp%04x", ulpi->id.vendor,
+ ulpi->id.product);
ret = device_register(&ulpi->dev);
if (ret)
@@ -232,6 +283,7 @@ EXPORT_SYMBOL_GPL(ulpi_register_interface);
*/
void ulpi_unregister_interface(struct ulpi *ulpi)
{
+ of_node_put(ulpi->dev.of_node);
device_unregister(&ulpi->dev);
}
EXPORT_SYMBOL_GPL(ulpi_unregister_interface);
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 02/21] usb: ulpi: Support device discovery via DT
2016-06-26 7:28 ` [PATCH 02/21] usb: ulpi: Support device discovery via DT Stephen Boyd
@ 2016-06-27 4:21 ` kbuild test robot
2016-06-27 14:34 ` Heikki Krogerus
2016-06-28 20:56 ` Rob Herring
2 siblings, 0 replies; 69+ messages in thread
From: kbuild test robot @ 2016-06-27 4:21 UTC (permalink / raw)
To: Stephen Boyd
Cc: kbuild-all, linux-usb, linux-arm-kernel, linux-kernel,
linux-arm-msm, Andy Gross, Bjorn Andersson, Neil Armstrong,
Arnd Bergmann, Felipe Balbi, Greg Kroah-Hartman, Heikki Krogerus,
devicetree, Rob Herring
[-- Attachment #1: Type: text/plain, Size: 1066 bytes --]
Hi,
[auto build test ERROR on peter.chen-usb/ci-for-usb-next]
[also build test ERROR on v4.7-rc5 next-20160624]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/Support-qcom-s-HSIC-USB-and-rewrite-USB2-HS-phy-support/20160627-102637
base: https://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb ci-for-usb-next
config: x86_64-randconfig-h0-06270614 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
>> ERROR: "of_device_request_module" [drivers/usb/common/ulpi.ko] undefined!
>> ERROR: "of_device_get_modalias" [drivers/usb/common/ulpi.ko] undefined!
>> ERROR: "of_device_uevent_modalias" [drivers/usb/common/ulpi.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 22307 bytes --]
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 02/21] usb: ulpi: Support device discovery via DT
2016-06-26 7:28 ` [PATCH 02/21] usb: ulpi: Support device discovery via DT Stephen Boyd
2016-06-27 4:21 ` kbuild test robot
@ 2016-06-27 14:34 ` Heikki Krogerus
[not found] ` <146706544012.30684.15569003844798199881@sboyd-linaro>
2016-06-28 20:56 ` Rob Herring
2 siblings, 1 reply; 69+ messages in thread
From: Heikki Krogerus @ 2016-06-27 14:34 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Greg Kroah-Hartman, devicetree, Rob Herring
Hi,
I'm fine with most of the patch, except..
On Sun, Jun 26, 2016 at 12:28:19AM -0700, Stephen Boyd wrote:
> @@ -39,7 +42,10 @@ static int ulpi_match(struct device *dev, struct device_driver *driver)
> struct ulpi *ulpi = to_ulpi_dev(dev);
> const struct ulpi_device_id *id;
>
> - for (id = drv->id_table; id->vendor; id++)
> + if (of_driver_match_device(dev, driver))
> + return 1;
I don't like this part. We should match separately like that only
if the bus does not support native enumeration, and of course ULPI
with its vendor and product IDs does. There really should always be
IDs to match with here. So exceptions have to be solved before we
attempt matching.
Since we also have to support platforms where the PHY is initially
powered off and reading the IDs from the registers is not possible
because of that, I think we should consider getting the product and
vendor IDs optionally from device properties. Something like this:
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index 01c0c04..6228a85 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -152,7 +152,7 @@ EXPORT_SYMBOL_GPL(ulpi_unregister_driver);
/* -------------------------------------------------------------------------- */
-static int ulpi_register(struct device *dev, struct ulpi *ulpi)
+static int ulpi_read_id(struct ulpi *ulpi)
{
int ret;
@@ -174,6 +174,21 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi)
ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW);
ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8;
+ return 0;
+}
+
+static int ulpi_register(struct device *dev, struct ulpi *ulpi)
+{
+ int ret;
+
+ ret = device_property_read_u16(dev, "ulpi-vendor", &ulpi->id.vendor);
+ ret |= device_property_read_u16(dev, "ulpi-product", &ulpi->id.product);
+ if (ret) {
+ ret = ulpi_read_id(ulpi);
+ if (ret)
+ return ret;
+ }
+
ulpi->dev.parent = dev;
ulpi->dev.bus = &ulpi_bus;
ulpi->dev.type = &ulpi_dev_type;
That should cover both cases. You would just have to create the IDs
yourself in this case.
Thanks,
--
heikki
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 02/21] usb: ulpi: Support device discovery via DT
2016-06-26 7:28 ` [PATCH 02/21] usb: ulpi: Support device discovery via DT Stephen Boyd
2016-06-27 4:21 ` kbuild test robot
2016-06-27 14:34 ` Heikki Krogerus
@ 2016-06-28 20:56 ` Rob Herring
[not found] ` <146715176149.31418.10938517376423447782@sboyd-linaro>
2 siblings, 1 reply; 69+ messages in thread
From: Rob Herring @ 2016-06-28 20:56 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Greg Kroah-Hartman, Heikki Krogerus, devicetree
On Sun, Jun 26, 2016 at 12:28:19AM -0700, Stephen Boyd wrote:
> The qcom HSIC ulpi phy doesn't have any bits set in the vendor or
> product id ulpi registers. This makes it impossible to make a
> ulpi driver match against the id registers. Add support to
> discover the ulpi phys via DT to help alleviate this problem.
> We'll look for a ulpi bus node underneath the device registering
> the ulpi viewport (or the parent of that device to support
> chipidea's device layout) and then match up the phy node
> underneath that with the ulpi device that's created.
>
> The side benefit of this is that we can use standard DT
> properties in the phy node like clks, regulators, gpios, etc.
> because we don't have firmware like ACPI to turn these things on
> for us. And we can use the DT phy binding to point our phy
> consumer to the phy provider.
>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Cc: <devicetree@vger.kernel.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> Documentation/devicetree/bindings/usb/ulpi.txt | 20 +++++++++
> drivers/usb/common/ulpi.c | 56 +++++++++++++++++++++++++-
> 2 files changed, 74 insertions(+), 2 deletions(-)
> create mode 100644 Documentation/devicetree/bindings/usb/ulpi.txt
>
> diff --git a/Documentation/devicetree/bindings/usb/ulpi.txt b/Documentation/devicetree/bindings/usb/ulpi.txt
> new file mode 100644
> index 000000000000..ca179dc4bd50
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/usb/ulpi.txt
> @@ -0,0 +1,20 @@
> +ULPI bus binding
> +----------------
> +
> +Phys that are behind a ULPI connection can be described with the following
> +binding. The host controller shall have a "ulpi" named node as a child, and
> +that node shall have one enabled node underneath it representing the ulpi
> +device on the bus.
This needs to co-exist with the USB bus binding which has the controller
ports for the child nodes. Maybe use the phy binding?
> +
> +EXAMPLE
> +-------
> +
> +usb {
> + compatible = "vendor,usb-controller";
> +
> + ulpi {
> + phy {
> + compatible = "vendor,phy";
> + };
> + };
> +};
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 03/21] usb: ulpi: Avoid reading/writing in device creation with OF devices
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
2016-06-26 7:28 ` [PATCH 01/21] of: device: Support loading a module with OF based modalias Stephen Boyd
2016-06-26 7:28 ` [PATCH 02/21] usb: ulpi: Support device discovery via DT Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-26 7:28 ` [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place Stephen Boyd
` (18 subsequent siblings)
21 siblings, 0 replies; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Greg Kroah-Hartman, Heikki Krogerus
ULPI devices are matched up against ULPI drivers by reading the
vendor id and product id registers in the ULPI address space.
Before we try to read those registers we'll do a scratch write to
test the interface. Unfortunately, this doesn't work well if the
ULPI device is not powered at the time of device creation. In
that case, the scratch register writes fail and product and
vendor ids can't be read.
If the ULPI spec had some way to describe generic power
requirements for the scratch, product, and vendor registers we
could but power sequencing into the ULPI bus layer and power up
the device before touching the hardware. Unfortunately this
doesn't exist. Furthermore, the power information is device
specific, so it varies from device to device and is not standard.
Let's punt on doing the reads/writes here when we're using DT
backed ULPI devices. This avoids any problems where we need to
power on the device but haven't figured out which device it is
yet to know what sort of regulators, clks, etc. that need to be
turned on for it to work.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/common/ulpi.c | 40 +++++++++++++++++++++-------------------
1 file changed, 21 insertions(+), 19 deletions(-)
diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c
index 980af672bfe3..a6b2a150b176 100644
--- a/drivers/usb/common/ulpi.c
+++ b/drivers/usb/common/ulpi.c
@@ -197,25 +197,7 @@ static int ulpi_of_register(struct ulpi *ulpi)
static int ulpi_register(struct device *dev, struct ulpi *ulpi)
{
- int ret;
-
- /* Test the interface */
- ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa);
- if (ret < 0)
- return ret;
-
- ret = ulpi_read(ulpi, ULPI_SCRATCH);
- if (ret < 0)
- return ret;
-
- if (ret != 0xaa)
- return -ENODEV;
-
- ulpi->id.vendor = ulpi_read(ulpi, ULPI_VENDOR_ID_LOW);
- ulpi->id.vendor |= ulpi_read(ulpi, ULPI_VENDOR_ID_HIGH) << 8;
-
- ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW);
- ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8;
+ int ret = -ENODEV;
ulpi->dev.parent = dev;
ulpi->dev.bus = &ulpi_bus;
@@ -230,6 +212,26 @@ static int ulpi_register(struct device *dev, struct ulpi *ulpi)
return ret;
}
+ if (ret) {
+ /* Test the interface */
+ ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa);
+ if (ret < 0)
+ return ret;
+
+ ret = ulpi_read(ulpi, ULPI_SCRATCH);
+ if (ret < 0)
+ return ret;
+
+ if (ret != 0xaa)
+ return -ENODEV;
+
+ ulpi->id.vendor = ulpi_read(ulpi, ULPI_VENDOR_ID_LOW);
+ ulpi->id.vendor |= ulpi_read(ulpi, ULPI_VENDOR_ID_HIGH) << 8;
+
+ ulpi->id.product = ulpi_read(ulpi, ULPI_PRODUCT_ID_LOW);
+ ulpi->id.product |= ulpi_read(ulpi, ULPI_PRODUCT_ID_HIGH) << 8;
+ }
+
if (of_device_request_module(&ulpi->dev))
request_module("ulpi:v%04xp%04x", ulpi->id.vendor,
ulpi->id.product);
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (2 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 03/21] usb: ulpi: Avoid reading/writing in device creation with OF devices Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-27 8:04 ` Jun Li
2016-06-26 7:28 ` [PATCH 05/21] usb: chipidea: Handle extcon events properly Stephen Boyd
` (17 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman, Ivan T. Ivanov
With the id and vbus detection done via extcon we need to make
sure we poll the status of OTGSC properly by considering what the
extcon is saying, and not just what the register is saying. Let's
move this hw_wait_reg() function to the only place it's used and
simplify it for polling the OTGSC register. Then we can make
certain we only use the hw_read_otgsc() API to read OTGSC, which
will make sure we properly handle extcon events.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Ivan T. Ivanov" <iivanov.xz@gmail.com>
Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID detect")
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/core.c | 32 --------------------------------
drivers/usb/chipidea/otg.c | 35 +++++++++++++++++++++++++++++++----
2 files changed, 31 insertions(+), 36 deletions(-)
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 69426e644d17..01390e02ee53 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -516,38 +516,6 @@ int hw_device_reset(struct ci_hdrc *ci)
return 0;
}
-/**
- * hw_wait_reg: wait the register value
- *
- * Sometimes, it needs to wait register value before going on.
- * Eg, when switch to device mode, the vbus value should be lower
- * than OTGSC_BSV before connects to host.
- *
- * @ci: the controller
- * @reg: register index
- * @mask: mast bit
- * @value: the bit value to wait
- * @timeout_ms: timeout in millisecond
- *
- * This function returns an error code if timeout
- */
-int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
- u32 value, unsigned int timeout_ms)
-{
- unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
-
- while (hw_read(ci, reg, mask) != value) {
- if (time_after(jiffies, elapse)) {
- dev_err(ci->dev, "timeout waiting for %08x in %d\n",
- mask, reg);
- return -ETIMEDOUT;
- }
- msleep(20);
- }
-
- return 0;
-}
-
static irqreturn_t ci_irq(int irq, void *data)
{
struct ci_hdrc *ci = data;
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 03b6743461d1..763a8332b009 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -104,7 +104,32 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
usb_gadget_vbus_disconnect(&ci->gadget);
}
-#define CI_VBUS_STABLE_TIMEOUT_MS 5000
+/**
+ * Sometimes, it needs to wait register value before going on.
+ * Eg, when switch to device mode, the vbus value should be lower
+ * than OTGSC_BSV before connects to host.
+ *
+ * @ci: the controller
+ *
+ * This function returns an error code if timeout
+ */
+static int hw_wait_otgsc_bsv(struct ci_hdrc *ci)
+{
+ unsigned long elapse = jiffies + msecs_to_jiffies(5000);
+ u32 mask = OTGSC_BSV;
+
+ while (!hw_read_otgsc(ci, mask)) {
+ if (time_after(jiffies, elapse)) {
+ dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
+ mask);
+ return -ETIMEDOUT;
+ }
+ msleep(20);
+ }
+
+ return 0;
+}
+
static void ci_handle_id_switch(struct ci_hdrc *ci)
{
enum ci_role role = ci_otg_role(ci);
@@ -116,9 +141,11 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
ci_role_stop(ci);
if (role == CI_ROLE_GADGET)
- /* wait vbus lower than OTGSC_BSV */
- hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
- CI_VBUS_STABLE_TIMEOUT_MS);
+ /*
+ * wait vbus lower than OTGSC_BSV before connecting
+ * to host
+ */
+ hw_wait_otgsc_bsv(ci);
ci_role_start(ci, role);
}
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* RE: [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place
2016-06-26 7:28 ` [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place Stephen Boyd
@ 2016-06-27 8:04 ` Jun Li
2016-06-27 19:07 ` Stephen Boyd
0 siblings, 1 reply; 69+ messages in thread
From: Jun Li @ 2016-06-27 8:04 UTC (permalink / raw)
To: Stephen Boyd, linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman, Ivan T. Ivanov
Hi
> -----Original Message-----
> From: linux-usb-owner@vger.kernel.org [mailto:linux-usb-
> owner@vger.kernel.org] On Behalf Of Stephen Boyd
> Sent: Sunday, June 26, 2016 3:28 PM
> To: linux-usb@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org; linux-kernel@vger.kernel.org;
> linux-arm-msm@vger.kernel.org; Andy Gross <andy.gross@linaro.org>; Bjorn
> Andersson <bjorn.andersson@linaro.org>; Neil Armstrong
> <narmstrong@baylibre.com>; Arnd Bergmann <arnd@arndb.de>; Felipe Balbi
> <balbi@kernel.org>; Peter Chen <peter.chen@nxp.com>; Greg Kroah-Hartman
> <gregkh@linuxfoundation.org>; Ivan T. Ivanov <iivanov.xz@gmail.com>
> Subject: [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place
>
> With the id and vbus detection done via extcon we need to make sure we
> poll the status of OTGSC properly by considering what the extcon is saying,
> and not just what the register is saying. Let's move this hw_wait_reg()
> function to the only place it's used and simplify it for polling the OTGSC
> register. Then we can make certain we only use the hw_read_otgsc() API to
> read OTGSC, which will make sure we properly handle extcon events.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: "Ivan T. Ivanov" <iivanov.xz@gmail.com>
> Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID
> detect")
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/core.c | 32 --------------------------------
> drivers/usb/chipidea/otg.c | 35 +++++++++++++++++++++++++++++++----
> 2 files changed, 31 insertions(+), 36 deletions(-)
>
> diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> index 69426e644d17..01390e02ee53 100644
> --- a/drivers/usb/chipidea/core.c
> +++ b/drivers/usb/chipidea/core.c
> @@ -516,38 +516,6 @@ int hw_device_reset(struct ci_hdrc *ci)
> return 0;
> }
>
> -/**
> - * hw_wait_reg: wait the register value
> - *
> - * Sometimes, it needs to wait register value before going on.
> - * Eg, when switch to device mode, the vbus value should be lower
> - * than OTGSC_BSV before connects to host.
> - *
> - * @ci: the controller
> - * @reg: register index
> - * @mask: mast bit
> - * @value: the bit value to wait
> - * @timeout_ms: timeout in millisecond
> - *
> - * This function returns an error code if timeout
> - */
> -int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
> - u32 value, unsigned int timeout_ms)
> -{
> - unsigned long elapse = jiffies + msecs_to_jiffies(timeout_ms);
> -
> - while (hw_read(ci, reg, mask) != value) {
> - if (time_after(jiffies, elapse)) {
> - dev_err(ci->dev, "timeout waiting for %08x in %d\n",
> - mask, reg);
> - return -ETIMEDOUT;
> - }
> - msleep(20);
> - }
> -
> - return 0;
> -}
> -
> static irqreturn_t ci_irq(int irq, void *data) {
> struct ci_hdrc *ci = data;
> diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index
> 03b6743461d1..763a8332b009 100644
> --- a/drivers/usb/chipidea/otg.c
> +++ b/drivers/usb/chipidea/otg.c
> @@ -104,7 +104,32 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
> usb_gadget_vbus_disconnect(&ci->gadget);
> }
>
> -#define CI_VBUS_STABLE_TIMEOUT_MS 5000
> +/**
> + * Sometimes, it needs to wait register value before going on.
> + * Eg, when switch to device mode, the vbus value should be lower
> + * than OTGSC_BSV before connects to host.
This should be updated since this API is dedicated for BSV now.
> + *
> + * @ci: the controller
> + *
> + * This function returns an error code if timeout */ static int
> +hw_wait_otgsc_bsv(struct ci_hdrc *ci) {
> + unsigned long elapse = jiffies + msecs_to_jiffies(5000);
> + u32 mask = OTGSC_BSV;
> +
> + while (!hw_read_otgsc(ci, mask)) {
Reverse logic, should be:
while (hw_read_otgsc(ci, mask)) {
Li Jun
> + if (time_after(jiffies, elapse)) {
> + dev_err(ci->dev, "timeout waiting for %08x in OTGSC\n",
> + mask);
> + return -ETIMEDOUT;
> + }
> + msleep(20);
> + }
> +
> + return 0;
> +}
> +
> static void ci_handle_id_switch(struct ci_hdrc *ci) {
> enum ci_role role = ci_otg_role(ci);
> @@ -116,9 +141,11 @@ static void ci_handle_id_switch(struct ci_hdrc *ci)
> ci_role_stop(ci);
>
> if (role == CI_ROLE_GADGET)
> - /* wait vbus lower than OTGSC_BSV */
> - hw_wait_reg(ci, OP_OTGSC, OTGSC_BSV, 0,
> - CI_VBUS_STABLE_TIMEOUT_MS);
> + /*
> + * wait vbus lower than OTGSC_BSV before connecting
> + * to host
> + */
> + hw_wait_otgsc_bsv(ci);
>
> ci_role_start(ci, role);
> }
> --
> 2.9.0.rc2.8.ga28705d
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org More majordomo info at
> http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 69+ messages in thread
* RE: [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place
2016-06-27 8:04 ` Jun Li
@ 2016-06-27 19:07 ` Stephen Boyd
2016-06-28 9:36 ` Peter Chen
0 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-27 19:07 UTC (permalink / raw)
To: Jun Li, linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman, Ivan T. Ivanov
Quoting Jun Li (2016-06-27 01:04:39)
> > diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index
> > 03b6743461d1..763a8332b009 100644
> > --- a/drivers/usb/chipidea/otg.c
> > +++ b/drivers/usb/chipidea/otg.c
> > @@ -104,7 +104,32 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
> > usb_gadget_vbus_disconnect(&ci->gadget);
> > }
> >
> > -#define CI_VBUS_STABLE_TIMEOUT_MS 5000
> > +/**
> > + * Sometimes, it needs to wait register value before going on.
> > + * Eg, when switch to device mode, the vbus value should be lower
> > + * than OTGSC_BSV before connects to host.
>
> This should be updated since this API is dedicated for BSV now.
Ok I've updated it to say:
When we switch to device mode, the vbus value should be lower
than OTGSC_BSV before connecting to host.
>
> > + *
> > + * @ci: the controller
> > + *
> > + * This function returns an error code if timeout */ static int
> > +hw_wait_otgsc_bsv(struct ci_hdrc *ci) {
> > + unsigned long elapse = jiffies + msecs_to_jiffies(5000);
> > + u32 mask = OTGSC_BSV;
> > +
> > + while (!hw_read_otgsc(ci, mask)) {
>
> Reverse logic, should be:
> while (hw_read_otgsc(ci, mask)) {
>
Good catch! Thanks.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place
2016-06-27 19:07 ` Stephen Boyd
@ 2016-06-28 9:36 ` Peter Chen
0 siblings, 0 replies; 69+ messages in thread
From: Peter Chen @ 2016-06-28 9:36 UTC (permalink / raw)
To: Stephen Boyd
Cc: Jun Li, linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman, Ivan T. Ivanov
On Mon, Jun 27, 2016 at 12:07:54PM -0700, Stephen Boyd wrote:
> Quoting Jun Li (2016-06-27 01:04:39)
> > > diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index
> > > 03b6743461d1..763a8332b009 100644
> > > --- a/drivers/usb/chipidea/otg.c
> > > +++ b/drivers/usb/chipidea/otg.c
> > > @@ -104,7 +104,32 @@ void ci_handle_vbus_change(struct ci_hdrc *ci)
> > > usb_gadget_vbus_disconnect(&ci->gadget);
> > > }
> > >
> > > -#define CI_VBUS_STABLE_TIMEOUT_MS 5000
> > > +/**
> > > + * Sometimes, it needs to wait register value before going on.
> > > + * Eg, when switch to device mode, the vbus value should be lower
> > > + * than OTGSC_BSV before connects to host.
> >
> > This should be updated since this API is dedicated for BSV now.
>
> Ok I've updated it to say:
>
> When we switch to device mode, the vbus value should be lower
> than OTGSC_BSV before connecting to host.
>
> >
> > > + *
> > > + * @ci: the controller
> > > + *
> > > + * This function returns an error code if timeout */ static int
> > > +hw_wait_otgsc_bsv(struct ci_hdrc *ci) {
> > > + unsigned long elapse = jiffies + msecs_to_jiffies(5000);
> > > + u32 mask = OTGSC_BSV;
> > > +
> > > + while (!hw_read_otgsc(ci, mask)) {
> >
> > Reverse logic, should be:
> > while (hw_read_otgsc(ci, mask)) {
> >
>
> Good catch! Thanks.
Besides above, please delete the declaration at ci.h.
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 05/21] usb: chipidea: Handle extcon events properly
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (3 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 04/21] usb: chipidea: Only read/write OTGSC from one place Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-28 10:01 ` Peter Chen
2016-06-26 7:28 ` [PATCH 06/21] usb: chipidea: Initialize and reinitialize phy later Stephen Boyd
` (16 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman, Ivan T. Ivanov
We're currently emulating the vbus and id interrupts in the OTGSC
read API, but we also need to make sure that if we're handling
the events with extcon that we don't enable the interrupts for
those events in the hardware. Therefore, properly emulate this
register if we're using extcon, but don't enable the interrupts.
This allows me to get my cable connect/disconnect working
properly without getting spurious interrupts on my device that
uses an extcon for these two events.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Ivan T. Ivanov" <iivanov.xz@gmail.com>
Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID detect")
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/otg.c | 46 +++++++++++++++++++++++++++++++++++++++-----
include/linux/usb/chipidea.h | 2 ++
2 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 763a8332b009..b6a88bea4cac 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -44,12 +44,15 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
else
val &= ~OTGSC_BSVIS;
- cable->changed = false;
-
if (cable->state)
val |= OTGSC_BSV;
else
val &= ~OTGSC_BSV;
+
+ if (cable->enabled)
+ val |= OTGSC_BSVIE;
+ else
+ val &= ~OTGSC_BSVIE;
}
cable = &ci->platdata->id_extcon;
@@ -59,15 +62,18 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
else
val &= ~OTGSC_IDIS;
- cable->changed = false;
-
if (cable->state)
val |= OTGSC_ID;
else
val &= ~OTGSC_ID;
+
+ if (cable->enabled)
+ val |= OTGSC_IDIE;
+ else
+ val &= ~OTGSC_IDIE;
}
- return val;
+ return val & mask;
}
/**
@@ -77,6 +83,36 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
*/
void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
{
+ struct ci_hdrc_cable *cable;
+
+ cable = &ci->platdata->vbus_extcon;
+ if (!IS_ERR(cable->edev)) {
+ if (data & mask & OTGSC_BSVIS)
+ cable->changed = false;
+
+ /* Don't enable vbus interrupt if using external notifier */
+ if (data & mask & OTGSC_BSVIE) {
+ cable->enabled = true;
+ data &= ~OTGSC_BSVIE;
+ } else if (mask & OTGSC_BSVIE) {
+ cable->enabled = false;
+ }
+ }
+
+ cable = &ci->platdata->id_extcon;
+ if (!IS_ERR(cable->edev)) {
+ if (data & mask & OTGSC_IDIS)
+ cable->changed = false;
+
+ /* Don't enable id interrupt if using external notifier */
+ if (data & mask & OTGSC_IDIE) {
+ cable->enabled = true;
+ data &= ~OTGSC_IDIE;
+ } else if (mask & OTGSC_IDIE) {
+ cable->enabled = false;
+ }
+ }
+
hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
}
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index 5dd75fa47dd8..f9be467d6695 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -14,6 +14,7 @@ struct ci_hdrc;
* struct ci_hdrc_cable - structure for external connector cable state tracking
* @state: current state of the line
* @changed: set to true when extcon event happen
+ * @enabled: set to true if we've enabled the vbus or id interrupt
* @edev: device which generate events
* @ci: driver state of the chipidea device
* @nb: hold event notification callback
@@ -22,6 +23,7 @@ struct ci_hdrc;
struct ci_hdrc_cable {
bool state;
bool changed;
+ bool enabled;
struct extcon_dev *edev;
struct ci_hdrc *ci;
struct notifier_block nb;
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 05/21] usb: chipidea: Handle extcon events properly
2016-06-26 7:28 ` [PATCH 05/21] usb: chipidea: Handle extcon events properly Stephen Boyd
@ 2016-06-28 10:01 ` Peter Chen
0 siblings, 0 replies; 69+ messages in thread
From: Peter Chen @ 2016-06-28 10:01 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, Felipe Balbi, Arnd Bergmann, Neil Armstrong,
linux-arm-msm, linux-kernel, Bjorn Andersson, Peter Chen,
Greg Kroah-Hartman, Andy Gross, Ivan T. Ivanov, linux-arm-kernel
On Sun, Jun 26, 2016 at 12:28:22AM -0700, Stephen Boyd wrote:
> We're currently emulating the vbus and id interrupts in the OTGSC
> read API, but we also need to make sure that if we're handling
> the events with extcon that we don't enable the interrupts for
> those events in the hardware. Therefore, properly emulate this
> register if we're using extcon, but don't enable the interrupts.
> This allows me to get my cable connect/disconnect working
> properly without getting spurious interrupts on my device that
> uses an extcon for these two events.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: "Ivan T. Ivanov" <iivanov.xz@gmail.com>
> Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID detect")
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/otg.c | 46 +++++++++++++++++++++++++++++++++++++++-----
> include/linux/usb/chipidea.h | 2 ++
> 2 files changed, 43 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
> index 763a8332b009..b6a88bea4cac 100644
> --- a/drivers/usb/chipidea/otg.c
> +++ b/drivers/usb/chipidea/otg.c
> @@ -44,12 +44,15 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
> else
> val &= ~OTGSC_BSVIS;
>
> - cable->changed = false;
> -
> if (cable->state)
> val |= OTGSC_BSV;
> else
> val &= ~OTGSC_BSV;
> +
> + if (cable->enabled)
> + val |= OTGSC_BSVIE;
> + else
> + val &= ~OTGSC_BSVIE;
> }
>
> cable = &ci->platdata->id_extcon;
> @@ -59,15 +62,18 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
> else
> val &= ~OTGSC_IDIS;
>
> - cable->changed = false;
> -
> if (cable->state)
> val |= OTGSC_ID;
> else
> val &= ~OTGSC_ID;
> +
> + if (cable->enabled)
> + val |= OTGSC_IDIE;
> + else
> + val &= ~OTGSC_IDIE;
> }
>
> - return val;
> + return val & mask;
> }
>
> /**
> @@ -77,6 +83,36 @@ u32 hw_read_otgsc(struct ci_hdrc *ci, u32 mask)
> */
> void hw_write_otgsc(struct ci_hdrc *ci, u32 mask, u32 data)
> {
> + struct ci_hdrc_cable *cable;
> +
> + cable = &ci->platdata->vbus_extcon;
> + if (!IS_ERR(cable->edev)) {
> + if (data & mask & OTGSC_BSVIS)
> + cable->changed = false;
> +
> + /* Don't enable vbus interrupt if using external notifier */
> + if (data & mask & OTGSC_BSVIE) {
> + cable->enabled = true;
> + data &= ~OTGSC_BSVIE;
> + } else if (mask & OTGSC_BSVIE) {
> + cable->enabled = false;
> + }
> + }
> +
> + cable = &ci->platdata->id_extcon;
> + if (!IS_ERR(cable->edev)) {
> + if (data & mask & OTGSC_IDIS)
> + cable->changed = false;
> +
> + /* Don't enable id interrupt if using external notifier */
> + if (data & mask & OTGSC_IDIE) {
> + cable->enabled = true;
> + data &= ~OTGSC_IDIE;
> + } else if (mask & OTGSC_IDIE) {
> + cable->enabled = false;
> + }
> + }
> +
> hw_write(ci, OP_OTGSC, mask | OTGSC_INT_STATUS_BITS, data);
> }
>
> diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
> index 5dd75fa47dd8..f9be467d6695 100644
> --- a/include/linux/usb/chipidea.h
> +++ b/include/linux/usb/chipidea.h
> @@ -14,6 +14,7 @@ struct ci_hdrc;
> * struct ci_hdrc_cable - structure for external connector cable state tracking
> * @state: current state of the line
> * @changed: set to true when extcon event happen
> + * @enabled: set to true if we've enabled the vbus or id interrupt
> * @edev: device which generate events
> * @ci: driver state of the chipidea device
> * @nb: hold event notification callback
> @@ -22,6 +23,7 @@ struct ci_hdrc;
> struct ci_hdrc_cable {
> bool state;
> bool changed;
> + bool enabled;
> struct extcon_dev *edev;
> struct ci_hdrc *ci;
> struct notifier_block nb;
> --
Acked-by: Peter Chen <peter.chen@nxp.com>
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 06/21] usb: chipidea: Initialize and reinitialize phy later
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (4 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 05/21] usb: chipidea: Handle extcon events properly Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 2:30 ` Peter Chen
2016-06-26 7:28 ` [PATCH 07/21] usb: chipidea: Notify of reset when switching into host mode Stephen Boyd
` (15 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
The ULPI phy on qcom platforms needs to be initialized and
powered on after a USB reset and before we toggle the run/stop
bit. Otherwise, the phy locks up and doesn't work properly. Move
the phy initialization to a later point, and shut it down outside
of driver remove so that the phy state is properly managed across
role switches.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci.h | 3 ++-
drivers/usb/chipidea/core.c | 23 ++++++++++-------------
drivers/usb/chipidea/host.c | 5 ++---
drivers/usb/chipidea/udc.c | 2 ++
4 files changed, 16 insertions(+), 17 deletions(-)
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index cd414559040f..f87805235caa 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -431,7 +431,8 @@ u8 hw_port_test_get(struct ci_hdrc *ci);
int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
u32 value, unsigned int timeout_ms);
-void ci_platform_configure(struct ci_hdrc *ci);
+void ci_usb_phy_exit(struct ci_hdrc *ci);
+int ci_platform_configure(struct ci_hdrc *ci);
int dbg_create_files(struct ci_hdrc *ci);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 01390e02ee53..a01611c7f815 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -359,7 +359,7 @@ static int _ci_usb_phy_init(struct ci_hdrc *ci)
* interfaces
* @ci: the controller
*/
-static void ci_usb_phy_exit(struct ci_hdrc *ci)
+void ci_usb_phy_exit(struct ci_hdrc *ci)
{
if (ci->phy) {
phy_power_off(ci->phy);
@@ -412,9 +412,14 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
* @ci: the controller
*
*/
-void ci_platform_configure(struct ci_hdrc *ci)
+int ci_platform_configure(struct ci_hdrc *ci)
{
bool is_device_mode, is_host_mode;
+ int ret;
+
+ ret = ci_usb_phy_init(ci);
+ if (ret)
+ return ret;
is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC;
is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC;
@@ -453,6 +458,8 @@ void ci_platform_configure(struct ci_hdrc *ci)
hw_write(ci, OP_BURSTSIZE, RX_BURST_MASK,
ci->platdata->rx_burst_size);
}
+
+ return 0;
}
/**
@@ -511,9 +518,7 @@ int hw_device_reset(struct ci_hdrc *ci)
return -ENODEV;
}
- ci_platform_configure(ci);
-
- return 0;
+ return ci_platform_configure(ci);
}
static irqreturn_t ci_irq(int irq, void *data)
@@ -917,12 +922,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ci->usb_phy = NULL;
}
- ret = ci_usb_phy_init(ci);
- if (ret) {
- dev_err(dev, "unable to init phy: %d\n", ret);
- return ret;
- }
-
ci->hw_bank.phys = res->start;
ci->irq = platform_get_irq(pdev, 0);
@@ -1025,7 +1024,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
stop:
ci_role_destroy(ci);
deinit_phy:
- ci_usb_phy_exit(ci);
return ret;
}
@@ -1044,7 +1042,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
ci_extcon_unregister(ci);
ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true);
- ci_usb_phy_exit(ci);
return 0;
}
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 053bac9d983c..523c155daea8 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -87,9 +87,7 @@ static int ehci_ci_reset(struct usb_hcd *hcd)
if (ret)
return ret;
- ci_platform_configure(ci);
-
- return ret;
+ return ci_platform_configure(ci);
}
static const struct ehci_driver_overrides ehci_ci_overrides = {
@@ -186,6 +184,7 @@ static void host_stop(struct ci_hdrc *ci)
if (hcd) {
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
+ ci_usb_phy_exit(ci);
if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
(ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
regulator_disable(ci->platdata->reg_vbus);
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 065f5d97aa67..8f44e2d1e0c0 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1534,6 +1534,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
if (ci->driver)
ci->driver->disconnect(&ci->gadget);
hw_device_state(ci, 0);
+ ci_usb_phy_exit(ci);
if (ci->platdata->notify_event)
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT);
@@ -1794,6 +1795,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
ci->platdata->notify_event(ci,
CI_HDRC_CONTROLLER_STOPPED_EVENT);
spin_unlock_irqrestore(&ci->lock, flags);
+ ci_usb_phy_exit(ci);
_gadget_stop_activity(&ci->gadget);
spin_lock_irqsave(&ci->lock, flags);
pm_runtime_put(&ci->gadget.dev);
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 06/21] usb: chipidea: Initialize and reinitialize phy later
2016-06-26 7:28 ` [PATCH 06/21] usb: chipidea: Initialize and reinitialize phy later Stephen Boyd
@ 2016-06-29 2:30 ` Peter Chen
[not found] ` <146724983020.16253.12640673678669134952@sboyd-linaro>
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 2:30 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, Felipe Balbi, Arnd Bergmann, Neil Armstrong,
linux-arm-msm, linux-kernel, Bjorn Andersson, Peter Chen,
Greg Kroah-Hartman, Andy Gross, linux-arm-kernel
On Sun, Jun 26, 2016 at 12:28:23AM -0700, Stephen Boyd wrote:
> The ULPI phy on qcom platforms needs to be initialized and
> powered on after a USB reset and before we toggle the run/stop
> bit. Otherwise, the phy locks up and doesn't work properly.
This requirement is so strange, try to see if any other initialization
sequences.
Since this driver is multi-platforms, I can't accept this change for
common, if you had to do that, would you please move your changes to
msm glue layer using CI_HDRC_CONTROLLER_RESET_EVENT and
CI_HDRC_CONTROLLER_STOPPED_EVENT? Besides, you need to add one flag
at ci_hdrc_platform_data.flags for your case to avoid normal
initialization.
Peter
> Move
> the phy initialization to a later point, and shut it down outside
> of driver remove so that the phy state is properly managed across
> role switches.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci.h | 3 ++-
> drivers/usb/chipidea/core.c | 23 ++++++++++-------------
> drivers/usb/chipidea/host.c | 5 ++---
> drivers/usb/chipidea/udc.c | 2 ++
> 4 files changed, 16 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
> index cd414559040f..f87805235caa 100644
> --- a/drivers/usb/chipidea/ci.h
> +++ b/drivers/usb/chipidea/ci.h
> @@ -431,7 +431,8 @@ u8 hw_port_test_get(struct ci_hdrc *ci);
> int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
> u32 value, unsigned int timeout_ms);
>
> -void ci_platform_configure(struct ci_hdrc *ci);
> +void ci_usb_phy_exit(struct ci_hdrc *ci);
> +int ci_platform_configure(struct ci_hdrc *ci);
>
> int dbg_create_files(struct ci_hdrc *ci);
>
> diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
> index 01390e02ee53..a01611c7f815 100644
> --- a/drivers/usb/chipidea/core.c
> +++ b/drivers/usb/chipidea/core.c
> @@ -359,7 +359,7 @@ static int _ci_usb_phy_init(struct ci_hdrc *ci)
> * interfaces
> * @ci: the controller
> */
> -static void ci_usb_phy_exit(struct ci_hdrc *ci)
> +void ci_usb_phy_exit(struct ci_hdrc *ci)
> {
> if (ci->phy) {
> phy_power_off(ci->phy);
> @@ -412,9 +412,14 @@ static int ci_usb_phy_init(struct ci_hdrc *ci)
> * @ci: the controller
> *
> */
> -void ci_platform_configure(struct ci_hdrc *ci)
> +int ci_platform_configure(struct ci_hdrc *ci)
> {
> bool is_device_mode, is_host_mode;
> + int ret;
> +
> + ret = ci_usb_phy_init(ci);
> + if (ret)
> + return ret;
>
> is_device_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_DC;
> is_host_mode = hw_read(ci, OP_USBMODE, USBMODE_CM) == USBMODE_CM_HC;
> @@ -453,6 +458,8 @@ void ci_platform_configure(struct ci_hdrc *ci)
> hw_write(ci, OP_BURSTSIZE, RX_BURST_MASK,
> ci->platdata->rx_burst_size);
> }
> +
> + return 0;
> }
>
> /**
> @@ -511,9 +518,7 @@ int hw_device_reset(struct ci_hdrc *ci)
> return -ENODEV;
> }
>
> - ci_platform_configure(ci);
> -
> - return 0;
> + return ci_platform_configure(ci);
> }
>
> static irqreturn_t ci_irq(int irq, void *data)
> @@ -917,12 +922,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
> ci->usb_phy = NULL;
> }
>
> - ret = ci_usb_phy_init(ci);
> - if (ret) {
> - dev_err(dev, "unable to init phy: %d\n", ret);
> - return ret;
> - }
> -
> ci->hw_bank.phys = res->start;
>
> ci->irq = platform_get_irq(pdev, 0);
> @@ -1025,7 +1024,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
> stop:
> ci_role_destroy(ci);
> deinit_phy:
> - ci_usb_phy_exit(ci);
>
> return ret;
> }
> @@ -1044,7 +1042,6 @@ static int ci_hdrc_remove(struct platform_device *pdev)
> ci_extcon_unregister(ci);
> ci_role_destroy(ci);
> ci_hdrc_enter_lpm(ci, true);
> - ci_usb_phy_exit(ci);
>
> return 0;
> }
> diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
> index 053bac9d983c..523c155daea8 100644
> --- a/drivers/usb/chipidea/host.c
> +++ b/drivers/usb/chipidea/host.c
> @@ -87,9 +87,7 @@ static int ehci_ci_reset(struct usb_hcd *hcd)
> if (ret)
> return ret;
>
> - ci_platform_configure(ci);
> -
> - return ret;
> + return ci_platform_configure(ci);
> }
>
> static const struct ehci_driver_overrides ehci_ci_overrides = {
> @@ -186,6 +184,7 @@ static void host_stop(struct ci_hdrc *ci)
> if (hcd) {
> usb_remove_hcd(hcd);
> usb_put_hcd(hcd);
> + ci_usb_phy_exit(ci);
> if (ci->platdata->reg_vbus && !ci_otg_is_fsm_mode(ci) &&
> (ci->platdata->flags & CI_HDRC_TURN_VBUS_EARLY_ON))
> regulator_disable(ci->platdata->reg_vbus);
> diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
> index 065f5d97aa67..8f44e2d1e0c0 100644
> --- a/drivers/usb/chipidea/udc.c
> +++ b/drivers/usb/chipidea/udc.c
> @@ -1534,6 +1534,7 @@ static int ci_udc_vbus_session(struct usb_gadget *_gadget, int is_active)
> if (ci->driver)
> ci->driver->disconnect(&ci->gadget);
> hw_device_state(ci, 0);
> + ci_usb_phy_exit(ci);
> if (ci->platdata->notify_event)
> ci->platdata->notify_event(ci,
> CI_HDRC_CONTROLLER_STOPPED_EVENT);
> @@ -1794,6 +1795,7 @@ static int ci_udc_stop(struct usb_gadget *gadget)
> ci->platdata->notify_event(ci,
> CI_HDRC_CONTROLLER_STOPPED_EVENT);
> spin_unlock_irqrestore(&ci->lock, flags);
> + ci_usb_phy_exit(ci);
> _gadget_stop_activity(&ci->gadget);
> spin_lock_irqsave(&ci->lock, flags);
> pm_runtime_put(&ci->gadget.dev);
> --
> 2.9.0.rc2.8.ga28705d
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 07/21] usb: chipidea: Notify of reset when switching into host mode
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (5 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 06/21] usb: chipidea: Initialize and reinitialize phy later Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-26 7:28 ` [PATCH 08/21] usb: chipidea: Kick OTG state machine for AVVIS with vbus extcon Stephen Boyd
` (14 subsequent siblings)
21 siblings, 0 replies; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
The chipidea/udc.c file sends a CI_HDRC_CONTROLLER_RESET_EVENT to
the wrapper drivers when it calls hw_device_reset(), but that
function is not called from chipidea/host.c. The intent of this
event is to allow the wrapper driver to do any wrapper specific
things after the reset bit has been set in the usb command
register. Therefore, add this event hook in the host role after
we toggle that bit.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/host.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index 523c155daea8..3344d3256a60 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -87,6 +87,9 @@ static int ehci_ci_reset(struct usb_hcd *hcd)
if (ret)
return ret;
+ if (ci->platdata->notify_event)
+ ci->platdata->notify_event(ci, CI_HDRC_CONTROLLER_RESET_EVENT);
+
return ci_platform_configure(ci);
}
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* [PATCH 08/21] usb: chipidea: Kick OTG state machine for AVVIS with vbus extcon
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (6 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 07/21] usb: chipidea: Notify of reset when switching into host mode Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 3:09 ` Peter Chen
2016-06-26 7:28 ` [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus Stephen Boyd
` (13 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
Force the OTG state machine to go forward when we're using an
extcon for vbus detection. In this case, the controller may never
raise an interrupt for AVVIS, so we need to simulate the event by
toggling the appropriate OTG fsm bits and kicking the state
machine again.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/otg_fsm.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
index de8e22ec3902..aab076fc4d82 100644
--- a/drivers/usb/chipidea/otg_fsm.c
+++ b/drivers/usb/chipidea/otg_fsm.c
@@ -475,6 +475,14 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
return;
}
}
+ /*
+ * Force state machine forward if we use extcon
+ * to detect vbus state (i.e. simulate AVVIS event)
+ */
+ if (!IS_ERR(ci->platdata->vbus_extcon.edev)) {
+ fsm->a_vbus_vld = 1;
+ ci_otg_queue_work(ci);
+ }
/* Disable data pulse irq */
hw_write_otgsc(ci, OTGSC_DPIE, 0);
@@ -486,6 +494,15 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
fsm->a_bus_drop = 1;
fsm->a_bus_req = 0;
+ /*
+ * Force state machine forward if we use extcon
+ * to detect vbus state (i.e. simulate AVVIS event)
+ */
+ if (!IS_ERR(ci->platdata->vbus_extcon.edev)) {
+ fsm->a_vbus_vld = 0;
+ fsm->b_conn = 0;
+ ci_otg_queue_work(ci);
+ }
}
}
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 08/21] usb: chipidea: Kick OTG state machine for AVVIS with vbus extcon
2016-06-26 7:28 ` [PATCH 08/21] usb: chipidea: Kick OTG state machine for AVVIS with vbus extcon Stephen Boyd
@ 2016-06-29 3:09 ` Peter Chen
[not found] ` <146724959973.16253.818114721999543873@sboyd-linaro>
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 3:09 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:25AM -0700, Stephen Boyd wrote:
> Force the OTG state machine to go forward when we're using an
> extcon for vbus detection. In this case, the controller may never
> raise an interrupt for AVVIS, so we need to simulate the event by
> toggling the appropriate OTG fsm bits and kicking the state
> machine again.
>
Well, I think you may misunderstand the OTG FSM and dual-role.
>From my and Felipe's point, there are seldom users for USB FSM,
there are only OTG FSM spec and related OTG certification.
The OTG FSM needs related SoC support, the vbus will be off at
several states, and the SRP should be supported by SoC.
By default, the dts needs below properties for disabling it if you
choose otg fsm support at kernel configuration.
&usbotg1 {
vbus-supply = <®_usb_otg1_vbus>;
srp-disable;
hnp-disable;
adp-disable;
status = "okay";
};
See Documentation/devicetree/bindings/usb/generic.txt.
Peter
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/otg_fsm.c | 17 +++++++++++++++++
> 1 file changed, 17 insertions(+)
>
> diff --git a/drivers/usb/chipidea/otg_fsm.c b/drivers/usb/chipidea/otg_fsm.c
> index de8e22ec3902..aab076fc4d82 100644
> --- a/drivers/usb/chipidea/otg_fsm.c
> +++ b/drivers/usb/chipidea/otg_fsm.c
> @@ -475,6 +475,14 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
> return;
> }
> }
> + /*
> + * Force state machine forward if we use extcon
> + * to detect vbus state (i.e. simulate AVVIS event)
> + */
> + if (!IS_ERR(ci->platdata->vbus_extcon.edev)) {
> + fsm->a_vbus_vld = 1;
> + ci_otg_queue_work(ci);
> + }
> /* Disable data pulse irq */
> hw_write_otgsc(ci, OTGSC_DPIE, 0);
>
> @@ -486,6 +494,15 @@ static void ci_otg_drv_vbus(struct otg_fsm *fsm, int on)
>
> fsm->a_bus_drop = 1;
> fsm->a_bus_req = 0;
> + /*
> + * Force state machine forward if we use extcon
> + * to detect vbus state (i.e. simulate AVVIS event)
> + */
> + if (!IS_ERR(ci->platdata->vbus_extcon.edev)) {
> + fsm->a_vbus_vld = 0;
> + fsm->b_conn = 0;
> + ci_otg_queue_work(ci);
> + }
> }
> }
>
> --
> 2.9.0.rc2.8.ga28705d
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (7 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 08/21] usb: chipidea: Kick OTG state machine for AVVIS with vbus extcon Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 6:26 ` Peter Chen
2016-06-26 7:28 ` [PATCH 10/21] usb: chipidea: msm: Rely on core to override AHBBURST Stephen Boyd
` (12 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman, Heikki Krogerus
Some phys for the chipidea controller are controlled via the ULPI
viewport. Add support for the ULPI bus so that these sorts of
phys can be probed and read/written automatically without having
to duplicate the viewport logic in each phy driver.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/Kconfig | 7 +++
drivers/usb/chipidea/Makefile | 1 +
drivers/usb/chipidea/ci.h | 20 ++++++++
drivers/usb/chipidea/core.c | 30 ++++++++---
drivers/usb/chipidea/ulpi.c | 113 ++++++++++++++++++++++++++++++++++++++++++
5 files changed, 165 insertions(+), 6 deletions(-)
create mode 100644 drivers/usb/chipidea/ulpi.c
diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
index 3644a3500b70..4f8c342a8865 100644
--- a/drivers/usb/chipidea/Kconfig
+++ b/drivers/usb/chipidea/Kconfig
@@ -37,4 +37,11 @@ config USB_CHIPIDEA_HOST
Say Y here to enable host controller functionality of the
ChipIdea driver.
+config USB_CHIPIDEA_ULPI
+ bool "ChipIdea ULPI PHY support"
+ depends on USB_ULPI_BUS=y || USB_ULPI_BUS=USB_CHIPIDEA
+ help
+ Say Y here if you have a ULPI PHY attached to your ChipIdea
+ controller.
+
endif
diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
index 518e445476c3..39fca5715ed3 100644
--- a/drivers/usb/chipidea/Makefile
+++ b/drivers/usb/chipidea/Makefile
@@ -4,6 +4,7 @@ ci_hdrc-y := core.o otg.o debug.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
ci_hdrc-$(CONFIG_USB_OTG_FSM) += otg_fsm.o
+ci_hdrc-$(CONFIG_USB_CHIPIDEA_ULPI) += ulpi.o
# Glue/Bridge layers go here
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index f87805235caa..14aa20525547 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -18,6 +18,8 @@
#include <linux/usb.h>
#include <linux/usb/gadget.h>
#include <linux/usb/otg-fsm.h>
+#include <linux/usb/otg.h>
+#include <linux/ulpi/interface.h>
/******************************************************************************
* DEFINE
@@ -52,6 +54,7 @@ enum ci_hw_regs {
OP_ENDPTLISTADDR,
OP_TTCTRL,
OP_BURSTSIZE,
+ OP_ULPI_VIEWPORT,
OP_PORTSC,
OP_DEVLC,
OP_OTGSC,
@@ -187,6 +190,7 @@ struct hw_bank {
* @test_mode: the selected test mode
* @platdata: platform specific information supplied by parent device
* @vbus_active: is VBUS active
+ * @ulpi: pointer to ULPI device, if any
* @phy: pointer to PHY, if any
* @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework
* @hcd: pointer to usb_hcd for ehci host driver
@@ -236,6 +240,10 @@ struct ci_hdrc {
struct ci_hdrc_platform_data *platdata;
int vbus_active;
+#ifdef CONFIG_USB_CHIPIDEA_ULPI
+ struct ulpi *ulpi;
+ struct ulpi_ops ulpi_ops;
+#endif
struct phy *phy;
/* old usb_phy interface */
struct usb_phy *usb_phy;
@@ -418,6 +426,17 @@ static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci)
#endif
}
+#if IS_ENABLED(CONFIG_USB_CHIPIDEA_ULPI)
+int ci_ulpi_init(struct ci_hdrc *ci);
+void ci_ulpi_exit(struct ci_hdrc *ci);
+int ci_ulpi_resume(struct ci_hdrc *ci);
+#else
+static inline int ci_ulpi_init(struct ci_hdrc *ci) { return 0; }
+static inline void ci_ulpi_exit(struct ci_hdrc *ci) { }
+static inline int ci_ulpi_resume(struct ci_hdrc *ci) { return 0; }
+#endif
+
+
u32 hw_read_intr_enable(struct ci_hdrc *ci);
u32 hw_read_intr_status(struct ci_hdrc *ci);
@@ -432,6 +451,7 @@ int hw_wait_reg(struct ci_hdrc *ci, enum ci_hw_regs reg, u32 mask,
u32 value, unsigned int timeout_ms);
void ci_usb_phy_exit(struct ci_hdrc *ci);
+void hw_phymode_configure(struct ci_hdrc *ci);
int ci_platform_configure(struct ci_hdrc *ci);
int dbg_create_files(struct ci_hdrc *ci);
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index a01611c7f815..ea84fc0a03a6 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -86,6 +86,7 @@ static const u8 ci_regs_nolpm[] = {
[OP_ENDPTLISTADDR] = 0x18U,
[OP_TTCTRL] = 0x1CU,
[OP_BURSTSIZE] = 0x20U,
+ [OP_ULPI_VIEWPORT] = 0x30U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0x64U,
@@ -110,6 +111,7 @@ static const u8 ci_regs_lpm[] = {
[OP_ENDPTLISTADDR] = 0x18U,
[OP_TTCTRL] = 0x1CU,
[OP_BURSTSIZE] = 0x20U,
+ [OP_ULPI_VIEWPORT] = 0x30U,
[OP_PORTSC] = 0x44U,
[OP_DEVLC] = 0x84U,
[OP_OTGSC] = 0xC4U,
@@ -285,7 +287,7 @@ static int hw_device_init(struct ci_hdrc *ci, void __iomem *base)
return 0;
}
-static void hw_phymode_configure(struct ci_hdrc *ci)
+void hw_phymode_configure(struct ci_hdrc *ci)
{
u32 portsc, lpm, sts = 0;
@@ -893,6 +895,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
CI_HDRC_IMX28_WRITE_FIX);
ci->supports_runtime_pm = !!(ci->platdata->flags &
CI_HDRC_SUPPORTS_RUNTIME_PM);
+ platform_set_drvdata(pdev, ci);
ret = hw_device_init(ci, base);
if (ret < 0) {
@@ -900,6 +903,10 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENODEV;
}
+ ret = ci_ulpi_init(ci);
+ if (ret)
+ return ret;
+
if (ci->platdata->phy) {
ci->phy = ci->platdata->phy;
} else if (ci->platdata->usb_phy) {
@@ -910,11 +917,15 @@ static int ci_hdrc_probe(struct platform_device *pdev)
/* if both generic PHY and USB PHY layers aren't enabled */
if (PTR_ERR(ci->phy) == -ENOSYS &&
- PTR_ERR(ci->usb_phy) == -ENXIO)
- return -ENXIO;
+ PTR_ERR(ci->usb_phy) == -ENXIO) {
+ ret = -ENXIO;
+ goto deinit_phy;
+ }
- if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy))
- return -EPROBE_DEFER;
+ if (IS_ERR(ci->phy) && IS_ERR(ci->usb_phy)) {
+ ret = -EPROBE_DEFER;
+ goto deinit_phy;
+ }
if (IS_ERR(ci->phy))
ci->phy = NULL;
@@ -993,7 +1004,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
}
}
- platform_set_drvdata(pdev, ci);
ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED,
ci->platdata->name, ci);
if (ret)
@@ -1024,6 +1034,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
stop:
ci_role_destroy(ci);
deinit_phy:
+ ci_ulpi_exit(ci);
return ret;
}
@@ -1042,6 +1053,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
ci_extcon_unregister(ci);
ci_role_destroy(ci);
ci_hdrc_enter_lpm(ci, true);
+ ci_ulpi_exit(ci);
return 0;
}
@@ -1089,6 +1101,7 @@ static void ci_controller_suspend(struct ci_hdrc *ci)
static int ci_controller_resume(struct device *dev)
{
struct ci_hdrc *ci = dev_get_drvdata(dev);
+ int ret;
dev_dbg(dev, "at %s\n", __func__);
@@ -1098,6 +1111,11 @@ static int ci_controller_resume(struct device *dev)
}
ci_hdrc_enter_lpm(ci, false);
+
+ ret = ci_ulpi_resume(ci);
+ if (ret)
+ return ret;
+
if (ci->usb_phy) {
usb_phy_set_suspend(ci->usb_phy, 0);
usb_phy_set_wakeup(ci->usb_phy, false);
diff --git a/drivers/usb/chipidea/ulpi.c b/drivers/usb/chipidea/ulpi.c
new file mode 100644
index 000000000000..3962255ff687
--- /dev/null
+++ b/drivers/usb/chipidea/ulpi.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2016 Linaro Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/device.h>
+#include <linux/usb/chipidea.h>
+#include <linux/ulpi/interface.h>
+
+#include "ci.h"
+
+#define ULPI_WAKEUP BIT(31)
+#define ULPI_RUN BIT(30)
+#define ULPI_WRITE BIT(29)
+#define ULPI_SYNC_STATE BIT(27)
+#define ULPI_ADDR(n) ((n) << 16)
+#define ULPI_DATA(n) (n)
+
+static int ci_ulpi_wait(struct ci_hdrc *ci, u32 mask)
+{
+ unsigned long usec = 10000;
+
+ while (usec--) {
+ if (!hw_read(ci, OP_ULPI_VIEWPORT, mask))
+ return 0;
+
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int ci_ulpi_read(struct ulpi_ops *ops, u8 addr)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(ops->dev);
+ int ret;
+
+ hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
+ ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
+ if (ret)
+ return ret;
+
+ hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_RUN | ULPI_ADDR(addr));
+ ret = ci_ulpi_wait(ci, ULPI_RUN);
+ if (ret)
+ return ret;
+
+ return hw_read(ci, OP_ULPI_VIEWPORT, GENMASK(15, 8)) >> 8;
+}
+
+static int ci_ulpi_write(struct ulpi_ops *ops, u8 addr, u8 val)
+{
+ struct ci_hdrc *ci = dev_get_drvdata(ops->dev);
+ int ret;
+
+ hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff, ULPI_WRITE | ULPI_WAKEUP);
+ ret = ci_ulpi_wait(ci, ULPI_WAKEUP);
+ if (ret)
+ return ret;
+
+ hw_write(ci, OP_ULPI_VIEWPORT, 0xffffffff,
+ ULPI_RUN | ULPI_WRITE | ULPI_ADDR(addr) | val);
+ return ci_ulpi_wait(ci, ULPI_RUN);
+}
+
+int ci_ulpi_init(struct ci_hdrc *ci)
+{
+ if (ci->platdata->phy_mode != USBPHY_INTERFACE_MODE_ULPI)
+ return 0;
+
+ /*
+ * Set PORTSC correctly so we can read/write ULPI registers for
+ * identification purposes
+ */
+ hw_phymode_configure(ci);
+
+ ci->ulpi_ops.read = ci_ulpi_read;
+ ci->ulpi_ops.write = ci_ulpi_write;
+ ci->ulpi = ulpi_register_interface(ci->dev, &ci->ulpi_ops);
+ if (IS_ERR(ci->ulpi))
+ dev_err(ci->dev, "failed to register ULPI interface");
+
+ return PTR_ERR_OR_ZERO(ci->ulpi);
+}
+
+void ci_ulpi_exit(struct ci_hdrc *ci)
+{
+ if (ci->ulpi) {
+ ulpi_unregister_interface(ci->ulpi);
+ ci->ulpi = NULL;
+ }
+}
+
+int ci_ulpi_resume(struct ci_hdrc *ci)
+{
+ int cnt = 100000;
+
+ while (cnt-- > 0) {
+ if (hw_read(ci, OP_ULPI_VIEWPORT, ULPI_SYNC_STATE))
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus
2016-06-26 7:28 ` [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus Stephen Boyd
@ 2016-06-29 6:26 ` Peter Chen
0 siblings, 0 replies; 69+ messages in thread
From: Peter Chen @ 2016-06-29 6:26 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman, Heikki Krogerus
On Sun, Jun 26, 2016 at 12:28:26AM -0700, Stephen Boyd wrote:
> Some phys for the chipidea controller are controlled via the ULPI
> viewport. Add support for the ULPI bus so that these sorts of
> phys can be probed and read/written automatically without having
> to duplicate the viewport logic in each phy driver.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: Heikki Krogerus <heikki.krogerus@linux.intel.com>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/Kconfig | 7 +++
> drivers/usb/chipidea/Makefile | 1 +
> drivers/usb/chipidea/ci.h | 20 ++++++++
> drivers/usb/chipidea/core.c | 30 ++++++++---
> drivers/usb/chipidea/ulpi.c | 113 ++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 165 insertions(+), 6 deletions(-)
> create mode 100644 drivers/usb/chipidea/ulpi.c
>
> diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig
> index 3644a3500b70..4f8c342a8865 100644
> --- a/drivers/usb/chipidea/Kconfig
> +++ b/drivers/usb/chipidea/Kconfig
> @@ -37,4 +37,11 @@ config USB_CHIPIDEA_HOST
> Say Y here to enable host controller functionality of the
> ChipIdea driver.
>
> +config USB_CHIPIDEA_ULPI
> + bool "ChipIdea ULPI PHY support"
> + depends on USB_ULPI_BUS=y || USB_ULPI_BUS=USB_CHIPIDEA
> + help
> + Say Y here if you have a ULPI PHY attached to your ChipIdea
> + controller.
> +
> endif
> diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile
> index 518e445476c3..39fca5715ed3 100644
> --- a/drivers/usb/chipidea/Makefile
> +++ b/drivers/usb/chipidea/Makefile
> @@ -4,6 +4,7 @@ ci_hdrc-y := core.o otg.o debug.o
> ci_hdrc-$(CONFIG_USB_CHIPIDEA_UDC) += udc.o
> ci_hdrc-$(CONFIG_USB_CHIPIDEA_HOST) += host.o
> ci_hdrc-$(CONFIG_USB_OTG_FSM) += otg_fsm.o
> +ci_hdrc-$(CONFIG_USB_CHIPIDEA_ULPI) += ulpi.o
>
> # Glue/Bridge layers go here
>
> diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
> index f87805235caa..14aa20525547 100644
> --- a/drivers/usb/chipidea/ci.h
> +++ b/drivers/usb/chipidea/ci.h
> @@ -18,6 +18,8 @@
> #include <linux/usb.h>
> #include <linux/usb/gadget.h>
> #include <linux/usb/otg-fsm.h>
> +#include <linux/usb/otg.h>
> +#include <linux/ulpi/interface.h>
>
> /******************************************************************************
> * DEFINE
> @@ -52,6 +54,7 @@ enum ci_hw_regs {
> OP_ENDPTLISTADDR,
> OP_TTCTRL,
> OP_BURSTSIZE,
> + OP_ULPI_VIEWPORT,
> OP_PORTSC,
> OP_DEVLC,
> OP_OTGSC,
> @@ -187,6 +190,7 @@ struct hw_bank {
> * @test_mode: the selected test mode
> * @platdata: platform specific information supplied by parent device
> * @vbus_active: is VBUS active
> + * @ulpi: pointer to ULPI device, if any
One more kernel-doc
> * @phy: pointer to PHY, if any
> * @usb_phy: pointer to USB PHY, if any and if using the USB PHY framework
> * @hcd: pointer to usb_hcd for ehci host driver
> @@ -236,6 +240,10 @@ struct ci_hdrc {
>
> struct ci_hdrc_platform_data *platdata;
> int vbus_active;
> +#ifdef CONFIG_USB_CHIPIDEA_ULPI
> + struct ulpi *ulpi;
> + struct ulpi_ops ulpi_ops;
> +#endif
> struct phy *phy;
> /* old usb_phy interface */
> struct usb_phy *usb_phy;
> @@ -418,6 +426,17 @@ static inline bool ci_otg_is_fsm_mode(struct ci_hdrc *ci)
> #endif
> }
>
Others are ok, but I can't accept you change current PHY initialization
at your previous patch, so you may need to refine this patch a little.
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 10/21] usb: chipidea: msm: Rely on core to override AHBBURST
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (8 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 09/21] usb: chipidea: Add support for ULPI PHY bus Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 6:32 ` Peter Chen
2016-06-26 7:28 ` [PATCH 11/21] usb: chipidea: msm: Use hw_write_id_reg() instead of writel directly Stephen Boyd
` (11 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
The core framework already handles setting this parameter with a
platform quirk. Add the appropriate flag so that we always set
AHBBURST to 0. Technically DT should be doing this, but we always
do it for msm chipidea devices so setting the flag in the driver
works just as well.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 3889809fd0c4..37591a4b1346 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -24,7 +24,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
switch (event) {
case CI_HDRC_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
- writel(0, USB_AHBBURST);
/* use AHB transactor, allow posted data writes */
writel(0x8, USB_AHBMODE);
usb_phy_init(ci->usb_phy);
@@ -47,7 +46,8 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
.name = "ci_hdrc_msm",
.capoffset = DEF_CAPOFFSET,
.flags = CI_HDRC_REGS_SHARED |
- CI_HDRC_DISABLE_STREAMING,
+ CI_HDRC_DISABLE_STREAMING |
+ CI_HDRC_OVERRIDE_AHB_BURST,
.notify_event = ci_hdrc_msm_notify_event,
};
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 10/21] usb: chipidea: msm: Rely on core to override AHBBURST
2016-06-26 7:28 ` [PATCH 10/21] usb: chipidea: msm: Rely on core to override AHBBURST Stephen Boyd
@ 2016-06-29 6:32 ` Peter Chen
[not found] ` <146722676163.16253.15476996138920236894@sboyd-linaro>
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 6:32 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:27AM -0700, Stephen Boyd wrote:
> The core framework already handles setting this parameter with a
> platform quirk. Add the appropriate flag so that we always set
> AHBBURST to 0. Technically DT should be doing this, but we always
> do it for msm chipidea devices so setting the flag in the driver
> works just as well.
You still need to set AHB burst value at dts, this flag is just for
override, see below:
ahb-burst-config = <0x0>;
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index 3889809fd0c4..37591a4b1346 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -24,7 +24,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> switch (event) {
> case CI_HDRC_CONTROLLER_RESET_EVENT:
> dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
> - writel(0, USB_AHBBURST);
> /* use AHB transactor, allow posted data writes */
> writel(0x8, USB_AHBMODE);
> usb_phy_init(ci->usb_phy);
> @@ -47,7 +46,8 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
> .name = "ci_hdrc_msm",
> .capoffset = DEF_CAPOFFSET,
> .flags = CI_HDRC_REGS_SHARED |
> - CI_HDRC_DISABLE_STREAMING,
> + CI_HDRC_DISABLE_STREAMING |
> + CI_HDRC_OVERRIDE_AHB_BURST,
>
> .notify_event = ci_hdrc_msm_notify_event,
> };
> --
> 2.9.0.rc2.8.ga28705d
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 11/21] usb: chipidea: msm: Use hw_write_id_reg() instead of writel directly
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (9 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 10/21] usb: chipidea: msm: Rely on core to override AHBBURST Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 6:37 ` Peter Chen
2016-06-26 7:28 ` [PATCH 12/21] usb: chipidea: msm: Keep device runtime enabled Stephen Boyd
` (10 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
The MSM_USB_BASE macro trick is not very clear, and we're using
it for only one register write so let's just move to using
hw_write_id_reg() and passing the ci pointer instead. That
clearly shows what offset we're using and avoids needing to
include the msm_hsusb_hw.h file when we're going to delete that
file soon.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 37591a4b1346..520c85e701ef 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -8,14 +8,12 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/usb/msm_hsusb_hw.h>
-#include <linux/usb/ulpi.h>
#include <linux/usb/gadget.h>
#include <linux/usb/chipidea.h>
#include "ci.h"
-#define MSM_USB_BASE (ci->hw_bank.abs)
+#define HS_PHY_AHB_MODE 0x0098
static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{
@@ -25,7 +23,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
case CI_HDRC_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
/* use AHB transactor, allow posted data writes */
- writel(0x8, USB_AHBMODE);
+ hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
usb_phy_init(ci->usb_phy);
break;
case CI_HDRC_CONTROLLER_STOPPED_EVENT:
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 11/21] usb: chipidea: msm: Use hw_write_id_reg() instead of writel directly
2016-06-26 7:28 ` [PATCH 11/21] usb: chipidea: msm: Use hw_write_id_reg() instead of writel directly Stephen Boyd
@ 2016-06-29 6:37 ` Peter Chen
0 siblings, 0 replies; 69+ messages in thread
From: Peter Chen @ 2016-06-29 6:37 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, Felipe Balbi, Arnd Bergmann, Neil Armstrong,
linux-arm-msm, linux-kernel, Bjorn Andersson, Peter Chen,
Greg Kroah-Hartman, Andy Gross, linux-arm-kernel
On Sun, Jun 26, 2016 at 12:28:28AM -0700, Stephen Boyd wrote:
> The MSM_USB_BASE macro trick is not very clear, and we're using
> it for only one register write so let's just move to using
> hw_write_id_reg() and passing the ci pointer instead. That
> clearly shows what offset we're using and avoids needing to
> include the msm_hsusb_hw.h file when we're going to delete that
> file soon.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index 37591a4b1346..520c85e701ef 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -8,14 +8,12 @@
> #include <linux/module.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> -#include <linux/usb/msm_hsusb_hw.h>
> -#include <linux/usb/ulpi.h>
> #include <linux/usb/gadget.h>
> #include <linux/usb/chipidea.h>
>
> #include "ci.h"
>
> -#define MSM_USB_BASE (ci->hw_bank.abs)
> +#define HS_PHY_AHB_MODE 0x0098
>
> static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> {
> @@ -25,7 +23,7 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> case CI_HDRC_CONTROLLER_RESET_EVENT:
> dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
> /* use AHB transactor, allow posted data writes */
> - writel(0x8, USB_AHBMODE);
> + hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
> usb_phy_init(ci->usb_phy);
> break;
> case CI_HDRC_CONTROLLER_STOPPED_EVENT:
> --
Acked-by: Peter Chen <peter.chen@nxp.com>
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 12/21] usb: chipidea: msm: Keep device runtime enabled
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (10 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 11/21] usb: chipidea: msm: Use hw_write_id_reg() instead of writel directly Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 6:46 ` Peter Chen
2016-06-26 7:28 ` [PATCH 13/21] usb: chipidea: msm: Allow core to get usb phy Stephen Boyd
` (9 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
Sometimes the usb wrapper device is part of a power domain that
needs to stay on as long as the device is active. Let's get and
put the device in driver probe/remove so that we keep the power
domain powered as long as the device is attached. We can fine
tune this later to handle wakeup interrupts, etc. for finer grain
power management later, but this is necessary to make sure we can
keep accessing the device right now.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 520c85e701ef..430856ef1be3 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -80,6 +80,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
+ pm_runtime_get(&pdev->dev);
return 0;
}
@@ -88,6 +89,7 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev)
{
struct platform_device *plat_ci = platform_get_drvdata(pdev);
+ pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
ci_hdrc_remove_device(plat_ci);
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 12/21] usb: chipidea: msm: Keep device runtime enabled
2016-06-26 7:28 ` [PATCH 12/21] usb: chipidea: msm: Keep device runtime enabled Stephen Boyd
@ 2016-06-29 6:46 ` Peter Chen
[not found] ` <146724741028.16253.4741331543289283958@sboyd-linaro>
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 6:46 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:29AM -0700, Stephen Boyd wrote:
> Sometimes the usb wrapper device is part of a power domain that
> needs to stay on as long as the device is active. Let's get and
> put the device in driver probe/remove so that we keep the power
> domain powered as long as the device is attached. We can fine
> tune this later to handle wakeup interrupts, etc. for finer grain
> power management later, but this is necessary to make sure we can
> keep accessing the device right now.
Since some of the controllers work abnormal if we enables runtime
pm unconditionally, so I use one system flag CI_HDRC_SUPPORTS_RUNTIME_PM
for it. I can't understand why you can't access device without enable
parent's runtime pm, the controller will not enter runtime suspend
without that flag.
Peter
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index 520c85e701ef..430856ef1be3 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -80,6 +80,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
>
> pm_runtime_no_callbacks(&pdev->dev);
> pm_runtime_enable(&pdev->dev);
> + pm_runtime_get(&pdev->dev);
>
> return 0;
> }
> @@ -88,6 +89,7 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev)
> {
> struct platform_device *plat_ci = platform_get_drvdata(pdev);
>
> + pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
> ci_hdrc_remove_device(plat_ci);
>
> --
> 2.9.0.rc2.8.ga28705d
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 13/21] usb: chipidea: msm: Allow core to get usb phy
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (11 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 12/21] usb: chipidea: msm: Keep device runtime enabled Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 6:48 ` Peter Chen
2016-06-26 7:28 ` [PATCH 14/21] usb: chipidea: msm: Add proper clk and reset support Stephen Boyd
` (8 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
The chipidea core gets the usb phy and initializes the phy at the
right point now so we don't need to get the phy in this driver.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 21 ---------------------
1 file changed, 21 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 430856ef1be3..07cccd24a87f 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -24,15 +24,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
/* use AHB transactor, allow posted data writes */
hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
- usb_phy_init(ci->usb_phy);
- break;
- case CI_HDRC_CONTROLLER_STOPPED_EVENT:
- dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
- /*
- * Put the phy in non-driving mode. Otherwise host
- * may not detect soft-disconnection.
- */
- usb_phy_notify_disconnect(ci->usb_phy, USB_SPEED_UNKNOWN);
break;
default:
dev_dbg(dev, "unknown ci_hdrc event\n");
@@ -53,21 +44,9 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
static int ci_hdrc_msm_probe(struct platform_device *pdev)
{
struct platform_device *plat_ci;
- struct usb_phy *phy;
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
- /*
- * OTG(PHY) driver takes care of PHY initialization, clock management,
- * powering up VBUS, mapping of registers address space and power
- * management.
- */
- phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
- if (IS_ERR(phy))
- return PTR_ERR(phy);
-
- ci_hdrc_msm_platdata.usb_phy = phy;
-
plat_ci = ci_hdrc_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci_hdrc_msm_platdata);
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 13/21] usb: chipidea: msm: Allow core to get usb phy
2016-06-26 7:28 ` [PATCH 13/21] usb: chipidea: msm: Allow core to get usb phy Stephen Boyd
@ 2016-06-29 6:48 ` Peter Chen
2016-06-29 11:34 ` Peter Chen
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 6:48 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:30AM -0700, Stephen Boyd wrote:
> The chipidea core gets the usb phy and initializes the phy at the
> right point now so we don't need to get the phy in this driver.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 21 ---------------------
> 1 file changed, 21 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index 430856ef1be3..07cccd24a87f 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -24,15 +24,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
> /* use AHB transactor, allow posted data writes */
> hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
> - usb_phy_init(ci->usb_phy);
> - break;
> - case CI_HDRC_CONTROLLER_STOPPED_EVENT:
> - dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
> - /*
> - * Put the phy in non-driving mode. Otherwise host
> - * may not detect soft-disconnection.
> - */
> - usb_phy_notify_disconnect(ci->usb_phy, USB_SPEED_UNKNOWN);
> break;
> default:
> dev_dbg(dev, "unknown ci_hdrc event\n");
> @@ -53,21 +44,9 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
> static int ci_hdrc_msm_probe(struct platform_device *pdev)
> {
> struct platform_device *plat_ci;
> - struct usb_phy *phy;
>
> dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
>
> - /*
> - * OTG(PHY) driver takes care of PHY initialization, clock management,
> - * powering up VBUS, mapping of registers address space and power
> - * management.
> - */
> - phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
> - if (IS_ERR(phy))
> - return PTR_ERR(phy);
> -
> - ci_hdrc_msm_platdata.usb_phy = phy;
> -
> plat_ci = ci_hdrc_add_device(&pdev->dev,
> pdev->resource, pdev->num_resources,
> &ci_hdrc_msm_platdata);
> --
Acked-by: Peter Chen <peter.chen@nxp.com>
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 13/21] usb: chipidea: msm: Allow core to get usb phy
2016-06-29 6:48 ` Peter Chen
@ 2016-06-29 11:34 ` Peter Chen
[not found] ` <146722867837.16253.5338887948471498730@sboyd-linaro>
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 11:34 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Wed, Jun 29, 2016 at 02:48:11PM +0800, Peter Chen wrote:
> On Sun, Jun 26, 2016 at 12:28:30AM -0700, Stephen Boyd wrote:
> > The chipidea core gets the usb phy and initializes the phy at the
> > right point now so we don't need to get the phy in this driver.
> >
> > Cc: Peter Chen <peter.chen@nxp.com>
> > Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> > Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> > ---
> > drivers/usb/chipidea/ci_hdrc_msm.c | 21 ---------------------
> > 1 file changed, 21 deletions(-)
> >
> > diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> > index 430856ef1be3..07cccd24a87f 100644
> > --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> > +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> > @@ -24,15 +24,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> > dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
> > /* use AHB transactor, allow posted data writes */
> > hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
> > - usb_phy_init(ci->usb_phy);
> > - break;
> > - case CI_HDRC_CONTROLLER_STOPPED_EVENT:
> > - dev_dbg(dev, "CI_HDRC_CONTROLLER_STOPPED_EVENT received\n");
> > - /*
> > - * Put the phy in non-driving mode. Otherwise host
> > - * may not detect soft-disconnection.
> > - */
> > - usb_phy_notify_disconnect(ci->usb_phy, USB_SPEED_UNKNOWN);
> > break;
> > default:
> > dev_dbg(dev, "unknown ci_hdrc event\n");
> > @@ -53,21 +44,9 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
> > static int ci_hdrc_msm_probe(struct platform_device *pdev)
> > {
> > struct platform_device *plat_ci;
> > - struct usb_phy *phy;
> >
> > dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
> >
> > - /*
> > - * OTG(PHY) driver takes care of PHY initialization, clock management,
> > - * powering up VBUS, mapping of registers address space and power
> > - * management.
> > - */
> > - phy = devm_usb_get_phy_by_phandle(&pdev->dev, "usb-phy", 0);
> > - if (IS_ERR(phy))
> > - return PTR_ERR(phy);
> > -
> > - ci_hdrc_msm_platdata.usb_phy = phy;
> > -
> > plat_ci = ci_hdrc_add_device(&pdev->dev,
> > pdev->resource, pdev->num_resources,
> > &ci_hdrc_msm_platdata);
> > --
>
Wait, how about the UTMI PHY? You don't have a platform which needs
to get PHY through the phandle?
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 14/21] usb: chipidea: msm: Add proper clk and reset support
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (12 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 13/21] usb: chipidea: msm: Allow core to get usb phy Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 7:02 ` Peter Chen
2016-06-26 7:28 ` [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time Stephen Boyd
` (7 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
The msm chipidea controller uses two main clks, an AHB clk to
read/write the MMIO registers and a core clk called the system
clk that drives the controller itself. Add support for these clks
as they're required in all designs.
Also add support for an optional third clk that we need to turn
on to read/write the ULPI phy registers. Some ULPI phys drive
this clk themselves and so it isn't necessary to turn on to probe
a ULPI device, but the HSIC phy doesn't provide one itself, so we
must turn it on here.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 58 +++++++++++++++++++++++++++++++++++---
1 file changed, 54 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 07cccd24a87f..40249b0e3e93 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -10,11 +10,19 @@
#include <linux/pm_runtime.h>
#include <linux/usb/gadget.h>
#include <linux/usb/chipidea.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
#include "ci.h"
#define HS_PHY_AHB_MODE 0x0098
+struct ci_hdrc_msm {
+ struct platform_device *ci;
+ struct clk *core_clk;
+ struct clk *iface_clk;
+};
+
static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{
struct device *dev = ci->gadget.dev.parent;
@@ -43,34 +51,76 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
static int ci_hdrc_msm_probe(struct platform_device *pdev)
{
+ struct ci_hdrc_msm *ci;
struct platform_device *plat_ci;
+ struct clk *clk;
+ struct reset_control *reset;
+ int ret;
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
+ ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
+ if (!ci)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, ci);
+
+ reset = devm_reset_control_get(&pdev->dev, "core");
+ if (IS_ERR(reset))
+ return PTR_ERR(reset);
+
+ ci->core_clk = clk = devm_clk_get(&pdev->dev, "core");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ ci->iface_clk = clk = devm_clk_get(&pdev->dev, "iface");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ reset_control_assert(reset);
+ usleep_range(10000, 12000);
+ reset_control_deassert(reset);
+
+ ret = clk_prepare_enable(ci->core_clk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(ci->iface_clk);
+ if (ret)
+ goto err_iface;
+
plat_ci = ci_hdrc_add_device(&pdev->dev,
pdev->resource, pdev->num_resources,
&ci_hdrc_msm_platdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
- return PTR_ERR(plat_ci);
+ ret = PTR_ERR(plat_ci);
+ goto err_mux;
}
- platform_set_drvdata(pdev, plat_ci);
+ ci->ci = plat_ci;
pm_runtime_no_callbacks(&pdev->dev);
pm_runtime_enable(&pdev->dev);
pm_runtime_get(&pdev->dev);
return 0;
+
+err_mux:
+ clk_disable_unprepare(ci->iface_clk);
+err_iface:
+ clk_disable_unprepare(ci->core_clk);
+ return ret;
}
static int ci_hdrc_msm_remove(struct platform_device *pdev)
{
- struct platform_device *plat_ci = platform_get_drvdata(pdev);
+ struct ci_hdrc_msm *ci = platform_get_drvdata(pdev);
pm_runtime_put(&pdev->dev);
pm_runtime_disable(&pdev->dev);
- ci_hdrc_remove_device(plat_ci);
+ ci_hdrc_remove_device(ci->ci);
+ clk_disable_unprepare(ci->iface_clk);
+ clk_disable_unprepare(ci->core_clk);
return 0;
}
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 14/21] usb: chipidea: msm: Add proper clk and reset support
2016-06-26 7:28 ` [PATCH 14/21] usb: chipidea: msm: Add proper clk and reset support Stephen Boyd
@ 2016-06-29 7:02 ` Peter Chen
0 siblings, 0 replies; 69+ messages in thread
From: Peter Chen @ 2016-06-29 7:02 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:31AM -0700, Stephen Boyd wrote:
> The msm chipidea controller uses two main clks, an AHB clk to
> read/write the MMIO registers and a core clk called the system
> clk that drives the controller itself. Add support for these clks
> as they're required in all designs.
>
> Also add support for an optional third clk that we need to turn
> on to read/write the ULPI phy registers. Some ULPI phys drive
> this clk themselves and so it isn't necessary to turn on to probe
> a ULPI device, but the HSIC phy doesn't provide one itself, so we
> must turn it on here.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 58 +++++++++++++++++++++++++++++++++++---
> 1 file changed, 54 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index 07cccd24a87f..40249b0e3e93 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -10,11 +10,19 @@
> #include <linux/pm_runtime.h>
> #include <linux/usb/gadget.h>
> #include <linux/usb/chipidea.h>
> +#include <linux/clk.h>
> +#include <linux/reset.h>
>
> #include "ci.h"
>
> #define HS_PHY_AHB_MODE 0x0098
>
> +struct ci_hdrc_msm {
> + struct platform_device *ci;
> + struct clk *core_clk;
> + struct clk *iface_clk;
> +};
> +
> static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> {
> struct device *dev = ci->gadget.dev.parent;
> @@ -43,34 +51,76 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
>
> static int ci_hdrc_msm_probe(struct platform_device *pdev)
> {
> + struct ci_hdrc_msm *ci;
> struct platform_device *plat_ci;
> + struct clk *clk;
> + struct reset_control *reset;
> + int ret;
>
> dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
>
> + ci = devm_kzalloc(&pdev->dev, sizeof(*ci), GFP_KERNEL);
> + if (!ci)
> + return -ENOMEM;
> + platform_set_drvdata(pdev, ci);
> +
> + reset = devm_reset_control_get(&pdev->dev, "core");
> + if (IS_ERR(reset))
> + return PTR_ERR(reset);
> +
> + ci->core_clk = clk = devm_clk_get(&pdev->dev, "core");
> + if (IS_ERR(clk))
> + return PTR_ERR(clk);
> +
> + ci->iface_clk = clk = devm_clk_get(&pdev->dev, "iface");
> + if (IS_ERR(clk))
> + return PTR_ERR(clk);
You say it has three clocks in commit log, why it is only two in the code?
> +
> + reset_control_assert(reset);
> + usleep_range(10000, 12000);
> + reset_control_deassert(reset);
> +
> + ret = clk_prepare_enable(ci->core_clk);
> + if (ret)
> + return ret;
> +
> + ret = clk_prepare_enable(ci->iface_clk);
> + if (ret)
> + goto err_iface;
> +
> plat_ci = ci_hdrc_add_device(&pdev->dev,
> pdev->resource, pdev->num_resources,
> &ci_hdrc_msm_platdata);
ci->plat_ci(or ci) = ...
Delete the local variable plat_ci
> if (IS_ERR(plat_ci)) {
> dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
> - return PTR_ERR(plat_ci);
> + ret = PTR_ERR(plat_ci);
> + goto err_mux;
> }
>
> - platform_set_drvdata(pdev, plat_ci);
> + ci->ci = plat_ci;
[...]
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (13 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 14/21] usb: chipidea: msm: Add proper clk and reset support Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-28 4:51 ` Bjorn Andersson
2016-06-29 8:08 ` Peter Chen
2016-06-26 7:28 ` [PATCH 16/21] usb: chipidea: msm: Restore wrapper settings after reset Stephen Boyd
` (6 subsequent siblings)
21 siblings, 2 replies; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
We need to pick the correct phy at runtime based on how the SoC
has been wired onto the board. If the secondary phy is used, take
it out of reset and mux over to it by writing into the TCSR
register. Make sure to do this on reset too, because this
register is reset to the default value (primary phy) after the
RESET bit is set in USBCMD.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 78 +++++++++++++++++++++++++++++++++++---
1 file changed, 73 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 40249b0e3e93..df0f8b31db4f 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -8,30 +8,40 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/usb/gadget.h>
#include <linux/usb/chipidea.h>
#include <linux/clk.h>
#include <linux/reset.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/io.h>
#include "ci.h"
#define HS_PHY_AHB_MODE 0x0098
+#define HS_PHY_SEC_CTRL 0x0278
+# define HS_PHY_DIG_CLAMP_N BIT(16)
struct ci_hdrc_msm {
struct platform_device *ci;
struct clk *core_clk;
struct clk *iface_clk;
+ bool secondary_phy;
+ void __iomem *base;
};
static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{
- struct device *dev = ci->gadget.dev.parent;
+ struct device *dev = ci->dev->parent;
+ struct ci_hdrc_msm *msm_ci = dev_get_drvdata(dev);
switch (event) {
case CI_HDRC_CONTROLLER_RESET_EVENT:
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
/* use AHB transactor, allow posted data writes */
hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
+ if (msm_ci->secondary_phy)
+ hw_write_id_reg(ci, HS_PHY_SEC_CTRL, HS_PHY_DIG_CLAMP_N,
+ HS_PHY_DIG_CLAMP_N);
break;
default:
dev_dbg(dev, "unknown ci_hdrc event\n");
@@ -49,12 +59,58 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
.notify_event = ci_hdrc_msm_notify_event,
};
+static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
+ struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ struct device_node *syscon;
+ struct device *dev = &pdev->dev;
+ u32 off, val;
+ int ret;
+
+ syscon = of_parse_phandle(dev->of_node, "phy-select", 0);
+ if (!syscon)
+ return 0;
+
+ regmap = syscon_node_to_regmap(syscon);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ ret = of_property_read_u32_index(dev->of_node, "phy-select", 1, &off);
+ if (ret < 0) {
+ dev_err(dev, "no offset in syscon\n");
+ return -EINVAL;
+ }
+
+ ret = of_property_read_u32_index(dev->of_node, "phy-select", 2, &val);
+ if (ret < 0) {
+ dev_err(dev, "no value in syscon\n");
+ return -EINVAL;
+ }
+
+ ret = regmap_write(regmap, off, val);
+ if (ret)
+ return ret;
+
+ ci->secondary_phy = !!val;
+ if (ci->secondary_phy) {
+ val = readl_relaxed(ci->base + HS_PHY_SEC_CTRL);
+ val |= HS_PHY_DIG_CLAMP_N;
+ writel_relaxed(val, ci->base + HS_PHY_SEC_CTRL);
+ }
+
+ return 0;
+}
+
static int ci_hdrc_msm_probe(struct platform_device *pdev)
{
struct ci_hdrc_msm *ci;
struct platform_device *plat_ci;
struct clk *clk;
struct reset_control *reset;
+ struct resource *res;
+ void __iomem *base;
+ resource_size_t size;
int ret;
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
@@ -76,6 +132,15 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
if (IS_ERR(clk))
return PTR_ERR(clk);
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ size = resource_size(res);
+ ci->base = base = devm_ioremap(&pdev->dev, res->start, size);
+ if (!base)
+ return -ENOMEM;
+
reset_control_assert(reset);
usleep_range(10000, 12000);
reset_control_deassert(reset);
@@ -88,9 +153,12 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
if (ret)
goto err_iface;
- plat_ci = ci_hdrc_add_device(&pdev->dev,
- pdev->resource, pdev->num_resources,
- &ci_hdrc_msm_platdata);
+ ret = ci_hdrc_msm_mux_phy(ci, pdev);
+ if (ret)
+ goto err_mux;
+
+ plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
+ pdev->num_resources, &ci_hdrc_msm_platdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
ret = PTR_ERR(plat_ci);
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time
2016-06-26 7:28 ` [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time Stephen Boyd
@ 2016-06-28 4:51 ` Bjorn Andersson
2016-06-29 8:08 ` Peter Chen
1 sibling, 0 replies; 69+ messages in thread
From: Bjorn Andersson @ 2016-06-28 4:51 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
On Sun 26 Jun 00:28 PDT 2016, Stephen Boyd wrote:
> We need to pick the correct phy at runtime based on how the SoC
> has been wired onto the board. If the secondary phy is used, take
> it out of reset and mux over to it by writing into the TCSR
> register. Make sure to do this on reset too, because this
> register is reset to the default value (primary phy) after the
> RESET bit is set in USBCMD.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 78 +++++++++++++++++++++++++++++++++++---
> 1 file changed, 73 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
[..]
>
> +static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
> + struct platform_device *pdev)
> +{
> + struct regmap *regmap;
> + struct device_node *syscon;
> + struct device *dev = &pdev->dev;
> + u32 off, val;
> + int ret;
> +
> + syscon = of_parse_phandle(dev->of_node, "phy-select", 0);
> + if (!syscon)
> + return 0;
> +
> + regmap = syscon_node_to_regmap(syscon);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + ret = of_property_read_u32_index(dev->of_node, "phy-select", 1, &off);
> + if (ret < 0) {
> + dev_err(dev, "no offset in syscon\n");
> + return -EINVAL;
> + }
> +
> + ret = of_property_read_u32_index(dev->of_node, "phy-select", 2, &val);
> + if (ret < 0) {
> + dev_err(dev, "no value in syscon\n");
> + return -EINVAL;
> + }
> +
> + ret = regmap_write(regmap, off, val);
I recently found out (thanks to a comment from Srinivas) that you can
drop the last two error checks by using
of_parse_phandle_with_fixed_args() as in:
struct of_phandle_args args;
ret = of_parse_phandle_with_fixed_args(dev->of_node, "phy-select", 2, 0, &args);
if (ret < 0)
...
regmap = syscon_node_to_regmap(args.np);
of_node_put(args.np);
if (IS_ERR(regmap))
...
ret = regmap_write(regmap, args.args[0], args.args[1]);
> + if (ret)
> + return ret;
> +
> + ci->secondary_phy = !!val;
> + if (ci->secondary_phy) {
> + val = readl_relaxed(ci->base + HS_PHY_SEC_CTRL);
> + val |= HS_PHY_DIG_CLAMP_N;
> + writel_relaxed(val, ci->base + HS_PHY_SEC_CTRL);
> + }
> +
> + return 0;
> +}
> +
> static int ci_hdrc_msm_probe(struct platform_device *pdev)
> {
> struct ci_hdrc_msm *ci;
> struct platform_device *plat_ci;
> struct clk *clk;
> struct reset_control *reset;
> + struct resource *res;
> + void __iomem *base;
Doesn't look like you need "base".
> + resource_size_t size;
> int ret;
>
> dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
> @@ -76,6 +132,15 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> if (IS_ERR(clk))
> return PTR_ERR(clk);
>
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res)
> + return -ENODEV;
> +
> + size = resource_size(res);
> + ci->base = base = devm_ioremap(&pdev->dev, res->start, size);
> + if (!base)
> + return -ENOMEM;
Replace these two snippets with:
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ci->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(ci->base))
return PTR_ERR(ci->base);
> +
> reset_control_assert(reset);
> usleep_range(10000, 12000);
> reset_control_deassert(reset);
Regards,
Bjorn
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time
2016-06-26 7:28 ` [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time Stephen Boyd
2016-06-28 4:51 ` Bjorn Andersson
@ 2016-06-29 8:08 ` Peter Chen
[not found] ` <146722853892.16253.6137643683844696922@sboyd-linaro>
1 sibling, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 8:08 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, Felipe Balbi, Arnd Bergmann, Neil Armstrong,
linux-arm-msm, linux-kernel, Bjorn Andersson, Peter Chen,
Greg Kroah-Hartman, Andy Gross, linux-arm-kernel
On Sun, Jun 26, 2016 at 12:28:32AM -0700, Stephen Boyd wrote:
> We need to pick the correct phy at runtime based on how the SoC
> has been wired onto the board. If the secondary phy is used, take
> it out of reset and mux over to it by writing into the TCSR
> register. Make sure to do this on reset too, because this
> register is reset to the default value (primary phy) after the
> RESET bit is set in USBCMD.
>
I am curious when you need the secondary phy?
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 78 +++++++++++++++++++++++++++++++++++---
> 1 file changed, 73 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index 40249b0e3e93..df0f8b31db4f 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -8,30 +8,40 @@
> #include <linux/module.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> -#include <linux/usb/gadget.h>
> #include <linux/usb/chipidea.h>
> #include <linux/clk.h>
> #include <linux/reset.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/io.h>
>
> #include "ci.h"
>
> #define HS_PHY_AHB_MODE 0x0098
> +#define HS_PHY_SEC_CTRL 0x0278
> +# define HS_PHY_DIG_CLAMP_N BIT(16)
>
One space at the beginning, and keep alignment.
> struct ci_hdrc_msm {
> struct platform_device *ci;
> struct clk *core_clk;
> struct clk *iface_clk;
> + bool secondary_phy;
> + void __iomem *base;
> };
>
> static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> {
> - struct device *dev = ci->gadget.dev.parent;
> + struct device *dev = ci->dev->parent;
> + struct ci_hdrc_msm *msm_ci = dev_get_drvdata(dev);
>
> switch (event) {
> case CI_HDRC_CONTROLLER_RESET_EVENT:
> dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
> /* use AHB transactor, allow posted data writes */
> hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
> + if (msm_ci->secondary_phy)
> + hw_write_id_reg(ci, HS_PHY_SEC_CTRL, HS_PHY_DIG_CLAMP_N,
> + HS_PHY_DIG_CLAMP_N);
> break;
> default:
> dev_dbg(dev, "unknown ci_hdrc event\n");
> @@ -49,12 +59,58 @@ static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
> .notify_event = ci_hdrc_msm_notify_event,
> };
>
> +static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
> + struct platform_device *pdev)
> +{
> + struct regmap *regmap;
> + struct device_node *syscon;
> + struct device *dev = &pdev->dev;
> + u32 off, val;
> + int ret;
> +
> + syscon = of_parse_phandle(dev->of_node, "phy-select", 0);
> + if (!syscon)
> + return 0;
> +
> + regmap = syscon_node_to_regmap(syscon);
> + if (IS_ERR(regmap))
> + return PTR_ERR(regmap);
> +
> + ret = of_property_read_u32_index(dev->of_node, "phy-select", 1, &off);
> + if (ret < 0) {
> + dev_err(dev, "no offset in syscon\n");
> + return -EINVAL;
> + }
> +
> + ret = of_property_read_u32_index(dev->of_node, "phy-select", 2, &val);
> + if (ret < 0) {
> + dev_err(dev, "no value in syscon\n");
> + return -EINVAL;
> + }
> +
> + ret = regmap_write(regmap, off, val);
> + if (ret)
> + return ret;
> +
> + ci->secondary_phy = !!val;
> + if (ci->secondary_phy) {
> + val = readl_relaxed(ci->base + HS_PHY_SEC_CTRL);
> + val |= HS_PHY_DIG_CLAMP_N;
> + writel_relaxed(val, ci->base + HS_PHY_SEC_CTRL);
> + }
> +
> + return 0;
> +}
> +
> static int ci_hdrc_msm_probe(struct platform_device *pdev)
> {
> struct ci_hdrc_msm *ci;
> struct platform_device *plat_ci;
> struct clk *clk;
> struct reset_control *reset;
> + struct resource *res;
> + void __iomem *base;
> + resource_size_t size;
> int ret;
>
> dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
> @@ -76,6 +132,15 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> if (IS_ERR(clk))
> return PTR_ERR(clk);
>
> + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> + if (!res)
> + return -ENODEV;
> +
> + size = resource_size(res);
> + ci->base = base = devm_ioremap(&pdev->dev, res->start, size);
> + if (!base)
> + return -ENOMEM;
> +
The core will do the ioremap too, you can't remap io address two times.
The offset larger than 0x200 is vendor specific, you can map it as
the second io region.
> reset_control_assert(reset);
> usleep_range(10000, 12000);
> reset_control_deassert(reset);
> @@ -88,9 +153,12 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> if (ret)
> goto err_iface;
>
> - plat_ci = ci_hdrc_add_device(&pdev->dev,
> - pdev->resource, pdev->num_resources,
> - &ci_hdrc_msm_platdata);
> + ret = ci_hdrc_msm_mux_phy(ci, pdev);
> + if (ret)
> + goto err_mux;
> +
> + plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
> + pdev->num_resources, &ci_hdrc_msm_platdata);
> if (IS_ERR(plat_ci)) {
> dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
> ret = PTR_ERR(plat_ci);
> --
> 2.9.0.rc2.8.ga28705d
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 16/21] usb: chipidea: msm: Restore wrapper settings after reset
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (14 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 15/21] usb: chipidea: msm: Mux over secondary phy at the right time Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 8:26 ` Peter Chen
2016-06-26 7:28 ` [PATCH 17/21] usb: chipidea: msm: Make platform data driver local instead of global Stephen Boyd
` (5 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
When the RESET bit is set in the USBCMD register it resets quite
a few of the wrapper's registers to their reset state. This
includes the GENCONFIG and GENCONFIG2 registers. Currently this
is done by the usb phy and ehci-msm drivers writing into the
controller wrapper's MMIO address space. Let's consolidate the
register writes into the wrapper driver instead so that we
clearly split the wrapper from the phys.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 46 ++++++++++++++++++++++++++++++++++++++
1 file changed, 46 insertions(+)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index df0f8b31db4f..cc6f9b0df9d5 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -14,6 +14,8 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/io.h>
+#include <linux/extcon.h>
+#include <linux/of.h>
#include "ci.h"
@@ -21,11 +23,22 @@
#define HS_PHY_SEC_CTRL 0x0278
# define HS_PHY_DIG_CLAMP_N BIT(16)
+#define HS_PHY_GENCONFIG 0x009c
+# define HS_PHY_TXFIFO_IDLE_FORCE_DIS BIT(4)
+
+#define HS_PHY_GENCONFIG_2 0x00a0
+# define HS_PHY_SESS_VLD_CTRL_EN BIT(7)
+# define HS_PHY_ULPI_TX_PKT_EN_CLR_FIX BIT(19)
+
+#define HSPHY_SESS_VLD_CTRL BIT(25)
+
struct ci_hdrc_msm {
struct platform_device *ci;
struct clk *core_clk;
struct clk *iface_clk;
+ struct extcon_dev *vbus_edev;
bool secondary_phy;
+ bool hsic;
void __iomem *base;
};
@@ -39,9 +52,26 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
/* use AHB transactor, allow posted data writes */
hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
+ /* workaround for rx buffer collision issue */
+ hw_write_id_reg(ci, HS_PHY_GENCONFIG,
+ HS_PHY_TXFIFO_IDLE_FORCE_DIS, 0);
+
if (msm_ci->secondary_phy)
hw_write_id_reg(ci, HS_PHY_SEC_CTRL, HS_PHY_DIG_CLAMP_N,
HS_PHY_DIG_CLAMP_N);
+
+ if (!msm_ci->hsic)
+ hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
+ HS_PHY_ULPI_TX_PKT_EN_CLR_FIX, 0);
+
+ if (msm_ci->vbus_edev) {
+ hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
+ HS_PHY_SESS_VLD_CTRL_EN,
+ HS_PHY_SESS_VLD_CTRL_EN);
+ hw_write(ci, OP_USBCMD, HSPHY_SESS_VLD_CTRL,
+ HSPHY_SESS_VLD_CTRL);
+
+ }
break;
default:
dev_dbg(dev, "unknown ci_hdrc event\n");
@@ -112,6 +142,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
void __iomem *base;
resource_size_t size;
int ret;
+ struct device_node *ulpi_node, *phy_node;
dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
@@ -141,6 +172,13 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
if (!base)
return -ENOMEM;
+ ci->vbus_edev = extcon_get_edev_by_phandle(&pdev->dev, 0);
+ if (IS_ERR(ci->vbus_edev)) {
+ if (PTR_ERR(ci->vbus_edev) != -ENODEV)
+ return PTR_ERR(ci->vbus_edev);
+ ci->vbus_edev = NULL;
+ }
+
reset_control_assert(reset);
usleep_range(10000, 12000);
reset_control_deassert(reset);
@@ -157,6 +195,14 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
if (ret)
goto err_mux;
+ ulpi_node = of_find_node_by_name(pdev->dev.of_node, "ulpi");
+ if (ulpi_node) {
+ phy_node = of_get_next_available_child(ulpi_node, NULL);
+ ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");
+ of_node_put(phy_node);
+ }
+ of_node_put(ulpi_node);
+
plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
pdev->num_resources, &ci_hdrc_msm_platdata);
if (IS_ERR(plat_ci)) {
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 16/21] usb: chipidea: msm: Restore wrapper settings after reset
2016-06-26 7:28 ` [PATCH 16/21] usb: chipidea: msm: Restore wrapper settings after reset Stephen Boyd
@ 2016-06-29 8:26 ` Peter Chen
[not found] ` <146722762509.16253.13062209537472705701@sboyd-linaro>
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 8:26 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, Felipe Balbi, Arnd Bergmann, Neil Armstrong,
linux-arm-msm, linux-kernel, Bjorn Andersson, Peter Chen,
Greg Kroah-Hartman, Andy Gross, linux-arm-kernel
On Sun, Jun 26, 2016 at 12:28:33AM -0700, Stephen Boyd wrote:
> When the RESET bit is set in the USBCMD register it resets quite
> a few of the wrapper's registers to their reset state. This
> includes the GENCONFIG and GENCONFIG2 registers. Currently this
> is done by the usb phy and ehci-msm drivers writing into the
> controller wrapper's MMIO address space. Let's consolidate the
> register writes into the wrapper driver instead so that we
> clearly split the wrapper from the phys.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 46 ++++++++++++++++++++++++++++++++++++++
> 1 file changed, 46 insertions(+)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index df0f8b31db4f..cc6f9b0df9d5 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -14,6 +14,8 @@
> #include <linux/mfd/syscon.h>
> #include <linux/regmap.h>
> #include <linux/io.h>
> +#include <linux/extcon.h>
> +#include <linux/of.h>
>
> #include "ci.h"
>
> @@ -21,11 +23,22 @@
> #define HS_PHY_SEC_CTRL 0x0278
> # define HS_PHY_DIG_CLAMP_N BIT(16)
>
> +#define HS_PHY_GENCONFIG 0x009c
> +# define HS_PHY_TXFIFO_IDLE_FORCE_DIS BIT(4)
> +
> +#define HS_PHY_GENCONFIG_2 0x00a0
> +# define HS_PHY_SESS_VLD_CTRL_EN BIT(7)
> +# define HS_PHY_ULPI_TX_PKT_EN_CLR_FIX BIT(19)
> +
> +#define HSPHY_SESS_VLD_CTRL BIT(25)
> +
Keep alignment please.
> struct ci_hdrc_msm {
> struct platform_device *ci;
> struct clk *core_clk;
> struct clk *iface_clk;
> + struct extcon_dev *vbus_edev;
> bool secondary_phy;
> + bool hsic;
> void __iomem *base;
> };
>
> @@ -39,9 +52,26 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> dev_dbg(dev, "CI_HDRC_CONTROLLER_RESET_EVENT received\n");
> /* use AHB transactor, allow posted data writes */
> hw_write_id_reg(ci, HS_PHY_AHB_MODE, 0xffffffff, 0x8);
> + /* workaround for rx buffer collision issue */
> + hw_write_id_reg(ci, HS_PHY_GENCONFIG,
> + HS_PHY_TXFIFO_IDLE_FORCE_DIS, 0);
> +
> if (msm_ci->secondary_phy)
> hw_write_id_reg(ci, HS_PHY_SEC_CTRL, HS_PHY_DIG_CLAMP_N,
> HS_PHY_DIG_CLAMP_N);
> +
> + if (!msm_ci->hsic)
> + hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
> + HS_PHY_ULPI_TX_PKT_EN_CLR_FIX, 0);
> +
> + if (msm_ci->vbus_edev) {
> + hw_write_id_reg(ci, HS_PHY_GENCONFIG_2,
> + HS_PHY_SESS_VLD_CTRL_EN,
> + HS_PHY_SESS_VLD_CTRL_EN);
> + hw_write(ci, OP_USBCMD, HSPHY_SESS_VLD_CTRL,
> + HSPHY_SESS_VLD_CTRL);
> +
> + }
> break;
> default:
> dev_dbg(dev, "unknown ci_hdrc event\n");
> @@ -112,6 +142,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> void __iomem *base;
> resource_size_t size;
> int ret;
> + struct device_node *ulpi_node, *phy_node;
>
> dev_dbg(&pdev->dev, "ci_hdrc_msm_probe\n");
>
> @@ -141,6 +172,13 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> if (!base)
> return -ENOMEM;
>
> + ci->vbus_edev = extcon_get_edev_by_phandle(&pdev->dev, 0);
> + if (IS_ERR(ci->vbus_edev)) {
> + if (PTR_ERR(ci->vbus_edev) != -ENODEV)
> + return PTR_ERR(ci->vbus_edev);
> + ci->vbus_edev = NULL;
> + }
> +
Why not using ci->platdata->vbus_extcon directly?
> reset_control_assert(reset);
> usleep_range(10000, 12000);
> reset_control_deassert(reset);
> @@ -157,6 +195,14 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> if (ret)
> goto err_mux;
>
> + ulpi_node = of_find_node_by_name(pdev->dev.of_node, "ulpi");
> + if (ulpi_node) {
> + phy_node = of_get_next_available_child(ulpi_node, NULL);
> + ci->hsic = of_device_is_compatible(phy_node, "qcom,usb-hsic-phy");
> + of_node_put(phy_node);
> + }
> + of_node_put(ulpi_node);
> +
Just confirm with you that ci->platdata->phy_mode is not enough?
> plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
> pdev->num_resources, &ci_hdrc_msm_platdata);
> if (IS_ERR(plat_ci)) {
> --
> 2.9.0.rc2.8.ga28705d
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 17/21] usb: chipidea: msm: Make platform data driver local instead of global
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (15 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 16/21] usb: chipidea: msm: Restore wrapper settings after reset Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-29 11:29 ` Peter Chen
2016-06-26 7:28 ` [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd
` (4 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
If two devices are probed with this same driver, they'll share
the same platform data structure, while the chipidea core layer
writes and modifies it. This can lead to interesting results
especially if one device is an OTG type chipidea controller and
another is a host. Let's create a copy of this structure per each
device instance so that odd things don't happen.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 19 ++++++++-----------
1 file changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index cc6f9b0df9d5..fb4340f02c16 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -37,6 +37,7 @@ struct ci_hdrc_msm {
struct clk *core_clk;
struct clk *iface_clk;
struct extcon_dev *vbus_edev;
+ struct ci_hdrc_platform_data pdata;
bool secondary_phy;
bool hsic;
void __iomem *base;
@@ -79,16 +80,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
}
}
-static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
- .name = "ci_hdrc_msm",
- .capoffset = DEF_CAPOFFSET,
- .flags = CI_HDRC_REGS_SHARED |
- CI_HDRC_DISABLE_STREAMING |
- CI_HDRC_OVERRIDE_AHB_BURST,
-
- .notify_event = ci_hdrc_msm_notify_event,
-};
-
static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
struct platform_device *pdev)
{
@@ -151,6 +142,12 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
return -ENOMEM;
platform_set_drvdata(pdev, ci);
+ ci->pdata.name = "ci_hdrc_msm";
+ ci->pdata.capoffset = DEF_CAPOFFSET;
+ ci->pdata.flags = CI_HDRC_REGS_SHARED | CI_HDRC_DISABLE_STREAMING |
+ CI_HDRC_OVERRIDE_AHB_BURST;
+ ci->pdata.notify_event = ci_hdrc_msm_notify_event;
+
reset = devm_reset_control_get(&pdev->dev, "core");
if (IS_ERR(reset))
return PTR_ERR(reset);
@@ -204,7 +201,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
of_node_put(ulpi_node);
plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
- pdev->num_resources, &ci_hdrc_msm_platdata);
+ pdev->num_resources, &ci->pdata);
if (IS_ERR(plat_ci)) {
dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
ret = PTR_ERR(plat_ci);
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 17/21] usb: chipidea: msm: Make platform data driver local instead of global
2016-06-26 7:28 ` [PATCH 17/21] usb: chipidea: msm: Make platform data driver local instead of global Stephen Boyd
@ 2016-06-29 11:29 ` Peter Chen
[not found] ` <146722783258.16253.8246581455698560411@sboyd-linaro>
0 siblings, 1 reply; 69+ messages in thread
From: Peter Chen @ 2016-06-29 11:29 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:34AM -0700, Stephen Boyd wrote:
> If two devices are probed with this same driver, they'll share
> the same platform data structure, while the chipidea core layer
> writes and modifies it. This can lead to interesting results
> especially if one device is an OTG type chipidea controller and
> another is a host. Let's create a copy of this structure per each
> device instance so that odd things don't happen.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 19 ++++++++-----------
> 1 file changed, 8 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index cc6f9b0df9d5..fb4340f02c16 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -37,6 +37,7 @@ struct ci_hdrc_msm {
> struct clk *core_clk;
> struct clk *iface_clk;
> struct extcon_dev *vbus_edev;
> + struct ci_hdrc_platform_data pdata;
> bool secondary_phy;
> bool hsic;
> void __iomem *base;
> @@ -79,16 +80,6 @@ static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> }
> }
>
> -static struct ci_hdrc_platform_data ci_hdrc_msm_platdata = {
> - .name = "ci_hdrc_msm",
> - .capoffset = DEF_CAPOFFSET,
> - .flags = CI_HDRC_REGS_SHARED |
> - CI_HDRC_DISABLE_STREAMING |
> - CI_HDRC_OVERRIDE_AHB_BURST,
> -
> - .notify_event = ci_hdrc_msm_notify_event,
> -};
> -
> static int ci_hdrc_msm_mux_phy(struct ci_hdrc_msm *ci,
> struct platform_device *pdev)
> {
> @@ -151,6 +142,12 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> return -ENOMEM;
> platform_set_drvdata(pdev, ci);
>
> + ci->pdata.name = "ci_hdrc_msm";
> + ci->pdata.capoffset = DEF_CAPOFFSET;
> + ci->pdata.flags = CI_HDRC_REGS_SHARED | CI_HDRC_DISABLE_STREAMING |
> + CI_HDRC_OVERRIDE_AHB_BURST;
> + ci->pdata.notify_event = ci_hdrc_msm_notify_event;
> +
> reset = devm_reset_control_get(&pdev->dev, "core");
> if (IS_ERR(reset))
> return PTR_ERR(reset);
> @@ -204,7 +201,7 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> of_node_put(ulpi_node);
>
> plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
> - pdev->num_resources, &ci_hdrc_msm_platdata);
> + pdev->num_resources, &ci->pdata);
> if (IS_ERR(plat_ci)) {
> dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
> ret = PTR_ERR(plat_ci);
You can do something like ci_hdrc_usb2.c, it looks simpler.
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (16 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 17/21] usb: chipidea: msm: Make platform data driver local instead of global Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-27 3:41 ` kbuild test robot
` (3 more replies)
2016-06-26 7:28 ` [PATCH 19/21] usb: chipidea: msm: Be silent on probe defer errors Stephen Boyd
` (3 subsequent siblings)
21 siblings, 4 replies; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
The MSM chipidea wrapper has two bits that are used to reset the
first or second phy. Add support for these bits via the reset
controller framework, so that phy drivers can reset their
hardware at the right time during initialization.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 43 +++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index fb4340f02c16..7d191928e55b 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -14,14 +14,17 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/io.h>
+#include <linux/reset-controller.h>
#include <linux/extcon.h>
#include <linux/of.h>
#include "ci.h"
#define HS_PHY_AHB_MODE 0x0098
+#define HS_PHY_CTRL 0x0240
#define HS_PHY_SEC_CTRL 0x0278
# define HS_PHY_DIG_CLAMP_N BIT(16)
+# define HS_PHY_POR_ASSERT BIT(0)
#define HS_PHY_GENCONFIG 0x009c
# define HS_PHY_TXFIFO_IDLE_FORCE_DIS BIT(4)
@@ -38,11 +41,38 @@ struct ci_hdrc_msm {
struct clk *iface_clk;
struct extcon_dev *vbus_edev;
struct ci_hdrc_platform_data pdata;
+ struct reset_controller_dev rcdev;
bool secondary_phy;
bool hsic;
void __iomem *base;
};
+static int
+ci_hdrc_msm_por_reset(struct reset_controller_dev *r, unsigned long id)
+{
+ struct ci_hdrc_msm *ci_msm = container_of(r, struct ci_hdrc_msm, rcdev);
+ void __iomem *addr = ci_msm->base;
+ u32 val;
+
+ if (id)
+ addr += HS_PHY_SEC_CTRL;
+ else
+ addr += HS_PHY_CTRL;
+
+ val = readl_relaxed(addr);
+ val |= HS_PHY_POR_ASSERT;
+ writel_relaxed(val, addr);
+ udelay(12);
+ val &= ~HS_PHY_POR_ASSERT;
+ writel(val, addr);
+
+ return 0;
+}
+
+static const struct reset_control_ops ci_hdrc_msm_reset_ops = {
+ .reset = ci_hdrc_msm_por_reset,
+};
+
static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
{
struct device *dev = ci->dev->parent;
@@ -176,13 +206,21 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
ci->vbus_edev = NULL;
}
+ ci->rcdev.owner = THIS_MODULE;
+ ci->rcdev.ops = &ci_hdrc_msm_reset_ops;
+ ci->rcdev.of_node = pdev->dev.of_node;
+ ci->rcdev.nr_resets = 2;
+ ret = reset_controller_register(&ci->rcdev);
+ if (ret)
+ return ret;
+
reset_control_assert(reset);
usleep_range(10000, 12000);
reset_control_deassert(reset);
ret = clk_prepare_enable(ci->core_clk);
if (ret)
- return ret;
+ goto err_core;
ret = clk_prepare_enable(ci->iface_clk);
if (ret)
@@ -220,6 +258,8 @@ err_mux:
clk_disable_unprepare(ci->iface_clk);
err_iface:
clk_disable_unprepare(ci->core_clk);
+err_core:
+ reset_controller_unregister(&ci->rcdev);
return ret;
}
@@ -232,6 +272,7 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev)
ci_hdrc_remove_device(ci->ci);
clk_disable_unprepare(ci->iface_clk);
clk_disable_unprepare(ci->core_clk);
+ reset_controller_unregister(&ci->rcdev);
return 0;
}
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit
2016-06-26 7:28 ` [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd
@ 2016-06-27 3:41 ` kbuild test robot
2016-06-27 4:51 ` kbuild test robot
` (2 subsequent siblings)
3 siblings, 0 replies; 69+ messages in thread
From: kbuild test robot @ 2016-06-27 3:41 UTC (permalink / raw)
To: Stephen Boyd
Cc: kbuild-all, linux-usb, linux-arm-kernel, linux-kernel,
linux-arm-msm, Andy Gross, Bjorn Andersson, Neil Armstrong,
Arnd Bergmann, Felipe Balbi, Peter Chen, Greg Kroah-Hartman
[-- Attachment #1: Type: text/plain, Size: 969 bytes --]
Hi,
[auto build test ERROR on peter.chen-usb/ci-for-usb-next]
[also build test ERROR on v4.7-rc5 next-20160624]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/Support-qcom-s-HSIC-USB-and-rewrite-USB2-HS-phy-support/20160627-102637
base: https://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb ci-for-usb-next
config: x86_64-acpi-redef (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
drivers/built-in.o: In function `ci_hdrc_msm_remove':
>> ci_hdrc_msm.c:(.text+0x4fffd2): undefined reference to `reset_controller_unregister'
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 28294 bytes --]
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit
2016-06-26 7:28 ` [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd
2016-06-27 3:41 ` kbuild test robot
@ 2016-06-27 4:51 ` kbuild test robot
2016-06-27 7:50 ` kbuild test robot
2016-06-29 11:45 ` Peter Chen
3 siblings, 0 replies; 69+ messages in thread
From: kbuild test robot @ 2016-06-27 4:51 UTC (permalink / raw)
To: Stephen Boyd
Cc: kbuild-all, linux-usb, linux-arm-kernel, linux-kernel,
linux-arm-msm, Andy Gross, Bjorn Andersson, Neil Armstrong,
Arnd Bergmann, Felipe Balbi, Peter Chen, Greg Kroah-Hartman
[-- Attachment #1: Type: text/plain, Size: 1497 bytes --]
Hi,
[auto build test ERROR on peter.chen-usb/ci-for-usb-next]
[also build test ERROR on v4.7-rc5 next-20160624]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/Support-qcom-s-HSIC-USB-and-rewrite-USB2-HS-phy-support/20160627-102637
base: https://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb ci-for-usb-next
config: arm-multi_v5_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All errors (new ones prefixed by >>):
drivers/built-in.o: In function `ci_hdrc_msm_remove':
>> drivers/usb/chipidea/ci_hdrc_msm.c:275: undefined reference to `reset_controller_unregister'
vim +275 drivers/usb/chipidea/ci_hdrc_msm.c
269
270 pm_runtime_put(&pdev->dev);
271 pm_runtime_disable(&pdev->dev);
272 ci_hdrc_remove_device(ci->ci);
273 clk_disable_unprepare(ci->iface_clk);
274 clk_disable_unprepare(ci->core_clk);
> 275 reset_controller_unregister(&ci->rcdev);
276
277 return 0;
278 }
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 23385 bytes --]
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit
2016-06-26 7:28 ` [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd
2016-06-27 3:41 ` kbuild test robot
2016-06-27 4:51 ` kbuild test robot
@ 2016-06-27 7:50 ` kbuild test robot
2016-06-29 11:45 ` Peter Chen
3 siblings, 0 replies; 69+ messages in thread
From: kbuild test robot @ 2016-06-27 7:50 UTC (permalink / raw)
To: Stephen Boyd
Cc: kbuild-all, linux-usb, linux-arm-kernel, linux-kernel,
linux-arm-msm, Andy Gross, Bjorn Andersson, Neil Armstrong,
Arnd Bergmann, Felipe Balbi, Peter Chen, Greg Kroah-Hartman
[-- Attachment #1: Type: text/plain, Size: 925 bytes --]
Hi,
[auto build test ERROR on peter.chen-usb/ci-for-usb-next]
[also build test ERROR on v4.7-rc5 next-20160624]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/Support-qcom-s-HSIC-USB-and-rewrite-USB2-HS-phy-support/20160627-102637
base: https://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb ci-for-usb-next
config: x86_64-randconfig-s5-06271251 (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
>> ERROR: "reset_controller_unregister" [drivers/usb/chipidea/ci_hdrc_msm.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 21055 bytes --]
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit
2016-06-26 7:28 ` [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd
` (2 preceding siblings ...)
2016-06-27 7:50 ` kbuild test robot
@ 2016-06-29 11:45 ` Peter Chen
3 siblings, 0 replies; 69+ messages in thread
From: Peter Chen @ 2016-06-29 11:45 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:35AM -0700, Stephen Boyd wrote:
> The MSM chipidea wrapper has two bits that are used to reset the
> first or second phy. Add support for these bits via the reset
> controller framework, so that phy drivers can reset their
> hardware at the right time during initialization.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 43 +++++++++++++++++++++++++++++++++++++-
> 1 file changed, 42 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index fb4340f02c16..7d191928e55b 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -14,14 +14,17 @@
> #include <linux/mfd/syscon.h>
> #include <linux/regmap.h>
> #include <linux/io.h>
> +#include <linux/reset-controller.h>
> #include <linux/extcon.h>
> #include <linux/of.h>
>
> #include "ci.h"
>
> #define HS_PHY_AHB_MODE 0x0098
> +#define HS_PHY_CTRL 0x0240
> #define HS_PHY_SEC_CTRL 0x0278
> # define HS_PHY_DIG_CLAMP_N BIT(16)
> +# define HS_PHY_POR_ASSERT BIT(0)
>
> #define HS_PHY_GENCONFIG 0x009c
> # define HS_PHY_TXFIFO_IDLE_FORCE_DIS BIT(4)
> @@ -38,11 +41,38 @@ struct ci_hdrc_msm {
> struct clk *iface_clk;
> struct extcon_dev *vbus_edev;
> struct ci_hdrc_platform_data pdata;
> + struct reset_controller_dev rcdev;
> bool secondary_phy;
> bool hsic;
> void __iomem *base;
> };
>
> +static int
> +ci_hdrc_msm_por_reset(struct reset_controller_dev *r, unsigned long id)
> +{
> + struct ci_hdrc_msm *ci_msm = container_of(r, struct ci_hdrc_msm, rcdev);
> + void __iomem *addr = ci_msm->base;
Like I mentioned at previous email, you can use vendor base for
0x200.
> + u32 val;
> +
> + if (id)
> + addr += HS_PHY_SEC_CTRL;
> + else
> + addr += HS_PHY_CTRL;
> +
> + val = readl_relaxed(addr);
> + val |= HS_PHY_POR_ASSERT;
> + writel_relaxed(val, addr);
> + udelay(12);
> + val &= ~HS_PHY_POR_ASSERT;
> + writel(val, addr);
> +
> + return 0;
> +}
> +
> +static const struct reset_control_ops ci_hdrc_msm_reset_ops = {
> + .reset = ci_hdrc_msm_por_reset,
> +};
> +
> static void ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event)
> {
> struct device *dev = ci->dev->parent;
> @@ -176,13 +206,21 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> ci->vbus_edev = NULL;
> }
>
> + ci->rcdev.owner = THIS_MODULE;
> + ci->rcdev.ops = &ci_hdrc_msm_reset_ops;
> + ci->rcdev.of_node = pdev->dev.of_node;
> + ci->rcdev.nr_resets = 2;
> + ret = reset_controller_register(&ci->rcdev);
> + if (ret)
> + return ret;
> +
> reset_control_assert(reset);
> usleep_range(10000, 12000);
> reset_control_deassert(reset);
>
> ret = clk_prepare_enable(ci->core_clk);
> if (ret)
> - return ret;
> + goto err_core;
>
> ret = clk_prepare_enable(ci->iface_clk);
> if (ret)
> @@ -220,6 +258,8 @@ err_mux:
> clk_disable_unprepare(ci->iface_clk);
> err_iface:
> clk_disable_unprepare(ci->core_clk);
> +err_core:
> + reset_controller_unregister(&ci->rcdev);
> return ret;
> }
>
> @@ -232,6 +272,7 @@ static int ci_hdrc_msm_remove(struct platform_device *pdev)
> ci_hdrc_remove_device(ci->ci);
> clk_disable_unprepare(ci->iface_clk);
> clk_disable_unprepare(ci->core_clk);
> + reset_controller_unregister(&ci->rcdev);
>
> return 0;
> }
> --
> 2.9.0.rc2.8.ga28705d
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 19/21] usb: chipidea: msm: Be silent on probe defer errors
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (17 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 18/21] usb: chipidea: msm: Add reset controller for PHY POR bit Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-30 1:06 ` Peter Chen
2016-06-26 7:28 ` [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy Stephen Boyd
` (2 subsequent siblings)
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Peter Chen, Greg Kroah-Hartman
If something fails in ci_hdrc_add_device() due to probe defer, we
shouldn't print an error message. Be silent in this case as we'll
try probe again later.
Cc: Peter Chen <peter.chen@nxp.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
drivers/usb/chipidea/ci_hdrc_msm.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 7d191928e55b..2ed9a181f4b6 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -241,7 +241,8 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
pdev->num_resources, &ci->pdata);
if (IS_ERR(plat_ci)) {
- dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
+ if (PTR_ERR(plat_ci) != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
ret = PTR_ERR(plat_ci);
goto err_mux;
}
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 19/21] usb: chipidea: msm: Be silent on probe defer errors
2016-06-26 7:28 ` [PATCH 19/21] usb: chipidea: msm: Be silent on probe defer errors Stephen Boyd
@ 2016-06-30 1:06 ` Peter Chen
0 siblings, 0 replies; 69+ messages in thread
From: Peter Chen @ 2016-06-30 1:06 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, linux-arm-kernel, linux-kernel, linux-arm-msm,
Andy Gross, Bjorn Andersson, Neil Armstrong, Arnd Bergmann,
Felipe Balbi, Peter Chen, Greg Kroah-Hartman
On Sun, Jun 26, 2016 at 12:28:36AM -0700, Stephen Boyd wrote:
> If something fails in ci_hdrc_add_device() due to probe defer, we
> shouldn't print an error message. Be silent in this case as we'll
> try probe again later.
>
> Cc: Peter Chen <peter.chen@nxp.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/usb/chipidea/ci_hdrc_msm.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
> index 7d191928e55b..2ed9a181f4b6 100644
> --- a/drivers/usb/chipidea/ci_hdrc_msm.c
> +++ b/drivers/usb/chipidea/ci_hdrc_msm.c
> @@ -241,7 +241,8 @@ static int ci_hdrc_msm_probe(struct platform_device *pdev)
> plat_ci = ci_hdrc_add_device(&pdev->dev, pdev->resource,
> pdev->num_resources, &ci->pdata);
> if (IS_ERR(plat_ci)) {
> - dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
> + if (PTR_ERR(plat_ci) != -EPROBE_DEFER)
> + dev_err(&pdev->dev, "ci_hdrc_add_device failed!\n");
> ret = PTR_ERR(plat_ci);
> goto err_mux;
> }
Why not let ret equals to PTR_ERR(plat_ci) first, and using ret to
compare?
--
Best Regards,
Peter Chen
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (18 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 19/21] usb: chipidea: msm: Be silent on probe defer errors Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-28 8:49 ` Neil Armstrong
2016-06-26 7:28 ` [PATCH 21/21] phy: Add support for Qualcomm's USB HS phy Stephen Boyd
2016-06-28 3:09 ` [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support John Stultz
21 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Kishon Vijay Abraham I, devicetree
The HSIC USB controller on qcom SoCs has an integrated all
digital phy controlled via the ULPI viewport.
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
.../devicetree/bindings/phy/qcom,usb-hsic-phy.txt | 60 ++++++++
drivers/phy/Kconfig | 7 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-qcom-usb-hsic.c | 161 +++++++++++++++++++++
4 files changed, 229 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt
create mode 100644 drivers/phy/phy-qcom-usb-hsic.c
diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt b/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt
new file mode 100644
index 000000000000..6b1c6aad2962
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt
@@ -0,0 +1,60 @@
+Qualcomm's USB HSIC PHY
+
+PROPERTIES
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: Should contain "qcom,usb-hsic-phy"
+
+- #phy-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: Should contain 0
+
+- clocks:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Should contain clock specifier for phy, calibration and
+ optionally a calibration sleep clock
+
+- clock-names:
+ Usage: required
+ Value type: <stringlist>
+ Definition: Should contain "phy, "cal" and optionally "cal_sleep"
+
+- pinctrl-names:
+ Usage: required
+ Value type: <stringlist>
+ Definition: Should contain "init" and "default" in that order
+
+- pinctrl-0:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: List of pinctrl settings to apply to keep HSIC pins in a glitch
+ free state
+
+- pinctrl-1:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: List of pinctrl settings to apply to mux out the HSIC pins
+
+EXAMPLE
+
+usb-controller {
+ ulpi {
+ phy {
+ compatible = "qcom,usb-hsic-phy";
+ #phy-cells = <0>;
+ pinctrl-names = "init", "default";
+ pinctrl-0 = <&hsic_sleep>;
+ pinctrl-1 = <&hsic_default>;
+ clocks = <&gcc GCC_USB_HSIC_CLK>,
+ <&gcc GCC_USB_HSIC_IO_CAL_CLK>,
+ <&gcc GCC_USB_HSIC_IO_CAL_SLEEP_CLK>;
+ clock-names = "phy", "cal", "cal_sleep";
+ assigned-clocks = <&gcc GCC_USB_HSIC_IO_CAL_CLK>;
+ assigned-clock-rates = <960000>;
+ };
+ };
+};
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index b869b98835f4..a2866949dc97 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -406,6 +406,13 @@ config PHY_QCOM_UFS
help
Support for UFS PHY on QCOM chipsets.
+config PHY_QCOM_USB_HSIC
+ tristate "Qualcomm USB HSIC ULPI PHY module"
+ depends on USB_ULPI_BUS
+ select GENERIC_PHY
+ help
+ Support for the USB HSIC ULPI compliant PHY on QCOM chipsets.
+
config PHY_TUSB1210
tristate "TI TUSB1210 ULPI PHY module"
depends on USB_ULPI_BUS
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 9c3e73ccabc4..982e84a290ec 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_PHY_STIH41X_USB) += phy-stih41x-usb.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
+obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o
diff --git a/drivers/phy/phy-qcom-usb-hsic.c b/drivers/phy/phy-qcom-usb-hsic.c
new file mode 100644
index 000000000000..a81b2f8bfe37
--- /dev/null
+++ b/drivers/phy/phy-qcom-usb-hsic.c
@@ -0,0 +1,161 @@
+/**
+ * Copyright (C) 2016 Linaro Ltd
+ *
+ * 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/module.h>
+#include <linux/ulpi/driver.h>
+#include <linux/ulpi/regs.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinctrl-state.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+
+#include "ulpi_phy.h"
+
+#define ULPI_HSIC_CFG 0x30
+#define ULPI_HSIC_IO_CAL 0x33
+
+struct qcom_usb_hsic_phy {
+ struct ulpi *ulpi;
+ struct phy *phy;
+ struct pinctrl *pctl;
+ struct clk *phy_clk;
+ struct clk *cal_clk;
+ struct clk *cal_sleep_clk;
+};
+
+static int qcom_usb_hsic_phy_power_on(struct phy *phy)
+{
+ struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
+ struct ulpi *ulpi = uphy->ulpi;
+ struct pinctrl_state *pins_default;
+ int ret;
+
+ ret = clk_prepare_enable(uphy->phy_clk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(uphy->cal_clk);
+ if (ret)
+ goto err_cal;
+
+ ret = clk_prepare_enable(uphy->cal_sleep_clk);
+ if (ret)
+ goto err_sleep;
+
+ /* Set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */
+ ret = ulpi_write(ulpi, ULPI_HSIC_IO_CAL, 0xff);
+ if (ret)
+ goto err_ulpi;
+
+ /* Enable periodic IO calibration in HSIC_CFG register */
+ ret = ulpi_write(ulpi, ULPI_HSIC_CFG, 0xa8);
+ if (ret)
+ goto err_ulpi;
+
+ /* Configure pins for HSIC functionality */
+ pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(pins_default))
+ return PTR_ERR(pins_default);
+
+ ret = pinctrl_select_state(uphy->pctl, pins_default);
+ if (ret)
+ goto err_ulpi;
+
+ /* Enable HSIC mode in HSIC_CFG register */
+ ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01);
+ if (ret)
+ goto err_ulpi;
+
+ /* Disable auto-resume */
+ ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL),
+ ULPI_IFC_CTRL_AUTORESUME);
+ if (ret)
+ goto err_ulpi;
+
+ return ret;
+err_ulpi:
+ clk_disable_unprepare(uphy->cal_sleep_clk);
+err_sleep:
+ clk_disable_unprepare(uphy->cal_clk);
+err_cal:
+ clk_disable_unprepare(uphy->phy_clk);
+ return ret;
+}
+
+static int qcom_usb_hsic_phy_power_off(struct phy *phy)
+{
+ struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
+
+ clk_disable_unprepare(uphy->cal_sleep_clk);
+ clk_disable_unprepare(uphy->cal_clk);
+ clk_disable_unprepare(uphy->phy_clk);
+
+ return 0;
+}
+
+static const struct phy_ops qcom_usb_hsic_phy_ops = {
+ .power_on = qcom_usb_hsic_phy_power_on,
+ .power_off = qcom_usb_hsic_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi)
+{
+ struct qcom_usb_hsic_phy *uphy;
+ struct phy_provider *p;
+ struct clk *clk;
+
+ uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
+ if (!uphy)
+ return -ENOMEM;
+ ulpi_set_drvdata(ulpi, uphy);
+
+ uphy->ulpi = ulpi;
+ uphy->pctl = devm_pinctrl_get(&ulpi->dev);
+ if (IS_ERR(uphy->pctl))
+ return PTR_ERR(uphy->pctl);
+
+ uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
+ &qcom_usb_hsic_phy_ops);
+ if (IS_ERR(uphy->phy))
+ return PTR_ERR(uphy->phy);
+ phy_set_drvdata(uphy->phy, uphy);
+
+ p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
+ return PTR_ERR_OR_ZERO(p);
+}
+
+
+static const struct of_device_id qcom_usb_hsic_phy_match[] = {
+ { .compatible = "qcom,usb-hsic-phy", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match);
+
+static struct ulpi_driver qcom_usb_hsic_phy_driver = {
+ .probe = qcom_usb_hsic_phy_probe,
+ .driver = {
+ .name = "qcom_usb_hsic_phy",
+ .of_match_table = qcom_usb_hsic_phy_match
+ },
+};
+module_ulpi_driver(qcom_usb_hsic_phy_driver);
+
+MODULE_DESCRIPTION("Qualcomm USB HSIC phy");
+MODULE_LICENSE("GPL v2");
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy
2016-06-26 7:28 ` [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy Stephen Boyd
@ 2016-06-28 8:49 ` Neil Armstrong
2016-06-28 21:58 ` Stephen Boyd
0 siblings, 1 reply; 69+ messages in thread
From: Neil Armstrong @ 2016-06-28 8:49 UTC (permalink / raw)
To: Stephen Boyd, linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Arnd Bergmann, Felipe Balbi,
Kishon Vijay Abraham I, devicetree
On 06/26/2016 09:28 AM, Stephen Boyd wrote:
> The HSIC USB controller on qcom SoCs has an integrated all
> digital phy controlled via the ULPI viewport.
>
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: <devicetree@vger.kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> .../devicetree/bindings/phy/qcom,usb-hsic-phy.txt | 60 ++++++++
> drivers/phy/Kconfig | 7 +
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-qcom-usb-hsic.c | 161 +++++++++++++++++++++
> 4 files changed, 229 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt
> create mode 100644 drivers/phy/phy-qcom-usb-hsic.c
>
> diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt b/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt
> new file mode 100644
> index 000000000000..6b1c6aad2962
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt
> @@ -0,0 +1,60 @@
> +Qualcomm's USB HSIC PHY
> +
> +PROPERTIES
> +
> +- compatible:
> + Usage: required
> + Value type: <string>
> + Definition: Should contain "qcom,usb-hsic-phy"
> +
> +- #phy-cells:
> + Usage: required
> + Value type: <u32>
> + Definition: Should contain 0
> +
> +- clocks:
> + Usage: required
> + Value type: <prop-encoded-array>
> + Definition: Should contain clock specifier for phy, calibration and
> + optionally a calibration sleep clock
> +
> +- clock-names:
> + Usage: required
> + Value type: <stringlist>
> + Definition: Should contain "phy, "cal" and optionally "cal_sleep"
> +
[...]
> +
> +static int qcom_usb_hsic_phy_power_on(struct phy *phy)
> +{
> + struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
> + struct ulpi *ulpi = uphy->ulpi;
> + struct pinctrl_state *pins_default;
> + int ret;
> +
> + ret = clk_prepare_enable(uphy->phy_clk);
> + if (ret)
> + return ret;
> +
> + ret = clk_prepare_enable(uphy->cal_clk);
> + if (ret)
> + goto err_cal;
> +
> + ret = clk_prepare_enable(uphy->cal_sleep_clk);
> + if (ret)
> + goto err_sleep;
> +
[...]
> +
> + return ret;
> +err_ulpi:
> + clk_disable_unprepare(uphy->cal_sleep_clk);
> +err_sleep:
> + clk_disable_unprepare(uphy->cal_clk);
> +err_cal:
> + clk_disable_unprepare(uphy->phy_clk);
> + return ret;
> +}
> +
> +static int qcom_usb_hsic_phy_power_off(struct phy *phy)
> +{
> + struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy);
> +
> + clk_disable_unprepare(uphy->cal_sleep_clk);
> + clk_disable_unprepare(uphy->cal_clk);
> + clk_disable_unprepare(uphy->phy_clk);
[...]
> +static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi)
> +{
> + struct qcom_usb_hsic_phy *uphy;
> + struct phy_provider *p;
> + struct clk *clk;
> +
> + uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
> + if (!uphy)
> + return -ENOMEM;
> + ulpi_set_drvdata(ulpi, uphy);
> +
> + uphy->ulpi = ulpi;
> + uphy->pctl = devm_pinctrl_get(&ulpi->dev);
> + if (IS_ERR(uphy->pctl))
> + return PTR_ERR(uphy->pctl);
> +
> + uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy");
> + if (IS_ERR(clk))
> + return PTR_ERR(clk);
> +
> + uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal");
> + if (IS_ERR(clk))
> + return PTR_ERR(clk);
> +
> + uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
> + if (IS_ERR(clk))
> + return PTR_ERR(clk);
Hi Stephen,
In the bindings the cal_sleep is marked optional, and I think should be since AFAIK
it's not present on MDM9615 for example.
Also MDM9615 HSIC requires "core", "alt-core", "phy", "cal" and "iface" clocks.
I assume "core" can be attributed to the main chipidea node, but I think "alt-core" and "iface" should be also optionnal.
Finally, it misses an optional reset line AFAIK mandatory on MDM9615.
Neil
> +
> + uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
> + &qcom_usb_hsic_phy_ops);
> + if (IS_ERR(uphy->phy))
> + return PTR_ERR(uphy->phy);
> + phy_set_drvdata(uphy->phy, uphy);
> +
> + p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
> + return PTR_ERR_OR_ZERO(p);
> +}
> +
> +
> +static const struct of_device_id qcom_usb_hsic_phy_match[] = {
> + { .compatible = "qcom,usb-hsic-phy", },
> + { }
> +};
> +MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match);
> +
> +static struct ulpi_driver qcom_usb_hsic_phy_driver = {
> + .probe = qcom_usb_hsic_phy_probe,
> + .driver = {
> + .name = "qcom_usb_hsic_phy",
> + .of_match_table = qcom_usb_hsic_phy_match
> + },
> +};
> +module_ulpi_driver(qcom_usb_hsic_phy_driver);
> +
> +MODULE_DESCRIPTION("Qualcomm USB HSIC phy");
> +MODULE_LICENSE("GPL v2");
>
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy
2016-06-28 8:49 ` Neil Armstrong
@ 2016-06-28 21:58 ` Stephen Boyd
2016-06-29 9:16 ` Neil Armstrong
0 siblings, 1 reply; 69+ messages in thread
From: Stephen Boyd @ 2016-06-28 21:58 UTC (permalink / raw)
To: Neil Armstrong, linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Arnd Bergmann, Felipe Balbi,
Kishon Vijay Abraham I, devicetree
Quoting Neil Armstrong (2016-06-28 01:49:37)
> On 06/26/2016 09:28 AM, Stephen Boyd wrote:
> > + uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
> > + if (IS_ERR(clk))
> > + return PTR_ERR(clk);
>
> Hi Stephen,
>
> In the bindings the cal_sleep is marked optional, and I think should be since AFAIK
> it's not present on MDM9615 for example.
The cal_sleep clk is just the sleep clk then (should be a board clk in
DT). Sometimes there's a gate in GCC to allow us to turn it off, other
times there isn't. Either way, it's always wired there so I'll update
the binding to say it isn't optional.
>
> Also MDM9615 HSIC requires "core", "alt-core", "phy", "cal" and "iface" clocks.
> I assume "core" can be attributed to the main chipidea node, but I think "alt-core" and "iface" should be also optionnal.
Looking at the downstream sources I see this:
"core_clk" -> usb_hsic_sys_clk
"iface_clk" -> usb_hsic_p_clk
"alt_core_clk" -> usb_hsic_xcvr_clk
"cal_clk" -> usb_hsic_hsio_cal_clk
"phy_clk" -> usb_hsic_clk
"core_clk" would be the core clk in ci_hdrc_msm. "iface_clk" would be
the iface clk in ci_hdrc_msm. "cal_clk" would be the cal clk in the hsic
phy and "phy_clk" would be the phy clk in the hsic phy.
That leaves alt_core_clk which seems to be a clock that needs to be on
during the reset assert/deassert and possibly for LPM and USB1.1 FS
modes. Sometimes it's referred to as the "housekeeping" clk. Due to the
way resets are done on msm8974 and later SoCs it looks like this clk was
removed. I can make this an optional clk in the ci_hdrc_msm driver, or
we can have two versions of the ci_hdrc_msm compatible string, one for a
device that has the housekeeping clk and one for the device that
doesn't.
>
> Finally, it misses an optional reset line AFAIK mandatory on MDM9615.
>
>From what I can tell downstream, all those clks point to the same bit 0
of HSIC_RESET register? So there isn't any phy reset, just the chipidea
controller wrapper reset bit, which should go into the wrapper node?
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy
2016-06-28 21:58 ` Stephen Boyd
@ 2016-06-29 9:16 ` Neil Armstrong
2016-06-29 18:54 ` Stephen Boyd
0 siblings, 1 reply; 69+ messages in thread
From: Neil Armstrong @ 2016-06-29 9:16 UTC (permalink / raw)
To: Stephen Boyd, linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Arnd Bergmann, Felipe Balbi,
Kishon Vijay Abraham I, devicetree
On 06/28/2016 11:58 PM, Stephen Boyd wrote:
> Quoting Neil Armstrong (2016-06-28 01:49:37)
>> On 06/26/2016 09:28 AM, Stephen Boyd wrote:
>>> + uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
>>> + if (IS_ERR(clk))
>>> + return PTR_ERR(clk);
>>
>> Hi Stephen,
>>
>> In the bindings the cal_sleep is marked optional, and I think should be since AFAIK
>> it's not present on MDM9615 for example.
>
> The cal_sleep clk is just the sleep clk then (should be a board clk in
> DT). Sometimes there's a gate in GCC to allow us to turn it off, other
> times there isn't. Either way, it's always wired there so I'll update
> the binding to say it isn't optional.
Sorry I don't understand !
What should I do if GCC does not provide a gate here ? And looking at the driver, it could be optional.
>
>>
>> Also MDM9615 HSIC requires "core", "alt-core", "phy", "cal" and "iface" clocks.
>> I assume "core" can be attributed to the main chipidea node, but I think "alt-core" and "iface" should be also optionnal.
>
> Looking at the downstream sources I see this:
>
> "core_clk" -> usb_hsic_sys_clk
> "iface_clk" -> usb_hsic_p_clk
> "alt_core_clk" -> usb_hsic_xcvr_clk
>
> "cal_clk" -> usb_hsic_hsio_cal_clk
> "phy_clk" -> usb_hsic_clk
>
> "core_clk" would be the core clk in ci_hdrc_msm. "iface_clk" would be
> the iface clk in ci_hdrc_msm. "cal_clk" would be the cal clk in the hsic
> phy and "phy_clk" would be the phy clk in the hsic phy.
>
> That leaves alt_core_clk which seems to be a clock that needs to be on
> during the reset assert/deassert and possibly for LPM and USB1.1 FS
> modes. Sometimes it's referred to as the "housekeeping" clk. Due to the
> way resets are done on msm8974 and later SoCs it looks like this clk was
> removed. I can make this an optional clk in the ci_hdrc_msm driver, or
> we can have two versions of the ci_hdrc_msm compatible string, one for a
> device that has the housekeeping clk and one for the device that
> doesn't.
Having it optional would be the best solution I think.
>
>>
>> Finally, it misses an optional reset line AFAIK mandatory on MDM9615.
>>
>
> From what I can tell downstream, all those clks point to the same bit 0
> of HSIC_RESET register? So there isn't any phy reset, just the chipidea
> controller wrapper reset bit, which should go into the wrapper node?
Ok, makes sense.
^ permalink raw reply [flat|nested] 69+ messages in thread
* Re: [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy
2016-06-29 9:16 ` Neil Armstrong
@ 2016-06-29 18:54 ` Stephen Boyd
0 siblings, 0 replies; 69+ messages in thread
From: Stephen Boyd @ 2016-06-29 18:54 UTC (permalink / raw)
To: Neil Armstrong, linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Arnd Bergmann, Felipe Balbi,
Kishon Vijay Abraham I, devicetree
Quoting Neil Armstrong (2016-06-29 02:16:51)
> On 06/28/2016 11:58 PM, Stephen Boyd wrote:
> > Quoting Neil Armstrong (2016-06-28 01:49:37)
> >> On 06/26/2016 09:28 AM, Stephen Boyd wrote:
> >>> + uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep");
> >>> + if (IS_ERR(clk))
> >>> + return PTR_ERR(clk);
> >>
> >> Hi Stephen,
> >>
> >> In the bindings the cal_sleep is marked optional, and I think should be since AFAIK
> >> it's not present on MDM9615 for example.
> >
> > The cal_sleep clk is just the sleep clk then (should be a board clk in
> > DT). Sometimes there's a gate in GCC to allow us to turn it off, other
> > times there isn't. Either way, it's always wired there so I'll update
> > the binding to say it isn't optional.
>
> Sorry I don't understand !
> What should I do if GCC does not provide a gate here ? And looking at the driver, it could be optional.
You should set the property to point to &sleep_clk which should be under
the "clocks" node at the root of the OF tree. For example, see the
sleep_clk node in arch/arm/boot/dts/qcom-apq8064.dtsi.
^ permalink raw reply [flat|nested] 69+ messages in thread
* [PATCH 21/21] phy: Add support for Qualcomm's USB HS phy
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (19 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 20/21] phy: Add support for Qualcomm's USB HSIC phy Stephen Boyd
@ 2016-06-26 7:28 ` Stephen Boyd
2016-06-28 3:09 ` [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support John Stultz
21 siblings, 0 replies; 69+ messages in thread
From: Stephen Boyd @ 2016-06-26 7:28 UTC (permalink / raw)
To: linux-usb
Cc: linux-arm-kernel, linux-kernel, linux-arm-msm, Andy Gross,
Bjorn Andersson, Neil Armstrong, Arnd Bergmann, Felipe Balbi,
Kishon Vijay Abraham I, devicetree
The high-speed phy on qcom SoCs is controlled via the ULPI
viewport.
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
.../devicetree/bindings/phy/qcom,usb-hs-phy.txt | 71 ++++++
drivers/phy/Kconfig | 8 +
drivers/phy/Makefile | 1 +
drivers/phy/phy-qcom-usb-hs.c | 283 +++++++++++++++++++++
4 files changed, 363 insertions(+)
create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
create mode 100644 drivers/phy/phy-qcom-usb-hs.c
diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
new file mode 100644
index 000000000000..2bd22c53cee0
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt
@@ -0,0 +1,71 @@
+Qualcomm's USB HS PHY
+
+PROPERTIES
+
+- compatible:
+ Usage: required
+ Value type: <string>
+ Definition: Should contain "qcom,usb-hs-phy"
+
+- #phy-cells:
+ Usage: required
+ Value type: <u32>
+ Definition: Should contain 0
+
+- clocks:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Should contain clock specifier for the reference and sleep
+ clocks
+
+- clock-names:
+ Usage: required
+ Value type: <stringlist>
+ Definition: Should contain "ref" and "sleep" for the reference and sleep
+ clocks respectively
+
+- resets:
+ Usage: required
+ Value type: <prop-encoded-array>
+ Definition: Should contain the phy and POR resets
+
+- reset-names:
+ Usage: required
+ Value type: <stringlist>
+ Definition: Should contain "phy" and "por" for the phy and POR resets
+ respectively
+
+- v3p3-supply:
+ Usage: required
+ Value type: <phandle>
+ Definition: Should contain a reference to the 3.3V supply
+
+- v1p8-supply:
+ Usage: required
+ Value type: <phandle>
+ Definition: Should contain a reference to the 1.8V supply
+
+- qcom,init-seq:
+ Usage: optional
+ Value type: <u8 array>
+ Definition: Should contain a sequence of ULPI register and address pairs to
+ program into the ULPI_EXT_VENDOR_SPECIFIC area. This is related
+ to Device Mode Eye Diagram test.
+
+EXAMPLE
+
+otg: usb-controller {
+ ulpi {
+ phy {
+ compatible = "qcom,usb-hs-phy";
+ #phy-cells = <0>;
+ clocks = <&xo_board>, <&gcc GCC_USB2A_PHY_SLEEP_CLK>;
+ clock-names = "ref", "sleep";
+ resets = <&gcc GCC_USB2A_PHY_BCR>, <&otg 0>;
+ reset-names = "phy", "por";
+ v3p3-supply = <&pm8941_l24>;
+ v1p8-supply = <&pm8941_l6>;
+ qcom,init-seq = /bits/ 8 <0x81 0x63>;
+ };
+ };
+};
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index a2866949dc97..cfb3ded0896d 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -406,6 +406,14 @@ config PHY_QCOM_UFS
help
Support for UFS PHY on QCOM chipsets.
+config PHY_QCOM_USB_HS
+ tristate "Qualcomm USB HS PHY module"
+ depends on USB_ULPI_BUS
+ select GENERIC_PHY
+ help
+ Support for the USB high-speed ULPI compliant phy on Qualcomm
+ chipsets.
+
config PHY_QCOM_USB_HSIC
tristate "Qualcomm USB HSIC ULPI PHY module"
depends on USB_ULPI_BUS
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 982e84a290ec..21435fc0b656 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -49,6 +49,7 @@ obj-$(CONFIG_PHY_STIH41X_USB) += phy-stih41x-usb.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o
obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o
+obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o
obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o
diff --git a/drivers/phy/phy-qcom-usb-hs.c b/drivers/phy/phy-qcom-usb-hs.c
new file mode 100644
index 000000000000..8be83100ecd9
--- /dev/null
+++ b/drivers/phy/phy-qcom-usb-hs.c
@@ -0,0 +1,283 @@
+/**
+ * Copyright (C) 2016 Linaro Ltd
+ *
+ * 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/module.h>
+#include <linux/ulpi/driver.h>
+#include <linux/ulpi/regs.h>
+#include <linux/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of_device.h>
+#include <linux/reset.h>
+#include <linux/extcon.h>
+#include <linux/notifier.h>
+#include <linux/usb/of.h>
+
+#include "ulpi_phy.h"
+
+#define ULPI_PWR_CLK_MNG_REG 0x88
+# define ULPI_PWR_OTG_COMP_DISABLE BIT(0)
+
+#define ULPI_MISC_A 0x96
+# define ULPI_MISC_A_VBUSVLDEXTSEL BIT(1)
+# define ULPI_MISC_A_VBUSVLDEXT BIT(0)
+
+
+struct ulpi_seq {
+ u8 addr;
+ u8 val;
+};
+
+struct qcom_usb_hs_phy {
+ struct ulpi *ulpi;
+ struct phy *phy;
+ struct clk *ref_clk;
+ struct clk *sleep_clk;
+ struct regulator *v1p8;
+ struct regulator *v3p3;
+ struct reset_control *reset;
+ struct ulpi_seq *init_seq;
+ struct notifier_block vbus_notify;
+ struct extcon_dev *vbus_edev;
+ struct extcon_dev *id_edev;
+ enum usb_dr_mode dr_mode;
+};
+
+static int
+qcom_usb_hs_phy_vbus_notifier(struct notifier_block *nb, unsigned long event,
+ void *ptr)
+{
+ struct qcom_usb_hs_phy *uphy;
+ int is_host;
+ u8 addr;
+
+ uphy = container_of(nb, struct qcom_usb_hs_phy, vbus_notify);
+ is_host = extcon_get_cable_state_(uphy->id_edev, EXTCON_USB_HOST);
+ if (is_host < 0)
+ is_host = 0; /* No id event means always a peripheral */
+
+ if (event && !is_host)
+ addr = ULPI_SET(ULPI_MISC_A);
+ else
+ addr = ULPI_CLR(ULPI_MISC_A);
+
+ return ulpi_write(uphy->ulpi, addr,
+ ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT);
+}
+
+static int qcom_usb_hs_phy_power_on(struct phy *phy)
+{
+ struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
+ struct ulpi *ulpi = uphy->ulpi;
+ const struct ulpi_seq *seq;
+ int ret, state;
+
+ ret = clk_prepare_enable(uphy->ref_clk);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(uphy->sleep_clk);
+ if (ret)
+ goto err_sleep;
+
+ ret = regulator_set_voltage(uphy->v1p8, 1800000, 1800000);
+ if (ret)
+ goto err_1p8;
+ ret = regulator_set_load(uphy->v1p8, 50000);
+ if (ret < 0)
+ goto err_1p8;
+
+ ret = regulator_enable(uphy->v1p8);
+ if (ret)
+ goto err_1p8;
+
+ ret = regulator_set_voltage_triplet(uphy->v3p3, 3050000, 3300000,
+ 3300000);
+ if (ret)
+ goto err_3p3;
+
+ ret = regulator_set_load(uphy->v3p3, 50000);
+ if (ret < 0)
+ goto err_3p3;
+
+ ret = regulator_enable(uphy->v3p3);
+ if (ret)
+ goto err_3p3;
+
+ for (seq = uphy->init_seq; seq->addr; seq++) {
+ ret = ulpi_write(ulpi, seq->addr, seq->val);
+ if (ret)
+ goto err_ulpi;
+ }
+
+ if (uphy->reset) {
+ ret = reset_control_reset(uphy->reset);
+ if (ret)
+ goto err_ulpi;
+ }
+
+ if (uphy->vbus_edev) {
+ ulpi_write(ulpi, ULPI_SET(ULPI_PWR_CLK_MNG_REG),
+ ULPI_PWR_OTG_COMP_DISABLE);
+ state = extcon_get_cable_state_(uphy->vbus_edev, EXTCON_USB);
+ /* setup initial state */
+ qcom_usb_hs_phy_vbus_notifier(&uphy->vbus_notify, state,
+ uphy->vbus_edev);
+ } else {
+ u8 val;
+
+ switch (uphy->dr_mode) {
+ case USB_DR_MODE_OTG:
+ val = ULPI_INT_IDGRD;
+ case USB_DR_MODE_PERIPHERAL:
+ val |= ULPI_INT_SESS_VALID;
+ break;
+ default:
+ val = 0;
+ }
+
+ ret = ulpi_write(ulpi, ULPI_USB_INT_EN_RISE, val);
+ if (ret)
+ goto err_ulpi;
+ ret = ulpi_write(ulpi, ULPI_USB_INT_EN_FALL, val);
+ if (ret)
+ goto err_ulpi;
+ }
+
+ return 0;
+err_ulpi:
+ regulator_disable(uphy->v3p3);
+err_3p3:
+ regulator_disable(uphy->v1p8);
+err_1p8:
+ clk_disable_unprepare(uphy->sleep_clk);
+err_sleep:
+ clk_disable_unprepare(uphy->ref_clk);
+ return ret;
+}
+
+static int qcom_usb_hs_phy_power_off(struct phy *phy)
+{
+ struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy);
+
+ regulator_disable(uphy->v3p3);
+ regulator_disable(uphy->v1p8);
+ clk_disable_unprepare(uphy->sleep_clk);
+ clk_disable_unprepare(uphy->ref_clk);
+
+ return 0;
+}
+
+static const struct phy_ops qcom_usb_hs_phy_ops = {
+ .power_on = qcom_usb_hs_phy_power_on,
+ .power_off = qcom_usb_hs_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int qcom_usb_hs_phy_probe(struct ulpi *ulpi)
+{
+ struct qcom_usb_hs_phy *uphy;
+ struct phy_provider *p;
+ struct clk *clk;
+ struct regulator *reg;
+ struct reset_control *reset;
+ int size;
+ int ret;
+
+ uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL);
+ if (!uphy)
+ return -ENOMEM;
+ ulpi_set_drvdata(ulpi, uphy);
+ uphy->ulpi = ulpi;
+ uphy->dr_mode = of_usb_get_dr_mode_by_phy(ulpi->dev.of_node);
+
+ size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq");
+ if (size < 0)
+ size = 0;
+ uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1,
+ sizeof(*uphy->init_seq), GFP_KERNEL);
+ if (!uphy->init_seq)
+ return -ENOMEM;
+ ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq",
+ (u8 *)uphy->init_seq, size);
+ if (ret && size)
+ return ret;
+ /* NUL terminate */
+ uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0;
+
+ uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ uphy->sleep_clk = clk = devm_clk_get(&ulpi->dev, "sleep");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ uphy->v1p8 = reg = devm_regulator_get(&ulpi->dev, "v1p8");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ uphy->v3p3 = reg = devm_regulator_get(&ulpi->dev, "v3p3");
+ if (IS_ERR(reg))
+ return PTR_ERR(reg);
+
+ uphy->reset = reset = devm_reset_control_get(&ulpi->dev, "por");
+ if (IS_ERR(reset)) {
+ if (PTR_ERR(reset) == -EPROBE_DEFER)
+ return PTR_ERR(reset);
+ uphy->reset = NULL;
+ }
+
+ uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node,
+ &qcom_usb_hs_phy_ops);
+ if (IS_ERR(uphy->phy))
+ return PTR_ERR(uphy->phy);
+
+ uphy->vbus_edev = extcon_get_edev_by_phandle(&ulpi->dev, 0);
+ if (IS_ERR(uphy->vbus_edev)) {
+ if (PTR_ERR(uphy->vbus_edev) != -ENODEV)
+ return PTR_ERR(uphy->vbus_edev);
+ uphy->vbus_edev = NULL;
+ }
+
+ uphy->id_edev = extcon_get_edev_by_phandle(&ulpi->dev, 1);
+ if (IS_ERR(uphy->id_edev)) {
+ if (PTR_ERR(uphy->id_edev) != -ENODEV)
+ return PTR_ERR(uphy->id_edev);
+ uphy->id_edev = NULL;
+ }
+
+ if (uphy->vbus_edev) {
+ uphy->vbus_notify.notifier_call = qcom_usb_hs_phy_vbus_notifier;
+ ret = extcon_register_notifier(uphy->vbus_edev, EXTCON_USB,
+ &uphy->vbus_notify);
+ if (ret)
+ return ret;
+ }
+
+ phy_set_drvdata(uphy->phy, uphy);
+
+ p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate);
+ return PTR_ERR_OR_ZERO(p);
+}
+
+static const struct of_device_id qcom_usb_hs_phy_match[] = {
+ { .compatible = "qcom,usb-hs-phy", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, qcom_usb_hs_phy_match);
+
+static struct ulpi_driver qcom_usb_hs_phy_driver = {
+ .probe = qcom_usb_hs_phy_probe,
+ .driver = {
+ .name = "qcom_usb_hs_phy",
+ .of_match_table = qcom_usb_hs_phy_match
+ },
+};
+module_ulpi_driver(qcom_usb_hs_phy_driver);
+
+MODULE_DESCRIPTION("Qualcomm USB HS phy");
+MODULE_LICENSE("GPL v2");
--
2.9.0.rc2.8.ga28705d
^ permalink raw reply related [flat|nested] 69+ messages in thread
* Re: [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support
2016-06-26 7:28 [PATCH 00/21] Support qcom's HSIC USB and rewrite USB2 HS phy support Stephen Boyd
` (20 preceding siblings ...)
2016-06-26 7:28 ` [PATCH 21/21] phy: Add support for Qualcomm's USB HS phy Stephen Boyd
@ 2016-06-28 3:09 ` John Stultz
[not found] ` <146710289677.3879.15364764209076318827@sboyd-linaro>
21 siblings, 1 reply; 69+ messages in thread
From: John Stultz @ 2016-06-28 3:09 UTC (permalink / raw)
To: Stephen Boyd
Cc: linux-usb, Felipe Balbi, Heikki Krogerus, Arnd Bergmann,
Neil Armstrong, linux-arm-msm, lkml, Bjorn Andersson, devicetree,
Rob Herring, Peter Chen, Greg Kroah-Hartman, Andy Gross,
Ivan T. Ivanov, Kishon Vijay Abraham I, linux-arm-kernel
On Sun, Jun 26, 2016 at 12:28 AM, Stephen Boyd <stephen.boyd@linaro.org> wrote:
> The state of USB ChipIdea support on Qualcomm's platforms is not great.
> The DT description of these devices requires up to three different nodes
> for what amounts to be the same hardware block, when there should really
> only be one. Furthermore, the "phy" driver that is in mainline (phy-msm-usb.c)
> duplicates the OTG state machine and touches the ci controller wrapper
> registers when it should really be focused on the phy and the ULPI accesses
> needed to get the phy working. There's also a slimmed down phy driver for
> the msm8916 platform, but really the phy hardware is the same as other MSMs,
> so we have two drivers doing pretty much the same thing. This leads to a
> situtaion where we have the chipidea core driver, the "phy" driver, and
> sometimes the ehci-msm.c driver operating the same device all at the same
> time with very little coordination. This just isn't very safe and is
> confusing from a driver perspective when trying to figure out who does what.
> Finally, there isn't any HSIC support on platforms like apq8074 so we
> should add that.
>
> This patch series updates the ChipIdea driver and the MSM wrapper
> (ci_hdrc_msm.c) to properly handle the PHY and wrapper bits at the right
> times in the right places. To get there, we update the ChipIdea core to
> have support for the ULPI phy bus introduced by Heikki. Along the way
> we fix bugs with the extcon handling for peripheral and OTG mode controllers
> and move the parts of phy-usb-msm.c that are touching the CI controller
> wrapper into the wrapper driver (ci_hdrc_msm.c). Finally we add support
> for the HSIC phy based on the ULPI bus and rewrite the HS phy driver
> (phy-usb-msm.c) as a standard ULPI phy driver.
>
> Once this series is accepted, we should be able to delete the phy-usb-msm.c
> phy-qcom-8x16-usb.c, and ehci-msm.c drivers from the tree and use the ULPI
> based phy driver (which also lives in drivers/phy/ instead of drivers/usb/phy/)
> and the chipidea host core instead.
>
> I've also sent seperate patches for other minor pieces to make this
> all work. The full tree can be found here[3], hacks and all to get
> things working. I've tested this on the db410c, apq8074 dragonboard,
> and ifc6410 with configfs gadgets and otg cables.
...
> [3] https://git.linaro.org/people/stephen.boyd/linux.git/shortlog/refs/heads/usb-hsic-8074
Very excited to see this moving upstream!
Just a heads up, trying to build with this branch gives me:
drivers/usb/Kconfig:39:error: recursive dependency detected!
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/usb/Kconfig:39: symbol USB is selected by MOUSE_APPLETOUCH
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/input/mouse/Kconfig:187: symbol MOUSE_APPLETOUCH depends on INPUT
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/input/Kconfig:8: symbol INPUT is selected by VT
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/tty/Kconfig:12: symbol VT is selected by FB_STI
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/video/fbdev/Kconfig:674: symbol FB_STI depends on FB
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/video/fbdev/Kconfig:5: symbol FB is selected by DRM_KMS_FB_HELPER
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/gpu/drm/Kconfig:42: symbol DRM_KMS_FB_HELPER is selected
by DRM_KMS_CMA_HELPER
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/gpu/drm/Kconfig:98: symbol DRM_KMS_CMA_HELPER is selected by DRM_IMX
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/gpu/drm/imx/Kconfig:1: symbol DRM_IMX depends on IMX_IPUV3_CORE
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/gpu/ipu-v3/Kconfig:1: symbol IMX_IPUV3_CORE depends on
RESET_CONTROLLER
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/reset/Kconfig:4: symbol RESET_CONTROLLER is selected by
USB_CHIPIDEA
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/usb/chipidea/Kconfig:1: symbol USB_CHIPIDEA depends on USB_EHCI_HCD
For a resolution refer to Documentation/kbuild/kconfig-language.txt
subsection "Kconfig recursive dependency limitations"
drivers/usb/host/Kconfig:84: symbol USB_EHCI_HCD depends on USB
drivers/usb/chipidea/otg.c: In function ‘hw_write_otgsc’:
drivers/usb/chipidea/otg.c:120:2: warning: format ‘%x’ expects
argument of type ‘unsigned int’, but argument 3 has type ‘long
unsigned int’ [-Wformat]
drivers/usb/chipidea/otg.c:120:2: warning: format ‘%x’ expects
argument of type ‘unsigned int’, but argument 4 has type ‘long
unsigned int’ [-Wformat]
I haven't yet been able to test with this, as I need some other fixes
it seems too to deal with some of the iommu changes in my flo-WIP tree
(it can't find of_dma_configure), but will let you know how things
work once I have all that sorted.
thanks
-john
^ permalink raw reply [flat|nested] 69+ messages in thread