Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 4/8] drm/sun4i: crtc: Add a custom crtc atomic_check
From: Maxime Ripard @ 2017-12-13 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.63722fe4aeb908cf3c6f73874bdf69b193fe43c9.1513178989.git-series.maxime.ripard@free-electrons.com>

We have some restrictions on what the planes and CRTC can provide that are
tied to only one generation of display engines.

For example, on the first generation, we can only have one YUV plane or one
plane that uses the frontend output.

Let's allow our engines to provide an atomic_check callback to validate the
current configuration.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_crtc.c   | 14 ++++++++++++++
 drivers/gpu/drm/sun4i/sunxi_engine.h |  2 ++
 2 files changed, 16 insertions(+)

diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c
index 5decae0069d0..2a565325714f 100644
--- a/drivers/gpu/drm/sun4i/sun4i_crtc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c
@@ -46,6 +46,19 @@ static struct drm_encoder *sun4i_crtc_get_encoder(struct drm_crtc *crtc)
 	return NULL;
 }
 
+static int sun4i_crtc_atomic_check(struct drm_crtc *crtc,
+				    struct drm_crtc_state *state)
+{
+	struct sun4i_crtc *scrtc = drm_crtc_to_sun4i_crtc(crtc);
+	struct sunxi_engine *engine = scrtc->engine;
+	int ret = 0;
+
+	if (engine && engine->ops && engine->ops->atomic_check)
+		ret = engine->ops->atomic_check(engine, state);
+
+	return ret;
+}
+
 static void sun4i_crtc_atomic_begin(struct drm_crtc *crtc,
 				    struct drm_crtc_state *old_state)
 {
@@ -125,6 +138,7 @@ static void sun4i_crtc_mode_set_nofb(struct drm_crtc *crtc)
 }
 
 static const struct drm_crtc_helper_funcs sun4i_crtc_helper_funcs = {
+	.atomic_check	= sun4i_crtc_atomic_check,
 	.atomic_begin	= sun4i_crtc_atomic_begin,
 	.atomic_flush	= sun4i_crtc_atomic_flush,
 	.atomic_enable	= sun4i_crtc_atomic_enable,
diff --git a/drivers/gpu/drm/sun4i/sunxi_engine.h b/drivers/gpu/drm/sun4i/sunxi_engine.h
index 4cb70ae65c79..42655230aeba 100644
--- a/drivers/gpu/drm/sun4i/sunxi_engine.h
+++ b/drivers/gpu/drm/sun4i/sunxi_engine.h
@@ -16,6 +16,8 @@ struct drm_device;
 struct sunxi_engine;
 
 struct sunxi_engine_ops {
+	int (*atomic_check)(struct sunxi_engine *engine,
+			    struct drm_crtc_state *state);
 	void (*commit)(struct sunxi_engine *engine);
 	struct drm_plane **(*layers_init)(struct drm_device *drm,
 					  struct sunxi_engine *engine);
-- 
git-series 0.9.1

^ permalink raw reply related

* [PATCH 3/8] drm/sun4i: sun4i_layer: Add a custom plane state
From: Maxime Ripard @ 2017-12-13 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.63722fe4aeb908cf3c6f73874bdf69b193fe43c9.1513178989.git-series.maxime.ripard@free-electrons.com>

We will need to store some additional data in the future to the state.
Create a custom plane state that will embed those data, in order to store
the pipe or whether or not that plane should use the frontend.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_layer.c | 48 ++++++++++++++++++++++++++++--
 drivers/gpu/drm/sun4i/sun4i_layer.h | 10 ++++++-
 2 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c
index 7bddf12548d3..c3afcf888906 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.c
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.c
@@ -25,6 +25,48 @@ struct sun4i_plane_desc {
 	       uint32_t                nformats;
 };
 
+static void sun4i_backend_layer_reset(struct drm_plane *plane)
+{
+	struct sun4i_layer_state *state;
+
+	if (plane->state) {
+		state = state_to_sun4i_layer_state(plane->state);
+
+		__drm_atomic_helper_plane_destroy_state(&state->state);
+		kfree(state);
+		plane->state = NULL;
+	}
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (state) {
+		plane->state = &state->state;
+		plane->state->plane = plane;
+	}
+}
+
+static struct drm_plane_state *
+sun4i_backend_layer_duplicate_state(struct drm_plane *plane)
+{
+	struct sun4i_layer_state *copy;
+
+	copy = kzalloc(sizeof(*copy), GFP_KERNEL);
+	if (!copy)
+		return NULL;
+
+	__drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
+
+	return &copy->state;
+}
+
+static void sun4i_backend_layer_destroy_state(struct drm_plane *plane,
+					      struct drm_plane_state *state)
+{
+	struct sun4i_layer_state *s_state = state_to_sun4i_layer_state(state);
+
+	__drm_atomic_helper_plane_destroy_state(state);
+	kfree(s_state);
+}
+
 static void sun4i_backend_layer_atomic_disable(struct drm_plane *plane,
 					       struct drm_plane_state *old_state)
 {
@@ -52,11 +94,11 @@ static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = {
 };
 
 static const struct drm_plane_funcs sun4i_backend_layer_funcs = {
-	.atomic_destroy_state	= drm_atomic_helper_plane_destroy_state,
-	.atomic_duplicate_state	= drm_atomic_helper_plane_duplicate_state,
+	.atomic_destroy_state	= sun4i_backend_layer_destroy_state,
+	.atomic_duplicate_state	= sun4i_backend_layer_duplicate_state,
 	.destroy		= drm_plane_cleanup,
 	.disable_plane		= drm_atomic_helper_disable_plane,
-	.reset			= drm_atomic_helper_plane_reset,
+	.reset			= sun4i_backend_layer_reset,
 	.update_plane		= drm_atomic_helper_update_plane,
 };
 
diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.h b/drivers/gpu/drm/sun4i/sun4i_layer.h
index 4e84f438b346..d2c19348d1b0 100644
--- a/drivers/gpu/drm/sun4i/sun4i_layer.h
+++ b/drivers/gpu/drm/sun4i/sun4i_layer.h
@@ -22,12 +22,22 @@ struct sun4i_layer {
 	int			id;
 };
 
+struct sun4i_layer_state {
+	struct drm_plane_state	state;
+};
+
 static inline struct sun4i_layer *
 plane_to_sun4i_layer(struct drm_plane *plane)
 {
 	return container_of(plane, struct sun4i_layer, plane);
 }
 
+static inline struct sun4i_layer_state *
+state_to_sun4i_layer_state(struct drm_plane_state *state)
+{
+	return container_of(state, struct sun4i_layer_state, state);
+}
+
 struct drm_plane **sun4i_layers_init(struct drm_device *drm,
 				     struct sunxi_engine *engine);
 
-- 
git-series 0.9.1

^ permalink raw reply related

* [PATCH 2/8] drm/sun4i: backend: Allow a NULL plane pointer to retrieve the format
From: Maxime Ripard @ 2017-12-13 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.63722fe4aeb908cf3c6f73874bdf69b193fe43c9.1513178989.git-series.maxime.ripard@free-electrons.com>

The function converting the DRM format to its equivalent in the backend
registers was assuming that we were having a plane.

However, we might want to use that function when setting up a plane using
the frontend, in which case we will not have a plane associated to the
backend's layer. Yet, we still need to setup the format to the one output
by the frontend.

Test for NULL plane pointers before referencing them, so that we can work
around it.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index c99d1a7e815a..f971d3fb5ee4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -93,7 +93,7 @@ void sun4i_backend_layer_enable(struct sun4i_backend *backend,
 static int sun4i_backend_drm_format_to_layer(struct drm_plane *plane,
 					     u32 format, u32 *mode)
 {
-	if ((plane->type == DRM_PLANE_TYPE_PRIMARY) &&
+	if (plane && (plane->type == DRM_PLANE_TYPE_PRIMARY) &&
 	    (format == DRM_FORMAT_ARGB8888))
 		format = DRM_FORMAT_XRGB8888;
 
-- 
git-series 0.9.1

^ permalink raw reply related

* [PATCH 1/8] drm/sun4i: backend: Move line stride setup to buffer setup function
From: Maxime Ripard @ 2017-12-13 15:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <cover.63722fe4aeb908cf3c6f73874bdf69b193fe43c9.1513178989.git-series.maxime.ripard@free-electrons.com>

Setup the line stride in the buffer setup function, since it's tied to the
buffer itself, and is not needed when we do not set the buffer in the
backend.

This is for example the case when using the frontend and then routing its
output to the backend.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 drivers/gpu/drm/sun4i/sun4i_backend.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index 847eecbe4d14..c99d1a7e815a 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -141,7 +141,6 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
 				     int layer, struct drm_plane *plane)
 {
 	struct drm_plane_state *state = plane->state;
-	struct drm_framebuffer *fb = state->fb;
 
 	DRM_DEBUG_DRIVER("Updating layer %d\n", layer);
 
@@ -153,12 +152,6 @@ int sun4i_backend_update_layer_coord(struct sun4i_backend *backend,
 						   state->crtc_h));
 	}
 
-	/* Set the line width */
-	DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
-	regmap_write(backend->engine.regs,
-		     SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
-		     fb->pitches[0] * 8);
-
 	/* Set height and width */
 	DRM_DEBUG_DRIVER("Layer size W: %u H: %u\n",
 			 state->crtc_w, state->crtc_h);
@@ -218,6 +211,13 @@ int sun4i_backend_update_layer_buffer(struct sun4i_backend *backend,
 	u32 lo_paddr, hi_paddr;
 	dma_addr_t paddr;
 
+	/* Set the line width */
+	DRM_DEBUG_DRIVER("Layer line width: %d bits\n", fb->pitches[0] * 8);
+	regmap_write(backend->engine.regs,
+		     SUN4I_BACKEND_LAYLINEWIDTH_REG(layer),
+		     fb->pitches[0] * 8);
+
+
 	/* Get the start of the displayed memory */
 	paddr = drm_fb_cma_get_gem_addr(fb, state, 0);
 	DRM_DEBUG_DRIVER("Setting buffer address to %pad\n", &paddr);
-- 
git-series 0.9.1

^ permalink raw reply related

* [PATCH 0/8] drm/sun4i: Support the Display Engine frontend
From: Maxime Ripard @ 2017-12-13 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

This is a first serie to enable the display engine frontend.

This hardware block is found in the first generation Display Engine from
Allwinner. Its role is to implement more advanced features that the
associated backend, even though the backend alone can be used (and was used
so far) for basic composition.

Among those features, we will find hardware scaling, that is supported in
this serie, colorspace conversions, or more exotic formats support such as
the one output by the VPU.

Let me know what you think,
Maxime

Maxime Ripard (8):
  drm/sun4i: backend: Move line stride setup to buffer setup function
  drm/sun4i: backend: Allow a NULL plane pointer to retrieve the format
  drm/sun4i: sun4i_layer: Add a custom plane state
  drm/sun4i: crtc: Add a custom crtc atomic_check
  drm/sun4i: Add a driver for the display frontend
  drm/sun4i: sun4i_layer: Wire in the frontend
  drm/sun4i: sun4i_layer: Add a custom atomic_check for the frontend
  ARM: dts: sun8i: a33 Enable our display frontend

 arch/arm/boot/dts/sun8i-a33.dtsi       |   1 +-
 drivers/gpu/drm/sun4i/Makefile         |   3 +-
 drivers/gpu/drm/sun4i/sun4i_backend.c  | 139 +++++++++-
 drivers/gpu/drm/sun4i/sun4i_backend.h  |   6 +-
 drivers/gpu/drm/sun4i/sun4i_crtc.c     |  14 +-
 drivers/gpu/drm/sun4i/sun4i_drv.c      |  16 +-
 drivers/gpu/drm/sun4i/sun4i_drv.h      |   1 +-
 drivers/gpu/drm/sun4i/sun4i_frontend.c | 377 ++++++++++++++++++++++++++-
 drivers/gpu/drm/sun4i/sun4i_frontend.h | 102 +++++++-
 drivers/gpu/drm/sun4i/sun4i_layer.c    |  75 ++++-
 drivers/gpu/drm/sun4i/sun4i_layer.h    |  11 +-
 drivers/gpu/drm/sun4i/sunxi_engine.h   |   2 +-
 12 files changed, 727 insertions(+), 20 deletions(-)
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_frontend.c
 create mode 100644 drivers/gpu/drm/sun4i/sun4i_frontend.h

base-commit: 4fbd8d194f06c8a3fd2af1ce560ddb31f7ec8323
-- 
git-series 0.9.1

^ permalink raw reply

* [xlnx:2017.3_video_ea 6599/6607] drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c:896:22: warning: ') - ' directive output may be truncated writing 4 bytes into a region of size between 3 and 7
From: kbuild test robot @ 2017-12-13 15:22 UTC (permalink / raw)
  To: linux-arm-kernel

tree:   https://github.com/Xilinx/linux-xlnx 2017.3_video_ea
head:   af045f9682c65a0c26afb2f638603d3c01079222
commit: 15c99dce11944aa6657cade4fb30d978d002e783 [6599/6607] staging: xilinx: hdmirx: Fix hdcp authentication problem on key load
config: blackfin-allmodconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        git checkout 15c99dce11944aa6657cade4fb30d978d002e783
        # save the attached .config to linux build tree
        make.cross ARCH=blackfin 

All warnings (new ones prefixed by >>):

   drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c: In function 'XHdcp1x_RxDebugLog.isra.6':
>> drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c:896:22: warning: ') - ' directive output may be truncated writing 4 bytes into a region of size between 3 and 7 [-Wformat-truncation=]
     snprintf(Label, 16, "hdcp-rx(%d) - ", InstancePtr->Config.DeviceId);
                         ^~~~~~~~~~~~~~~~
   drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c:896:2: note: 'snprintf' output between 14 and 18 bytes into a destination of size 16
     snprintf(Label, 16, "hdcp-rx(%d) - ", InstancePtr->Config.DeviceId);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

vim +896 drivers/staging/xilinx/hdmi/phy-xilinx-vphy/xhdcp1x_rx.c

73634d89 Rohit Consul 2017-10-31  878  
73634d89 Rohit Consul 2017-10-31  879  /*****************************************************************************/
73634d89 Rohit Consul 2017-10-31  880  /**
73634d89 Rohit Consul 2017-10-31  881  * This function logs a debug message on behalf of a handler state machine.
73634d89 Rohit Consul 2017-10-31  882  *
73634d89 Rohit Consul 2017-10-31  883  * @param	InstancePtr is the receiver instance.
73634d89 Rohit Consul 2017-10-31  884  * @param	LogMsg is the message to log.
73634d89 Rohit Consul 2017-10-31  885  *
73634d89 Rohit Consul 2017-10-31  886  * @return	None.
73634d89 Rohit Consul 2017-10-31  887  *
73634d89 Rohit Consul 2017-10-31  888  * @note		None.
73634d89 Rohit Consul 2017-10-31  889  *
73634d89 Rohit Consul 2017-10-31  890  ******************************************************************************/
73634d89 Rohit Consul 2017-10-31  891  static void XHdcp1x_RxDebugLog(const XHdcp1x *InstancePtr, const char *LogMsg)
73634d89 Rohit Consul 2017-10-31  892  {
73634d89 Rohit Consul 2017-10-31  893  	char Label[16];
73634d89 Rohit Consul 2017-10-31  894  
73634d89 Rohit Consul 2017-10-31  895  	/* Format Label */
73634d89 Rohit Consul 2017-10-31 @896  	snprintf(Label, 16, "hdcp-rx(%d) - ", InstancePtr->Config.DeviceId);
73634d89 Rohit Consul 2017-10-31  897  
73634d89 Rohit Consul 2017-10-31  898  	/* Log it */
73634d89 Rohit Consul 2017-10-31  899  	XHDCP1X_DEBUG_LOGMSG(Label);
73634d89 Rohit Consul 2017-10-31  900  	XHDCP1X_DEBUG_LOGMSG(LogMsg);
15c99dce Rohit Consul 2017-11-14  901  	XHDCP1X_DEBUG_LOGMSG("\n");
73634d89 Rohit Consul 2017-10-31  902  }
73634d89 Rohit Consul 2017-10-31  903  

:::::: The code at line 896 was first introduced by commit
:::::: 73634d891211ef92c9d8c789a1ccc002118164ba phy: xilinx-vphy: Initial release of xilinx video phy soft IP driver

:::::: TO: Rohit Consul <rohit.consul@xilinx.com>
:::::: CC: Jeffrey Mouroux <jmouroux@xilinx.com>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 42262 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20171213/1acd4476/attachment-0001.gz>

^ permalink raw reply

* [PATCH 4/4] [v4] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002
From: Timur Tabi @ 2017-12-13 15:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <9c28bebb-5f57-83e8-9885-5262bbdc1b94@codeaurora.org>

On 12/13/2017 08:46 AM, Timur Tabi wrote:
> 
>> Please, read my comment again. The key part of the phrase:
>> "Use members of struct device_driver"
>>
>> So, do not move the IDs. There are examples in the kernel how to access
>> it.
> 
> Sorry, I don't understand what you're talking about.? I don't see how I 
> can call
> 
>  ????const struct acpi_device_id *id =
>  ??????? acpi_match_device(qdf2xxx_acpi_ids, &pdev->dev);
> 
> without having qdf2xxx_acpi_ids already defined previously.? And without 
> the 'id', I can't figure out whether I've probed via QCOM8001 or QCOM8002.

I think I found it.  Are you talking about doing this instead:

id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH] arm64: dts: hisilicon: Add hi3660 cpu capacity-dmips-mhz information
From: Valentin Schneider @ 2017-12-13 15:16 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213145311.GA30463@leoy-ThinkPad-T440>

Hi Leo,


On 12/13/2017 02:53 PM, Leo Yan wrote:
> Hi Valentin,
>
> On Wed, Dec 13, 2017 at 02:21:06PM +0000, Valentin Schneider wrote:
>> The following dt entries are added:
>>   cpus [0-3] (Cortex A53):
>>     - capacity-dmips-mhz = <592>;
>>
>>   cpus [4-7] (Cortex A73):
>>     - capacity-dmips-mhz = <1024>;
>>
>> Those values were obtained by running dhrystone 2.1 on a
>> HiKey960 with the following procedure:
>> - Offline all CPUs but CPU0 (A53)
>> - Set CPU0 frequency to maximum
>> - Run Dhrystone 2.1 for 20 seconds
>>
>> - Offline all CPUs but CPU4 (A73)
>> - set CPU4 frequency to maximum
>> - Run Dhrystone 2.1 for 20 seconds
>>
>> The results are as follows:
>> A53: 129633887 loops
>> A73: 287034147 loops
> Seems to me the capacity-dmips-mhz should be:
>
> CA53: 129633887 / 20 / 1844 = 3515
> CA73: 287034147 / 20 / 2362 = 6076
>
> After normalized to range [0..1024], we could get:
>
> CA53:  592
> CA73: 1024

Yes, that's the "direct approach". I wanted to underline the fact that 
there are two different max frequencies so what I followed would be:

1) Computing the performance ratio:
(129633887 / 287034147) * 1024 = 462.47

2) Scaling that to the same frequency scale:
462.47 * (2362/1844) = 592.38

Which gives the same end result (it's the same equation but split in two 
steps). Also it makes it easy to check that the cpu_capacity sysfs entry 
for the A53s gets correctly set (to 462).

>
> Reviewed-by: Leo Yan <leo.yan@linaro.org>
>
>> By scaling those values so that the A73s use 1024, we end up with 462
>> for the A53s. However, they have different maximum frequencies:
>> 1.844GHz for A53s and 2.362GHz for A73s. Thus, we can scale the A53
>> value to truly represent dmips per MHz, and we end up with 592.
>>
>> The impact of this change can be verified on HiKey960:
>>
>> $ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
>> 1844000
>> 1844000
>> 1844000
>> 1844000
>> 2362000
>> 2362000
>> 2362000
>> 2362000
>>
>> $ cat /sys/devices/system/cpu/cpu*/cpu_capacity
>> 462
>> 462
>> 462
>> 462
>> 1024
>> 1024
>> 1024
>> 1024
>>
>> Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
>> ---
>>   arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 ++++++++
>>   1 file changed, 8 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> index ab0b95b..04a8d28 100644
>> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
>> @@ -61,6 +61,7 @@
>>   			enable-method = "psci";
>>   			next-level-cache = <&A53_L2>;
>>   			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
>> +			capacity-dmips-mhz = <592>;
>>   		};
>>   
>>   		cpu1: cpu at 1 {
>> @@ -70,6 +71,7 @@
>>   			enable-method = "psci";
>>   			next-level-cache = <&A53_L2>;
>>   			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
>> +			capacity-dmips-mhz = <592>;
>>   		};
>>   
>>   		cpu2: cpu at 2 {
>> @@ -79,6 +81,7 @@
>>   			enable-method = "psci";
>>   			next-level-cache = <&A53_L2>;
>>   			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
>> +			capacity-dmips-mhz = <592>;
>>   		};
>>   
>>   		cpu3: cpu at 3 {
>> @@ -88,6 +91,7 @@
>>   			enable-method = "psci";
>>   			next-level-cache = <&A53_L2>;
>>   			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
>> +			capacity-dmips-mhz = <592>;
>>   		};
>>   
>>   		cpu4: cpu at 100 {
>> @@ -101,6 +105,7 @@
>>   					&CPU_SLEEP
>>   					&CLUSTER_SLEEP_1
>>   			>;
>> +			capacity-dmips-mhz = <1024>;
>>   		};
>>   
>>   		cpu5: cpu at 101 {
>> @@ -114,6 +119,7 @@
>>   					&CPU_SLEEP
>>   					&CLUSTER_SLEEP_1
>>   			>;
>> +			capacity-dmips-mhz = <1024>;
>>   		};
>>   
>>   		cpu6: cpu at 102 {
>> @@ -127,6 +133,7 @@
>>   					&CPU_SLEEP
>>   					&CLUSTER_SLEEP_1
>>   			>;
>> +			capacity-dmips-mhz = <1024>;
>>   		};
>>   
>>   		cpu7: cpu at 103 {
>> @@ -140,6 +147,7 @@
>>   					&CPU_SLEEP
>>   					&CLUSTER_SLEEP_1
>>   			>;
>> +			capacity-dmips-mhz = <1024>;
>>   		};
>>   
>>   		idle-states {
>> --
>> 2.7.4
>>

^ permalink raw reply

* [PATCH] arm64: dts: hisilicon: Add hi3660 cpu capacity-dmips-mhz information
From: Leo Yan @ 2017-12-13 14:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513174866-6678-1-git-send-email-valentin.schneider@arm.com>

Hi Valentin,

On Wed, Dec 13, 2017 at 02:21:06PM +0000, Valentin Schneider wrote:
> The following dt entries are added:
>  cpus [0-3] (Cortex A53):
>    - capacity-dmips-mhz = <592>;
> 
>  cpus [4-7] (Cortex A73):
>    - capacity-dmips-mhz = <1024>;
> 
> Those values were obtained by running dhrystone 2.1 on a
> HiKey960 with the following procedure:
> - Offline all CPUs but CPU0 (A53)
> - Set CPU0 frequency to maximum
> - Run Dhrystone 2.1 for 20 seconds
> 
> - Offline all CPUs but CPU4 (A73)
> - set CPU4 frequency to maximum
> - Run Dhrystone 2.1 for 20 seconds
> 
> The results are as follows:
> A53: 129633887 loops
> A73: 287034147 loops

Seems to me the capacity-dmips-mhz should be:

CA53: 129633887 / 20 / 1844 = 3515
CA73: 287034147 / 20 / 2362 = 6076

After normalized to range [0..1024], we could get:

CA53:  592
CA73: 1024

Reviewed-by: Leo Yan <leo.yan@linaro.org>

> By scaling those values so that the A73s use 1024, we end up with 462
> for the A53s. However, they have different maximum frequencies:
> 1.844GHz for A53s and 2.362GHz for A73s. Thus, we can scale the A53
> value to truly represent dmips per MHz, and we end up with 592.
> 
> The impact of this change can be verified on HiKey960:
> 
> $ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
> 1844000
> 1844000
> 1844000
> 1844000
> 2362000
> 2362000
> 2362000
> 2362000
> 
> $ cat /sys/devices/system/cpu/cpu*/cpu_capacity
> 462
> 462
> 462
> 462
> 1024
> 1024
> 1024
> 1024
> 
> Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
> ---
>  arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 ++++++++
>  1 file changed, 8 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> index ab0b95b..04a8d28 100644
> --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
> @@ -61,6 +61,7 @@
>  			enable-method = "psci";
>  			next-level-cache = <&A53_L2>;
>  			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
> +			capacity-dmips-mhz = <592>;
>  		};
>  
>  		cpu1: cpu at 1 {
> @@ -70,6 +71,7 @@
>  			enable-method = "psci";
>  			next-level-cache = <&A53_L2>;
>  			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
> +			capacity-dmips-mhz = <592>;
>  		};
>  
>  		cpu2: cpu at 2 {
> @@ -79,6 +81,7 @@
>  			enable-method = "psci";
>  			next-level-cache = <&A53_L2>;
>  			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
> +			capacity-dmips-mhz = <592>;
>  		};
>  
>  		cpu3: cpu at 3 {
> @@ -88,6 +91,7 @@
>  			enable-method = "psci";
>  			next-level-cache = <&A53_L2>;
>  			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
> +			capacity-dmips-mhz = <592>;
>  		};
>  
>  		cpu4: cpu at 100 {
> @@ -101,6 +105,7 @@
>  					&CPU_SLEEP
>  					&CLUSTER_SLEEP_1
>  			>;
> +			capacity-dmips-mhz = <1024>;
>  		};
>  
>  		cpu5: cpu at 101 {
> @@ -114,6 +119,7 @@
>  					&CPU_SLEEP
>  					&CLUSTER_SLEEP_1
>  			>;
> +			capacity-dmips-mhz = <1024>;
>  		};
>  
>  		cpu6: cpu at 102 {
> @@ -127,6 +133,7 @@
>  					&CPU_SLEEP
>  					&CLUSTER_SLEEP_1
>  			>;
> +			capacity-dmips-mhz = <1024>;
>  		};
>  
>  		cpu7: cpu at 103 {
> @@ -140,6 +147,7 @@
>  					&CPU_SLEEP
>  					&CLUSTER_SLEEP_1
>  			>;
> +			capacity-dmips-mhz = <1024>;
>  		};
>  
>  		idle-states {
> --
> 2.7.4
> 

^ permalink raw reply

* [PATCH 4/4] [v4] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002
From: Timur Tabi @ 2017-12-13 14:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513175798.7000.15.camel@linux.intel.com>

On 12/13/2017 08:36 AM, Andy Shevchenko wrote:
> Wait, runtime muxing is a matter of requesting another function (usually
> GPIO) and putting it back afterwards. Do you really need anything like
> this at*runtime*?

No, there is no runtime muxing on ACPI platforms.

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH v4 4/4] ARM: pinctrl: sunxi-pinctrl: fix pin funtion can not be match correctly.
From: hao_zhang @ 2017-12-13 14:47 UTC (permalink / raw)
  To: linux-arm-kernel

Pin function can not be match correctly when SUNXI_PIN describe with
mutiple variant and same function.

such as:
on pinctrl-sun4i-a10.c

SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2),
		SUNXI_FUNCTION(0x0, "gpio_in"),
		SUNXI_FUNCTION(0x1, "gpio_out"),
		SUNXI_FUNCTION_VARIANT(0x2, "pwm",    /* PWM0 */
			PINCTRL_SUN4I_A10 |
			PINCTRL_SUN7I_A20),
		SUNXI_FUNCTION_VARIANT(0x3, "pwm",    /* PWM0 */
			PINCTRL_SUN8I_R40)),

it would always match to the first variant function
(PINCTRL_SUN4I_A10, PINCTRL_SUN7I_A20)

so we should add variant compare on it.

Signed-off-by: hao_zhang <hao5781286@gmail.com>
---
 drivers/pinctrl/sunxi/pinctrl-sunxi.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index 4b6cb25..f23e74e 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -83,9 +83,11 @@ sunxi_pinctrl_desc_find_function_by_name(struct sunxi_pinctrl *pctl,
 			struct sunxi_desc_function *func = pin->functions;
 
 			while (func->name) {
-				if (!strcmp(func->name, func_name))
+				if (!strcmp(func->name, func_name)) {
+					if (!(func->variant) ||
+					   (func->variant & pctl->variant))
 					return func;
-
+				}
 				func++;
 			}
 		}
-- 
2.7.4

^ permalink raw reply related

* [PATCH 4/4] [v4] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002
From: Timur Tabi @ 2017-12-13 14:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513175535.7000.10.camel@linux.intel.com>

On 12/13/2017 08:32 AM, Andy Shevchenko wrote:
> Please, read my comment again. The key part of the phrase:
> "Use members of struct device_driver"
> 
> So, do not move the IDs. There are examples in the kernel how to access
> it.

Sorry, I don't understand what you're talking about.  I don't see how I 
can call

	const struct acpi_device_id *id =
		acpi_match_device(qdf2xxx_acpi_ids, &pdev->dev);

without having qdf2xxx_acpi_ids already defined previously.  And without 
the 'id', I can't figure out whether I've probed via QCOM8001 or QCOM8002.

-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc.  Qualcomm Technologies, Inc. is a member of the
Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH v4 3/4] ARM: dts: add pwm node for r40.
From: hao_zhang @ 2017-12-13 14:46 UTC (permalink / raw)
  To: linux-arm-kernel

This patch add pwm node for r40.

Signed-off-by: hao_zhang <hao5781286@gmail.com>
---
 arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts |  6 ++++++
 arch/arm/boot/dts/sun8i-r40.dtsi                  | 13 +++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
index 8c5efe2..6cf6273 100644
--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -196,6 +196,12 @@
 	status = "okay";
 };
 
+&pwm {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pwm_pins>;
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pb_pins>;
diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi
index 173dcc1..6628b17 100644
--- a/arch/arm/boot/dts/sun8i-r40.dtsi
+++ b/arch/arm/boot/dts/sun8i-r40.dtsi
@@ -295,6 +295,11 @@
 				bias-pull-up;
 			};
 
+			pwm_pins: pwm0-pin {
+				pins = "PB2", "PB3";
+				function = "pwm";
+			};
+
 			uart0_pb_pins: uart0-pb-pins {
 				pins = "PB22", "PB23";
 				function = "uart0";
@@ -306,6 +311,14 @@
 			reg = <0x01c20c90 0x10>;
 		};
 
