Devicetree
 help / color / mirror / Atom feed
* [PATCH v2 1/8] regulator: arizona-micsupp: Avoid potential memory leak reading init_data
From: Charles Keepax @ 2017-03-28 14:14 UTC (permalink / raw)
  To: broonie
  Cc: mark.rutland, devicetree, alsa-devel, patches, lgirdwood,
	linux-kernel, robh+dt, lee.jones

The device argument passed to of_get_regulator_init_data is used to
do some devres memory allocation. Currently the driver passes the MFD
device pointer to this function, this could result in the init_data
allocation being leaked if the regulator is unbound but the MFD isn't.

Correct this issue by correctly passing the local platform device.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
---

New patch in the series since v1.

 drivers/regulator/arizona-micsupp.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
index 22bd714..5e38861 100644
--- a/drivers/regulator/arizona-micsupp.c
+++ b/drivers/regulator/arizona-micsupp.c
@@ -199,7 +199,8 @@ static const struct regulator_init_data arizona_micsupp_ext_default = {
 	.num_consumer_supplies = 1,
 };
 
-static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
+static int arizona_micsupp_of_get_pdata(struct device *dev,
+					struct arizona *arizona,
 					struct regulator_config *config,
 					const struct regulator_desc *desc)
 {
@@ -213,7 +214,7 @@ static int arizona_micsupp_of_get_pdata(struct arizona *arizona,
 	if (np) {
 		config->of_node = np;
 
-		init_data = of_get_regulator_init_data(arizona->dev, np, desc);
+		init_data = of_get_regulator_init_data(dev, np, desc);
 
 		if (init_data) {
 			init_data->consumer_supplies = &micsupp->supply;
@@ -268,8 +269,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
 
 	if (IS_ENABLED(CONFIG_OF)) {
 		if (!dev_get_platdata(arizona->dev)) {
-			ret = arizona_micsupp_of_get_pdata(arizona, &config,
-							   desc);
+			ret = arizona_micsupp_of_get_pdata(&pdev->dev, arizona,
+							   &config, desc);
 			if (ret < 0)
 				return ret;
 		}
-- 
2.1.4

^ permalink raw reply related

* Re: [RFC PATCH 1/3] of/pci: dma-ranges to account highest possible host bridge dma_mask
From: Rob Herring @ 2017-03-28 14:13 UTC (permalink / raw)
  To: Oza Oza
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-pci-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux IOMMU,
	bcm-kernel-feedback-list-dY08KVG/lbpWk0Htik3J/w@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <CAMSpPPdnQdWeyTsnESRFx52gtxQLxwfPQwQgDFSN=katfW7suA-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

On Tue, Mar 28, 2017 at 12:27 AM, Oza Oza <oza.oza-dY08KVG/lbpWk0Htik3J/w@public.gmane.org> wrote:
> On Mon, Mar 27, 2017 at 8:16 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
>> On Sat, Mar 25, 2017 at 12:31 AM, Oza Pawandeep <oza.oza-dY08KVG/lbpWk0Htik3J/w@public.gmane.org> wrote:
>>> it is possible that PCI device supports 64-bit DMA addressing,
>>> and thus it's driver sets device's dma_mask to DMA_BIT_MASK(64),
>>> however PCI host bridge may have limitations on the inbound
>>> transaction addressing. As an example, consider NVME SSD device
>>> connected to iproc-PCIe controller.
>>>
>>> Currently, the IOMMU DMA ops only considers PCI device dma_mask
>>> when allocating an IOVA. This is particularly problematic on
>>> ARM/ARM64 SOCs where the IOMMU (i.e. SMMU) translates IOVA to
>>> PA for in-bound transactions only after PCI Host has forwarded
>>> these transactions on SOC IO bus. This means on such ARM/ARM64
>>> SOCs the IOVA of in-bound transactions has to honor the addressing
>>> restrictions of the PCI Host.
>>>
>>> current pcie frmework and of framework integration assumes dma-ranges
>>> in a way where memory-mapped devices define their dma-ranges.
>>> dma-ranges: (child-bus-address, parent-bus-address, length).
>>>
>>> but iproc based SOCs and even Rcar based SOCs has PCI world dma-ranges.
>>> dma-ranges = <0x43000000 0x00 0x00 0x00 0x00 0x80 0x00>;
>>
>> If you implement a common function, then I expect to see other users
>> converted to use it. There's also PCI hosts in arch/powerpc that parse
>> dma-ranges.
>
> the common function should be similar to what
> of_pci_get_host_bridge_resources is doing right now.
> it parses ranges property right now.
>
> the new function would look look following.
>
> of_pci_get_dma_ranges(struct device_node *dev, struct list_head *resources)
> where resources would return the dma-ranges.
>
> but right now if you see the patch, of_dma_configure calls the new
> function, which actually returns the largest possible size.
> so this new function has to be generic in a way where other PCI hosts
> can use it. but certainly iproc(Broadcom SOC) , rcar based SOCs can
> use it for sure.
>
> although having powerpc using it;  is a separate exercise, since I do
> not have any access to other PCI hosts such as powerpc. but we can
> workout with them on thsi forum if required.

You don't need h/w. You can analyze what parts are common, write
patches to convert to common implementation, and build test. The PPC
and rcar folks can test on h/w.

Rob

^ permalink raw reply

* Re: [PATCH v6 17/39] platform: add video-multiplexer subdevice driver
From: Vladimir Zapolskiy @ 2017-03-28 14:12 UTC (permalink / raw)
  To: Steve Longerbeam, robh+dt, mark.rutland, shawnguo, kernel,
	fabio.estevam, linux, mchehab, hverkuil, nick, markus.heiser,
	p.zabel, laurent.pinchart+renesas, bparrot, geert, arnd,
	sudipm.mukherjee, minghsiu.tsai, tiffany.lin,
	jean-christophe.trotin, horms+renesas, niklas.soderlund+renesas,
	robert.jarzmik, songjun.wu, andrew-ct.chen, gregkh, shuah,
	sakari.ailus, pavel
  Cc: devel, devicetree, Steve Longerbeam, Sascha Hauer, linux-kernel,
	linux-arm-kernel, linux-media
In-Reply-To: <1490661656-10318-18-git-send-email-steve_longerbeam@mentor.com>

Hi Steve,

On 03/28/2017 03:40 AM, Steve Longerbeam wrote:
> From: Philipp Zabel <p.zabel@pengutronix.de>
> 
> This driver can handle SoC internal and external video bus multiplexers,
> controlled either by register bit fields or by a GPIO. The subdevice
> passes through frame interval and mbus configuration of the active input
> to the output side.
> 
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
> 
> - fixed a cut&paste error in vidsw_remove(): v4l2_async_register_subdev()
>   should be unregister.
> 
> - added media_entity_cleanup() to vidsw_remove().
> 
> - added missing MODULE_DEVICE_TABLE().
>   Suggested-by: Javier Martinez Canillas <javier@dowhile0.org>
> 
> - there was a line left over from a previous iteration that negated
>   the new way of determining the pad count just before it which
>   has been removed (num_pads = of_get_child_count(np)).
> 
> - removed [gs]_frame_interval ops. timeperframe is not used anywhwere
>   in this subdev, and currently it has no control over frame rate.
> 
> - add link_validate to media_entity_operations.
> 
> - moved devicetree binding doc to a separate commit.
> 
> - Philipp Zabel has developed a set of patches that allow adding
>   to the subdev async notifier waiting list using a chaining method
>   from the async registered callbacks (v4l2_of_subdev_registered()
>   and the prep patches for that). For now, I've removed the use of
>   v4l2_of_subdev_registered() for the vidmux driver's registered
>   callback. This doesn't affect the functionality of this driver,
>   but allows for it to be merged now, before adding the chaining
>   support.
> 
> Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
> ---
>  drivers/media/platform/Kconfig             |   8 +
>  drivers/media/platform/Makefile            |   2 +
>  drivers/media/platform/video-multiplexer.c | 451 +++++++++++++++++++++++++++++
>  3 files changed, 461 insertions(+)
>  create mode 100644 drivers/media/platform/video-multiplexer.c
> 
> diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
> index ab0bb48..c9b8d9c 100644
> --- a/drivers/media/platform/Kconfig
> +++ b/drivers/media/platform/Kconfig
> @@ -74,6 +74,14 @@ config VIDEO_M32R_AR_M64278
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called arv.
>  
> +config VIDEO_MULTIPLEXER
> +	tristate "Video Multiplexer"
> +	depends on VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER

+ depends on OF

> +	help
> +	  This driver provides support for SoC internal N:1 video bus
> +	  multiplexers controlled by register bitfields as well as external
> +	  2:1 video multiplexers controlled by a single GPIO.
> +

[snip]

> +static int vidsw_probe(struct platform_device *pdev)
> +{
> +	struct device_node *np = pdev->dev.of_node;
> +	struct of_endpoint endpoint;
> +	struct device_node *ep;
> +	struct reg_field field;
> +	struct vidsw *vidsw;
> +	struct regmap *map;
> +	unsigned int num_pads;
> +	int ret;
> +
> +	vidsw = devm_kzalloc(&pdev->dev, sizeof(*vidsw), GFP_KERNEL);
> +	if (!vidsw)
> +		return -ENOMEM;
> +
> +	platform_set_drvdata(pdev, vidsw);
> +
> +	v4l2_subdev_init(&vidsw->subdev, &vidsw_subdev_ops);
> +	snprintf(vidsw->subdev.name, sizeof(vidsw->subdev.name), "%s",
> +			np->name);

.... or oops here       ^^^^^^^^^.

> +	vidsw->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
> +	vidsw->subdev.dev = &pdev->dev;
> +
> +	/*
> +	 * The largest numbered port is the output port. It determines
> +	 * total number of pads
> +	 */
> +	num_pads = 0;
> +	for_each_endpoint_of_node(np, ep) {
> +		of_graph_parse_endpoint(ep, &endpoint);
> +		num_pads = max(num_pads, endpoint.port + 1);
> +	}
> +
> +	if (num_pads < 2) {
> +		dev_err(&pdev->dev, "Not enough ports %d\n", num_pads);
> +		return -EINVAL;
> +	}

This unveils another runtime dependency on OF.

> +
> +	ret = of_get_reg_field(np, &field);
> +	if (ret == 0) {
> +		map = syscon_node_to_regmap(np->parent);
> +		if (!map) {
> +			dev_err(&pdev->dev, "Failed to get syscon register map\n");
> +			return PTR_ERR(map);
> +		}
> +
> +		vidsw->field = devm_regmap_field_alloc(&pdev->dev, map, field);
> +		if (IS_ERR(vidsw->field)) {
> +			dev_err(&pdev->dev, "Failed to allocate regmap field\n");
> +			return PTR_ERR(vidsw->field);
> +		}
> +
> +		regmap_field_read(vidsw->field, &vidsw->active);
> +	} else {
> +		if (num_pads > 3) {
> +			dev_err(&pdev->dev, "Too many ports %d\n", num_pads);
> +			return -EINVAL;
> +		}
> +
> +		vidsw->gpio = devm_gpiod_get(&pdev->dev, NULL, GPIOD_OUT_LOW);
> +		if (IS_ERR(vidsw->gpio)) {
> +			dev_warn(&pdev->dev,
> +				 "could not request control gpio: %d\n", ret);
> +			vidsw->gpio = NULL;
> +		}
> +
> +		vidsw->active = gpiod_get_value(vidsw->gpio) ? 1 : 0;

vidsw->active is always set to 0 ?

> +	}
> +
> +	vidsw->num_pads = num_pads;
> +	vidsw->pads = devm_kzalloc(&pdev->dev, sizeof(*vidsw->pads) * num_pads,
> +			GFP_KERNEL);
> +	vidsw->format_mbus = devm_kzalloc(&pdev->dev,
> +			sizeof(*vidsw->format_mbus) * num_pads, GFP_KERNEL);
> +	vidsw->endpoint = devm_kzalloc(&pdev->dev,
> +			sizeof(*vidsw->endpoint) * (num_pads - 1), GFP_KERNEL);
> +
> +	ret = vidsw_async_init(vidsw, np);
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +

--
With best wishes,
Vladimir

^ permalink raw reply

* Re: [PATCH v4 0/4] gpio: mvebu: Add PWM fan support
From: Andrew Lunn @ 2017-03-28 13:57 UTC (permalink / raw)
  To: Ralph Sennhauser
  Cc: Mark Rutland, Alexandre Courbot, Jason Cooper, linux-pwm,
	Linus Walleij, Russell King, Rob Herring, linux-kernel,
	linux-gpio, devicetree, Thierry Reding, Gregory Clement,
	Imre Kaloz, linux-arm-kernel, Sebastian Hesselbarth
In-Reply-To: <20170327194301.1104-1-ralph.sennhauser@gmail.com>

> Pending:
>   * npwm = 1? I vote no if that counts. ;) (suggested by Thierry Reding)
>   * Tested-by: Andrew Lunn for v1 needs renewing

Hi Ralph

I just tested this version. Fan it still keeping my Mamba board cool.

Tested-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply

* Re: [PATCH v5 1/5] usb: dwc2: Add support for STM32F429/439/469 USB OTG HS/FS in FS mode (internal PHY)
From: Alexandre Torgue @ 2017-03-28 13:49 UTC (permalink / raw)
  To: Felipe Balbi, John Youn, Bruno Herrera,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
	mark.rutland-5wv7dgnIgG8@public.gmane.org,
	mcoquelin.stm32-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org
  Cc: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org
In-Reply-To: <8760ith6a6.fsf-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>



On 03/28/2017 03:36 PM, Felipe Balbi wrote:
>
> Hi,
>
> Alexandre Torgue <alexandre.torgue-qxv4g6HH51o@public.gmane.org> writes:
>> Hi John,
>>
>> On 02/01/2017 04:37 AM, John Youn wrote:
>>> On 1/31/2017 5:26 PM, Bruno Herrera wrote:
>>>> This patch introduces a new parameter to activate USB OTG HS/FS core
>>>> embedded phy transceiver. The STM32F4x9 SoC uses the GGPIO register
>>>> to enable the transceiver.
>>>> Also add the dwc2_set_params function for stm32f4 otg fs.
>>>>
>>>> Signed-off-by: Bruno Herrera <bruherrera-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
>>>
>>> Acked-by: John Youn <johnyoun-HKixBCOQz3hWk0Htik3J/w@public.gmane.org>
>>>
>> Do you plan to take those patches on your pull-request for 4.12?
>> I was wondering if I take machine parts (DT) in my pull request for 4.12
>> or if I wait an official version with driver part merged.
>
> patches already in my queue for v4.12

Thanks for info.

Regards
Alex

>
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 0/5] rtc: Reuse rtc-sh driver to support RZ/A1
From: bobethtarsi3-Re5JQEeQqe8AvxtiuMwx3w @ 2017-03-28 13:38 UTC (permalink / raw)
  To: rtc-linux
  Cc: a.zummo-BfzFCNDTiLLj+vYz1yj4TQ,
	alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, mark.rutland-5wv7dgnIgG8,
	horms+renesas-/R6kz+dDXgpPR4JQBCEnsQ,
	geert-Td1EMuHUCqxL1ZNQvxDV9g, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
	chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ
In-Reply-To: <20170316175112.27913-1-chris.brandt-zM6kxYcvzFBBDgjK7y7TUQ@public.gmane.org>


[-- Attachment #1.1: Type: text/plain, Size: 1072 bytes --]


>
>
> Thank you for contacting Mr PAMPHILE this gentleman who gave me a smile 
> again by offering me a loan of 32,000 Dollars and has two of my colleagues 
> who have also received loans at his level without problems instead of 
> getting you through Unwilling individuals, who take to work to defraud the 
> innocent. If you need funding; Lending money or any project to achieve this 
> man will help you achieve it and support you financially.
> Here is his mail: phamphileserge-PkbjNfxxIARBDgjK7y7TUQ@public.gmane.org
>

-- 
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
--- 
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.

[-- Attachment #1.2: Type: text/html, Size: 1644 bytes --]

[-- Attachment #2: 113791658.jpg --]
[-- Type: image/jpeg, Size: 37896 bytes --]

^ permalink raw reply

* Re: [PATCH v5 1/5] usb: dwc2: Add support for STM32F429/439/469 USB OTG HS/FS in FS mode (internal PHY)
From: Felipe Balbi @ 2017-03-28 13:36 UTC (permalink / raw)
  To: Alexandre Torgue, John Youn, Bruno Herrera, robh+dt@kernel.org,
	mark.rutland@arm.com, mcoquelin.stm32@gmail.com
  Cc: devicetree@vger.kernel.org, linux-usb@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <58187797-2c11-c75b-571c-27fe64578099@st.com>


Hi,

Alexandre Torgue <alexandre.torgue@st.com> writes:
> Hi John,
>
> On 02/01/2017 04:37 AM, John Youn wrote:
>> On 1/31/2017 5:26 PM, Bruno Herrera wrote:
>>> This patch introduces a new parameter to activate USB OTG HS/FS core
>>> embedded phy transceiver. The STM32F4x9 SoC uses the GGPIO register
>>> to enable the transceiver.
>>> Also add the dwc2_set_params function for stm32f4 otg fs.
>>>
>>> Signed-off-by: Bruno Herrera <bruherrera@gmail.com>
>>
>> Acked-by: John Youn <johnyoun@synopsys.com>
>>
> Do you plan to take those patches on your pull-request for 4.12?
> I was wondering if I take machine parts (DT) in my pull request for 4.12 
> or if I wait an official version with driver part merged.

patches already in my queue for v4.12

-- 
balbi

^ permalink raw reply

* Re: [PATCH 1/2] drm/bridge: ti-tfp410: support hpd via gpio
From: Jyri Sarha @ 2017-03-28 13:32 UTC (permalink / raw)
  To: Archit Taneja, Christopher Spinrath
  Cc: Mark Rutland, devicetree@vger.kernel.org,
	Russell King - ARM Linux, DRI mailing list, robh+dt@kernel.org,
	Igor Grinberg, Sascha Hauer, Fabio Estevam, Shawn Guo,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <d6b2391f-3e4a-2761-b6a0-8997d2c78600@codeaurora.org>

On 03/27/17 08:58, Archit Taneja wrote:
> Hi,
> 
> On 03/07/2017 03:21 AM, Christopher Spinrath wrote:
>> Hi Fabio,
>>
>> On 03/06/2017 10:46 PM, Fabio Estevam wrote:
>>> Hi Christopher,
>>>
>>> On Mon, Mar 6, 2017 at 6:40 PM, 
>>> <christopher.spinrath@rwth-aachen.de> wrote:
>>>> From: Christopher Spinrath <christopher.spinrath@rwth-aachen.de>
>>>>
>>>> On some boards the hpd pin of a hdmi connector is wired up to a gpio
>>>> pin. Since in the DRM world the tfp410 driver is responsible for
>>>> handling the connector, add support for hpd gpios in this very driver.
>>>>
>>>> Signed-off-by: Christopher Spinrath
>>>> <christopher.spinrath@rwth-aachen.de>
>>>> ---
>>>>  drivers/gpu/drm/bridge/ti-tfp410.c | 72
>>>> ++++++++++++++++++++++++++++++++++++--
>>>
...
>>
> 
> The patch looks good to me.
> 
> Jyri,
> 
> Is it possible for you to verify this on Beaglebone platform?
> 

If I read my BeagleBone DVI-D Cape docs right, it does not have the HPD
pin connected. At least it does not mention any gpio that could be used
for the purpose. So I can not easily test this patch in real world
situation. For what it is worth the patch looks ok to me too.

Best regards,
Jyri

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: [PATCH 5/8] ARM64: dts: meson-gxbb: add i2s output pins
From: Linus Walleij @ 2017-03-28 13:15 UTC (permalink / raw)
  To: Jerome Brunet
  Cc: devicetree@vger.kernel.org, Kevin Hilman,
	linux-kernel@vger.kernel.org, linux-gpio@vger.kernel.org,
	Carlo Caione, open list:ARM/Amlogic Meson...,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <20170323165101.29262-6-jbrunet@baylibre.com>

On Thu, Mar 23, 2017 at 5:50 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:

> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>

Acked-by: Linus Walleij <linus.walleij@linaro.org>

For this and the other Meson DTS patches.

Please funnel these through the apropriate ARM SoC-feed tree.

Yours,
Linus Walleij

^ permalink raw reply

* [PATCH v2] ARM: dts: am335x-baltos: add LED support
From: yegorslists-gM/Ye1E23mwN+BqQ9rBEUg @ 2017-03-28 13:09 UTC (permalink / raw)
  To: linux-omap-u79uwXL29TY76Z2rM5mHXA
  Cc: devicetree-u79uwXL29TY76Z2rM5mHXA, tony-4v6yS6AI5VpBDgjK7y7TUQ,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, Yegor Yefremov

From: Yegor Yefremov <yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>

All three devices provide GPIO based LEDs named power,
wlan and app.

Place LEDs definition into a separate dtsi file as not all
devices including am335x-baltos.dtsi have the same LED layout.

Signed-off-by: Yegor Yefremov <yegorslists-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org>
---
Changes v1 -> v2:
  - move LEDs definition to a separate dtsi file (Tony Lindgren)

 arch/arm/boot/dts/am335x-baltos-ir2110.dts |  1 +
 arch/arm/boot/dts/am335x-baltos-ir3220.dts |  1 +
 arch/arm/boot/dts/am335x-baltos-ir5221.dts |  1 +
 arch/arm/boot/dts/am335x-baltos-leds.dtsi  | 50 ++++++++++++++++++++++++++++++
 4 files changed, 53 insertions(+)
 create mode 100644 arch/arm/boot/dts/am335x-baltos-leds.dtsi

diff --git a/arch/arm/boot/dts/am335x-baltos-ir2110.dts b/arch/arm/boot/dts/am335x-baltos-ir2110.dts
index 501c752..75de1e7 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir2110.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir2110.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "am335x-baltos.dtsi"
+#include "am335x-baltos-leds.dtsi"
 
 / {
 	model = "OnRISC Baltos iR 2110";
diff --git a/arch/arm/boot/dts/am335x-baltos-ir3220.dts b/arch/arm/boot/dts/am335x-baltos-ir3220.dts
index 19f53b8..46df1b2 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir3220.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir3220.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "am335x-baltos.dtsi"
+#include "am335x-baltos-leds.dtsi"
 
 / {
 	model = "OnRISC Baltos iR 3220";
diff --git a/arch/arm/boot/dts/am335x-baltos-ir5221.dts b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
index 2b9d7f4..5d56355 100644
--- a/arch/arm/boot/dts/am335x-baltos-ir5221.dts
+++ b/arch/arm/boot/dts/am335x-baltos-ir5221.dts
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "am335x-baltos.dtsi"
+#include "am335x-baltos-leds.dtsi"
 
 / {
 	model = "OnRISC Baltos iR 5221";
diff --git a/arch/arm/boot/dts/am335x-baltos-leds.dtsi b/arch/arm/boot/dts/am335x-baltos-leds.dtsi
new file mode 100644
index 0000000..3ab1767
--- /dev/null
+++ b/arch/arm/boot/dts/am335x-baltos-leds.dtsi
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * VScom OnRISC
+ * http://www.vscom.de
+ */
+
+/*#include "am33xx.dtsi"*/
+
+/ {
+	leds {
+		pinctrl-names = "default";
+		pinctrl-0 = <&user_leds>;
+
+		compatible = "gpio-leds";
+
+		power {
+			label = "onrisc:red:power";
+			linux,default-trigger = "default-on";
+			gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+			default-state = "on";
+		};
+		wlan {
+			label = "onrisc:blue:wlan";
+			gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+		app {
+			label = "onrisc:green:app";
+			gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+};
+
+&am33xx_pinmux {
+	user_leds: pinmux_user_leds {
+		pinctrl-single,pins = <
+			AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* mii1_col.gpio3_0 PWR LED */
+			AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* mii1_txd3.gpio0_16 WLAN LED */
+			AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE7)	/* mii1_txd2.gpio0_17 APP LED */
+		>;
+	};
+};
-- 
2.1.4

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

^ permalink raw reply related

* Re: [PATCH v2 3/3] device property: fwnode_property_read_string_array() returns nr of strings
From: Sakari Ailus @ 2017-03-28 13:07 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Sakari Ailus, linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, rafael-DgEjT+Ai2ygdnm+yROfE0A,
	sudeep.holla-5wv7dgnIgG8, lorenzo.pieralisi-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	robh-DgEjT+Ai2ygdnm+yROfE0A, ahs3-H+wXaHxf7aLQT0dZR+AlfA
In-Reply-To: <20170328125231.GP2957-3PARRvDOhMZrdx17CPfAsdBPR1lH4CV8@public.gmane.org>

Hi Mika,

Thank you for the review!

On Tue, Mar 28, 2017 at 03:52:31PM +0300, Mika Westerberg wrote:
> On Tue, Mar 28, 2017 at 03:22:19PM +0300, Sakari Ailus wrote:
> > -		ret = acpi_copy_property_array_string(items, (char **)val, nval);
> > +		ret = acpi_copy_property_array_string(
> > +			items, (char **)val,
> > +			min_t(u32, nval, obj->package.count));
> 
> I think this looks better if written like:
> 
> 		ret = acpi_copy_property_array_string(items, (char **)val,
> 					min_t(u32, nval, obj->package.count));

I prefer the former although I have no strong opinion either way. Using an
indentation that is automatically intended by a text editor is also an
advantage.

I can change it if you insist. :-)

> 
> Regardless of that,
> 
> Reviewed-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

Thanks!

-- 
Regards,

Sakari Ailus
e-mail: sakari.ailus-X3B1VOXEql0@public.gmane.org	XMPP: sailus-PCDdDYkjdNMDXYZnReoRVg@public.gmane.org
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 5/7] pinctrl: aramda-37xx: Add irqchip support
From: Linus Walleij @ 2017-03-28 13:04 UTC (permalink / raw)
  To: Gregory CLEMENT
  Cc: linux-gpio@vger.kernel.org, Jason Cooper, Andrew Lunn,
	Sebastian Hesselbarth, Thomas Petazzoni,
	linux-arm-kernel@lists.infradead.org, Rob Herring,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	Nadav Haklai, Victor Gu, Marcin Wojtas, Wilson Ding, Hua Jing,
	Neta Zur Hershkovits
In-Reply-To: <87vaqtadry.fsf@free-electrons.com>

On Tue, Mar 28, 2017 at 12:36 PM, Gregory CLEMENT
<gregory.clement@free-electrons.com> wrote:
>  On lun., mars 27 2017, Linus Walleij <linus.walleij@linaro.org> wrote:

>>> +                       u32 virq = irq_linear_revmap(d, hwirq +
>>> +                                                    i * GPIO_PER_REG);
>>
>> Use irq_find_mapping() instead please.
>
> As we are in the interrupt handler I chose to use this function because
> according to its documentation: "This is a fast path alternative to
> irq_find_mapping() that can be called directly by irq controller code to
> save a handful of instructions".
>
> The only restriction is "It is always safe to call, but won't find irqs
> mapped using the radix tree.". So I think that for this driver it is
> okay.

So you are relying on the core code in gpiolib to select a linear
map. That is implicit semantics, and either all drivers using
GPIOLIB_IRQCHIP should be changed to irq_linear_revmap()
or all stay with irq_find_mapping().

In this case, I doubt it that you are actually so timing critical that
it matters. Please use irq_find_mapping().

>>> +       nr_irq_parent = of_irq_count(np);
>>> +       spin_lock_init(&info->irq_lock);
>>> +
>>> +       if (!nr_irq_parent) {
>>> +               dev_err(&pdev->dev, "Invalid or no IRQ\n");
>>> +               return 0;
>>> +       }
>>
>> What if it is > 1? That doesn't seem to work but will pass this
>> check silently.
>
> If we have nr_irq_parent > 1, it will work and it is actually expected.

Ah, I get it. Nice.

>>> +       ret = gpiochip_irqchip_add(gc, irqchip, 0,
>>> +                                  handle_level_irq, IRQ_TYPE_NONE);
>>
>> If you also set up the handler in .set_type() you can assign
>> handle_bad_irq() here and let .set_type set the right handler
>> as e.g. drivers/gpio/gpio-pl061.c.
>
> Well the hardware can only manage the edge trigger, so there is no
> benefit to modify it each time we want to change the kind of edge we
> want (raising or falling). But your comment make me realized that I used
> the wrong one, I will move to handle_edge_irq in the v4.

Ooops, yeah handle_edge_irq() is what calls the ACK callback.

>>> +       for (i = 0; i < nrirqs; i++) {
>>> +               struct irq_data *d = irq_get_irq_data(gc->irq_base + i);
>>> +
>>> +               d->mask = 1 << (i % GPIO_PER_REG);
>>> +       }
>>
>> What is this? It looks like a big hack. At least put in a fat
>> comment about what is going on and why.
>
> I can reuse a part of the commit log here: "The only unusual "feature"
> is that many interrupts are connected to the parent interrupt
> controller. But we do not take advantage of this and use the chained irq
> with all of them."

What you're doing is mocking around with core irqchip semantics.
Is ->mask really supposed to be played around with from the outsid
like this?

Anyways: BIT(i % GPIO_PER_REG) is nicer.

>>> +       for (i = 0; i < nr_irq_parent; i++) {
>>> +               int irq = irq_of_parse_and_map(np, i);
>>
>> I think gpiochip_irqchip_add() will do this for you already,
>> as it calls irq_create_mapping() for all offsets which will call
>> irq_of_parse_and_map() am I right?
>
> After reading the code, it doesn't seem it is the case. At least there
> is no irq_of_parse_and_map() call from gpiochip_irqchip_add(). And waht
> we need here is to associate each IRQ to the same GPIO handler.
>
> I can still try without this line to confirm it.

It has irq_create_mapping(gpiochip->irqdomain, offset); that get
called for every IRQ, and that will eventually call irq_of_parse_and_map()
if the IRQs are defined in the device tree. (IIRC)

Yours,
Linus Walleij

^ permalink raw reply

* Re: [PATCH v2 3/3] device property: fwnode_property_read_string_array() returns nr of strings
From: Mika Westerberg @ 2017-03-28 12:52 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, rafael-DgEjT+Ai2ygdnm+yROfE0A,
	sudeep.holla-5wv7dgnIgG8, lorenzo.pieralisi-5wv7dgnIgG8,
	mark.rutland-5wv7dgnIgG8, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	robh-DgEjT+Ai2ygdnm+yROfE0A, ahs3-H+wXaHxf7aLQT0dZR+AlfA
In-Reply-To: <1490703739-28270-4-git-send-email-sakari.ailus-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>

On Tue, Mar 28, 2017 at 03:22:19PM +0300, Sakari Ailus wrote:
> -		ret = acpi_copy_property_array_string(items, (char **)val, nval);
> +		ret = acpi_copy_property_array_string(
> +			items, (char **)val,
> +			min_t(u32, nval, obj->package.count));

I think this looks better if written like:

		ret = acpi_copy_property_array_string(items, (char **)val,
					min_t(u32, nval, obj->package.count));

Regardless of that,

Reviewed-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v2 2/3] device property: Fix reading pset strings using array access functions
From: Mika Westerberg @ 2017-03-28 12:48 UTC (permalink / raw)
  To: Sakari Ailus
  Cc: linux-acpi, devicetree, rafael, sudeep.holla, lorenzo.pieralisi,
	mark.rutland, broonie, robh, ahs3
In-Reply-To: <1490703739-28270-3-git-send-email-sakari.ailus@linux.intel.com>

On Tue, Mar 28, 2017 at 03:22:18PM +0300, Sakari Ailus wrote:
> The length field value of non-array string properties is the length of the
> string itself. Non-array string properties thus require specific handling.
> Fix this.
> 
> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>

Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>

^ permalink raw reply

* [PATCH V3 6/6] soc/tegra: Add initial flowctrl support for Tegra132/210
From: Jon Hunter @ 2017-03-28 12:42 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Mark Rutland, devicetree, Stephen Warren, Russell King,
	Jon Hunter, Rob Herring, linux-tegra, linux-arm-kernel
In-Reply-To: <1490704978-22906-1-git-send-email-jonathanh@nvidia.com>

Tegra132 and Tegra210 support the flowctrl module and so add initial
support for these devices.

Please note that Tegra186 does not support the flowctrl module, so
update the initialisation function such that we do not fall back and
attempt to map the 'hardcoded' address range for Tegra186. Furthermore
64-bit Tegra devices have always had the flowctrl node defined in their
device-tree and so only use the 'hardcoded' addresses for 32-bit Tegra
devices.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 drivers/soc/tegra/Kconfig    |  2 ++
 drivers/soc/tegra/flowctrl.c | 31 +++++++++++++++++++++----------
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index c7e8ddfb574e..dcf088db40b6 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -63,6 +63,7 @@ if ARM64
 config ARCH_TEGRA_132_SOC
 	bool "NVIDIA Tegra132 SoC"
 	select PINCTRL_TEGRA124
+	select SOC_TEGRA_FLOWCTRL
 	select SOC_TEGRA_PMC
 	help
 	  Enable support for NVIDIA Tegra132 SoC, based on the Denver
@@ -73,6 +74,7 @@ config ARCH_TEGRA_132_SOC
 config ARCH_TEGRA_210_SOC
 	bool "NVIDIA Tegra210 SoC"
 	select PINCTRL_TEGRA210
+	select SOC_TEGRA_FLOWCTRL
 	select SOC_TEGRA_PMC
 	help
 	  Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1,
diff --git a/drivers/soc/tegra/flowctrl.c b/drivers/soc/tegra/flowctrl.c
index 25eddfc8475d..0e345c05fc65 100644
--- a/drivers/soc/tegra/flowctrl.c
+++ b/drivers/soc/tegra/flowctrl.c
@@ -165,6 +165,7 @@ static int tegra_flowctrl_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id tegra_flowctrl_match[] = {
+	{ .compatible = "nvidia,tegra210-flowctrl" },
 	{ .compatible = "nvidia,tegra124-flowctrl" },
 	{ .compatible = "nvidia,tegra114-flowctrl" },
 	{ .compatible = "nvidia,tegra30-flowctrl" },
@@ -184,9 +185,7 @@ builtin_platform_driver(tegra_flowctrl_driver);
 
 static int __init tegra_flowctrl_init(void)
 {
-	/* hardcoded fallback if device tree node is missing */
-	unsigned long base = 0x60007000;
-	unsigned long size = SZ_4K;
+	struct resource res;
 	struct device_node *np;
 
 	if (!soc_is_tegra())
@@ -194,17 +193,29 @@ static int __init tegra_flowctrl_init(void)
 
 	np = of_find_matching_node(NULL, tegra_flowctrl_match);
 	if (np) {
-		struct resource res;
-
-		if (of_address_to_resource(np, 0, &res) == 0) {
-			size = resource_size(&res);
-			base = res.start;
+		if (of_address_to_resource(np, 0, &res) < 0) {
+			pr_err("failed to get flowctrl register\n");
+			return -ENXIO;
 		}
-
 		of_node_put(np);
+	} else if (IS_ENABLED(CONFIG_ARM)) {
+		/*
+		 * Hardcoded fallback for 32-bit Tegra
+		 * devices if device tree node is missing.
+		 */
+		res.start = 0x60007000;
+		res.end = 0x60007fff;
+		res.flags = IORESOURCE_MEM;
+	} else {
+		/*
+		 * At this point we're running on a Tegra,
+		 * that doesn't support the flow controller
+		 * (eg. Tegra186), so just return.
+		 */
+		return 0;
 	}
 
-	tegra_flowctrl_base = ioremap_nocache(base, size);
+	tegra_flowctrl_base = ioremap_nocache(res.start, resource_size(&res));
 	if (!tegra_flowctrl_base)
 		return -ENXIO;
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH V3 5/6] arm64: tegra: Update the Tegra132 flowctrl compatible string
From: Jon Hunter @ 2017-03-28 12:42 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Mark Rutland, devicetree, Stephen Warren, Russell King,
	Jon Hunter, Rob Herring, linux-tegra, linux-arm-kernel
In-Reply-To: <1490704978-22906-1-git-send-email-jonathanh@nvidia.com>

Update the Tegra132 flowctrl compatible string to include
"nvidia,tegra132-flowctrl" so it is aligned with the flowctrl binding
documentation.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 arch/arm64/boot/dts/nvidia/tegra132.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
index 3f3a46a4bd01..2b17936ac5be 100644
--- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
@@ -224,7 +224,7 @@
 	};
 
 	flow-controller@60007000 {
-		compatible = "nvidia,tegra124-flowctrl";
+		compatible = "nvidia,tegra132-flowctrl", "nvidia,tegra124-flowctrl";
 		reg = <0x0 0x60007000 0x0 0x1000>;
 	};
 
-- 
2.7.4

^ permalink raw reply related

* [PATCH V3 4/6] dt-bindings: tegra: Update compatible strings for Tegra flowctrl
From: Jon Hunter @ 2017-03-28 12:42 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Mark Rutland, devicetree, Stephen Warren, Russell King,
	Jon Hunter, Rob Herring, linux-tegra, linux-arm-kernel
In-Reply-To: <1490704978-22906-1-git-send-email-jonathanh@nvidia.com>

Update the compatible strings for Tegra Flow Control driver to match
the device-tree source files for Tegra.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 .../devicetree/bindings/arm/tegra/nvidia,tegra20-flowctrl.txt     | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-flowctrl.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-flowctrl.txt
index ccf0adddc820..a855c1bffc0f 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-flowctrl.txt
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-flowctrl.txt
@@ -1,7 +1,13 @@
 NVIDIA Tegra Flow Controller
 
 Required properties:
-- compatible: Should be "nvidia,tegra<chip>-flowctrl"
+- compatible: Should contain one of the following:
+  - "nvidia,tegra20-flowctrl": for Tegra20
+  - "nvidia,tegra30-flowctrl": for Tegra30
+  - "nvidia,tegra114-flowctrl": for Tegra114
+  - "nvidia,tegra124-flowctrl": for Tegra124
+  - "nvidia,tegra132-flowctrl", "nvidia,tegra124-flowctrl": for Tegra132
+  - "nvidia,tegra210-flowctrl": for Tegra210
 - reg: Should contain one register range (address and length)
 
 Example:
-- 
2.7.4

^ permalink raw reply related

* [PATCH V3 3/6] soc/tegra: flowctrl: Add basic platform driver
From: Jon Hunter @ 2017-03-28 12:42 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Rob Herring, Mark Rutland, Russell King, Stephen Warren,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jon Hunter
In-Reply-To: <1490704978-22906-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

Add a simple platform driver for the flowctrl module so that it gets
registered as a proper device.

Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 drivers/soc/tegra/flowctrl.c | 34 ++++++++++++++++++++++++++++++----
 1 file changed, 30 insertions(+), 4 deletions(-)

diff --git a/drivers/soc/tegra/flowctrl.c b/drivers/soc/tegra/flowctrl.c
index 3a5a1cb9ae90..25eddfc8475d 100644
--- a/drivers/soc/tegra/flowctrl.c
+++ b/drivers/soc/tegra/flowctrl.c
@@ -24,6 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/platform_device.h>
 
 #include <soc/tegra/common.h>
 #include <soc/tegra/flowctrl.h>
@@ -47,7 +48,7 @@ static void __iomem *tegra_flowctrl_base;
 
 static void flowctrl_update(u8 offset, u32 value)
 {
-	if (WARN_ONCE(!tegra_flowctrl_base,
+	if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
 		      "Tegra flowctrl not initialised!\n"))
 		return;
 
@@ -62,7 +63,7 @@ u32 flowctrl_read_cpu_csr(unsigned int cpuid)
 {
 	u8 offset = flowctrl_offset_cpu_csr[cpuid];
 
-	if (WARN_ONCE(!tegra_flowctrl_base,
+	if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
 		      "Tegra flowctrl not initialised!\n"))
 		return 0;
 
@@ -148,7 +149,22 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
 	flowctrl_write_cpu_csr(cpuid, reg);
 }
 
-static const struct of_device_id matches[] __initconst = {
+static int tegra_flowctrl_probe(struct platform_device *pdev)
+{
+	void __iomem *base = tegra_flowctrl_base;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(tegra_flowctrl_base))
+		return PTR_ERR(base);
+
+	iounmap(base);
+
+	return 0;
+}
+
+static const struct of_device_id tegra_flowctrl_match[] = {
 	{ .compatible = "nvidia,tegra124-flowctrl" },
 	{ .compatible = "nvidia,tegra114-flowctrl" },
 	{ .compatible = "nvidia,tegra30-flowctrl" },
@@ -156,6 +172,16 @@ static const struct of_device_id matches[] __initconst = {
 	{ }
 };
 
+static struct platform_driver tegra_flowctrl_driver = {
+	.driver = {
+		.name = "tegra-flowctrl",
+		.suppress_bind_attrs = true,
+		.of_match_table = tegra_flowctrl_match,
+	},
+	.probe = tegra_flowctrl_probe,
+};
+builtin_platform_driver(tegra_flowctrl_driver);
+
 static int __init tegra_flowctrl_init(void)
 {
 	/* hardcoded fallback if device tree node is missing */
@@ -166,7 +192,7 @@ static int __init tegra_flowctrl_init(void)
 	if (!soc_is_tegra())
 		return 0;
 
-	np = of_find_matching_node(NULL, matches);
+	np = of_find_matching_node(NULL, tegra_flowctrl_match);
 	if (np) {
 		struct resource res;
 
-- 
2.7.4

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

^ permalink raw reply related

* [PATCH V3 2/6] soc/tegra: Move Tegra flowctrl driver
From: Jon Hunter @ 2017-03-28 12:42 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Mark Rutland, devicetree, Stephen Warren, Russell King,
	Jon Hunter, Rob Herring, linux-tegra, linux-arm-kernel
In-Reply-To: <1490704978-22906-1-git-send-email-jonathanh@nvidia.com>

The flowctrl driver is required for both ARM and ARM64 Tegra devices
and in order to enable support for it for ARM64, move the Tegra flowctrl
driver into drivers/soc/tegra.

By moving the flowctrl driver, tegra_flowctrl_init() is now called by
via an early initcall and to prevent this function from attempting to
mapping IO space for a non-Tegra device, a test for 'soc_is_tegra()'
is also added.

Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
---
 arch/arm/mach-tegra/Makefile          |   1 -
 arch/arm/mach-tegra/cpuidle-tegra20.c |   3 +-
 arch/arm/mach-tegra/flowctrl.c        | 179 --------------------------------
 arch/arm/mach-tegra/flowctrl.h        |  66 ------------
 arch/arm/mach-tegra/platsmp.c         |   2 +-
 arch/arm/mach-tegra/pm.c              |   2 +-
 arch/arm/mach-tegra/reset-handler.S   |   2 +-
 arch/arm/mach-tegra/sleep-tegra20.S   |   3 +-
 arch/arm/mach-tegra/sleep-tegra30.S   |   2 +-
 arch/arm/mach-tegra/tegra.c           |   2 -
 drivers/soc/tegra/Kconfig             |   7 ++
 drivers/soc/tegra/Makefile            |   1 +
 drivers/soc/tegra/flowctrl.c          | 187 ++++++++++++++++++++++++++++++++++
 include/soc/tegra/flowctrl.h          |  82 +++++++++++++++
 14 files changed, 285 insertions(+), 254 deletions(-)
 delete mode 100644 arch/arm/mach-tegra/flowctrl.c
 delete mode 100644 arch/arm/mach-tegra/flowctrl.h
 create mode 100644 drivers/soc/tegra/flowctrl.c
 create mode 100644 include/soc/tegra/flowctrl.h

diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index fffad2426ee4..3b33f0bb78ae 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -2,7 +2,6 @@ asflags-y				+= -march=armv7-a
 
 obj-y                                   += io.o
 obj-y                                   += irq.o
-obj-y					+= flowctrl.o
 obj-y					+= pm.o
 obj-y					+= reset.o
 obj-y					+= reset-handler.o
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index afcee04f2616..76e4c83cd5c8 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -26,12 +26,13 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
+#include <soc/tegra/flowctrl.h>
+
 #include <asm/cpuidle.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 
 #include "cpuidle.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "irq.h"
 #include "pm.h"
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
deleted file mode 100644
index 07c688de248e..000000000000
--- a/arch/arm/mach-tegra/flowctrl.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * arch/arm/mach-tegra/flowctrl.c
- *
- * functions and macros to control the flowcontroller
- *
- * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/cpumask.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <soc/tegra/fuse.h>
-
-#include "flowctrl.h"
-
-static u8 flowctrl_offset_halt_cpu[] = {
-	FLOW_CTRL_HALT_CPU0_EVENTS,
-	FLOW_CTRL_HALT_CPU1_EVENTS,
-	FLOW_CTRL_HALT_CPU1_EVENTS + 8,
-	FLOW_CTRL_HALT_CPU1_EVENTS + 16,
-};
-
-static u8 flowctrl_offset_cpu_csr[] = {
-	FLOW_CTRL_CPU0_CSR,
-	FLOW_CTRL_CPU1_CSR,
-	FLOW_CTRL_CPU1_CSR + 8,
-	FLOW_CTRL_CPU1_CSR + 16,
-};
-
-static void __iomem *tegra_flowctrl_base;
-
-static void flowctrl_update(u8 offset, u32 value)
-{
-	if (WARN_ONCE(!tegra_flowctrl_base,
-		      "Tegra flowctrl not initialised!\n"))
-		return;
-
-	writel(value, tegra_flowctrl_base + offset);
-
-	/* ensure the update has reached the flow controller */
-	wmb();
-	readl_relaxed(tegra_flowctrl_base + offset);
-}
-
-u32 flowctrl_read_cpu_csr(unsigned int cpuid)
-{
-	u8 offset = flowctrl_offset_cpu_csr[cpuid];
-
-	if (WARN_ONCE(!tegra_flowctrl_base,
-		      "Tegra flowctrl not initialised!\n"))
-		return 0;
-
-	return readl(tegra_flowctrl_base + offset);
-}
-
-void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
-{
-	return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
-}
-
-void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
-{
-	return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
-}
-
-void flowctrl_cpu_suspend_enter(unsigned int cpuid)
-{
-	unsigned int reg;
-	int i;
-
-	reg = flowctrl_read_cpu_csr(cpuid);
-	switch (tegra_get_chip_id()) {
-	case TEGRA20:
-		/* clear wfe bitmap */
-		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
-		/* clear wfi bitmap */
-		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
-		/* pwr gating on wfe */
-		reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
-		break;
-	case TEGRA30:
-	case TEGRA114:
-	case TEGRA124:
-		/* clear wfe bitmap */
-		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
-		/* clear wfi bitmap */
-		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
-		/* pwr gating on wfi */
-		reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;
-		break;
-	}
-	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr flag */
-	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event flag */
-	reg |= FLOW_CTRL_CSR_ENABLE;			/* pwr gating */
-	flowctrl_write_cpu_csr(cpuid, reg);
-
-	for (i = 0; i < num_possible_cpus(); i++) {
-		if (i == cpuid)
-			continue;
-		reg = flowctrl_read_cpu_csr(i);
-		reg |= FLOW_CTRL_CSR_EVENT_FLAG;
-		reg |= FLOW_CTRL_CSR_INTR_FLAG;
-		flowctrl_write_cpu_csr(i, reg);
-	}
-}
-
-void flowctrl_cpu_suspend_exit(unsigned int cpuid)
-{
-	unsigned int reg;
-
-	/* Disable powergating via flow controller for CPU0 */
-	reg = flowctrl_read_cpu_csr(cpuid);
-	switch (tegra_get_chip_id()) {
-	case TEGRA20:
-		/* clear wfe bitmap */
-		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
-		/* clear wfi bitmap */
-		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
-		break;
-	case TEGRA30:
-	case TEGRA114:
-	case TEGRA124:
-		/* clear wfe bitmap */
-		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
-		/* clear wfi bitmap */
-		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
-		break;
-	}
-	reg &= ~FLOW_CTRL_CSR_ENABLE;			/* clear enable */
-	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr */
-	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event */
-	flowctrl_write_cpu_csr(cpuid, reg);
-}
-
-static const struct of_device_id matches[] __initconst = {
-	{ .compatible = "nvidia,tegra124-flowctrl" },
-	{ .compatible = "nvidia,tegra114-flowctrl" },
-	{ .compatible = "nvidia,tegra30-flowctrl" },
-	{ .compatible = "nvidia,tegra20-flowctrl" },
-	{ }
-};
-
-void __init tegra_flowctrl_init(void)
-{
-	/* hardcoded fallback if device tree node is missing */
-	unsigned long base = 0x60007000;
-	unsigned long size = SZ_4K;
-	struct device_node *np;
-
-	np = of_find_matching_node(NULL, matches);
-	if (np) {
-		struct resource res;
-
-		if (of_address_to_resource(np, 0, &res) == 0) {
-			size = resource_size(&res);
-			base = res.start;
-		}
-
-		of_node_put(np);
-	}
-
-	tegra_flowctrl_base = ioremap_nocache(base, size);
-}
diff --git a/arch/arm/mach-tegra/flowctrl.h b/arch/arm/mach-tegra/flowctrl.h
deleted file mode 100644
index 73a9c5016c1a..000000000000
--- a/arch/arm/mach-tegra/flowctrl.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * arch/arm/mach-tegra/flowctrl.h
- *
- * functions and macros to control the flowcontroller
- *
- * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __MACH_TEGRA_FLOWCTRL_H
-#define __MACH_TEGRA_FLOWCTRL_H
-
-#define FLOW_CTRL_HALT_CPU0_EVENTS	0x0
-#define FLOW_CTRL_WAITEVENT		(2 << 29)
-#define FLOW_CTRL_WAIT_FOR_INTERRUPT	(4 << 29)
-#define FLOW_CTRL_JTAG_RESUME		(1 << 28)
-#define FLOW_CTRL_SCLK_RESUME		(1 << 27)
-#define FLOW_CTRL_HALT_CPU_IRQ		(1 << 10)
-#define	FLOW_CTRL_HALT_CPU_FIQ		(1 << 8)
-#define FLOW_CTRL_HALT_LIC_IRQ		(1 << 11)
-#define FLOW_CTRL_HALT_LIC_FIQ		(1 << 10)
-#define FLOW_CTRL_HALT_GIC_IRQ		(1 << 9)
-#define FLOW_CTRL_HALT_GIC_FIQ		(1 << 8)
-#define FLOW_CTRL_CPU0_CSR		0x8
-#define	FLOW_CTRL_CSR_INTR_FLAG		(1 << 15)
-#define FLOW_CTRL_CSR_EVENT_FLAG	(1 << 14)
-#define FLOW_CTRL_CSR_ENABLE_EXT_CRAIL	(1 << 13)
-#define FLOW_CTRL_CSR_ENABLE_EXT_NCPU	(1 << 12)
-#define FLOW_CTRL_CSR_ENABLE_EXT_MASK ( \
-		FLOW_CTRL_CSR_ENABLE_EXT_NCPU | \
-		FLOW_CTRL_CSR_ENABLE_EXT_CRAIL)
-#define FLOW_CTRL_CSR_ENABLE		(1 << 0)
-#define FLOW_CTRL_HALT_CPU1_EVENTS	0x14
-#define FLOW_CTRL_CPU1_CSR		0x18
-
-#define TEGRA20_FLOW_CTRL_CSR_WFE_CPU0		(1 << 4)
-#define TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP	(3 << 4)
-#define TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP	0
-
-#define TEGRA30_FLOW_CTRL_CSR_WFI_CPU0		(1 << 8)
-#define TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP	(0xF << 4)
-#define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP	(0xF << 8)
-
-#ifndef __ASSEMBLY__
-u32 flowctrl_read_cpu_csr(unsigned int cpuid);
-void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
-void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
-
-void flowctrl_cpu_suspend_enter(unsigned int cpuid);
-void flowctrl_cpu_suspend_exit(unsigned int cpuid);
-
-void tegra_flowctrl_init(void);
-#endif
-
-#endif
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 75620ae73913..b5a2afe99101 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -21,6 +21,7 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
@@ -30,7 +31,6 @@
 #include <asm/smp_scu.h>
 
 #include "common.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "reset.h"
 
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index b0f48a3946fa..1ad5719779b0 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/suspend.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pm.h>
 #include <soc/tegra/pmc.h>
@@ -38,7 +39,6 @@
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
 
-#include "flowctrl.h"
 #include "iomap.h"
 #include "pm.h"
 #include "reset.h"
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index e3070fdab80b..805f306fa6f7 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -17,12 +17,12 @@
 #include <linux/init.h>
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
-#include "flowctrl.h"
 #include "iomap.h"
 #include "reset.h"
 #include "sleep.h"
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index f5d19667484e..5c8e638ee51a 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -20,6 +20,8 @@
 
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
+
 #include <asm/assembler.h>
 #include <asm/proc-fns.h>
 #include <asm/cp15.h>
@@ -27,7 +29,6 @@
 
 #include "irammap.h"
 #include "sleep.h"
-#include "flowctrl.h"
 
 #define EMC_CFG				0xc
 #define EMC_ADR_CFG			0x10
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 16e5ff03383c..dd4a67dabd91 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -16,13 +16,13 @@
 
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/assembler.h>
 #include <asm/cache.h>
 
-#include "flowctrl.h"
 #include "irammap.h"
 #include "sleep.h"
 
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index e01cbca196b5..649e9e8c7bcc 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -48,7 +48,6 @@
 #include "board.h"
 #include "common.h"
 #include "cpuidle.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "irq.h"
 #include "pm.h"
@@ -75,7 +74,6 @@ static void __init tegra_init_early(void)
 {
 	of_register_trusted_foundations();
 	tegra_cpu_reset_handler_init();
-	tegra_flowctrl_init();
 }
 
 static void __init tegra_dt_init_irq(void)
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index 208d6edb3fdb..c7e8ddfb574e 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -12,6 +12,7 @@ config ARCH_TEGRA_2x_SOC
 	select PINCTRL_TEGRA20
 	select PL310_ERRATA_727915 if CACHE_L2X0
 	select PL310_ERRATA_769419 if CACHE_L2X0
+	select SOC_TEGRA_FLOWCTRL
 	select SOC_TEGRA_PMC
 	select TEGRA_TIMER
 	help
@@ -24,6 +25,7 @@ config ARCH_TEGRA_3x_SOC
 	select ARM_ERRATA_764369 if SMP
 	select PINCTRL_TEGRA30
 	select PL310_ERRATA_769419 if CACHE_L2X0
+	select SOC_TEGRA_FLOWCTRL
 	select SOC_TEGRA_PMC
 	select TEGRA_TIMER
 	help
@@ -35,6 +37,7 @@ config ARCH_TEGRA_114_SOC
 	select ARM_ERRATA_798181 if SMP
 	select HAVE_ARM_ARCH_TIMER
 	select PINCTRL_TEGRA114
+	select SOC_TEGRA_FLOWCTRL
 	select SOC_TEGRA_PMC
 	select TEGRA_TIMER
 	help
@@ -45,6 +48,7 @@ config ARCH_TEGRA_124_SOC
 	bool "Enable support for Tegra124 family"
 	select HAVE_ARM_ARCH_TIMER
 	select PINCTRL_TEGRA124
+	select SOC_TEGRA_FLOWCTRL
 	select SOC_TEGRA_PMC
 	select TEGRA_TIMER
 	help
@@ -101,6 +105,9 @@ config ARCH_TEGRA_186_SOC
 endif
 endif
 
+config SOC_TEGRA_FLOWCTRL
+	bool
+
 config SOC_TEGRA_PMC
 	bool
 
diff --git a/drivers/soc/tegra/Makefile b/drivers/soc/tegra/Makefile
index b4425e4319ff..4f81dd55e5d1 100644
--- a/drivers/soc/tegra/Makefile
+++ b/drivers/soc/tegra/Makefile
@@ -1,5 +1,6 @@
 obj-y += fuse/
 
 obj-y += common.o
+obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o
 obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o
 obj-$(CONFIG_SOC_TEGRA_PMC_TEGRA186) += pmc-tegra186.o
diff --git a/drivers/soc/tegra/flowctrl.c b/drivers/soc/tegra/flowctrl.c
new file mode 100644
index 000000000000..3a5a1cb9ae90
--- /dev/null
+++ b/drivers/soc/tegra/flowctrl.c
@@ -0,0 +1,187 @@
+/*
+ * drivers/soc/tegra/flowctrl.c
+ *
+ * Functions and macros to control the flowcontroller
+ *
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include <soc/tegra/common.h>
+#include <soc/tegra/flowctrl.h>
+#include <soc/tegra/fuse.h>
+
+static u8 flowctrl_offset_halt_cpu[] = {
+	FLOW_CTRL_HALT_CPU0_EVENTS,
+	FLOW_CTRL_HALT_CPU1_EVENTS,
+	FLOW_CTRL_HALT_CPU1_EVENTS + 8,
+	FLOW_CTRL_HALT_CPU1_EVENTS + 16,
+};
+
+static u8 flowctrl_offset_cpu_csr[] = {
+	FLOW_CTRL_CPU0_CSR,
+	FLOW_CTRL_CPU1_CSR,
+	FLOW_CTRL_CPU1_CSR + 8,
+	FLOW_CTRL_CPU1_CSR + 16,
+};
+
+static void __iomem *tegra_flowctrl_base;
+
+static void flowctrl_update(u8 offset, u32 value)
+{
+	if (WARN_ONCE(!tegra_flowctrl_base,
+		      "Tegra flowctrl not initialised!\n"))
+		return;
+
+	writel(value, tegra_flowctrl_base + offset);
+
+	/* ensure the update has reached the flow controller */
+	wmb();
+	readl_relaxed(tegra_flowctrl_base + offset);
+}
+
+u32 flowctrl_read_cpu_csr(unsigned int cpuid)
+{
+	u8 offset = flowctrl_offset_cpu_csr[cpuid];
+
+	if (WARN_ONCE(!tegra_flowctrl_base,
+		      "Tegra flowctrl not initialised!\n"))
+		return 0;
+
+	return readl(tegra_flowctrl_base + offset);
+}
+
+void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
+{
+	return flowctrl_update(flowctrl_offset_cpu_csr[cpuid], value);
+}
+
+void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value)
+{
+	return flowctrl_update(flowctrl_offset_halt_cpu[cpuid], value);
+}
+
+void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+{
+	unsigned int reg;
+	int i;
+
+	reg = flowctrl_read_cpu_csr(cpuid);
+	switch (tegra_get_chip_id()) {
+	case TEGRA20:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
+		/* pwr gating on wfe */
+		reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
+		break;
+	case TEGRA30:
+	case TEGRA114:
+	case TEGRA124:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
+		/* pwr gating on wfi */
+		reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;
+		break;
+	}
+	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr flag */
+	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event flag */
+	reg |= FLOW_CTRL_CSR_ENABLE;			/* pwr gating */
+	flowctrl_write_cpu_csr(cpuid, reg);
+
+	for (i = 0; i < num_possible_cpus(); i++) {
+		if (i == cpuid)
+			continue;
+		reg = flowctrl_read_cpu_csr(i);
+		reg |= FLOW_CTRL_CSR_EVENT_FLAG;
+		reg |= FLOW_CTRL_CSR_INTR_FLAG;
+		flowctrl_write_cpu_csr(i, reg);
+	}
+}
+
+void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+{
+	unsigned int reg;
+
+	/* Disable powergating via flow controller for CPU0 */
+	reg = flowctrl_read_cpu_csr(cpuid);
+	switch (tegra_get_chip_id()) {
+	case TEGRA20:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
+		break;
+	case TEGRA30:
+	case TEGRA114:
+	case TEGRA124:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
+		break;
+	}
+	reg &= ~FLOW_CTRL_CSR_ENABLE;			/* clear enable */
+	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr */
+	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event */
+	flowctrl_write_cpu_csr(cpuid, reg);
+}
+
+static const struct of_device_id matches[] __initconst = {
+	{ .compatible = "nvidia,tegra124-flowctrl" },
+	{ .compatible = "nvidia,tegra114-flowctrl" },
+	{ .compatible = "nvidia,tegra30-flowctrl" },
+	{ .compatible = "nvidia,tegra20-flowctrl" },
+	{ }
+};
+
+static int __init tegra_flowctrl_init(void)
+{
+	/* hardcoded fallback if device tree node is missing */
+	unsigned long base = 0x60007000;
+	unsigned long size = SZ_4K;
+	struct device_node *np;
+
+	if (!soc_is_tegra())
+		return 0;
+
+	np = of_find_matching_node(NULL, matches);
+	if (np) {
+		struct resource res;
+
+		if (of_address_to_resource(np, 0, &res) == 0) {
+			size = resource_size(&res);
+			base = res.start;
+		}
+
+		of_node_put(np);
+	}
+
+	tegra_flowctrl_base = ioremap_nocache(base, size);
+	if (!tegra_flowctrl_base)
+		return -ENXIO;
+
+	return 0;
+}
+early_initcall(tegra_flowctrl_init);
diff --git a/include/soc/tegra/flowctrl.h b/include/soc/tegra/flowctrl.h
new file mode 100644
index 000000000000..8f86aea4024b
--- /dev/null
+++ b/include/soc/tegra/flowctrl.h
@@ -0,0 +1,82 @@
+/*
+ * Functions and macros to control the flowcontroller
+ *
+ * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SOC_TEGRA_FLOWCTRL_H__
+#define __SOC_TEGRA_FLOWCTRL_H__
+
+#define FLOW_CTRL_HALT_CPU0_EVENTS	0x0
+#define FLOW_CTRL_WAITEVENT		(2 << 29)
+#define FLOW_CTRL_WAIT_FOR_INTERRUPT	(4 << 29)
+#define FLOW_CTRL_JTAG_RESUME		(1 << 28)
+#define FLOW_CTRL_SCLK_RESUME		(1 << 27)
+#define FLOW_CTRL_HALT_CPU_IRQ		(1 << 10)
+#define	FLOW_CTRL_HALT_CPU_FIQ		(1 << 8)
+#define FLOW_CTRL_HALT_LIC_IRQ		(1 << 11)
+#define FLOW_CTRL_HALT_LIC_FIQ		(1 << 10)
+#define FLOW_CTRL_HALT_GIC_IRQ		(1 << 9)
+#define FLOW_CTRL_HALT_GIC_FIQ		(1 << 8)
+#define FLOW_CTRL_CPU0_CSR		0x8
+#define	FLOW_CTRL_CSR_INTR_FLAG		(1 << 15)
+#define FLOW_CTRL_CSR_EVENT_FLAG	(1 << 14)
+#define FLOW_CTRL_CSR_ENABLE_EXT_CRAIL	(1 << 13)
+#define FLOW_CTRL_CSR_ENABLE_EXT_NCPU	(1 << 12)
+#define FLOW_CTRL_CSR_ENABLE_EXT_MASK ( \
+		FLOW_CTRL_CSR_ENABLE_EXT_NCPU | \
+		FLOW_CTRL_CSR_ENABLE_EXT_CRAIL)
+#define FLOW_CTRL_CSR_ENABLE		(1 << 0)
+#define FLOW_CTRL_HALT_CPU1_EVENTS	0x14
+#define FLOW_CTRL_CPU1_CSR		0x18
+
+#define TEGRA20_FLOW_CTRL_CSR_WFE_CPU0		(1 << 4)
+#define TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP	(3 << 4)
+#define TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP	0
+
+#define TEGRA30_FLOW_CTRL_CSR_WFI_CPU0		(1 << 8)
+#define TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP	(0xF << 4)
+#define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP	(0xF << 8)
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_SOC_TEGRA_FLOWCTRL
+u32 flowctrl_read_cpu_csr(unsigned int cpuid);
+void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
+void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
+
+void flowctrl_cpu_suspend_enter(unsigned int cpuid);
+void flowctrl_cpu_suspend_exit(unsigned int cpuid);
+#else
+static inline u32 flowctrl_read_cpu_csr(unsigned int cpuid)
+{
+	return 0;
+}
+
+static inline void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
+{
+}
+
+static inline void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) {}
+
+static inline void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+{
+}
+
+static inline void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+{
+}
+#endif /* CONFIG_SOC_TEGRA_FLOWCTRL */
+#endif /* __ASSEMBLY */
+#endif /* __SOC_TEGRA_FLOWCTRL_H__ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V3 1/6] ARM: tegra: Remove unnecessary inclusion of flowctrl header
From: Jon Hunter @ 2017-03-28 12:42 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Rob Herring, Mark Rutland, Russell King, Stephen Warren,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Jon Hunter
In-Reply-To: <1490704978-22906-1-git-send-email-jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>

The Tegra flowctrl.h header is included unnecessarily by the Tegra
sleep.S source file. Remove this unnecessary inclusion.

Signed-off-by: Jon Hunter <jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
---
 arch/arm/mach-tegra/sleep.S | 2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index f024a5109e8e..5e3496753df1 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -30,8 +30,6 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include "iomap.h"
-
-#include "flowctrl.h"
 #include "sleep.h"
 
 #define CLK_RESET_CCLK_BURST	0x20
-- 
2.7.4

^ permalink raw reply related

* [PATCH V3 0/6] soc/tegra: Enable flowctrl support for Tegra132/210
From: Jon Hunter @ 2017-03-28 12:42 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Mark Rutland, devicetree, Stephen Warren, Russell King,
	Jon Hunter, Rob Herring, linux-tegra, linux-arm-kernel

The flowctrl modules is supported by both Tegra132 and Tegra210 devices.
These devices already have the flowctrl node defined in their respective
*.dtsi device-tree files. The flowctrl driver is currently located in
the arch/arm/mach-tegra directory and so can only be used for 32-bit
Tegra devices. Move this driver into drivers/soc/tegra so that it can
be used for all Tegra devices that support flowctrl.

I have also added a couple clean-up patches.

Changes since V2:
- Updated Dt compatible strings per Stephen's feedback
- Added patch to update Tegra132 compatible string

Changes since V1:
- Updated warning message per Thierry's feedback
- Added stub functions for public flowctrl APIs
- Added patch to register flowctrl driver as a platform driver
- Updated formatting of DT compatible strings per Thierry's feedback.

Jon Hunter (6):
  ARM: tegra: Remove unnecessary inclusion of flowctrl header
  soc/tegra: Move Tegra flowctrl driver
  soc/tegra: flowctrl: Add basic platform driver
  dt-bindings: tegra: Update compatible strings for Tegra flowctrl
  arm64: tegra: Update the Tegra132 flowctrl compatible string
  soc/tegra: Add initial flowctrl support for Tegra132/210

 .../bindings/arm/tegra/nvidia,tegra20-flowctrl.txt |   8 +-
 arch/arm/mach-tegra/Makefile                       |   1 -
 arch/arm/mach-tegra/cpuidle-tegra20.c              |   3 +-
 arch/arm/mach-tegra/flowctrl.c                     | 179 ----------------
 arch/arm/mach-tegra/flowctrl.h                     |  66 ------
 arch/arm/mach-tegra/platsmp.c                      |   2 +-
 arch/arm/mach-tegra/pm.c                           |   2 +-
 arch/arm/mach-tegra/reset-handler.S                |   2 +-
 arch/arm/mach-tegra/sleep-tegra20.S                |   3 +-
 arch/arm/mach-tegra/sleep-tegra30.S                |   2 +-
 arch/arm/mach-tegra/sleep.S                        |   2 -
 arch/arm/mach-tegra/tegra.c                        |   2 -
 arch/arm64/boot/dts/nvidia/tegra132.dtsi           |   2 +-
 drivers/soc/tegra/Kconfig                          |   9 +
 drivers/soc/tegra/Makefile                         |   1 +
 drivers/soc/tegra/flowctrl.c                       | 224 +++++++++++++++++++++
 include/soc/tegra/flowctrl.h                       |  82 ++++++++
 17 files changed, 332 insertions(+), 258 deletions(-)
 delete mode 100644 arch/arm/mach-tegra/flowctrl.c
 delete mode 100644 arch/arm/mach-tegra/flowctrl.h
 create mode 100644 drivers/soc/tegra/flowctrl.c
 create mode 100644 include/soc/tegra/flowctrl.h

-- 
2.7.4

^ permalink raw reply

* Re: [RFC 4/8] regulator: core: Check enabling bypass respects constraints
From: Leonard Crestez @ 2017-03-28 12:39 UTC (permalink / raw)
  To: Mark Brown, Sascha Hauer
  Cc: Mark Rutland, devicetree, Anson Huang, Irina Tirdea, Viresh Kumar,
	linux-pm, Rafael J. Wysocki, Liam Girdwood, linux-kernel,
	Rob Herring, Octavian Purdila, Fabio Estevam, Robin Gong,
	Shawn Guo, linux-arm-kernel
In-Reply-To: <20170324125212.vikgekqxsnu7htzl@sirena.org.uk>

On Fri, 2017-03-24 at 12:52 +0000, Mark Brown wrote:
> On Wed, Mar 22, 2017 at 06:53:06PM +0200, Leonard Crestez wrote:
> 
> > 
> > Enabling bypass mode makes a regulator passthrough the supply voltage
> > directly. It is possible that the supply voltage is set high enough that
> > it violates machine constraints so let's check for that.
> > 
> > The supply voltage might be higher because of min_dropout_uV or maybe
> > there is just an unrelated consumer who requested a higher voltage.
> I would expect that if bypass is enabled then the constraints on the
> parent regulator would be set appropriately to support this, I wouldn't
> expect that we'd try to apply the operating constraints of the regulator
> to the supply.  Usually bypass is used for low power retention modes
> with different settings to those used in normal operation that wouldn't
> be desired in normal operation, if we were going to have constraints for
> this I'd expect a separate set used during bypass.

In this particular case it's not possible to set constraints on the parent
regulator so that both ldo-enable and ldo-bypass modes work. The maximum allowed
voltage for ldo-bypass is lower than the minimum required to support the chip at
max frequency wit ldo-enable.

It would be possible to also change the constraint values on the PMIC together
with ldo-bypass in the .dts files but that seems awful.

I'm not sure I understand why you are against applying constraints to the parent
when in bypass mode, it seems like the obvious thing to do if you want to
support flexible configuration. The check I introduced is probably not enough to
cover all cases, for example it would still be possible to explicitly change
parent voltage afterwards.

A regulator_dev registers a consumer for the supply. Right now this is being
used to propagate minimum voltages upwards since commit fc42112c0eaa ("Propagate
voltage changes to supply regulators"). It seems to me like it would be
reasonable to also use it to propagate maximum voltage from constraints, right?

Instead of asking for [best_uV + min_dropout_uV, INT_MAX] it could instead ask
for [min_uV + bypass ? min_dropout_uV : 0, min(max_uV, constraints->max_uV)].
The _regulator_do_set_voltage call on the supply can deal with stuff like
mapping it to a selector, just like it does for regulator consumers.

If more elaborate constraints are required instead of this simple behavior it
could be handled by adding an interface for drivers to expose explicit dynamic
min/max constraints.

--
Regards,
Leonard

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v2] of: add stubs for of_n_{addr, size}_cells
From: Arnd Bergmann @ 2017-03-28 12:38 UTC (permalink / raw)
  To: Tobias Regnery
  Cc: Rob Herring, devicetree, Linux Kernel Mailing List, Simon Horman
In-Reply-To: <20170328093742.21528-1-tobias.regnery@gmail.com>

On Tue, Mar 28, 2017 at 11:37 AM, Tobias Regnery
<tobias.regnery@gmail.com> wrote:
> With CONFIG_OF=n and CONFIG_COMPILE_TEST=y the rcar pci-e driver fails to
> build on arm:
>
> drivers/pci/host/pcie-rcar.c: In function 'pci_dma_range_parser_init':
> drivers/pci/host/pcie-rcar.c:1035:16: error: implicit declaration of function 'of_n_addr_cells' [-Werror=implicit-function-declaration]
>   parser->pna = of_n_addr_cells(node);
>                 ^~~~~~~~~~~~~~~
>
> Fix this by adding an inline stub for of_n_addr_cells
>
> While at it also provide a stub for of_n_size_cells for consistency reasons.
>
> Signed-off-by: Tobias Regnery <tobias.regnery@gmail.com>
> ---
> Changes in v2:
>         - add a stub for of_n_size_cells as suggested by Arnd

Acked-by: Arnd Bergmann <arnd@arndb.de>

^ permalink raw reply

* [PATCH v4 3/3] DT nodes for Broadcom Northstar2 USB DRD Phy
From: Raviteja Garimella @ 2017-03-28 12:27 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Kishon Vijay Abraham I, Ray Jui,
	Scott Branden, Jon Mason, Catalin Marinas, Will Deacon
  Cc: devicetree, linux-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel
In-Reply-To: <1490704052-11314-1-git-send-email-raviteja.garimella@broadcom.com>

This patch adds device tree nodes for USB Dual Role Device Phy for
Broadcom's Northstar2 SoC.

Signed-off-by: Raviteja Garimella <raviteja.garimella@broadcom.com>
---
 arch/arm64/boot/dts/broadcom/ns2.dtsi | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/arch/arm64/boot/dts/broadcom/ns2.dtsi b/arch/arm64/boot/dts/broadcom/ns2.dtsi
index 9f9e203..97c35c4 100644
--- a/arch/arm64/boot/dts/broadcom/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/ns2.dtsi
@@ -428,6 +428,20 @@
 			};
 		};
 
+		usbdrd_phy: phy@66000960 {
+			#phy-cells = <0>;
+			compatible = "brcm,ns2-drd-phy";
+			reg = <0x66000960 0x24>,
+			      <0x67012800 0x4>,
+			      <0x6501d148 0x4>,
+			      <0x664d0700 0x4>;
+			reg-names = "icfg", "rst-ctrl",
+				    "crmu-ctrl", "usb2-strap";
+			id-gpios = <&gpio_g 30 0>;
+			vbus-gpios = <&gpio_g 31 0>;
+			status = "disabled";
+		};
+
 		pwm: pwm@66010000 {
 			compatible = "brcm,iproc-pwm";
 			reg = <0x66010000 0x28>;
-- 
2.1.0

^ permalink raw reply related

* [PATCH v4 2/3] Broadcom USB DRD Phy driver for Northstar2
From: Raviteja Garimella @ 2017-03-28 12:27 UTC (permalink / raw)
  To: Rob Herring, Mark Rutland, Kishon Vijay Abraham I, Ray Jui,
	Scott Branden, Jon Mason, Catalin Marinas, Will Deacon
  Cc: devicetree, linux-kernel, bcm-kernel-feedback-list,
	linux-arm-kernel
In-Reply-To: <1490704052-11314-1-git-send-email-raviteja.garimella@broadcom.com>

This is driver for USB DRD Phy used in Broadcom's Northstar2
SoC. The phy can be configured to be in Device mode or Host
mode based on the type of cable connected to the port. The
driver registers to  extcon framework to get appropriate
connect events for Host/Device cables connect/disconnect
states based on VBUS and ID interrupts.

Signed-off-by: Raviteja Garimella <raviteja.garimella@broadcom.com>
---
 drivers/phy/Kconfig              |  13 +
 drivers/phy/Makefile             |   1 +
 drivers/phy/phy-bcm-ns2-usbdrd.c | 567 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 581 insertions(+)
 create mode 100644 drivers/phy/phy-bcm-ns2-usbdrd.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index dc5277a..001bc33 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -487,6 +487,19 @@ config PHY_CYGNUS_PCIE
 	  Enable this to support the Broadcom Cygnus PCIe PHY.
 	  If unsure, say N.
 
+config PHY_NS2_USB_DRD
+	tristate "Broadcom Northstar2 USB DRD PHY support"
+	depends on OF && (ARCH_BCM_IPROC || COMPILE_TEST)
+	select GENERIC_PHY
+	select EXTCON
+	default ARCH_BCM_IPROC
+	help
+	  Enable this to support the Broadcom Northstar2 USB DRD PHY.
+	  This driver initializes the PHY in either HOST or DEVICE mode.
+	  The host or device configuration is read from device tree.
+
+	  If unsure, say N.
+
 source "drivers/phy/tegra/Kconfig"
 
 config PHY_NS2_PCIE
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index e7b0feb..122eee6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -59,6 +59,7 @@ 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
 obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o
+obj-$(CONFIG_PHY_NS2_USB_DRD)		+= phy-bcm-ns2-usbdrd.o
 obj-$(CONFIG_ARCH_TEGRA) += tegra/
 obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o
 obj-$(CONFIG_PHY_MESON8B_USB2)		+= phy-meson8b-usb2.o
diff --git a/drivers/phy/phy-bcm-ns2-usbdrd.c b/drivers/phy/phy-bcm-ns2-usbdrd.c
new file mode 100644
index 0000000..f41763f
--- /dev/null
+++ b/drivers/phy/phy-bcm-ns2-usbdrd.c
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/extcon.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+
+#define ICFG_DRD_AFE		0x0
+#define ICFG_MISC_STAT		0x18
+#define ICFG_DRD_P0CTL		0x1C
+#define ICFG_STRAP_CTRL		0x20
+#define ICFG_FSM_CTRL		0x24
+
+#define IDM_RST_BIT		BIT(0)
+#define AFE_CORERDY_VDDC	BIT(18)
+#define PHY_PLL_RESETB		BIT(15)
+#define PHY_RESETB		BIT(14)
+#define PHY_PLL_LOCK		BIT(0)
+
+#define DRD_DEV_MODE		BIT(20)
+#define OHCI_OVRCUR_POL		BIT(11)
+#define ICFG_OFF_MODE		BIT(6)
+#define PLL_LOCK_RETRY		1000
+
+#define EVT_DEVICE		0
+#define EVT_HOST		1
+#define EVT_IDLE		2
+
+#define DRD_HOST_MODE		(BIT(2) | BIT(3))
+#define DRD_DEVICE_MODE		(BIT(4) | BIT(5))
+#define DRD_HOST_VAL		0x803
+#define DRD_DEV_VAL		0x807
+#define GPIO_DELAY		20
+#define PHY_WQ_DELAY		msecs_to_jiffies(600)
+
+struct ns2_phy_data;
+struct ns2_phy_driver {
+	void __iomem *icfgdrd_regs;
+	void __iomem *idmdrd_rst_ctrl;
+	void __iomem *crmu_usb2_ctrl;
+	void __iomem *usb2h_strap_reg;
+	spinlock_t lock; /* spin lock for phy driver */
+	struct ns2_phy_data *data;
+	struct extcon_specific_cable_nb extcon_dev;
+	struct extcon_specific_cable_nb extcon_host;
+	struct notifier_block host_nb;
+	struct notifier_block dev_nb;
+	struct delayed_work conn_work;
+	struct extcon_dev *edev;
+	struct gpio_desc *vbus_gpiod;
+	struct gpio_desc *id_gpiod;
+	int id_irq;
+	int vbus_irq;
+	unsigned long debounce_jiffies;
+	struct delayed_work wq_extcon;
+};
+
+struct ns2_phy_data {
+	struct ns2_phy_driver *driver;
+	struct phy *phy;
+	int new_state;
+};
+
+static const unsigned int usb_extcon_cable[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_NONE,
+};
+
+static inline int pll_lock_stat(u32 usb_reg, int reg_mask,
+				struct ns2_phy_driver *driver)
+{
+	int retry = PLL_LOCK_RETRY;
+	u32 val;
+
+	do {
+		udelay(1);
+		val = readl(driver->icfgdrd_regs + usb_reg);
+		if (val & reg_mask)
+			return 0;
+	} while (--retry > 0);
+
+	return -EBUSY;
+}
+
+static int ns2_drd_phy_init(struct phy *phy)
+{
+	struct ns2_phy_data *data = phy_get_drvdata(phy);
+	struct ns2_phy_driver *driver = data->driver;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&driver->lock, flags);
+
+	val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+	if (data->new_state == EVT_HOST) {
+		val &= ~DRD_DEVICE_MODE;
+		val |= DRD_HOST_MODE;
+	} else {
+		val &= ~DRD_HOST_MODE;
+		val |= DRD_DEVICE_MODE;
+	}
+	writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+	spin_unlock_irqrestore(&driver->lock, flags);
+	return 0;
+}
+
+static int ns2_drd_phy_shutdown(struct phy *phy)
+{
+	struct ns2_phy_data *data = phy_get_drvdata(phy);
+	struct ns2_phy_driver *driver = data->driver;
+	unsigned long flags;
+	u32 val;
+
+	spin_lock_irqsave(&driver->lock, flags);
+
+	val = readl(driver->crmu_usb2_ctrl);
+	val &= ~AFE_CORERDY_VDDC;
+	writel(val, driver->crmu_usb2_ctrl);
+
+	val = readl(driver->crmu_usb2_ctrl);
+	val &= ~DRD_DEV_MODE;
+	writel(val, driver->crmu_usb2_ctrl);
+
+	/* Disable Host and Device Mode */
+	val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+	val &= ~(DRD_HOST_MODE | DRD_DEVICE_MODE | ICFG_OFF_MODE);
+	writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+	spin_unlock_irqrestore(&driver->lock, flags);
+	return 0;
+}
+
+static int ns2_drd_phy_poweron(struct phy *phy)
+{
+	struct ns2_phy_data *data = phy_get_drvdata(phy);
+	struct ns2_phy_driver *driver = data->driver;
+	u32 extcon_event = data->new_state;
+	unsigned long flags;
+	int ret;
+	u32 val;
+
+	spin_lock_irqsave(&driver->lock, flags);
+	if (extcon_event == EVT_DEVICE) {
+		writel(DRD_DEV_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+
+		val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+		val &= ~(DRD_HOST_MODE | ICFG_OFF_MODE);
+		val |= DRD_DEVICE_MODE;
+		writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+		val = readl(driver->idmdrd_rst_ctrl);
+		val &= ~IDM_RST_BIT;
+		writel(val, driver->idmdrd_rst_ctrl);
+
+		val = readl(driver->crmu_usb2_ctrl);
+		val |= (AFE_CORERDY_VDDC | DRD_DEV_MODE);
+		writel(val, driver->crmu_usb2_ctrl);
+
+		/* Bring PHY and PHY_PLL out of Reset */
+		val = readl(driver->crmu_usb2_ctrl);
+		val |= (PHY_PLL_RESETB | PHY_RESETB);
+		writel(val, driver->crmu_usb2_ctrl);
+
+		ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
+		if (ret < 0) {
+			dev_err(&phy->dev, "Phy PLL lock failed\n");
+			goto err_shutdown;
+		}
+	} else {
+		writel(DRD_HOST_VAL, driver->icfgdrd_regs + ICFG_DRD_P0CTL);
+
+		val = readl(driver->icfgdrd_regs + ICFG_FSM_CTRL);
+		val &= ~(DRD_DEVICE_MODE | ICFG_OFF_MODE);
+		val |= DRD_HOST_MODE;
+		writel(val, driver->icfgdrd_regs + ICFG_FSM_CTRL);
+
+		val = readl(driver->crmu_usb2_ctrl);
+		val |= AFE_CORERDY_VDDC;
+		writel(val, driver->crmu_usb2_ctrl);
+
+		ret = pll_lock_stat(ICFG_MISC_STAT, PHY_PLL_LOCK, driver);
+		if (ret < 0) {
+			dev_err(&phy->dev, "Phy PLL lock failed\n");
+			goto err_shutdown;
+		}
+
+		val = readl(driver->idmdrd_rst_ctrl);
+		val &= ~IDM_RST_BIT;
+		writel(val, driver->idmdrd_rst_ctrl);
+
+		/* port over current Polarity */
+		val = readl(driver->usb2h_strap_reg);
+		val |= OHCI_OVRCUR_POL;
+		writel(val, driver->usb2h_strap_reg);
+	}
+	spin_unlock_irqrestore(&driver->lock, flags);
+	return 0;
+
+err_shutdown:
+	spin_unlock_irqrestore(&driver->lock, flags);
+	ns2_drd_phy_shutdown(phy);
+	return ret;
+}
+
+static void connect_work(struct work_struct *work)
+{
+	struct ns2_phy_driver *driver;
+	struct ns2_phy_data *data;
+	u32 extcon_event;
+
+	driver  = container_of(to_delayed_work(work),
+			       struct ns2_phy_driver, conn_work);
+	data = driver->data;
+	extcon_event = data->new_state;
+
+	if (extcon_event == EVT_DEVICE || extcon_event == EVT_HOST) {
+		ns2_drd_phy_init(data->phy);
+		ns2_drd_phy_poweron(data->phy);
+	} else if (extcon_event == EVT_IDLE) {
+		ns2_drd_phy_shutdown(data->phy);
+	}
+}
+
+static int drd_device_notify(struct notifier_block *self,
+			     unsigned long event, void *ptr)
+{
+	struct ns2_phy_driver *driver = container_of(self,
+					struct ns2_phy_driver, dev_nb);
+
+	if (event) {
+		pr_debug("Device connected\n");
+		driver->data->new_state = EVT_DEVICE;
+		schedule_delayed_work(&driver->conn_work, 0);
+	} else {
+		pr_debug("Device disconnected\n");
+		driver->data->new_state = EVT_IDLE;
+		schedule_delayed_work(&driver->conn_work, PHY_WQ_DELAY);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static int drd_host_notify(struct notifier_block *self,
+			   unsigned long event, void *ptr)
+{
+	struct ns2_phy_driver *driver = container_of(self,
+					struct ns2_phy_driver, host_nb);
+
+	if (event) {
+		pr_debug("Host connected\n");
+		driver->data->new_state = EVT_HOST;
+		schedule_delayed_work(&driver->conn_work, 0);
+	} else {
+		pr_debug("Host disconnected\n");
+		driver->data->new_state = EVT_IDLE;
+		schedule_delayed_work(&driver->conn_work, PHY_WQ_DELAY);
+	}
+
+	return NOTIFY_DONE;
+}
+
+static void extcon_work(struct work_struct *work)
+{
+	struct ns2_phy_driver *driver;
+	int vbus;
+	int id;
+
+	driver  = container_of(to_delayed_work(work),
+			       struct ns2_phy_driver, wq_extcon);
+
+	id = gpiod_get_value_cansleep(driver->id_gpiod);
+	vbus = gpiod_get_value_cansleep(driver->vbus_gpiod);
+
+	if (!id && vbus) {
+		extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, true);
+	} else if (id && !vbus) {
+		extcon_set_cable_state_(driver->edev, EXTCON_USB_HOST, false);
+		extcon_set_cable_state_(driver->edev, EXTCON_USB, false);
+	} else if (id && vbus) {
+		extcon_set_cable_state_(driver->edev, EXTCON_USB, true);
+	}
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+	struct ns2_phy_driver *driver = dev_id;
+
+	queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
+			   driver->debounce_jiffies);
+
+	return IRQ_HANDLED;
+}
+
+static int register_extcon_notifier(struct ns2_phy_driver *phy_driver,
+				    struct device *dev)
+{
+	struct extcon_dev *edev;
+	int ret;
+
+	phy_driver->host_nb.notifier_call = drd_host_notify;
+	phy_driver->dev_nb.notifier_call = drd_device_notify;
+
+	edev = phy_driver->edev;
+
+	/* Register for device change notification */
+	ret = extcon_register_notifier(edev, EXTCON_USB,
+				       &phy_driver->dev_nb);
+	if (ret < 0) {
+		dev_err(dev, "can't register extcon_dev\n");
+		return ret;
+	}
+
+	/* Register for host change notification */
+	ret = extcon_register_notifier(edev, EXTCON_USB_HOST,
+				       &phy_driver->host_nb);
+	if (ret < 0) {
+		dev_err(dev, "can't register extcon_dev\n");
+		goto err_dev;
+	}
+
+	/* Check the device cable connect state */
+	ret = extcon_get_cable_state_(edev, EXTCON_USB);
+	if (ret < 0) {
+		dev_err(dev, "can't get extcon_dev state\n");
+		goto err_host;
+	} else if (ret) {
+		phy_driver->data->new_state = EVT_DEVICE;
+	}
+
+	/* Check the host cable connect state */
+	ret = extcon_get_cable_state_(edev, EXTCON_USB_HOST);
+	if (ret < 0) {
+		dev_err(dev, "can't get extcon_dev state\n");
+		goto err_host;
+	} else if (ret) {
+		phy_driver->data->new_state = EVT_HOST;
+	}
+
+	return 0;
+
+err_host:
+	ret = extcon_unregister_notifier(edev, EXTCON_USB_HOST,
+					&phy_driver->host_nb);
+err_dev:
+	ret = extcon_unregister_notifier(edev, EXTCON_USB,
+					&phy_driver->dev_nb);
+	return ret;
+}
+
+static struct phy_ops ops = {
+	.init		= ns2_drd_phy_init,
+	.power_on	= ns2_drd_phy_poweron,
+	.power_off	= ns2_drd_phy_shutdown,
+	.owner		= THIS_MODULE,
+};
+
+static const struct of_device_id ns2_drd_phy_dt_ids[] = {
+	{ .compatible = "brcm,ns2-drd-phy", },
+	{ }
+};
+
+static int ns2_drd_phy_remove(struct platform_device *pdev)
+{
+	struct ns2_phy_driver *driver = dev_get_drvdata(&pdev->dev);
+
+	if (driver->edev) {
+		extcon_unregister_notifier(driver->edev, EXTCON_USB_HOST,
+					  &driver->host_nb);
+		extcon_unregister_notifier(driver->edev, EXTCON_USB,
+					  &driver->dev_nb);
+	}
+
+	return 0;
+}
+static int ns2_drd_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct ns2_phy_driver *driver;
+	struct ns2_phy_data *data;
+	struct resource *res;
+	int ret;
+	u32 val;
+
+	driver = devm_kzalloc(dev, sizeof(struct ns2_phy_driver),
+			      GFP_KERNEL);
+	if (!driver)
+		return -ENOMEM;
+
+	driver->data = devm_kzalloc(dev, sizeof(struct ns2_phy_data),
+				  GFP_KERNEL);
+	if (!driver->data)
+		return -ENOMEM;
+
+	spin_lock_init(&driver->lock);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "icfg");
+	driver->icfgdrd_regs = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->icfgdrd_regs))
+		return PTR_ERR(driver->icfgdrd_regs);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rst-ctrl");
+	driver->idmdrd_rst_ctrl = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->idmdrd_rst_ctrl))
+		return PTR_ERR(driver->idmdrd_rst_ctrl);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "crmu-ctrl");
+	driver->crmu_usb2_ctrl = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->crmu_usb2_ctrl))
+		return PTR_ERR(driver->crmu_usb2_ctrl);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "usb2-strap");
+	driver->usb2h_strap_reg = devm_ioremap_resource(dev, res);
+	if (IS_ERR(driver->usb2h_strap_reg))
+		return PTR_ERR(driver->usb2h_strap_reg);
+
+	 /* create extcon */
+	driver->id_gpiod = devm_gpiod_get(&pdev->dev, "id", GPIOD_IN);
+	if (IS_ERR(driver->id_gpiod)) {
+		dev_err(dev, "failed to get ID GPIO\n");
+		return PTR_ERR(driver->id_gpiod);
+	}
+	driver->vbus_gpiod = devm_gpiod_get(&pdev->dev, "vbus", GPIOD_IN);
+	if (IS_ERR(driver->vbus_gpiod)) {
+		dev_err(dev, "failed to get VBUS GPIO\n");
+		return PTR_ERR(driver->vbus_gpiod);
+	}
+
+	driver->edev = devm_extcon_dev_allocate(dev, usb_extcon_cable);
+	if (IS_ERR(driver->edev)) {
+		dev_err(dev, "failed to allocate extcon device\n");
+		return -ENOMEM;
+	}
+
+	ret = devm_extcon_dev_register(dev, driver->edev);
+	if (ret < 0) {
+		dev_err(dev, "failed to register extcon device\n");
+		goto extcon_free;
+	}
+
+	ret = gpiod_set_debounce(driver->id_gpiod, GPIO_DELAY * 1000);
+	if (ret < 0)
+		driver->debounce_jiffies = msecs_to_jiffies(GPIO_DELAY);
+
+	INIT_DELAYED_WORK(&driver->wq_extcon, extcon_work);
+
+	driver->id_irq = gpiod_to_irq(driver->id_gpiod);
+	if (driver->id_irq < 0) {
+		dev_err(dev, "failed to get ID IRQ\n");
+		ret = driver->id_irq;
+		goto extcon_unregister;
+	}
+	driver->vbus_irq = gpiod_to_irq(driver->vbus_gpiod);
+	if (driver->vbus_irq < 0) {
+		dev_err(dev, "failed to get ID IRQ\n");
+		ret = driver->vbus_irq;
+		goto extcon_unregister;
+	}
+
+	ret = devm_request_threaded_irq(dev, driver->id_irq, NULL,
+					gpio_irq_handler,
+					IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					"usb_id", driver);
+	if (ret < 0) {
+		dev_err(dev, "failed to request handler for ID IRQ\n");
+		goto extcon_unregister;
+	}
+	ret = devm_request_threaded_irq(dev, driver->vbus_irq, NULL,
+					gpio_irq_handler,
+					IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					"usb_vbus", driver);
+	if (ret < 0) {
+		dev_err(dev, "failed to request handler for VBUS IRQ\n");
+		goto extcon_unregister;
+	}
+
+	dev_set_drvdata(dev, driver);
+
+	/* Shutdown all ports. They can be powered up as required */
+	val = readl(driver->crmu_usb2_ctrl);
+	val &= ~(AFE_CORERDY_VDDC | PHY_RESETB);
+	writel(val, driver->crmu_usb2_ctrl);
+
+	data = driver->data;
+	data->phy = devm_phy_create(dev, dev->of_node, &ops);
+	if (IS_ERR(data->phy)) {
+		dev_err(dev, "Failed to create usb drd phy\n");
+		ret = PTR_ERR(data->phy);
+		goto extcon_unregister;
+	}
+
+	data->driver = driver;
+	phy_set_drvdata(data->phy, data);
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		dev_err(dev, "Failed to register as phy provider\n");
+		ret = PTR_ERR(phy_provider);
+		goto extcon_unregister;
+	}
+
+	INIT_DELAYED_WORK(&driver->conn_work, connect_work);
+	platform_set_drvdata(pdev, driver);
+
+	ret = register_extcon_notifier(driver, dev);
+	if (ret < 0) {
+		dev_err(dev, "register extcon notifier failed (%d)\n", ret);
+		goto extcon_unregister;
+	}
+	dev_info(dev, "Registered extcon device\n");
+	queue_delayed_work(system_power_efficient_wq, &driver->wq_extcon,
+			   driver->debounce_jiffies);
+
+	return 0;
+
+extcon_unregister:
+	devm_extcon_dev_unregister(dev, driver->edev);
+extcon_free:
+	devm_extcon_dev_free(dev, driver->edev);
+	return ret;
+}
+
+MODULE_DEVICE_TABLE(of, ns2_drd_phy_dt_ids);
+
+static struct platform_driver ns2_drd_phy_driver = {
+	.probe = ns2_drd_phy_probe,
+	.remove = ns2_drd_phy_remove,
+	.driver = {
+		.name = "bcm-ns2-usbphy",
+		.of_match_table = of_match_ptr(ns2_drd_phy_dt_ids),
+	},
+};
+module_platform_driver(ns2_drd_phy_driver);
+
+MODULE_ALIAS("platform:bcm-ns2-drd-phy");
+MODULE_AUTHOR("Broadcom");
+MODULE_DESCRIPTION("Broadcom NS2 USB2 PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
2.1.0

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox