Re: [PATCH v6 11/19] usb: phy: msm: Add device tree support and binding information

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




Hi Srini,

On Tue, 2014-04-22 at 17:05 +0100, Srinivas Kandagatla wrote:
> Hi Ivan,
> 
> On 22/04/14 10:20, Ivan T. Ivanov wrote:
> > From: "Ivan T. Ivanov"<iivanov@xxxxxxxxxx>
> >
> > Allows MSM OTG controller to be specified via device tree.
> >
> > Signed-off-by: Ivan T. Ivanov<iivanov@xxxxxxxxxx>
> > ---
> >   .../devicetree/bindings/usb/msm-hsusb.txt          |  67 +++++++++++++
> >   drivers/usb/phy/phy-msm-usb.c                      | 108 +++++++++++++++++----
> >   include/linux/usb/msm_hsusb.h                      |   6 +-
> >   3 files changed, 159 insertions(+), 22 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt

<snip>

> > +Optional properties:
> > +- dr_mode:      One of "host", "peripheral" or "otg". Defaults to "otg"
> > +
> > +- qcom,phy-init-sequence: PHY configuration sequence values. This is related to Device
> > +                Mode Eye Diagram test. Start address at which these values will be
> > +                written is ULPI_EXT_VENDOR_SPECIFIC. Value of -1 is reserved as
> > +                "do not overwrite default value at this address".
> > +                For example: qcom,phy-init-sequence = < -1 0x63 >;
> > +                Will update only value at address ULPI_EXT_VENDOR_SPECIFIC + 1.
> 
> I don’t think DT maintainers will like the sound of it.
> Sorry If I missed some old discussion on this.
> But I don't this this is the correct way.
> 
> DT should describe the system hardware layout rather than initialization 
> sequence.
> 
> The initialization code with magic values should go directly into the 
> driver and depending on the dt-compatible driver should select the right 
> sequence.

While I agree in general, this sequence is board depended. It is related
to Eye diagrams tests.

> 
> /phy-msm-usb.c
> > +++ b/drivers/usb/phy/phy-msm-usb.c
> > @@ -30,9 +30,12 @@
> >   #include <linux/debugfs.h>
> >   #include <linux/seq_file.h>
> >   #include <linux/pm_runtime.h>
> > +#include <linux/of.h>
> > +#include <linux/of_device.h>
> >
> >   #include <linux/usb.h>
> >   #include <linux/usb/otg.h>
> > +#include <linux/usb/of.h>
> >   #include <linux/usb/ulpi.h>
> >   #include <linux/usb/gadget.h>
> >   #include <linux/usb/hcd.h>
> > @@ -217,16 +220,16 @@ static struct usb_phy_io_ops msm_otg_io_ops = {
> >   static void ulpi_init(struct msm_otg *motg)
> >   {
> >   	struct msm_otg_platform_data *pdata = motg->pdata;
> > -	int *seq = pdata->phy_init_seq;
> > +	int *seq = pdata->phy_init_seq, idx;
> > +	u32 addr = ULPI_EXT_VENDOR_SPECIFIC;
> >
> > -	if (!seq)
> > -		return;
> > +	for (idx = 0; idx < pdata->phy_init_sz; idx++) {
> > +		if (seq[idx] == -1)
> > +			continue;
> >
> > -	while (seq[0] >= 0) {
> >   		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n",
> > -				seq[0], seq[1]);
> > -		ulpi_write(&motg->phy, seq[0], seq[1]);
> > -		seq += 2;
> > +				seq[idx], addr + idx);
> > +		ulpi_write(&motg->phy, seq[idx], addr + idx);
> >   	}
> >   }
> 
> How is above change related to device trees?

It is related to above "qcom,phy-init-sequence" parameter.