+		pwm: pwm at 1c23400 {
+			     compatible = "allwinner,sun8i-r40-pwm";
+			     reg = <0x01c23400 0x154>;
+			     clocks = <&osc24M>;
+			     #pwm-cells = <3>;
+			     status = "disabled";
+		};
+
 		uart0: serial at 1c28000 {
 			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 2/4] ARM: PWM: add allwinner sun8i R40/V40/T3 pwm support.
From: hao_zhang @ 2017-12-13 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

This patch add allwinner sun8i R40/V40/T3 pwm support.

Signed-off-by: hao_zhang <hao5781286@gmail.com>
---
 drivers/pwm/Kconfig         |  10 +
 drivers/pwm/Makefile        |   1 +
 drivers/pwm/pwm-sun8i-r40.c | 449 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 460 insertions(+)
 create mode 100644 drivers/pwm/pwm-sun8i-r40.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 763ee50..cde5a70 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -444,6 +444,16 @@ config PWM_SUN4I
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-sun4i.
 
+config PWM_SUN8I_R40
+	tristate "Allwinner PWM SUN8I R40 support"
+	depends on ARCH_SUNXI || COMPILE_TEST
+	depends on HAS_IOMEM && COMMON_CLK
+	help
+	  Generic PWM framework driver for Allwinner SoCs R40, V40, T3.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-sun8i-r40.
+
 config PWM_TEGRA
 	tristate "NVIDIA Tegra PWM support"
 	depends on ARCH_TEGRA
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 0258a74..026a55b 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_PWM_STM32)		+= pwm-stm32.o
 obj-$(CONFIG_PWM_STM32_LP)	+= pwm-stm32-lp.o
 obj-$(CONFIG_PWM_STMPE)		+= pwm-stmpe.o
 obj-$(CONFIG_PWM_SUN4I)		+= pwm-sun4i.o
+obj-$(CONFIG_PWM_SUN8I_R40)	+= pwm-sun8i-r40.o
 obj-$(CONFIG_PWM_TEGRA)		+= pwm-tegra.o
 obj-$(CONFIG_PWM_TIECAP)	+= pwm-tiecap.o
 obj-$(CONFIG_PWM_TIEHRPWM)	+= pwm-tiehrpwm.o
diff --git a/drivers/pwm/pwm-sun8i-r40.c b/drivers/pwm/pwm-sun8i-r40.c
new file mode 100644
index 0000000..8df538d
--- /dev/null
+++ b/drivers/pwm/pwm-sun8i-r40.c
@@ -0,0 +1,449 @@
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+
+#define PWM_IRQ_ENABLE_REG	0x0000
+#define PCIE(ch)	BIT(ch)
+
+#define PWM_IRQ_STATUS_REG	0x0004
+#define PIS(ch)	BIT(ch)
+
+#define CAPTURE_IRQ_ENABLE_REG	0x0010
+#define CFIE(ch)	BIT(ch << 1 + 1)
+#define CRIE(ch)	BIT(ch << 1)
+
+#define CAPTURE_IRQ_STATUS_REG	0x0014
+#define CFIS(ch)	BIT(ch << 1 + 1)
+#define CRIS(ch)	BIT(ch << 1)
+
+#define CLK_CFG_REG(ch)	(0x0020 + (ch >> 1) * 4)
+#define CLK_SRC	BIT(7)
+#define CLK_SRC_BYPASS_SEC	BIT(6)
+#define CLK_SRC_BYPASS_FIR	BIT(5)
+#define CLK_GATING	BIT(4)
+#define CLK_DIV_M	GENMASK(3, 0)
+
+#define PWM_DZ_CTR_REG(ch)	(0x0030 + (ch >> 1) * 4)
+#define PWM_DZ_INTV	GENMASK(15, 8)
+#define PWM_DZ_EN	BIT(0)
+
+#define PWM_ENABLE_REG	0x0040
+#define PWM_EN(ch)	BIT(ch)
+
+#define CAPTURE_ENABLE_REG	0x0044
+#define CAP_EN(ch)	BIT(ch)
+
+#define PWM_CTR_REG(ch)	(0x0060 + ch * 0x20)
+#define PWM_PERIOD_RDY	BIT(11)
+#define PWM_PUL_START	BIT(10)
+#define PWM_MODE	BIT(9)
+#define PWM_ACT_STA	BIT(8)
+#define PWM_PRESCAL_K	GENMASK(7, 0)
+
+#define PWM_PERIOD_REG(ch)	(0x0064 + ch * 0x20)
+#define PWM_ENTIRE_CYCLE	GENMASK(31, 16)
+#define PWM_ACT_CYCLE	GENMASK(15, 0)
+
+#define PWM_CNT_REG(ch)	(0x0068 + ch * 0x20)
+#define PWM_CNT_VAL	GENMASK(15, 0)
+
+#define CAPTURE_CTR_REG(ch)	(0x006c + ch * 0x20)
+#define CAPTURE_CRLF	BIT(2)
+#define CAPTURE_CFLF	BIT(1)
+#define CAPINV	BIT(0)
+
+#define CAPTURE_RISE_REG(ch)	(0x0070 + ch * 0x20)
+#define CAPTURE_CRLR	GENMASK(15, 0)
+
+#define CAPTURE_FALL_REG(ch)	(0x0074 + ch * 0x20)
+#define CAPTURE_CFLR	GENMASK(15, 0)
+
+struct sunxi_pwm_data {
+	bool has_prescaler_bypass;
+	bool has_rdy;
+	unsigned int npwm;
+};
+
+struct sunxi_pwm_chip {
+	struct pwm_chip chip;
+	struct clk *clk;
+	void __iomem *base;
+	spinlock_t ctrl_lock;
+	const struct sunxi_pwm_data *data;
+};
+
+static const u16 div_m_table[] = {
+	1,
+	2,
+	4,
+	8,
+	16,
+	32,
+	64,
+	128,
+	256
+};
+
+static inline struct sunxi_pwm_chip *to_sunxi_pwm_chip(struct pwm_chip *chip)
+{
+	return container_of(chip, struct sunxi_pwm_chip, chip);
+}
+
+static inline u32 sunxi_pwm_readl(struct sunxi_pwm_chip *chip,
+		unsigned long offset)
+{
+	return readl(chip->base + offset);
+}
+
+static inline void sunxi_pwm_writel(struct sunxi_pwm_chip *chip,
+		u32 val, unsigned long offset)
+{
+	writel(val, chip->base + offset);
+}
+
+static void sunxi_pwm_set_bit(struct sunxi_pwm_chip *sunxi_pwm,
+		unsigned long reg, u32 bit)
+{
+	u32 val;
+
+	val = sunxi_pwm_readl(sunxi_pwm, reg);
+	val |= bit;
+	sunxi_pwm_writel(sunxi_pwm, val, reg);
+}
+
+static void sunxi_pwm_clear_bit(struct sunxi_pwm_chip *sunxi_pwm,
+		unsigned long reg, u32 bit)
+{
+	u32 val;
+
+	val = sunxi_pwm_readl(sunxi_pwm, reg);
+	val &= ~bit;
+	sunxi_pwm_writel(sunxi_pwm, val, reg);
+}
+
+static void sunxi_pwm_set_value(struct sunxi_pwm_chip *sunxi_pwm,
+		unsigned long reg, u32 mask, u32 val)
+{
+	u32 tmp;
+
+	tmp = sunxi_pwm_readl(sunxi_pwm, reg);
+	tmp &= ~mask;
+	tmp |= mask & val;
+	sunxi_pwm_writel(sunxi_pwm, tmp, reg);
+}
+
+static void sunxi_pwm_set_polarity(struct sunxi_pwm_chip *chip, u32 ch,
+		enum pwm_polarity polarity)
+{
+	if (polarity == PWM_POLARITY_NORMAL)
+		sunxi_pwm_set_bit(chip, PWM_CTR_REG(ch), PWM_ACT_STA);
+	else
+		sunxi_pwm_clear_bit(chip, PWM_CTR_REG(ch), PWM_ACT_STA);
+}
+
+static void sunxi_dump_reg(struct sunxi_pwm_chip *sunxi_pwm, u8 ch)
+{
+	dev_dbg(sunxi_pwm->chip.dev, "ch: %d\n"
+			"\tPWM_IRQ_ENABLE_REG(%04x): \t0x%08x\n"
+			"\tPWM_IRQ_STATUS_REG(%04x): \t0x%08x\n"
+			"\tCAPTURE_IRQ_ENABLE_REG(%04x): \t0x%08x\n"
+			"\tCAPTURE_IRQ_STATUS_REG(%04x): \t0x%08x\n"
+			"\tCLK_CFG_REG(%04x)(%d): \t0x%08x\n"
+			"\tPWM_DZ_CTR_REG(%04x)(%d): \t0x%08x\n"
+			"\tPWM_ENABLE_REG(%04x): \t0x%08x\n"
+			"\tCAPTURE_ENABLE_REG(%04x): \t0x%08x\n"
+			"\tPWM_CTR_REG(%04x)(%d): \t0x%08x\n"
+			"\tPWM_PERIOD_REG(%04x)(%d): \t0x%08x\n"
+			"\tPWM_CNT_REG(%04x)(%d): \t0x%08x\n"
+			"\tCAPTURE_CTR_REG(%04x)(%d): \t0x%08x\n"
+			"\tCAPTURE_RISE_REG(%04x)(%d): \t0x%08x\n"
+			"\tCAPTURE_FALL_REG(%04x)(%d): \t0x%08x\n",
+			ch,
+			PWM_IRQ_ENABLE_REG,
+			readl(sunxi_pwm->base + PWM_IRQ_ENABLE_REG),
+			PWM_IRQ_STATUS_REG,
+			readl(sunxi_pwm->base + PWM_IRQ_STATUS_REG),
+			CAPTURE_IRQ_ENABLE_REG,
+			readl(sunxi_pwm->base + CAPTURE_IRQ_ENABLE_REG),
+			CAPTURE_IRQ_STATUS_REG,
+			readl(sunxi_pwm->base + CAPTURE_IRQ_STATUS_REG),
+			CLK_CFG_REG(ch),
+			ch, readl(sunxi_pwm->base + CLK_CFG_REG(ch)),
+			PWM_DZ_CTR_REG(ch),
+			ch, readl(sunxi_pwm->base + PWM_DZ_CTR_REG(ch)),
+			PWM_ENABLE_REG,
+			readl(sunxi_pwm->base + PWM_ENABLE_REG),
+			CAPTURE_ENABLE_REG,
+			readl(sunxi_pwm->base + CAPTURE_ENABLE_REG),
+			PWM_CTR_REG(ch),
+			ch, readl(sunxi_pwm->base + PWM_CTR_REG(ch)),
+			PWM_PERIOD_REG(ch),
+			ch, readl(sunxi_pwm->base + PWM_PERIOD_REG(ch)),
+			PWM_CNT_REG(ch),
+			ch, readl(sunxi_pwm->base + PWM_CNT_REG(ch)),
+			CAPTURE_CTR_REG(ch),
+			ch, readl(sunxi_pwm->base + CAPTURE_CTR_REG(ch)),
+			CAPTURE_RISE_REG(ch),
+			ch, readl(sunxi_pwm->base + CAPTURE_RISE_REG(ch)),
+			CAPTURE_FALL_REG(ch),
+			ch, readl(sunxi_pwm->base + CAPTURE_FALL_REG(ch)));
+}
+
+static int sunxi_pwm_config(struct sunxi_pwm_chip *sunxi_pwm, u8 ch,
+		struct pwm_state *state)
+{
+	u64 clk_rate, clk_div, val;
+	u16 prescaler = 0;
+	u8 id = 0;
+
+	clk_rate = clk_get_rate(sunxi_pwm->clk);
+	dev_dbg(sunxi_pwm->chip.dev, "clock rate:%lld\n", clk_rate);
+
+	if (clk_rate == 24000000)
+		sunxi_pwm_clear_bit(sunxi_pwm, CLK_CFG_REG(ch), CLK_SRC);
+	else
+		sunxi_pwm_set_bit(sunxi_pwm, CLK_CFG_REG(ch), CLK_SRC);
+
+	if (sunxi_pwm->data->has_prescaler_bypass) {
+		/* pwm output bypass */
+		if (ch % 2)
+			sunxi_pwm_set_bit(sunxi_pwm, CLK_CFG_REG(ch),
+					CLK_SRC_BYPASS_FIR);
+		else
+			sunxi_pwm_set_bit(sunxi_pwm, CLK_CFG_REG(ch),
+					CLK_SRC_BYPASS_SEC);
+		return 0;
+	}
+
+	val = state->period * clk_rate;
+	do_div(val, NSEC_PER_SEC);
+	if (val < 1) {
+		dev_err(sunxi_pwm->chip.dev,
+				"period expects a larger value\n");
+		return -EINVAL;
+	}
+
+	/* calculate and set prescalar, div table, pwn entrie cycle */
+	clk_div = val;
+
+	while (clk_div > 65535) {
+		prescaler++;
+		clk_div = val;
+		do_div(clk_div, prescaler + 1);
+		do_div(clk_div, div_m_table[id]);
+
+		if (prescaler == 255) {
+			prescaler = 0;
+			id++;
+			if (id == 9)
+				return -EINVAL;
+		}
+	}
+
+	sunxi_pwm_set_value(sunxi_pwm, PWM_PERIOD_REG(ch),
+			PWM_ENTIRE_CYCLE, clk_div << 16);
+	sunxi_pwm_set_value(sunxi_pwm, PWM_CTR_REG(ch),
+			PWM_PRESCAL_K, prescaler << 0);
+	sunxi_pwm_set_value(sunxi_pwm, CLK_CFG_REG(ch),
+			CLK_DIV_M, id << 0);
+
+	/* set duty cycle */
+	val = (prescaler + 1) * div_m_table[id] * clk_div;
+	val = state->period;
+	do_div(val, clk_div);
+	clk_div = state->duty_cycle;
+	do_div(clk_div, val);
+
+	sunxi_pwm_set_value(sunxi_pwm, PWM_PERIOD_REG(ch),
+			PWM_ACT_CYCLE, clk_div << 0);
+
+	return 0;
+}
+
+static int sunxi_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+		struct pwm_state *state)
+{
+	int ret;
+	struct sunxi_pwm_chip *sunxi_pwm = to_sunxi_pwm_chip(chip);
+	struct pwm_state cstate;
+
+	sunxi_dump_reg(sunxi_pwm, pwm->hwpwm);
+	pwm_get_state(pwm, &cstate);
+	if (!cstate.enabled) {
+		ret = clk_prepare_enable(sunxi_pwm->clk);
+		if (ret) {
+			dev_err(chip->dev, "failed to enable PWM clock\n");
+			return ret;
+		}
+	}
+
+	spin_lock(&sunxi_pwm->ctrl_lock);
+
+	if (state->polarity != cstate.polarity)
+		sunxi_pwm_set_polarity(sunxi_pwm, pwm->hwpwm, state->polarity);
+
+	if ((cstate.period != state->period) ||
+			(cstate.duty_cycle != state->duty_cycle)) {
+		ret = sunxi_pwm_config(sunxi_pwm, pwm->hwpwm, state);
+		if (ret) {
+			dev_err(chip->dev, "failed to enable PWM clock\n");
+			return ret;
+		}
+	}
+
+	if (state->enabled) {
+		sunxi_pwm_set_bit(sunxi_pwm,
+				CLK_CFG_REG(pwm->hwpwm), CLK_GATING);
+
+		sunxi_pwm_set_bit(sunxi_pwm,
+				PWM_ENABLE_REG, PWM_EN(pwm->hwpwm));
+	} else {
+		sunxi_pwm_clear_bit(sunxi_pwm,
+				CLK_CFG_REG(pwm->hwpwm), CLK_GATING);
+
+		sunxi_pwm_clear_bit(sunxi_pwm,
+				PWM_ENABLE_REG, PWM_EN(pwm->hwpwm));
+	}
+
+	spin_unlock(&sunxi_pwm->ctrl_lock);
+	sunxi_dump_reg(sunxi_pwm, pwm->hwpwm);
+
+	return 0;
+}
+
+static void sunxi_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+		struct pwm_state *state)
+{
+	struct sunxi_pwm_chip *sunxi_pwm = to_sunxi_pwm_chip(chip);
+	u64 clk_rate, tmp;
+	u32 val;
+	u16 clk_div, act_cycle;
+	u8 prescal, id;
+
+	clk_rate = clk_get_rate(sunxi_pwm->clk);
+
+	val = sunxi_pwm_readl(sunxi_pwm, PWM_CTR_REG(pwm->hwpwm));
+	if (PWM_ACT_STA & val)
+		state->polarity = PWM_POLARITY_NORMAL;
+	else
+		state->polarity = PWM_POLARITY_INVERSED;
+
+	prescal = PWM_PRESCAL_K & val;
+
+	val = sunxi_pwm_readl(sunxi_pwm, PWM_ENABLE_REG);
+	if (PWM_EN(pwm->hwpwm) & val)
+		state->enabled = true;
+	else
+		state->enabled = false;
+
+	val = sunxi_pwm_readl(sunxi_pwm, PWM_PERIOD_REG(pwm->hwpwm));
+	act_cycle = PWM_ACT_CYCLE & val;
+	clk_div = val >> 16;
+
+	val = sunxi_pwm_readl(sunxi_pwm, CLK_CFG_REG(pwm->hwpwm));
+	id = CLK_DIV_M & val;
+
+	tmp = act_cycle * prescal * div_m_table[id] * NSEC_PER_SEC;
+	state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
+	tmp = clk_div * prescal * div_m_table[id] * NSEC_PER_SEC;
+	state->period = DIV_ROUND_CLOSEST_ULL(tmp, clk_rate);
+}
+
+static const struct pwm_ops sunxi_pwm_ops = {
+	.apply = sunxi_pwm_apply,
+	.get_state = sunxi_pwm_get_state,
+	.owner = THIS_MODULE,
+};
+
+static const struct sunxi_pwm_data sunxi_pwm_data_r40 = {
+	.has_prescaler_bypass = false,
+	.has_rdy = true,
+	.npwm = 8,
+};
+
+static const struct of_device_id sunxi_pwm_dt_ids[] = {
+	{
+		.compatible = "allwinner,sun8i-r40-pwm",
+		.data = &sunxi_pwm_data_r40,
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, sunxi_pwm_dt_ids);
+
+static int sunxi_pwm_probe(struct platform_device *pdev)
+{
+	struct sunxi_pwm_chip *pwm;
+	struct resource *res;
+	int ret;
+	const struct of_device_id *match;
+
+	match = of_match_device(sunxi_pwm_dt_ids, &pdev->dev);
+
+	pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
+	if (!pwm)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pwm->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pwm->base))
+		return PTR_ERR(pwm->base);
+
+	pwm->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(pwm->clk))
+		return PTR_ERR(pwm->clk);
+
+	pwm->data = match->data;
+	pwm->chip.dev = &pdev->dev;
+	pwm->chip.ops = &sunxi_pwm_ops;
+	pwm->chip.base = -1;
+	pwm->chip.npwm = pwm->data->npwm;
+	pwm->chip.of_xlate = of_pwm_xlate_with_flags;
+	pwm->chip.of_pwm_n_cells = 3;
+
+	dev_dbg(pwm->chip.dev, "npwm: %d\n", pwm->chip.npwm);
+
+	spin_lock_init(&pwm->ctrl_lock);
+
+	ret = pwmchip_add(&pwm->chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, pwm);
+
+	return 0;
+}
+
+static int sunxi_pwm_remove(struct platform_device *pdev)
+{
+	struct sunxi_pwm_chip *pwm = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&pwm->chip);
+}
+
+static struct platform_driver sunxi_pwm_driver = {
+	.driver = {
+		.name = "sun8i-r40-pwm",
+		.of_match_table = sunxi_pwm_dt_ids,
+	},
+	.probe = sunxi_pwm_probe,
+	.remove = sunxi_pwm_remove,
+};
+module_platform_driver(sunxi_pwm_driver);
+
+MODULE_ALIAS("platform:sun8i-r40-pwm");
+MODULE_AUTHOR("Hao Zhang <hao5781286@gmail.com>");
+MODULE_DESCRIPTION("Allwinner sun8i-r40 PWM driver");
+MODULE_LICENSE("GPL v2");
-- 
2.7.4