> >
> > @@ -1343,25 +1346,87 @@ static void msm_otg_debugfs_cleanup(void)
> >   	debugfs_remove(msm_otg_dbg_root);
> >   }
> >
> > +static struct of_device_id msm_otg_dt_match[] = {
> > +	{
> > +		.compatible = "qcom,usb-otg-ci",
> > +		.data = (void *) CI_45NM_INTEGRATED_PHY
> > +	}, {
> > +		.compatible = "qcom,usb-otg-snps",
> > +		.data = (void *) SNPS_28NM_INTEGRATED_PHY
> > +	}, {}
> > +};
> > +
> > +static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
> > +{
> > +	struct msm_otg_platform_data *pdata;
> > +	const struct of_device_id *id;
> > +	struct device_node *node = pdev->dev.of_node;
> > +	struct property *prop;
> > +	int len, ret;
> > +	u32 val;
> > +
> > +	pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
> > +	if (!pdata)
> > +		return -ENOMEM;
> > +
> > +	motg->pdata = pdata;
> > +
> > +	id = of_match_device(msm_otg_dt_match, &pdev->dev);
> > +	pdata->phy_type = (int) id->data;
> > +
> > +	pdata->mode = of_usb_get_dr_mode(node);
> > +	if (pdata->mode == USB_DR_MODE_UNKNOWN)
> > +		pdata->mode = USB_DR_MODE_OTG;
> > +
> > +	pdata->otg_control = OTG_PHY_CONTROL;
> > +	if (!of_property_read_u32(node, "qcom,otg-control", &val))
> > +		if (val == OTG_PMIC_CONTROL)
> > +			pdata->otg_control = val;
> > +
> > +	prop = of_find_property(node, "qcom,phy-init-sequence", &len);
> > +	if (!prop || !len)
> > +		return 0;
> > +
> > +	pdata->phy_init_seq = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
> > +	if (!pdata->phy_init_seq)
> > +		return 0;
> return -ENOMEM;

This is optional parameter, but probably I could at least
log the event?!

> > +
> > +	len /= sizeof(u32);
> > +
> > +	if (len >= ULPI_EXT_VENDOR_SPECIFIC) {
> > +		dev_warn(&pdev->dev, "Too big PHY init sequence %d\n", len);
> > +		return 0;
> > +	}
> > +
> > +	ret = of_property_read_u32_array(node, "qcom,phy-init-sequence",
> > +					 pdata->phy_init_seq, len);
> > +	if (!ret)
> > +		pdata->phy_init_sz = len;
> 
> empty line before return would be nice.

Sure.

> > +	return 0;
> > +}
> > +
> >   static int msm_otg_probe(struct platform_device *pdev)
> >   {
> >   	int ret = 0;
> > +	struct device_node *np = pdev->dev.of_node;
> > +	struct msm_otg_platform_data *pdata;
> >   	struct resource *res;
> >   	struct msm_otg *motg;
> >   	struct usb_phy *phy;
> >
> > -	dev_info(&pdev->dev, "msm_otg probe\n");
> > -	if (!dev_get_platdata(&pdev->dev)) {
> > -		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
> > -		return -ENODEV;
> > -	}
> > -
> >   	motg = devm_kzalloc(&pdev->dev, sizeof(struct msm_otg), GFP_KERNEL);
> >   	if (!motg) {
> >   		dev_err(&pdev->dev, "unable to allocate msm_otg\n");
> >   		return -ENOMEM;
> >   	}
> >
> > +	pdata = dev_get_platdata(&pdev->dev);
> > +	if (!pdata) {
> shouldn’t this be
> if (np) {

Yep, probably 

if (!pdata && np) {

> > +		ret = msm_otg_read_dt(pdev, motg);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> >   	motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
> >   				     GFP_KERNEL);
> >   	if (!motg->phy.otg) {
> > @@ -1369,17 +1434,17 @@ static int msm_otg_probe(struct platform_device *pdev)
> >   		return -ENOMEM;
> >   	}
> >
> > -	motg->pdata = dev_get_platdata(&pdev->dev);
> >   	phy = &motg->phy;
> >   	phy->dev = &pdev->dev;
> >
> > -	motg->phy_reset_clk = devm_clk_get(&pdev->dev, "usb_phy_clk");
> > +	motg->phy_reset_clk = devm_clk_get(&pdev->dev,
> > +					   np ? "phy" : "usb_phy_clk");
> Not sure why should it be different in dt and non-dt.

Why not? "usb" and "clk" are too much for a USB clock name in
context of this driver.

> >   	if (IS_ERR(motg->phy_reset_clk)) {
> >   		dev_err(&pdev->dev, "failed to get usb_phy_clk\n");
> >   		return PTR_ERR(motg->phy_reset_clk);
> >   	}
> >
> > -	motg->clk = devm_clk_get(&pdev->dev, "usb_hs_clk");
> > +	motg->clk = devm_clk_get(&pdev->dev, np ? "core" : "usb_hs_clk");
> 
> Not sure why should it be different in dt and non-dt.

"hs" doesn't make any sense This clock is a core clock
for LINK controller.


> >   	if (IS_ERR(motg->clk)) {
> >   		dev_err(&pdev->dev, "failed to get usb_hs_clk\n");
> >   		return PTR_ERR(motg->clk);
> > @@ -1391,7 +1456,7 @@ static int msm_otg_probe(struct platform_device *pdev)
> >   	 * operation and USB core cannot tolerate frequency changes on
> >   	 * CORE CLK.
> >   	 */
> > -	motg->pclk = devm_clk_get(&pdev->dev, "usb_hs_pclk");
> > +	motg->pclk = devm_clk_get(&pdev->dev, np ? "iface" : "usb_hs_pclk");
> >   	if (IS_ERR(motg->pclk)) {
> >   		dev_err(&pdev->dev, "failed to get usb_hs_pclk\n");
> >   		return PTR_ERR(motg->pclk);
> > @@ -1402,7 +1467,8 @@ static int msm_otg_probe(struct platform_device *pdev)
> >   	 * clock is introduced to remove the dependency on AXI
> >   	 * bus frequency.
> >   	 */
> > -	motg->core_clk = devm_clk_get(&pdev->dev, "usb_hs_core_clk");
> > +	motg->core_clk = devm_clk_get(&pdev->dev,
> > +				      np ? "alt_core" : "usb_hs_core_clk");
> >
> >   	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >   	motg->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
> > @@ -1490,8 +1556,7 @@ static int msm_otg_probe(struct platform_device *pdev)
> >   	platform_set_drvdata(pdev, motg);
> >   	device_init_wakeup(&pdev->dev, 1);
> >
> > -	if (motg->pdata->mode == USB_DR_MODE_OTG &&
> > -			motg->pdata->otg_control == OTG_USER_CONTROL) {
> > +	if (motg->pdata->mode == USB_DR_MODE_OTG) {
> 
> How is this change related to DT?

Yep, it is not really related, will revert.

> >   		ret = msm_otg_debugfs_init(motg);
> >   		if (ret)
> >   			dev_dbg(&pdev->dev, "Can not create mode change file\n");
> > @@ -1637,6 +1702,8 @@ static const struct dev_pm_ops msm_otg_dev_pm_ops = {
> >   				msm_otg_runtime_idle)
> >   };
> >
> > +MODULE_DEVICE_TABLE(of, msm_otg_dt_match);
> > +
> >   static struct platform_driver msm_otg_driver = {
> >   	.probe = msm_otg_probe,
> >   	.remove = msm_otg_remove,
> > @@ -1644,6 +1711,7 @@ static struct platform_driver msm_otg_driver = {
> >   		.name = DRIVER_NAME,
> >   		.owner = THIS_MODULE,
> 
> >   		.pm = &msm_otg_dev_pm_ops,
> > +		.of_match_table = msm_otg_dt_match,
> >   	},
> >   };
> >
> 
> [snip --
> > diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
> > index 262ed80..bd68299 100644
> > --- a/include/linux/usb/msm_hsusb.h
> > +++ b/include/linux/usb/msm_hsusb.h
> > @@ -100,8 +100,9 @@ enum usb_chg_type {
> >   /**
> >    * struct msm_otg_platform_data - platform device data
> >    *              for msm_otg driver.
> > - * @phy_init_seq: PHY configuration sequence. val, reg pairs
> > - *              terminated by -1.
> > + * @phy_init_seq: PHY configuration sequence values. Value of -1 is reserved as
> > + *              "do not overwrite default vaule at this address".
> > + * @phy_init_sz: PHY configuration sequence size.
> >    * @vbus_power: VBUS power on/off routine.
> >    * @power_budget: VBUS power budget in mA (0 will be treated as 500mA).
> >    * @mode: Supported mode (OTG/peripheral/host).
> > @@ -109,6 +110,7 @@ enum usb_chg_type {
> >    */
> >   struct msm_otg_platform_data {
> >   	int *phy_init_seq;
> > +	int phy_init_sz;
> >   	void (*vbus_power)(bool on);
> >   	unsigned power_budget;
> >   	enum usb_dr_mode mode;
> > --
> ---]
> 
> I think, this changeset should be a new patch.

It is part of "qcom,phy-init-sequence" DT property.

Regards,
Ivan

> 
> thanks,
> srini
> > 1.8.3.2

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Device Tree Compilter]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux PCI Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Yosemite Backpacking]
  Powered by Linux