^ permalink raw reply related

* [PATCH v4 1/4] dt-bindings: pwm: binding allwinner sun8i R40/V40/T3.
From: hao_zhang @ 2017-12-13 14:43 UTC (permalink / raw)
  To: linux-arm-kernel

This patch adds allwinner R40, V40, T3 pwm binding documents.

Signed-off-by: hao_zhang <hao5781286@gmail.com>
---
 Documentation/devicetree/bindings/pwm/pwm-sun8i.txt | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-sun8i.txt

diff --git a/Documentation/devicetree/bindings/pwm/pwm-sun8i.txt b/Documentation/devicetree/bindings/pwm/pwm-sun8i.txt
new file mode 100644
index 0000000..76750d8
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-sun8i.txt
@@ -0,0 +1,18 @@
+Allwinner sun8i R40/V40/T3 SoC PWM controller
+
+Required properties:
+- compatible: should be one of:
+- "allwinner,sun8i-r40-pwm"
+- reg: physical base address and length of the controller's registers
+- #pwm-cells: should be 3. See pwm.txt in this directory for a description of
+the cells format.
+- clocks: From common clock binding, handle to the parent clock.
+
+Example:
+
+pwm: pwm at 1c23400 {
+	     compatible = "allwinner,sun8i-r40-pwm";
+	     reg = <0x01c23400 0x154>;
+	     clocks = <&osc24M>;
+	     #pwm-cells = <3>;
+};
-- 
2.7.4

^ permalink raw reply related

* [PATCH 3/3] [v5] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002
From: Andy Shevchenko @ 2017-12-13 14:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513111858-6251-4-git-send-email-timur@codeaurora.org>

On Tue, 2017-12-12 at 14:50 -0600, Timur Tabi wrote:
> Newer versions of the firmware for the Qualcomm Datacenter
> Technologies
> QDF2400 restricts access to a subset of the GPIOs on the TLMM.  To
> prevent older kernels from accidentally accessing the restricted
> GPIOs,
> we change the ACPI HID for the TLMM block from QCOM8001 to QCOM8002,
> and introduce a new property "gpios".  This property is an array of
> specific GPIOs that are accessible.  When an older kernel boots on
> newer (restricted) firmware, it will fail to probe.
> 
> To implement the sparse GPIO map, we register all of the GPIOs, but
> set
> the pin count for the unavailable GPIOs to zero.  The pinctrl-msm
> driver will block those unavailable GPIOs from being accessed.
> 
> To allow newer kernels to support older firmware, the driver retains
> support for QCOM8001.

Please, read my comments to v8, same applies here.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply

* [PATCH 2/3] [v8] pinctrl: qcom: disable GPIO groups with no pins
From: Andy Shevchenko @ 2017-12-13 14:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1513111858-6251-3-git-send-email-timur@codeaurora.org>

On Tue, 2017-12-12 at 14:50 -0600, Timur Tabi wrote:
> pinctrl-msm only accepts an array of GPIOs from 0 to n-1, and it
> expects
> each group to support have only one pin (npins == 1).
> 
> We can support "sparse" GPIO maps if we allow for some groups to have
> zero
> pins (npins == 0).  These pins are "hidden" from the rest of the
> driver
> and gpiolib.
> 
> Access to unavailable GPIOs is blocked via a request callback.  If the
> requested GPIO is unavailable, -EACCES is returned, which prevents
> further access to that GPIO.

We recently have some interesting BIOS/Windows driver design which makes
a need of something similar. Mika did patched pinctrl-intel for that. I
dunno that approach can be used here, or your proposal be utilized in
pinctrl-intel. Mika, any comments?

See some nitpicks below.

>  
>  	seq_printf(s, " %-8s: %-3s %d", g->name, is_out ? "out" :
> "in", func);
>  	seq_printf(s, " %dmA", msm_regval_to_drive(drive));
> -	seq_printf(s, " %s", pulls[pull]);
> +	seq_printf(s, " %s\n", pulls[pull]);

I would rather do

 seq_putc(s, '\n');

which makes code slightly more flexible for maintenance and reading.


>  }
>  
>  static void msm_gpio_dbg_show(struct seq_file *s, struct gpio_chip
> *chip)
> @@ -524,23 +529,36 @@ static void msm_gpio_dbg_show(struct seq_file
> *s, struct gpio_chip *chip)
>  	unsigned gpio = chip->base;
>  	unsigned i;
>  
> -	for (i = 0; i < chip->ngpio; i++, gpio++) {
> +	for (i = 0; i < chip->ngpio; i++, gpio++)
>  		msm_gpio_dbg_show_one(s, NULL, chip, i, gpio);
> -		seq_puts(s, "\n");
> -	}

This kind of change looks like a candidate to a separate patch,
though I mentioned it's just a nit.


-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply

* [PATCH V4 08/12] boot_constraint: Manage deferrable constraints
From: Viresh Kumar @ 2017-12-13 14:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20171213103315.GI10595@n2100.armlinux.org.uk>

On 13-12-17, 10:33, Russell King - ARM Linux wrote:
> On Wed, Dec 13, 2017 at 03:57:07PM +0530, Viresh Kumar wrote:
> > On 13-12-17, 10:53, Greg Kroah-Hartman wrote:
> > > On Sun, Oct 29, 2017 at 07:18:56PM +0530, Viresh Kumar wrote:
> > > > +static void add_deferrable_of_single(struct device_node *np,
> > > > +				     struct dev_boot_constraint *constraints,
> > > > +				     int count)
> > > > +{
> > > > +	struct device *dev;
> > > > +	int ret;
> > > > +
> > > > +	if (!of_device_is_available(np))
> > > > +		return;
> > > > +
> > > > +	ret = of_platform_bus_create(np, NULL, NULL, NULL, false);
> > > > +	if (ret)
> > > > +		return;
> > > > +
> > > > +	if (of_device_is_compatible(np, "arm,primecell")) {
> > > 
> > > Why is "arm,primecell" in the core code here?
> > 
> > All we need here is a struct device pointer to add constraints. But how we get
> > the device node depends on what bus type the device corresponds to. Currently
> > this only support amba and platform devices, but we may need to get spi, i2c,
> > etc later on.
> > 
> > How do you suggest to keep this stuff out of core here ? Are you asking me to
> > add a generic API in the OF core to find the struct device pointer using a node
> > pointer ?
> 
> Why do we need this?  Why can't we lookup the "struct device" by DT
> node, and then look at the device's bus type and decide what to do
> from that?

My requirement is only to get the struct device * for the DT node and I don't
really need to get into the bus specific details at all. I was not sure if there
is a way to lookup for the "struct device" by its DT node currently and so
depended on helpers like of_find_device_by_node(). Can you please point me to
the routine (or the way we can traverse all devices) ?

> Wouldn't a better solution be to use fwnode stuff for this, and
> make the bus-type handling a property of the bus type itself,
> pushing the bus specific code into the bus layer?

As I said earlier, I don't really need to work at the bus level. I just need the
device structure and so that may not be required.

-- 
viresh

^ permalink raw reply

* [PATCH v4 0/4] pwm support for allwinner sun8i R40/V40/T3 SOCs.
From: hao_zhang @ 2017-12-13 14:38 UTC (permalink / raw)
  To: linux-arm-kernel

This patchset add pwm support for allwinner sun8i R40/V40/T3 SOCs.

all has been teat on T3 board.

Some features
	8 PWM channels outputs(4 PWM pairs) 
	Supports capturing input 
	Supports three kinds of output waveforms: continuous waveform, pulse
	waveform and complementarity pair 
	Programmable deadzone generator and controllable dead-time 
	0% to 100% adjustable duty cycle 
	Up to 24/100MHz output frequency 
	Minimum resolution is 1/65536 
	Supports interrupt for PWM output and capturing input


DOC:
https://github.com/tinalinux/docs/blob/r40-v1.y/Allwinner_R40_User_Manual_V1.0.pdf
https://github.com/tinalinux/docs/blob/r40-v1.y/R40_Datasheet_V1.0.pdf

Regards;-)
Hao Zhang

hao_zhang (4):
  dt-bindings: pwm: binding allwinner R40, V40, T3
  ARM: PWM: add allwinner sun8i R40/V40/T3 pwm support.
  ARM: dts: add pwm node for r40.
  ARM: pinctrl: sunxi-pinctrl: fix pin funtion can not be match
    correctly.

 .../devicetree/bindings/pwm/pwm-sun8i.txt          |  18 +
 arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts  |   6 +
 arch/arm/boot/dts/sun8i-r40.dtsi                   |  13 +
 drivers/pinctrl/sunxi/pinctrl-sunxi.c              |   6 +-
 drivers/pwm/Kconfig                                |  10 +
 drivers/pwm/Makefile                               |   1 +
 drivers/pwm/pwm-sun8i-r40.c                        | 449 +++++++++++++++++++++
 7 files changed, 501 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-sun8i.txt
 create mode 100644 drivers/pwm/pwm-sun8i-r40.c

-- 
2.7.4

^ permalink raw reply

* [PATCH 4/4] [v4] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002
From: Andy Shevchenko @ 2017-12-13 14:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <88349f2e-5243-8061-cc72-d01fa70e6f2e@codeaurora.org>

On Tue, 2017-12-12 at 14:27 -0600, Timur Tabi wrote:
> On 12/12/2017 05:07 AM, Andy Shevchenko wrote:
> 
> > Not ACPI standards as of my knowledge. ACPI standard defines a
> > common
> > scheme how to define properties, it doesn't tell anything about
> > property
> > names or any mappings between names to values or names to "OS
> > subsystem").
> 
> There was an attempt a while back to standardize this like we do for 
> device tree, but it fell apart.  Device-specific ACPI-only properties 
> are not standarized.  This driver is initialized only on ACPI
> systems. 
> It has no device tree binding.

It should follow DT *de facto* standard bindings like "ngpios" (though
it's not needed in ACPI case IIRC) and other properties.

> > As for GPIO we just follow *de facto* what DT has right now, i.e.
> > "xxx-
> > gpio" or "xxx-gpios" pattern is used to map ACPI standard resource
> > to a
> > GPIO name. That's how GPIO ACPI lib is being developed.
> 
> GPIOs in device tree are defined completely differently than in ACPI. 
> On DT, the kernel controls the pin muxing.  On ACPI, pins are muxed
> by 
> firmware and never re-muxed by the operating system.  So all this
> driver 
> does is expose a few pins as simple GPIOs.

Wait, runtime muxing is a matter of requesting another function (usually
GPIO) and putting it back afterwards. Do you really need anything like
this at *runtime*?

Pin control design is not compatible with hardware (too abstract), but
that is the problem of DT as well: I'm referring here to not carefully
designed so called "pin states". This is another story and has nothing
specific for ACPI.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply

* [PATCH 4/4] [v4] pinctrl: qcom: qdf2xxx: add support for new ACPI HID QCOM8002
From: Andy Shevchenko @ 2017-12-13 14:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <bae16fa3-1bdf-74b1-97b7-f6b2db212621@codeaurora.org>

On Tue, 2017-12-12 at 14:17 -0600, Timur Tabi wrote:
> On 12/12/2017 04:05 AM, Andy Shevchenko wrote:
> > > +static const struct acpi_device_id qdf2xxx_acpi_ids[] = {
> > > +	{"QCOM8001", QDF2XXX_V1},
> > > +	{"QCOM8002", QDF2XXX_V2},
> > > +	{},
> > > +};
> > > +MODULE_DEVICE_TABLE(acpi, qdf2xxx_acpi_ids);
> > > 
> > > +	const struct acpi_device_id *id =
> > > +		acpi_match_device(qdf2xxx_acpi_ids, &pdev->dev);
> > 
> > JFYI: there is no need to move IDs like this.
> > Use members of struct device_driver wisely.
> 
> I have to move it, otherwise I get:
> 
> drivers/pinctrl/qcom/pinctrl-qdf2xxx.c:49:21: error:
> 'qdf2xxx_acpi_ids' 
> undeclared (first use in this function); did you mean
> 'qdf2xxx_pinctrl'?
> 
> I reference the structure in qdf2xxx_pinctrl_probe().

Please, read my comment again. The key part of the phrase: 
"Use members of struct device_driver"

So, do not move the IDs. There are examples in the kernel how to access
it.

-- 
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy

^ permalink raw reply

* [PATCH v2 07/19] arm64: insn: Add encoder for bitwise operations using litterals
From: Marc Zyngier @ 2017-12-13 14:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <5A3020DA.8010309@arm.com>

Hi James,

On 12/12/17 18:32, James Morse wrote:
> Hi Marc,
> 
> On 11/12/17 14:49, Marc Zyngier wrote:
>> We lack a way to encode operations such as AND, ORR, EOR that take
>> an immediate value. Doing so is quite involved, and is all about
>> reverse engineering the decoding algorithm described in the
>> pseudocode function DecodeBitMasks().
> 
> 
> As this is over my head, I've been pushing random encodings through gas/objdump
> and then tracing them through here.... can this encode 0xf80000000fffffff?
> 
> gas thinks this is legal:
> |   0:   92458000        and     x0, x0, #0xf80000000fffffff
> 
> I make that N=1, S=0x20, R=0x05.
> (I'm still working out what 'S' means)
> 
> 
>> diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
>> index 7e432662d454..326b17016485 100644
>> --- a/arch/arm64/kernel/insn.c
>> +++ b/arch/arm64/kernel/insn.c
> 
>> +static u32 aarch64_encode_immediate(u64 imm,
>> +				    enum aarch64_insn_variant variant,
>> +				    u32 insn)
>> +{
>> +	unsigned int immr, imms, n, ones, ror, esz, tmp;
>> +	u64 mask;
> 
> [...]
> 
>> +	/* N is only set if we're encoding a 64bit value */
>> +	n = esz == 64;
>> +
>> +	/* Trim imm to the element size */
>> +	mask = BIT(esz - 1) - 1;
>> +	imm &= mask;
> 
> Won't this lose the top bit of a 64bit immediate?

Humfff... Yup, nicely spotted.

> 
> (but then you put it back later, so something funny is going on)
> 
> This becomes 0x780000000fffffff,
> 
> 
>> +
>> +	/* That's how many ones we need to encode */
>> +	ones = hweight64(imm);
> 
> meaning we're short a one here,
> 
> 
>> +
>> +	/*
>> +	 * imms is set to (ones - 1), prefixed with a string of ones
>> +	 * and a zero if they fit. Cap it to 6 bits.
>> +	 */
>> +	imms  = ones - 1;
>> +	imms |= 0xf << ffs(esz);
>> +	imms &= BIT(6) - 1;
> 
> so imms is 0x1f, not 0x20.
> 
> 
>> +	/* Compute the rotation */
>> +	if (range_of_ones(imm)) {
>> +		/*
>> +		 * Pattern: 0..01..10..0
>> +		 *
>> +		 * Compute how many rotate we need to align it right
>> +		 */
>> +		ror = ffs(imm) - 1;
> 
> (how come range_of_ones() uses __ffs64() on the same value?)

News flash: range_of_ones is completely buggy. It will fail on the 
trivial value 1 (__ffs64(1) = 0; 0 - 1 = -1; val >> -1 is... ermmmm).
I definitely got mixed up between the two.

>> +	} else {
>> +		/*
>> +		 * Pattern: 0..01..10..01..1
>> +		 *
>> +		 * Fill the unused top bits with ones, and check if
>> +		 * the result is a valid immediate (all ones with a
>> +		 * contiguous ranges of zeroes).
>> +		 */
> 
>> +		imm |= ~mask;
> 
> but here we put the missing one back,
> 
> 
>> +		if (!range_of_ones(~imm))
>> +			return AARCH64_BREAK_FAULT;
> 
> meaning we pass this check and carry on, (even though 0x780000000fffffff isn't a
> legal value)
> 
> 
> (this next bit I haven't worked out yet)
>> +		/*
>> +		 * Compute the rotation to get a continuous set of
>> +		 * ones, with the first bit set at position 0
>> +		 */
>> +		ror = fls(~imm);
>> +	}
>> +
>> +	/*
>> +	 * immr is the number of bits we need to rotate back to the
>> +	 * original set of ones. Note that this is relative to the
>> +	 * element size...
>> +	 */
>> +	immr = (esz - ror) & (esz - 1);
> 
> 
> If I've followed this through correctly, this results in:
> |   0:   92457c00        and     x0, x0, #0xf800000007ffffff
> 
> ... which wasn't the immediate I started with.
> 
> 
> Unless I've gone wrong, I think the 'Trim imm to the element size' code needs to
> move up into the esz-reducing loop so it doesn't happen for a 64bit immediate.

Yup. I've stashed the following patch:

diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
index b8fb2d89b3a6..e58be1c57f18 100644
--- a/arch/arm64/kernel/insn.c
+++ b/arch/arm64/kernel/insn.c
@@ -1503,8 +1503,7 @@ pstate_check_t * const aarch32_opcode_cond_checks[16] = {
 static bool range_of_ones(u64 val)
 {
 	/* Doesn't handle full ones or full zeroes */
-	int x = __ffs64(val) - 1;
-	u64 sval = val >> x;
+	u64 sval = val >> __ffs64(val);
 
 	/* One of Sean Eron Anderson's bithack tricks */
 	return ((sval + 1) & (sval)) == 0;
@@ -1515,7 +1514,7 @@ static u32 aarch64_encode_immediate(u64 imm,
 				    u32 insn)
 {
 	unsigned int immr, imms, n, ones, ror, esz, tmp;
-	u64 mask;
+	u64 mask = ~0UL;
 
 	/* Can't encode full zeroes or full ones */
 	if (!imm || !~imm)
@@ -1543,8 +1542,12 @@ static u32 aarch64_encode_immediate(u64 imm,
 	for (tmp = esz; tmp > 2; tmp /= 2) {
 		u64 emask = BIT(tmp / 2) - 1;
 
-		if ((imm & emask) != ((imm >> (tmp / 2)) & emask))
+		if ((imm & emask) != ((imm >> (tmp / 2)) & emask)) {
+			/* Trim imm to the element size */
+			mask = BIT(esz - 1) - 1;
+			imm &= mask;
 			break;
+		}
 
 		esz = tmp;
 	}
@@ -1552,10 +1555,6 @@ static u32 aarch64_encode_immediate(u64 imm,
 	/* N is only set if we're encoding a 64bit value */
 	n = esz == 64;
 
-	/* Trim imm to the element size */
-	mask = BIT(esz - 1) - 1;
-	imm &= mask;
-
 	/* That's how many ones we need to encode */
 	ones = hweight64(imm);
 
I really need to run this against gas in order to make sure
I get the same parameters for all the possible values.

Many thanks for this careful review!

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply related

* [PATCH] ARM: dts: imx51: add CodaHx4 VPU
From: Philipp Zabel @ 2017-12-13 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

Add the CodaHx4 VPU to the i.MX51 device tree.

Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
---
This patch should only be applied once the patch to fix VPU register access on
i.MX51 [1] is merged. The coda driver with patches [2] applied will start
accessing VPU registers on i.MX51, which hangs the system without [1].

[1] https://patchwork.kernel.org/patch/10109781/
    ("clk: imx51: uart4, uart5 gates only exist on imx50, imx53")
[2] https://patchwork.linuxtv.org/patch/45929/
    ("media: dt-bindings: coda: Add compatible for CodaHx4 on i.MX51")
    https://patchwork.linuxtv.org/patch/45930/
    ("media: coda: Add i.MX51 (CodaHx4) support")
---
 arch/arm/boot/dts/imx51.dtsi | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm/boot/dts/imx51.dtsi b/arch/arm/boot/dts/imx51.dtsi
index 378be720b3c76..6d6c19ede2be0 100644
--- a/arch/arm/boot/dts/imx51.dtsi
+++ b/arch/arm/boot/dts/imx51.dtsi
@@ -597,6 +597,17 @@
 				clock-names = "ipg", "ahb", "ptp";
 				status = "disabled";
 			};
+
+			vpu at 83ff4000 {
+				compatible = "fsl,imx51-vpu", "cnm,codahx4";
+				reg = <0x83ff4000 0x1000>;
+				interrupts = <9>;
+				clocks = <&clks IMX5_CLK_VPU_REFERENCE_GATE>,
+					 <&clks IMX5_CLK_VPU_GATE>;
+				clock-names = "per", "ahb";
+				resets = <&src 1>;
+				iram = <&iram>;
+			};
 		};
 	};
 };
-- 
2.11.0

^ permalink raw reply related

* [PATCH v6 3/6] kernel/reboot.c: export pm_power_off_prepare
From: Leonard Crestez @ 2017-12-13 14:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <b39d3ae2-5a93-854f-a0ff-aefd405da78b@pengutronix.de>

On Thu, 2017-12-07 at 06:36 +0100, Oleksij Rempel wrote:
> 
> On 07.12.2017 00:11, Christoph Hellwig wrote:
> > 
> > > 
> > > ?void (*pm_power_off_prepare)(void);
> > > +EXPORT_SYMBOL(pm_power_off_prepare);
> > EXPORT_SYMBOL_GPL for something this deeply internal, please.
> Ok,
> probably all other symbols should be converted in this file in to
> EXPORT_SYMBOL_GPL as well?
> 
> grep EXPORT_SYMBOL kernel/reboot.c
> EXPORT_SYMBOL(cad_pid);
> EXPORT_SYMBOL(pm_power_off_prepare);
> EXPORT_SYMBOL_GPL(emergency_restart);
> EXPORT_SYMBOL(register_reboot_notifier);
> EXPORT_SYMBOL(unregister_reboot_notifier);
> EXPORT_SYMBOL(devm_register_reboot_notifier);
> EXPORT_SYMBOL(register_restart_handler);
> EXPORT_SYMBOL(unregister_restart_handler);
> EXPORT_SYMBOL_GPL(kernel_restart);
> EXPORT_SYMBOL_GPL(kernel_halt);
> EXPORT_SYMBOL_GPL(kernel_power_off);
> EXPORT_SYMBOL_GPL(orderly_poweroff);
> EXPORT_SYMBOL_GPL(orderly_reboot);

This call looks much more deeply internal than those other functions,
it's not like reboot_notifier and restart_handler.

It seems that the only user of pm_power_off_prepare right now is the
ACPI core and your patch uses it in a regulator driver. This looks
extremely strange. Maybe this is why imx maintainers are stalling on
this patch?

It might help if the ACPI/PM maintainers ack/review this part
explicitly, and the usage in part 5:

https://patchwork.kernel.org/patch/9799615/

--
Regards,
Leonard

^ permalink raw reply

* [PATCH] arm64: dts: hisilicon: Add hi3660 cpu capacity-dmips-mhz information
From: Valentin Schneider @ 2017-12-13 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

The following dt entries are added:
 cpus [0-3] (Cortex A53):
   - capacity-dmips-mhz = <592>;

 cpus [4-7] (Cortex A73):
   - capacity-dmips-mhz = <1024>;

Those values were obtained by running dhrystone 2.1 on a
HiKey960 with the following procedure:
- Offline all CPUs but CPU0 (A53)
- Set CPU0 frequency to maximum
- Run Dhrystone 2.1 for 20 seconds

- Offline all CPUs but CPU4 (A73)
- set CPU4 frequency to maximum
- Run Dhrystone 2.1 for 20 seconds

The results are as follows:
A53: 129633887 loops
A73: 287034147 loops

By scaling those values so that the A73s use 1024, we end up with 462
for the A53s. However, they have different maximum frequencies:
1.844GHz for A53s and 2.362GHz for A73s. Thus, we can scale the A53
value to truly represent dmips per MHz, and we end up with 592.

The impact of this change can be verified on HiKey960:

$ cat /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
1844000
1844000
1844000
1844000
2362000
2362000
2362000
2362000

$ cat /sys/devices/system/cpu/cpu*/cpu_capacity
462
462
462
462
1024
1024
1024
1024

Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
---
 arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index ab0b95b..04a8d28 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -61,6 +61,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <592>;
 		};
 
 		cpu1: cpu at 1 {
@@ -70,6 +71,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <592>;
 		};
 
 		cpu2: cpu at 2 {
@@ -79,6 +81,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <592>;
 		};
 
 		cpu3: cpu at 3 {
@@ -88,6 +91,7 @@
 			enable-method = "psci";
 			next-level-cache = <&A53_L2>;
 			cpu-idle-states = <&CPU_SLEEP &CLUSTER_SLEEP_0>;
+			capacity-dmips-mhz = <592>;
 		};
 
 		cpu4: cpu at 100 {
@@ -101,6 +105,7 @@
 					&CPU_SLEEP
 					&CLUSTER_SLEEP_1
 			>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		cpu5: cpu at 101 {
@@ -114,6 +119,7 @@
 					&CPU_SLEEP
 					&CLUSTER_SLEEP_1
 			>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		cpu6: cpu at 102 {
@@ -127,6 +133,7 @@
 					&CPU_SLEEP
 					&CLUSTER_SLEEP_1
 			>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		cpu7: cpu at 103 {
@@ -140,6 +147,7 @@
 					&CPU_SLEEP
 					&CLUSTER_SLEEP_1
 			>;
+			capacity-dmips-mhz = <1024>;
 		};
 
 		idle-states {
--
2.7.4

^ 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