* [PATCH v4 2/8] scpi: Add alternative legacy structures, functions and macros
From: Neil Armstrong @ 2016-10-19 10:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e3f774ee-5268-3668-e7f8-0ae3bbceba6c@arm.com>
On 10/17/2016 01:16 PM, Sudeep Holla wrote:
>
>
> On 17/10/16 09:25, Neil Armstrong wrote:
>> On 10/10/2016 04:36 PM, Sudeep Holla wrote:
>>> Hi Neil,
>>>
>>> Sorry, I could not reply to your response on v3. Anyways I will review v4.
>>>
>>> On 05/10/16 08:33, Neil Armstrong wrote:
>>>> This patch adds support for the Legacy SCPI protocol in early JUNO versions and
>>>> shipped Amlogic ARMv8 based SoCs. Some Rockchip SoC are also known to use this
>>>> version of protocol with extended vendor commands
>>>> .
>>>> In order to support the legacy SCPI protocol variant, add back the structures
>>>> and macros that varies against the final specification.
>>>> Then add indirection table for legacy commands.
>>>> Finally Add bitmap field for channel selection since the Legacy protocol mandates to
>>>> send a selected subset of the commands on the high priority channel instead of the
>>>> low priority channel.
>>>>
>>>> The message sending path differs from the final SCPI procotocol because the
>>>> Amlogic SCP firmware always reply 1 instead of a special value containing the command
>>>> byte and replied rx data length.
>>>> For this reason commands queuing cannot be used and we assume the reply command is
>>>> the head of the rx_pending list since we ensure sequential command sending with a
>>>> separate dedicated mutex.
>>>>
>>>> Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
>>>> ---
>>>> drivers/firmware/arm_scpi.c | 221 +++++++++++++++++++++++++++++++++++++++-----
>>>> 1 file changed, 199 insertions(+), 22 deletions(-)
>>>>
>>>> diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
>>>> index 498afa0..6244eb1 100644
>>>> --- a/drivers/firmware/arm_scpi.c
>>>> +++ b/drivers/firmware/arm_scpi.c
>>>
>>> [...]
>>>
>>>> @@ -307,21 +398,46 @@ static void scpi_process_cmd(struct scpi_chan *ch, u32 cmd)
>>>> return;
>>>> }
>>>>
>>>> - list_for_each_entry(t, &ch->rx_pending, node)
>>>> - if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
>>>> - list_del(&t->node);
>>>> - match = t;
>>>> - break;
>>>> - }
>>>> + /* Command type is not replied by the SCP Firmware in legacy Mode
>>>> + * We should consider that command is the head of pending RX commands
>>>> + * if the list is not empty. In TX only mode, the list would be empty.
>>>> + */
>>>> + if (scpi_info->is_legacy) {
>>>> + match = list_first_entry(&ch->rx_pending, struct scpi_xfer,
>>>> + node);
>>>> + list_del(&match->node);
>>>> + } else {
>>>> + list_for_each_entry(t, &ch->rx_pending, node)
>>>> + if (CMD_XTRACT_UNIQ(t->cmd) == CMD_XTRACT_UNIQ(cmd)) {
>>>> + list_del(&t->node);
>>>> + match = t;
>>>> + break;
>>>> + }
>>>> + }
>>>> /* check if wait_for_completion is in progress or timed-out */
>>>> if (match && !completion_done(&match->done)) {
>>>> - struct scpi_shared_mem *mem = ch->rx_payload;
>>>> - unsigned int len = min(match->rx_len, CMD_SIZE(cmd));
>>>> + unsigned int len;
>>>> +
>>>> + if (scpi_info->is_legacy) {
>>>> + struct legacy_scpi_shared_mem *mem = ch->rx_payload;
>>>> +
>>>> + /* RX Length is not replied by the lagcy Firmware */
>
> Typo above legacy
>
>>>> + len = match->rx_len;
>>>> +
>>>> + match->status = le32_to_cpu(mem->status);
>>>> + memcpy_fromio(match->rx_buf, mem->payload, len);
>>>
>>> The above 2 seems common to both, no ?
>>
>> No, the shared_mem structure differs.
>>
>
> Yes I see that, I was just referring the last 2 statements.
>
>>>
>>>> + } else {
>>>> + struct scpi_shared_mem *mem = ch->rx_payload;
>>>> +
>>>> + len = min(match->rx_len, CMD_SIZE(cmd));
>>>> +
>>>> + match->status = le32_to_cpu(mem->status);
>>>> + memcpy_fromio(match->rx_buf, mem->payload, len);
>
> and the above 2 can be moved out of the conditions, no ?
>
> if (scpi_info->is_legacy) {
> struct legacy_scpi_shared_mem *mem = ch->rx_payload;
> len = match->rx_len;
> } else {
> struct scpi_shared_mem *mem = ch->rx_payload;
> len = min(match->rx_len, CMD_SIZE(cmd));
> }
> match->status = le32_to_cpu(mem->status);
> memcpy_fromio(match->rx_buf, mem->payload, len);
>
> should work.
Well, we will have "error: ?mem? undeclared (first use in this function)" since mem is not declared outside the if/else.
I don't see good solutions even with an union.
>
> [...]
>
>>>
>>>> + else
>>>> + cmd = le32_to_cpu(mem->command);
>>>>
>>>> scpi_process_cmd(ch, cmd);
>>>> }
>>>> @@ -343,17 +464,26 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
>>>> struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
>>>> struct scpi_shared_mem *mem = (struct scpi_shared_mem *)ch->tx_payload;
>>>>
>>>> - if (t->tx_buf)
>>>> - memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
>>>> + if (t->tx_buf) {
>>>> + if (scpi_info->is_legacy)
>>>> + memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len);
>>>> + else
>>>> + memcpy_toio(mem->payload, t->tx_buf, t->tx_len);
>>>> + }
>>>> +
>>>> if (t->rx_buf) {
>>>> if (!(++ch->token))
>>>> ++ch->token;
>>>> ADD_SCPI_TOKEN(t->cmd, ch->token);
>>>> + if (scpi_info->is_legacy)
>>>> + t->slot = t->cmd;
>>>
>>> I thought passing token was not an issue from your previous response,
>>> but you are overriding it here, why ?
>>
>> Indeed, I can leave it, but it's useless since it won't serve to
>> distinguish multiple similar commands.
>>
>
> OK, I don't see any point in such micro optimization, so please retain it.
>
I misread my code, I leaved the token passing, but I copy back the cmd to the slot which is used by the MHU.
If I remove the "t->slot = t->cmd;", the token won't be passed to the FW.
> [...]
>
>>>> + /* Since we cannot distinguish the original command in the
>>>> + * MHU reply stat value from a Legacy SCP firmware, ensure
>>>> + * sequential command sending to the firmware.
>>>> + */
>>>
>>> OK this comment now questions the existence of this extra lock.
>>> The mailbox will always send the commands in the sequential order.
>>> It's only firmware that can re-order the response. Since that can't
>>> happen in you case, I really don't see the need for this.
>>>
>>> Please explain the race you would see without this locking. Yes I
>>> understand that only one command is supposed to be sent to firmware at a
>>> time. Suppose you allow more callers here, all will wait on the
>>> completion flags and the first in the list gets unblocked right ?
>>> I am just trying to understand if there's real need for this extra
>>> lock when we already have that from the list.
>>
>> In my current tests I have huge kernel hang when having multiple callers,
>> I must find out where this issue comes from...
>
> Yes IMO, you should understand the root cause of this issue. There may
> be issue with the existing driver itself. But just adding a lock just to
> avoid the hang without understanding it is wrong.
>
>> In any case, we have an issue about the command sequencing. If we
>> push a tx-only command and then right after a tx-rx command, the
>> mailbox callback from the first command won't be able to distinguish
>> which command is handled !
>
> Hmm, how exactly ? I won't expect scpi_handle_remote_msg to becalled in
> that case.
>
>> In this case, the rx_pending list will not be empty, some garbage
>> will be returned to the second command handler and the real data from
>> the second command handling will be lost thinking it's a tx-only
>> command.
>>
>
> Yes as I said why is scpi_handle_remote_msg called for tx only command.
> And more over we don't have any tx only command in the driver, I am
> still unable to understand the issue you are facing. Are you sure you
> have tx-only command in the failure/hang case ?
>
>>
>> We have two choices here : - Also push the tx-only commands to the
>> rx_pending list, and also wait for their completion
>
> See above, I need to know details on this tx-only command. In fact, they
> may not be tx-only as SCP is sending some response back, may just status.
>
>> - Add an extra lock
>>
>
> Not this for sure.
>
>> What is your preferred scheme ?
>>
>
> Option 1 if it legitimate case. I mean we may be misunderstanding the
> definition of tx-only command.
>
>
>>>> + if (scpi_info->is_legacy)
>>>> + mutex_lock(&scpi_chan->legacy_lock);
>>>> +
>>>> ret = mbox_send_message(scpi_chan->chan, msg);
>>>> if (ret < 0 || !rx_buf)
>>>> goto out;
>>>> @@ -421,9 +567,13 @@ static int scpi_send_message(unsigned int offset, void *tx_buf,
>>>> /* first status word */
>>>> ret = msg->status;
>>>> out:
>>>> - if (ret < 0 && rx_buf) /* remove entry from the list if timed-out */
>>>> + if (ret < 0 && rx_buf)
>>>> + /* remove entry from the list if timed-out */
>>>> scpi_process_cmd(scpi_chan, msg->cmd);
>>>>
>>>> + if (scpi_info->is_legacy)
>>>> + mutex_unlock(&scpi_chan->legacy_lock);
>>>> +
>>>> put_scpi_xfer(msg, scpi_chan);
>>>> /* SCPI error codes > 0, translate them to Linux scale*/
>>>> return ret > 0 ? scpi_to_linux_errno(ret) : ret;
>>>
>
> [...]
>
>>
>> I will fix the issues, but I need your advice for the locking scheme. I really want this
>> to be merged and be able to go forward !
>>
>
> Yes I agree and I have no major concern with the series now except the
> locking.
>
^ permalink raw reply
* [PATCH] drm: convert DT component matching to component_match_add_release()
From: Russell King @ 2016-10-19 10:28 UTC (permalink / raw)
To: linux-arm-kernel
Convert DT component matching to use component_match_add_release().
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
Can we please get this patch from May merged into the drm-misc or
whatever trees so that we don't end up with conflicts? I've no idea
who looks after drm-misc, as they have _still_ failed to add
themselves to MAINTAINERS.
drivers/gpu/drm/arm/hdlcd_drv.c | 3 ++-
drivers/gpu/drm/arm/malidp_drv.c | 4 +++-
drivers/gpu/drm/armada/armada_drv.c | 2 +-
drivers/gpu/drm/drm_of.c | 28 +++++++++++++++++++++++--
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 5 +++--
drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 7 ++++---
drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 +++-
drivers/gpu/drm/msm/msm_drv.c | 12 ++++++-----
drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 6 ++++--
drivers/gpu/drm/sti/sti_drv.c | 5 +++--
drivers/gpu/drm/sun4i/sun4i_drv.c | 3 ++-
drivers/gpu/drm/tilcdc/tilcdc_external.c | 4 +++-
include/drm/drm_of.h | 12 +++++++++++
13 files changed, 73 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index fb6a418ce6be..6477d1a65266 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -453,7 +453,8 @@ static int hdlcd_probe(struct platform_device *pdev)
return -EAGAIN;
}
- component_match_add(&pdev->dev, &match, compare_dev, port);
+ drm_of_component_match_add(&pdev->dev, &match, compare_dev, port);
+ of_node_put(port);
return component_master_add_with_match(&pdev->dev, &hdlcd_master_ops,
match);
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 9280358b8f15..9f4739452a25 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -493,7 +493,9 @@ static int malidp_platform_probe(struct platform_device *pdev)
return -EAGAIN;
}
- component_match_add(&pdev->dev, &match, malidp_compare_dev, port);
+ drm_of_component_match_add(&pdev->dev, &match, malidp_compare_dev,
+ port);
+ of_node_put(port);
return component_master_add_with_match(&pdev->dev, &malidp_master_ops,
match);
}
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 1e0e68f608e4..94e46da9a758 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -254,7 +254,7 @@ static void armada_add_endpoints(struct device *dev,
continue;
}
- component_match_add(dev, match, compare_of, remote);
+ drm_of_component_match_add(dev, match, compare_of, remote);
of_node_put(remote);
}
}
diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c
index bc98bb94264d..47848ed8ca48 100644
--- a/drivers/gpu/drm/drm_of.c
+++ b/drivers/gpu/drm/drm_of.c
@@ -6,6 +6,11 @@
#include <drm/drm_crtc.h>
#include <drm/drm_of.h>
+static void drm_release_of(struct device *dev, void *data)
+{
+ of_node_put(data);
+}
+
/**
* drm_crtc_port_mask - find the mask of a registered CRTC by port OF node
* @dev: DRM device
@@ -64,6 +69,24 @@ uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
EXPORT_SYMBOL(drm_of_find_possible_crtcs);
/**
+ * drm_of_component_match_add - Add a component helper OF node match rule
+ * @master: master device
+ * @matchptr: component match pointer
+ * @compare: compare function used for matching component
+ * @node: of_node
+ */
+void drm_of_component_match_add(struct device *master,
+ struct component_match **matchptr,
+ int (*compare)(struct device *, void *),
+ struct device_node *node)
+{
+ of_node_get(node);
+ component_match_add_release(master, matchptr, drm_release_of,
+ compare, node);
+}
+EXPORT_SYMBOL_GPL(drm_of_component_match_add);
+
+/**
* drm_of_component_probe - Generic probe function for a component based master
* @dev: master device containing the OF node
* @compare_of: compare function used for matching components
@@ -101,7 +124,7 @@ int drm_of_component_probe(struct device *dev,
continue;
}
- component_match_add(dev, &match, compare_of, port);
+ drm_of_component_match_add(dev, &match, compare_of, port);
of_node_put(port);
}
@@ -140,7 +163,8 @@ int drm_of_component_probe(struct device *dev,
continue;
}
- component_match_add(dev, &match, compare_of, remote);
+ drm_of_component_match_add(dev, &match, compare_of,
+ remote);
of_node_put(remote);
}
of_node_put(port);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index aa687669e22b..0dee6acbd880 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -16,6 +16,7 @@
#include <linux/component.h>
#include <linux/of_platform.h>
+#include <drm/drm_of.h>
#include "etnaviv_drv.h"
#include "etnaviv_gpu.h"
@@ -629,8 +630,8 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
if (!core_node)
break;
- component_match_add(&pdev->dev, &match, compare_of,
- core_node);
+ drm_of_component_match_add(&pdev->dev, &match,
+ compare_of, core_node);
of_node_put(core_node);
}
} else if (dev->platform_data) {
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 90377a609c98..e88fde18c946 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -24,6 +24,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
#include "kirin_drm_drv.h"
@@ -260,14 +261,13 @@ static struct device_node *kirin_get_remote_node(struct device_node *np)
DRM_ERROR("no valid endpoint node\n");
return ERR_PTR(-ENODEV);
}
- of_node_put(endpoint);
remote = of_graph_get_remote_port_parent(endpoint);
+ of_node_put(endpoint);
if (!remote) {
DRM_ERROR("no valid remote node\n");
return ERR_PTR(-ENODEV);
}
- of_node_put(remote);
if (!of_device_is_available(remote)) {
DRM_ERROR("not available for remote node\n");
@@ -294,7 +294,8 @@ static int kirin_drm_platform_probe(struct platform_device *pdev)
if (IS_ERR(remote))
return PTR_ERR(remote);
- component_match_add(dev, &match, compare_of, remote);
+ drm_of_component_match_add(dev, &match, compare_of, remote);
+ of_node_put(remote);
return component_master_add_with_match(dev, &kirin_drm_ops, match);
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index cf83f6507ec8..9c5430fb82a2 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -18,6 +18,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
#include <linux/component.h>
#include <linux/iommu.h>
#include <linux/of_address.h>
@@ -415,7 +416,8 @@ static int mtk_drm_probe(struct platform_device *pdev)
comp_type == MTK_DPI) {
dev_info(dev, "Adding component match for %s\n",
node->full_name);
- component_match_add(dev, &match, compare_of, node);
+ drm_of_component_match_add(dev, &match, compare_of,
+ node);
} else {
struct mtk_ddp_comp *comp;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index fb5c0b0a7594..84d38eaea585 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -15,6 +15,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <drm/drm_of.h>
+
#include "msm_drv.h"
#include "msm_debugfs.h"
#include "msm_fence.h"
@@ -919,8 +921,8 @@ static int add_components_mdp(struct device *mdp_dev,
continue;
}
- component_match_add(master_dev, matchptr, compare_of, intf);
-
+ drm_of_component_match_add(master_dev, matchptr, compare_of,
+ intf);
of_node_put(intf);
of_node_put(ep_node);
}
@@ -962,8 +964,8 @@ static int add_display_components(struct device *dev,
put_device(mdp_dev);
/* add the MDP component itself */
- component_match_add(dev, matchptr, compare_of,
- mdp_dev->of_node);
+ drm_of_component_match_add(dev, matchptr, compare_of,
+ mdp_dev->of_node);
} else {
/* MDP4 */
mdp_dev = dev;
@@ -996,7 +998,7 @@ static int add_gpu_components(struct device *dev,
if (!np)
return 0;
- component_match_add(dev, matchptr, compare_of, np);
+ drm_of_component_match_add(dev, matchptr, compare_of, np);
of_node_put(np);
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 8c8cbe837e61..6fe161192bb4 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -20,6 +20,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_of.h>
#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/module.h>
@@ -388,7 +389,7 @@ static void rockchip_add_endpoints(struct device *dev,
continue;
}
- component_match_add(dev, match, compare_of, remote);
+ drm_of_component_match_add(dev, match, compare_of, remote);
of_node_put(remote);
}
}
@@ -437,7 +438,8 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
}
of_node_put(iommu);
- component_match_add(dev, &match, compare_of, port->parent);
+ drm_of_component_match_add(dev, &match, compare_of,
+ port->parent);
of_node_put(port);
}
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index 2784919a7366..5e819876e642 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -17,6 +17,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_cma_helper.h>
+#include <drm/drm_of.h>
#include "sti_crtc.h"
#include "sti_drv.h"
@@ -423,8 +424,8 @@ static int sti_platform_probe(struct platform_device *pdev)
child_np = of_get_next_available_child(node, NULL);
while (child_np) {
- component_match_add(dev, &match, compare_of, child_np);
- of_node_put(child_np);
+ drm_of_component_match_add(dev, &match, compare_of,
+ child_np);
child_np = of_get_next_available_child(node, child_np);
}
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 0da9862ad8ed..b3c4ad605e81 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -18,6 +18,7 @@
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_of.h>
#include "sun4i_crtc.h"
#include "sun4i_drv.h"
@@ -239,7 +240,7 @@ static int sun4i_drv_add_endpoints(struct device *dev,
/* Add current component */
DRM_DEBUG_DRIVER("Adding component %s\n",
of_node_full_name(node));
- component_match_add(dev, match, compare_of, node);
+ drm_of_component_match_add(dev, match, compare_of, node);
count++;
}
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c
index 68e895021005..06a4c584f3cb 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_external.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c
@@ -10,6 +10,7 @@
#include <linux/component.h>
#include <linux/of_graph.h>
+#include <drm/drm_of.h>
#include "tilcdc_drv.h"
#include "tilcdc_external.h"
@@ -160,7 +161,8 @@ int tilcdc_get_external_components(struct device *dev,
dev_dbg(dev, "Subdevice node '%s' found\n", node->name);
if (match)
- component_match_add(dev, match, dev_match_of, node);
+ drm_of_component_match_add(dev, match, dev_match_of,
+ node);
of_node_put(node);
count++;
}
diff --git a/include/drm/drm_of.h b/include/drm/drm_of.h
index 3fd87b386ed7..d6b4c5587bbe 100644
--- a/include/drm/drm_of.h
+++ b/include/drm/drm_of.h
@@ -4,6 +4,7 @@
#include <linux/of_graph.h>
struct component_master_ops;
+struct component_match;
struct device;
struct drm_device;
struct drm_encoder;
@@ -12,6 +13,10 @@ struct device_node;
#ifdef CONFIG_OF
extern uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
struct device_node *port);
+extern void drm_of_component_match_add(struct device *master,
+ struct component_match **matchptr,
+ int (*compare)(struct device *, void *),
+ struct device_node *node);
extern int drm_of_component_probe(struct device *dev,
int (*compare_of)(struct device *, void *),
const struct component_master_ops *m_ops);
@@ -25,6 +30,13 @@ static inline uint32_t drm_of_find_possible_crtcs(struct drm_device *dev,
return 0;
}
+static void drm_of_component_match_add(struct device *master,
+ struct component_match **matchptr,
+ int (*compare)(struct device *, void *),
+ struct device_node *node)
+{
+}
+
static inline int
drm_of_component_probe(struct device *dev,
int (*compare_of)(struct device *, void *),
--
2.1.0
^ permalink raw reply related
* [PATCH] arm64: Cortex-A53 errata workaround: check for kernel addresses
From: Andre Przywara @ 2016-10-19 10:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018130047.GC15639@leverpostej>
Hi Mark,
On 18/10/16 14:00, Mark Rutland wrote:
> On Tue, Oct 18, 2016 at 12:16:27PM +0100, Andre Przywara wrote:
>> Commit 7dd01aef0557 ("arm64: trap userspace "dc cvau" cache operation on
>> errata-affected core") adds code to execute cache maintenance instructions
>> in the kernel on behalf of userland on CPUs with certain ARM CPU errata.
>> It turns out that the address hasn't been checked to be a valid user
>> space address, allowing userland to clean cache lines in kernel space.
>> Fix this by introducing an access_ok() check before executing the
>> instructions on behalf of userland, taking care of tagged pointers on
>> the way.
>
> It would be worth calling out why we need access_ok_tagged here (i.e.
> since this is not a syscall, the tag bits may validly be set, and we
> must mask them out to check the "real" address).
Agreed.
>
>> Reported-by: Kristina Martsenko <kristina.martsenko@arm.com>
>> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>> Cc: <stable@vger.kernel.org> # 4.8.x
>
> It would be good to have an explicit:
>
> Fixes: 7dd01aef0557 ("arm64: trap userspace "dc cvau" cache operation on errata-affected core")
>
>> ---
>> arch/arm64/include/asm/uaccess.h | 4 ++++
>> arch/arm64/kernel/traps.c | 32 ++++++++++++++++++++++++++++----
>> 2 files changed, 32 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
>> index bcaf6fb..f842b47 100644
>> --- a/arch/arm64/include/asm/uaccess.h
>> +++ b/arch/arm64/include/asm/uaccess.h
>> @@ -21,6 +21,7 @@
>> /*
>> * User space memory access functions
>> */
>> +#include <linux/bitops.h>
>> #include <linux/kasan-checks.h>
>> #include <linux/string.h>
>> #include <linux/thread_info.h>
>> @@ -103,6 +104,9 @@ static inline void set_fs(mm_segment_t fs)
>> })
>>
>> #define access_ok(type, addr, size) __range_ok(addr, size)
>> +#define access_ok_tagged(type, addr, size) access_ok(type, \
>> + sign_extend64(addr, 55), \
>> + size)
>> #define user_addr_max get_fs
>>
>> #define _ASM_EXTABLE(from, to) \
>> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
>> index 5ff020f..04ea0d7 100644
>> --- a/arch/arm64/kernel/traps.c
>> +++ b/arch/arm64/kernel/traps.c
>> @@ -447,6 +447,30 @@ void cpu_enable_cache_maint_trap(void *__unused)
>> : "=r" (res) \
>> : "r" (address), "i" (-EFAULT) )
>>
>> +enum {USER_CACHE_MAINT_DC_CIVAC, USER_CACHE_MAINT_IC_IVAU};
>> +
>> +static int do_user_cache_maint(int ins_type, unsigned long address)
>> +{
>> + int ret;
>> + unsigned long cl_size = cache_line_size();
>> +
>> + if (!access_ok_tagged(VERIFY_READ,
>> + round_down(address, cl_size),
>> + cl_size))
>> + return -EFAULT;
>
> We're only checking the D$ line size here; the I$ is not reported by
> cache_line_size().
>
> We may as well use PAGE_SIZE here, given cache lines have to be
> naturally aligned and permissions are at page granularity. There's no
> functional difference, but the value can't change under our feet, and
> the compiler may be able to better optimize by folding the contant in.
Yeah, I was thinking about that as well, but found cache_line_size() to
be more readable. I will replace this with PAGE_SIZE and a comment.
>> +
>> + switch (ins_type) {
>> + case USER_CACHE_MAINT_DC_CIVAC:
>> + __user_cache_maint("dc civac", address, ret);
>> + break;
>> + case USER_CACHE_MAINT_IC_IVAU:
>> + __user_cache_maint("ic ivau", address, ret);
>> + break;
>> + }
>> +
>> + return ret;
>> +}
>
> We could make this function a macro (passing in the instruction
> explicitly), and avoid the enum and switch.
I am not a big fan of putting too much stuff into a macro. After all the
kernel is written in C, not CPP ;-)
But now that the access check can use PAGE_SIZE, it should be much
simpler, so I will give it a try.
>
> Other than that, this looks good to me.
Thanks for looking at this!
Cheers,
Andre.
>
> Thanks,
> Mark.
>
>> +
>> static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
>> {
>> unsigned long address;
>> @@ -458,16 +482,16 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
>>
>> switch (crm) {
>> case ESR_ELx_SYS64_ISS_CRM_DC_CVAU: /* DC CVAU, gets promoted */
>> - __user_cache_maint("dc civac", address, ret);
>> + ret = do_user_cache_maint(USER_CACHE_MAINT_DC_CIVAC, address);
>> break;
>> case ESR_ELx_SYS64_ISS_CRM_DC_CVAC: /* DC CVAC, gets promoted */
>> - __user_cache_maint("dc civac", address, ret);
>> + ret = do_user_cache_maint(USER_CACHE_MAINT_DC_CIVAC, address);
>> break;
>> case ESR_ELx_SYS64_ISS_CRM_DC_CIVAC: /* DC CIVAC */
>> - __user_cache_maint("dc civac", address, ret);
>> + ret = do_user_cache_maint(USER_CACHE_MAINT_DC_CIVAC, address);
>> break;
>> case ESR_ELx_SYS64_ISS_CRM_IC_IVAU: /* IC IVAU */
>> - __user_cache_maint("ic ivau", address, ret);
>> + ret = do_user_cache_maint(USER_CACHE_MAINT_IC_IVAU, address);
>> break;
>> default:
>> force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
>> --
>> 2.9.0
>>
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>>
>
^ permalink raw reply
* [PATCH 0/5] Switch to the DT cpufreq policy on the Integrator
From: Arnd Bergmann @ 2016-10-19 10:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>
On Wednesday, October 19, 2016 11:59:09 AM CEST Linus Walleij wrote:
>
> If people are happy with this approach and approve of the patches
> I'd like an ACK from the cpufreq people and then merge the whole set
> through ARM SoC.
>
I don't see any hard dependency here, so I'd suggest to merge the
two cpufreq patches through the subsystem tree, and the ARM patches
through arm-soc.
The patches look fine.
Removing the custom driver of course means that we break machines
with old .dtb files, so we could consider leaving the driver in
place, but probably there is no need for integrator.
Arnd
^ permalink raw reply
* [PATCH] extcon: qcom-spmi-misc: Sync the extcon state on interrupt
From: Chanwoo Choi @ 2016-10-19 10:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018001602.18617-1-stephen.boyd@linaro.org>
Hi Stephen,
On 2016? 10? 18? 09:16, Stephen Boyd wrote:
> The driver was changed after submission to use the new style APIs
> like extcon_set_state(). Unfortunately, that only sets the state,
> and doesn't notify any consumers that the cable state has
> changed. Use extcon_set_state_sync() here instead so that we
> notify cable consumers of the state change. This fixes USB
> host-device role switching on the db8074 platform.
>
> Fixes: 38085c987f52 ("extcon: Add support for qcom SPMI PMIC USB id detection hardware")
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> drivers/extcon/extcon-qcom-spmi-misc.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/extcon/extcon-qcom-spmi-misc.c b/drivers/extcon/extcon-qcom-spmi-misc.c
> index ca957a5f4291..b8cde096a808 100644
> --- a/drivers/extcon/extcon-qcom-spmi-misc.c
> +++ b/drivers/extcon/extcon-qcom-spmi-misc.c
> @@ -51,7 +51,7 @@ static void qcom_usb_extcon_detect_cable(struct work_struct *work)
> if (ret)
> return;
>
> - extcon_set_state(info->edev, EXTCON_USB_HOST, !id);
> + extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !id);
> }
>
> static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id)
>
Applied it.
Best Regards,
Chanwoo Choi
^ permalink raw reply
* [PATCH 9/9] ARM: dts: amlogic: enable gpio interrupt controller on meson8
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm/boot/dts/meson8.dtsi | 11 +++++++++++
arch/arm/boot/dts/meson8b.dtsi | 11 +++++++++++
2 files changed, 22 insertions(+)
diff --git a/arch/arm/boot/dts/meson8.dtsi b/arch/arm/boot/dts/meson8.dtsi
index 45619f6162c5..713a22456ff1 100644
--- a/arch/arm/boot/dts/meson8.dtsi
+++ b/arch/arm/boot/dts/meson8.dtsi
@@ -43,6 +43,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/gpio/meson8-gpio.h>
/include/ "meson.dtsi"
@@ -91,6 +93,13 @@
clock-frequency = <141666666>;
};
+ gpio_interrupt: interrupt-controller at c1109880 {
+ compatible = "amlogic,meson8-gpio-intc";
+ reg = <0xc1109880 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
pinctrl_cbus: pinctrl at c1109880 {
compatible = "amlogic,meson8-cbus-pinctrl";
reg = <0xc1109880 0x10>;
@@ -106,6 +115,7 @@
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
+ interrupt-parent = <&gpio_interrupt>;
};
spi_nor_pins: nor {
@@ -148,6 +158,7 @@
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
+ interrupt-parent = <&gpio_interrupt>;
};
uart_ao_a_pins: uart_ao_a {
diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 41fd53671859..36a239a645f5 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -44,6 +44,8 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/meson8b-clkc.h>
#include <dt-bindings/gpio/meson8b-gpio.h>
#include <dt-bindings/reset/amlogic,meson8b-reset.h>
@@ -183,6 +185,13 @@
status = "disabled";
};
+ gpio_interrupt: interrupt-controller at c1109880 {
+ compatible = "amlogic,meson8b-gpio-intc";
+ reg = <0xc1109880 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
pinctrl_cbus: pinctrl at c1109880 {
compatible = "amlogic,meson8b-cbus-pinctrl";
reg = <0xc1109880 0x10>;
@@ -198,6 +207,7 @@
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
+ interrupt-parent = <&gpio_interrupt>;
};
};
@@ -215,6 +225,7 @@
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
+ interrupt-parent = <&gpio_interrupt>;
};
uart_ao_a_pins: uart_ao_a {
--
2.7.4
^ permalink raw reply related
* [PATCH 8/9] ARM64: dts: amlogic: enable gpio interrupt controller on gxbb
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index aad639ab0112..5208cb80b55e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -141,6 +141,13 @@
#reset-cells = <1>;
};
+ gpio_interrupt: interrupt-controller at 9880 {
+ compatible = "amlogic,meson-gxbb-gpio-intc";
+ reg = <0x0 0x9880 0x0 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
uart_B: serial at 84dc {
compatible = "amlogic,meson-uart";
reg = <0x0 0x84dc 0x0 0x14>;
@@ -238,6 +245,7 @@
reg-names = "mux", "pull", "gpio";
gpio-controller;
#gpio-cells = <2>;
+ interrupt-parent = <&gpio_interrupt>;
};
uart_ao_a_pins: uart_ao_a {
@@ -343,6 +351,7 @@
reg-names = "mux", "pull", "pull-enable", "gpio";
gpio-controller;
#gpio-cells = <2>;
+ interrupt-parent = <&gpio_interrupt>;
};
emmc_pins: emmc {
--
2.7.4
^ permalink raw reply related
* [PATCH 7/9] ARM: meson: enable MESON_IRQ_GPIO in Kconfig for meson8
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
Add select MESON_IRQ_GPIO in Kconfig for Amlogic's meson8 and meson8b SoC
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm/mach-meson/Kconfig | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig
index b6e3acc63e14..63157295cd9d 100644
--- a/arch/arm/mach-meson/Kconfig
+++ b/arch/arm/mach-meson/Kconfig
@@ -21,11 +21,13 @@ config MACH_MESON8
bool "Amlogic Meson8 SoCs support"
default ARCH_MESON
select MESON6_TIMER
+ select MESON_IRQ_GPIO
config MACH_MESON8B
bool "Amlogic Meson8b SoCs support"
default ARCH_MESON
select MESON6_TIMER
select COMMON_CLK_MESON8B
+ select MESON_IRQ_GPIO
endif
--
2.7.4
^ permalink raw reply related
* [PATCH 6/9] ARM64: meson: enable MESON_IRQ_GPIO in Kconfig
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
Add select MESON_IRQ_GPIO in Kconfig for Amlogic's meson SoC family
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
arch/arm64/Kconfig.platforms | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index cfbdf02ef566..846479d4492d 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -95,6 +95,7 @@ config ARCH_MESON
select PINCTRL_MESON
select COMMON_CLK_AMLOGIC
select COMMON_CLK_GXBB
+ select MESON_GPIO_IRQ
help
This enables support for the Amlogic S905 SoCs.
--
2.7.4
^ permalink raw reply related
* [PATCH 5/9] dt-bindings: pinctrl: meson: update gpio dt-bindings
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
Add description for the interrupt-parent property of the gpio sub-node
If provided here, this property must be a phandle to an interrupt
controller suitable for meson pinctrl, like the meson gpio interrupt
controller.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
index fe7fe0b03cfb..39932c4dfb32 100644
--- a/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/meson,pinctrl.txt
@@ -23,6 +23,10 @@ Required properties for sub-nodes are:
- gpio-controller: identifies the node as a gpio controller
- #gpio-cells: must be 2
+Optional property for sub-nodes is:
+ - interrupt-parent: must be a phandle to the meson gpio interrupt controller.
+ if this property is provided, enables gpio ability to generate interrupts
+
=== Other sub-nodes ===
Child nodes without the "gpio-controller" represent some desired
--
2.7.4
^ permalink raw reply related
* [PATCH 4/9] pinctrl: meson: allow gpio to request irq
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
Add the ability for gpio to request irq from the gpio interrupt controller
if present. We have to specificaly that the parent interrupt controller is
the gpio interrupt controller because gpio on meson SoCs can't generate
interrupt directly on the GIC.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/pinctrl/Kconfig | 2 +
drivers/pinctrl/meson/pinctrl-meson.c | 77 ++++++++++++++++++++++++++++++++++-
drivers/pinctrl/meson/pinctrl-meson.h | 1 +
3 files changed, 79 insertions(+), 1 deletion(-)
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 0e75d94972ba..d5bfbfcddab0 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -126,7 +126,9 @@ config PINCTRL_MESON
select PINCONF
select GENERIC_PINCONF
select GPIOLIB
+ select IRQ_DOMAIN
select OF_GPIO
+ select OF_IRQ
select REGMAP_MMIO
config PINCTRL_OXNAS
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index 57122eda155a..fd3c1d44978b 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -50,6 +50,7 @@
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
+#include <linux/of_irq.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinctrl.h>
@@ -481,6 +482,58 @@ static void meson_gpio_set(struct gpio_chip *chip, unsigned gpio, int value)
value ? BIT(bit) : 0);
}
+static int meson_gpio_to_hwirq(struct meson_bank *bank, unsigned int offset)
+{
+ unsigned int hwirq;
+
+ if (bank->irq_first < 0)
+ /* this bank cannot generate irqs */
+ return -1;
+
+ hwirq = offset - bank->first + bank->irq_first;
+
+ if (hwirq > bank->irq_last)
+ /* this pin cannot generate irqs */
+ return -1;
+
+ return hwirq;
+}
+
+static int meson_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+ struct meson_pinctrl *pc = gpiochip_get_data(chip);
+ struct meson_bank *bank;
+ struct irq_fwspec fwspec;
+ unsigned int hwirq;
+ int ret;
+
+ ret = meson_get_bank(pc, offset, &bank);
+ if (ret)
+ return ret;
+
+ /*
+ * The interrupt controller might be missing, in such case we can't
+ * provide an interrupt for a pin
+ */
+ if (is_fwnode_irqchip(pc->fwnode)) {
+ dev_info(pc->dev, "interrupt controller not found\n");
+ return 0;
+ }
+
+ hwirq = meson_gpio_to_hwirq(bank, offset);
+ if (hwirq < 0) {
+ dev_dbg(pc->dev, "no interrupt for pin %u\n", offset);
+ return 0;
+ }
+
+ fwspec.fwnode = pc->fwnode;
+ fwspec.param_count = 2;
+ fwspec.param[0] = hwirq;
+ fwspec.param[1] = IRQ_TYPE_NONE;
+
+ return irq_create_fwspec_mapping(&fwspec);
+}
+
static int meson_gpio_get(struct gpio_chip *chip, unsigned gpio)
{
struct meson_pinctrl *pc = gpiochip_get_data(chip);
@@ -539,6 +592,7 @@ static int meson_gpiolib_register(struct meson_pinctrl *pc)
pc->chip.direction_output = meson_gpio_direction_output;
pc->chip.get = meson_gpio_get;
pc->chip.set = meson_gpio_set;
+ pc->chip.to_irq = meson_gpio_to_irq;
pc->chip.base = pc->data->pin_base;
pc->chip.ngpio = pc->data->num_pins;
pc->chip.can_sleep = false;
@@ -598,6 +652,27 @@ static struct regmap *meson_map_resource(struct meson_pinctrl *pc,
return devm_regmap_init_mmio(pc->dev, base, &meson_regmap_config);
}
+static int meson_pinctrl_get_irq_gpio_intc(struct meson_pinctrl *pc,
+ struct device_node *node)
+{
+ struct device_node *np;
+
+ np = of_irq_find_parent(node);
+ if (unlikely(!np)) {
+ dev_err(pc->dev, "interrupt parent not found\n");
+ return -EINVAL;
+ }
+
+ if (!of_device_is_compatible(np, pc->data->irq_compat)) {
+ dev_info(pc->dev, "gpio interrupt disabled\n");
+ pc->fwnode = NULL;
+ }
+
+ pc->fwnode = of_node_to_fwnode(np);
+
+ return 0;
+}
+
static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
struct device_node *node)
{
@@ -643,7 +718,7 @@ static int meson_pinctrl_parse_dt(struct meson_pinctrl *pc,
return PTR_ERR(pc->reg_gpio);
}
- return 0;
+ return meson_pinctrl_get_irq_gpio_intc(pc, gpio_np);
}
static int meson_pinctrl_probe(struct platform_device *pdev)
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index b90d69e366df..2e6c83adbd1f 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -123,6 +123,7 @@ struct meson_pinctrl {
struct regmap *reg_gpio;
struct gpio_chip chip;
struct device_node *of_node;
+ struct fwnode_handle *fwnode;
};
#define PIN(x, b) (b + x)
--
2.7.4
^ permalink raw reply related
* [PATCH 3/9] pinctrl: meson: update pinctrl data with gpio irq data
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
This patch extends meson's pinctrl SoC specific data by adding the gpio
irq base number and the compatible controller for each SoC. This will
allow gpios to request an interrupt on the gpio interrupt controller
using this base irq number the pin offset inbank
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 24 +++++++++++----------
drivers/pinctrl/meson/pinctrl-meson.h | 16 +++++++++-----
drivers/pinctrl/meson/pinctrl-meson8.c | 22 ++++++++++---------
drivers/pinctrl/meson/pinctrl-meson8b.c | 34 +++++++++++++++++++++---------
4 files changed, 60 insertions(+), 36 deletions(-)
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
index c3928aa3fefa..ed8a1222de3b 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c
@@ -715,24 +715,25 @@ static struct meson_pmx_func meson_gxbb_aobus_functions[] = {
};
static struct meson_bank meson_gxbb_periphs_banks[] = {
- /* name first last pullen pull dir out in */
- BANK("X", PIN(GPIOX_0, EE_OFF), PIN(GPIOX_22, EE_OFF), 4, 0, 4, 0, 12, 0, 13, 0, 14, 0),
- BANK("Y", PIN(GPIOY_0, EE_OFF), PIN(GPIOY_16, EE_OFF), 1, 0, 1, 0, 3, 0, 4, 0, 5, 0),
- BANK("DV", PIN(GPIODV_0, EE_OFF), PIN(GPIODV_29, EE_OFF), 0, 0, 0, 0, 0, 0, 1, 0, 2, 0),
- BANK("H", PIN(GPIOH_0, EE_OFF), PIN(GPIOH_3, EE_OFF), 1, 20, 1, 20, 3, 20, 4, 20, 5, 20),
- BANK("Z", PIN(GPIOZ_0, EE_OFF), PIN(GPIOZ_15, EE_OFF), 3, 0, 3, 0, 9, 0, 10, 0, 11, 0),
- BANK("CARD", PIN(CARD_0, EE_OFF), PIN(CARD_6, EE_OFF), 2, 20, 2, 20, 6, 20, 7, 20, 8, 20),
- BANK("BOOT", PIN(BOOT_0, EE_OFF), PIN(BOOT_17, EE_OFF), 2, 0, 2, 0, 6, 0, 7, 0, 8, 0),
- BANK("CLK", PIN(GPIOCLK_0, EE_OFF), PIN(GPIOCLK_3, EE_OFF), 3, 28, 3, 28, 9, 28, 10, 28, 11, 28),
+ /* name first last irq pullen pull dir out in */
+ BANK("X", PIN(GPIOX_0, EE_OFF), PIN(GPIOX_22, EE_OFF), 106, 128, 4, 0, 4, 0, 12, 0, 13, 0, 14, 0),
+ BANK("Y", PIN(GPIOY_0, EE_OFF), PIN(GPIOY_16, EE_OFF), 89, 105, 1, 0, 1, 0, 3, 0, 4, 0, 5, 0),
+ BANK("DV", PIN(GPIODV_0, EE_OFF), PIN(GPIODV_29, EE_OFF), 59, 88, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0),
+ BANK("H", PIN(GPIOH_0, EE_OFF), PIN(GPIOH_3, EE_OFF), 30, 33, 1, 20, 1, 20, 3, 20, 4, 20, 5, 20),
+ BANK("Z", PIN(GPIOZ_0, EE_OFF), PIN(GPIOZ_15, EE_OFF), 14, 29, 3, 0, 3, 0, 9, 0, 10, 0, 11, 0),
+ BANK("CARD", PIN(CARD_0, EE_OFF), PIN(CARD_6, EE_OFF), 52, 58, 2, 20, 2, 20, 6, 20, 7, 20, 8, 20),
+ BANK("BOOT", PIN(BOOT_0, EE_OFF), PIN(BOOT_17, EE_OFF), 34, 51, 2, 0, 2, 0, 6, 0, 7, 0, 8, 0),
+ BANK("CLK", PIN(GPIOCLK_0, EE_OFF), PIN(GPIOCLK_3, EE_OFF), 129, 132, 3, 28, 3, 28, 9, 28, 10, 28, 11, 28),
};
static struct meson_bank meson_gxbb_aobus_banks[] = {
- /* name first last pullen pull dir out in */
- BANK("AO", PIN(GPIOAO_0, 0), PIN(GPIOAO_13, 0), 0, 0, 0, 16, 0, 0, 0, 16, 1, 0),
+ /* name first last irq pullen pull dir out in */
+ BANK("AO", PIN(GPIOAO_0, 0), PIN(GPIOAO_13, 0), 0, 13, 0, 0, 0, 16, 0, 0, 0, 16, 1, 0),
};
struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
.name = "periphs-banks",
+ .irq_compat = "amlogic,meson-gxbb-gpio-intc",
.pin_base = 14,
.pins = meson_gxbb_periphs_pins,
.groups = meson_gxbb_periphs_groups,
@@ -746,6 +747,7 @@ struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = {
struct meson_pinctrl_data meson_gxbb_aobus_pinctrl_data = {
.name = "aobus-banks",
+ .irq_compat = "amlogic,meson-gxbb-gpio-intc",
.pin_base = 0,
.pins = meson_gxbb_aobus_pins,
.groups = meson_gxbb_aobus_groups,
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index 98b5080650c1..b90d69e366df 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -81,6 +81,7 @@ enum meson_reg_type {
* @name: bank name
* @first: first pin of the bank
* @last: last pin of the bank
+ * @irq: hwirq base number of the bank
* @regs: array of register descriptors
*
* A bank represents a set of pins controlled by a contiguous set of
@@ -92,11 +93,14 @@ struct meson_bank {
const char *name;
unsigned int first;
unsigned int last;
+ int irq_first;
+ int irq_last;
struct meson_reg_desc regs[NUM_REG];
};
struct meson_pinctrl_data {
const char *name;
+ const char *irq_compat;
const struct pinctrl_pin_desc *pins;
struct meson_pmx_group *groups;
struct meson_pmx_func *funcs;
@@ -147,12 +151,14 @@ struct meson_pinctrl {
.num_groups = ARRAY_SIZE(fn ## _groups), \
}
-#define BANK(n, f, l, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
+#define BANK(n, f, l, fi, li, per, peb, pr, pb, dr, db, or, ob, ir, ib) \
{ \
- .name = n, \
- .first = f, \
- .last = l, \
- .regs = { \
+ .name = n, \
+ .first = f, \
+ .last = l, \
+ .irq_first = fi, \
+ .irq_last = li, \
+ .regs = { \
[REG_PULLEN] = { per, peb }, \
[REG_PULL] = { pr, pb }, \
[REG_DIR] = { dr, db }, \
diff --git a/drivers/pinctrl/meson/pinctrl-meson8.c b/drivers/pinctrl/meson/pinctrl-meson8.c
index 07f1cb21c1b8..eddab1091408 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8.c
@@ -916,23 +916,24 @@ static struct meson_pmx_func meson8_aobus_functions[] = {
};
static struct meson_bank meson8_cbus_banks[] = {
- /* name first last pullen pull dir out in */
- BANK("X", PIN(GPIOX_0, 0), PIN(GPIOX_21, 0), 4, 0, 4, 0, 0, 0, 1, 0, 2, 0),
- BANK("Y", PIN(GPIOY_0, 0), PIN(GPIOY_16, 0), 3, 0, 3, 0, 3, 0, 4, 0, 5, 0),
- BANK("DV", PIN(GPIODV_0, 0), PIN(GPIODV_29, 0), 0, 0, 0, 0, 7, 0, 8, 0, 9, 0),
- BANK("H", PIN(GPIOH_0, 0), PIN(GPIOH_9, 0), 1, 16, 1, 16, 9, 19, 10, 19, 11, 19),
- BANK("Z", PIN(GPIOZ_0, 0), PIN(GPIOZ_14, 0), 1, 0, 1, 0, 3, 17, 4, 17, 5, 17),
- BANK("CARD", PIN(CARD_0, 0), PIN(CARD_6, 0), 2, 20, 2, 20, 0, 22, 1, 22, 2, 22),
- BANK("BOOT", PIN(BOOT_0, 0), PIN(BOOT_18, 0), 2, 0, 2, 0, 9, 0, 10, 0, 11, 0),
+ /* name first last irq pullen pull dir out in */
+ BANK("X", PIN(GPIOX_0, 0), PIN(GPIOX_21, 0), 112, 133, 4, 0, 4, 0, 0, 0, 1, 0, 2, 0),
+ BANK("Y", PIN(GPIOY_0, 0), PIN(GPIOY_16, 0), 95, 111, 3, 0, 3, 0, 3, 0, 4, 0, 5, 0),
+ BANK("DV", PIN(GPIODV_0, 0), PIN(GPIODV_29, 0), 65, 94, 0, 0, 0, 0, 7, 0, 8, 0, 9, 0),
+ BANK("H", PIN(GPIOH_0, 0), PIN(GPIOH_9, 0), 29, 38, 1, 16, 1, 16, 9, 19, 10, 19, 11, 19),
+ BANK("Z", PIN(GPIOZ_0, 0), PIN(GPIOZ_14, 0), 14, 28, 1, 0, 1, 0, 3, 17, 4, 17, 5, 17),
+ BANK("CARD", PIN(CARD_0, 0), PIN(CARD_6, 0), 58, 64, 2, 20, 2, 20, 0, 22, 1, 22, 2, 22),
+ BANK("BOOT", PIN(BOOT_0, 0), PIN(BOOT_18, 0), 39, 57, 2, 0, 2, 0, 9, 0, 10, 0, 11, 0),
};
static struct meson_bank meson8_aobus_banks[] = {
- /* name first last pullen pull dir out in */
- BANK("AO", PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0, 0, 0, 16, 0, 0, 0, 16, 1, 0),
+ /* name first last irq pullen pull dir out in */
+ BANK("AO", PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0, 13, 0, 0, 0, 16, 0, 0, 0, 16, 1, 0),
};
struct meson_pinctrl_data meson8_cbus_pinctrl_data = {
.name = "cbus-banks",
+ .irq_compat = "amlogic,meson8-gpio-intc",
.pin_base = 0,
.pins = meson8_cbus_pins,
.groups = meson8_cbus_groups,
@@ -946,6 +947,7 @@ struct meson_pinctrl_data meson8_cbus_pinctrl_data = {
struct meson_pinctrl_data meson8_aobus_pinctrl_data = {
.name = "ao-bank",
+ .irq_compat = "amlogic,meson8-gpio-intc",
.pin_base = 120,
.pins = meson8_aobus_pins,
.groups = meson8_aobus_groups,
diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c
index 76f077f18193..d7505f492639 100644
--- a/drivers/pinctrl/meson/pinctrl-meson8b.c
+++ b/drivers/pinctrl/meson/pinctrl-meson8b.c
@@ -124,6 +124,12 @@ static const struct pinctrl_pin_desc meson8b_aobus_pins[] = {
MESON_PIN(GPIOAO_11, AO_OFF),
MESON_PIN(GPIOAO_12, AO_OFF),
MESON_PIN(GPIOAO_13, AO_OFF),
+
+ /*
+ * The following 2 pins are not mentionned in the public datasheet
+ * According to this datasheet, they can't be used with the gpio
+ * interrupt controller
+ */
MESON_PIN(GPIO_BSD_EN, AO_OFF),
MESON_PIN(GPIO_TEST_N, AO_OFF),
};
@@ -881,23 +887,30 @@ static struct meson_pmx_func meson8b_aobus_functions[] = {
};
static struct meson_bank meson8b_cbus_banks[] = {
- /* name first last pullen pull dir out in */
- BANK("X", PIN(GPIOX_0, 0), PIN(GPIOX_21, 0), 4, 0, 4, 0, 0, 0, 1, 0, 2, 0),
- BANK("Y", PIN(GPIOY_0, 0), PIN(GPIOY_14, 0), 3, 0, 3, 0, 3, 0, 4, 0, 5, 0),
- BANK("DV", PIN(GPIODV_9, 0), PIN(GPIODV_29, 0), 0, 0, 0, 0, 7, 0, 8, 0, 9, 0),
- BANK("H", PIN(GPIOH_0, 0), PIN(GPIOH_9, 0), 1, 16, 1, 16, 9, 19, 10, 19, 11, 19),
- BANK("CARD", PIN(CARD_0, 0), PIN(CARD_6, 0), 2, 20, 2, 20, 0, 22, 1, 22, 2, 22),
- BANK("BOOT", PIN(BOOT_0, 0), PIN(BOOT_18, 0), 2, 0, 2, 0, 9, 0, 10, 0, 11, 0),
- BANK("DIF", PIN(DIF_0_P, 0), PIN(DIF_4_N, 0), 5, 8, 5, 8, 12, 12, 13, 12, 14, 12),
+ /* name first last irq pullen pull dir out in */
+ BANK("X", PIN(GPIOX_0, 0), PIN(GPIOX_21, 0), 97, 118, 4, 0, 4, 0, 0, 0, 1, 0, 2, 0),
+ BANK("Y", PIN(GPIOY_0, 0), PIN(GPIOY_14, 0), 80, 96, 3, 0, 3, 0, 3, 0, 4, 0, 5, 0),
+ BANK("DV", PIN(GPIODV_9, 0), PIN(GPIODV_29, 0), 59, 79, 0, 0, 0, 0, 7, 0, 8, 0, 9, 0),
+ BANK("H", PIN(GPIOH_0, 0), PIN(GPIOH_9, 0), 14, 23, 1, 16, 1, 16, 9, 19, 10, 19, 11, 19),
+ BANK("CARD", PIN(CARD_0, 0), PIN(CARD_6, 0), 43, 49, 2, 20, 2, 20, 0, 22, 1, 22, 2, 22),
+ BANK("BOOT", PIN(BOOT_0, 0), PIN(BOOT_18, 0), 24, 42, 2, 0, 2, 0, 9, 0, 10, 0, 11, 0),
+
+ /*
+ * The following bank is not mentionned in the public datasheet
+ * There is no information whether it can be used with the gpio
+ * interrupt controller
+ */
+ BANK("DIF", PIN(DIF_0_P, 0), PIN(DIF_4_N, 0), -1, -1, 5, 8, 5, 8, 12, 12, 13, 12, 14, 12),
};
static struct meson_bank meson8b_aobus_banks[] = {
- /* name first last pullen pull dir out in */
- BANK("AO", PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0, 0, 0, 16, 0, 0, 0, 16, 1, 0),
+ /* name first last irq pullen pull dir out in */
+ BANK("AO", PIN(GPIOAO_0, AO_OFF), PIN(GPIO_TEST_N, AO_OFF), 0, 13, 0, 0, 0, 16, 0, 0, 0, 16, 1, 0),
};
struct meson_pinctrl_data meson8b_cbus_pinctrl_data = {
.name = "cbus-banks",
+ .irq_compat = "amlogic,meson8b-gpio-intc",
.pin_base = 0,
.pins = meson8b_cbus_pins,
.groups = meson8b_cbus_groups,
@@ -911,6 +924,7 @@ struct meson_pinctrl_data meson8b_cbus_pinctrl_data = {
struct meson_pinctrl_data meson8b_aobus_pinctrl_data = {
.name = "aobus-banks",
+ .irq_compat = "amlogic,meson8b-gpio-intc",
.pin_base = 130,
.pins = meson8b_aobus_pins,
.groups = meson8b_aobus_groups,
--
2.7.4
^ permalink raw reply related
* [PATCH 2/9] dt-bindings: interrupt-controller: add DT binding for meson GPIO interrupt controller
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
This commit adds the device tree bindings description for Amlogic's GPIO
interrupt controller available on the meson8, meson8b and gxbb SoC families
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
Rob, I did not include the Ack you gave for the RFC as bindings have slightly
changed. Only the interrupt property has be removed following a discussion I
had with Marc.
.../amlogic,meson-gpio-intc.txt | 31 ++++++++++++++++++++++
1 file changed, 31 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
diff --git a/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
new file mode 100644
index 000000000000..2464d9a0865d
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
@@ -0,0 +1,31 @@
+Amlogic meson GPIO interrupt controller
+
+Meson SoCs contains an interrupt controller which is able watch the SoC pads
+and generate an interrupt on edges or level. The controller is essentially a
+256 pads to 8 GIC interrupt multiplexer, with a filter block to select edge
+or level and polarity. We don?t expose all 256 mux inputs because the
+documentation shows that upper part is not mapped to any pad. The actual number
+of interrupt exposed depends on the SoC.
+
+Required properties:
+
+- compatible : should be either
+ "amlogic,meson8-gpio-intc? for meson8 SoCs (AML7826MX) or
+ ?amlogic,meson8b-gpio-intc? for meson8b SoCs (S805) or
+ ?amlogic,meson-gxbb-gpio-intc? for GXBB SoCs (S905)
+- interrupt-parent : a phandle to the GIC the interrupts are routed to.
+ Usually this is provided at the root level of the device tree as it is
+ common to most of the SoC
+- reg : Specifies base physical address and size of the registers.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ interrupt source. The value must be 2.
+
+Example:
+
+gpio_interrupt: interrupt-controller at 9880 {
+ compatible = "amlogic,meson-gxbb-gpio-intc";
+ reg = <0x0 0x9880 0x0 0x10>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+};
--
2.7.4
^ permalink raw reply related
* [PATCH 1/9] irqchip: meson: add support for gpio interrupt controller
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871709-8359-1-git-send-email-jbrunet@baylibre.com>
Add support for the interrupt gpio controller found on Amlogic's meson
SoC family.
Unlike what the IP name suggest, it is not directly linked to the gpio
subsystem. It is actually an independent IP that is able to spy on the
SoC pad. For that purpose, it can mux and filter (edge or level and
polarity) any single SoC pad to one of the 8 GIC's interrupts it owns.
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
drivers/irqchip/Kconfig | 9 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-meson-gpio.c | 423 +++++++++++++++++++++++++++++++++++++++
3 files changed, 433 insertions(+)
create mode 100644 drivers/irqchip/irq-meson-gpio.c
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 82b0b5daf3f5..168837263e80 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -279,3 +279,12 @@ config EZNPS_GIC
config STM32_EXTI
bool
select IRQ_DOMAIN
+
+config MESON_GPIO_IRQ
+ bool "Meson GPIO Interrupt Multiplexer"
+ depends on ARCH_MESON || COMPILE_TEST
+ select IRQ_DOMAIN
+ select IRQ_DOMAIN_HIERARCHY
+ help
+ Support Meson SoC Family GPIO Interrupt Multiplexer
+
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index e4dbfc85abdb..33f913d037d0 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -74,3 +74,4 @@ obj-$(CONFIG_LS_SCFG_MSI) += irq-ls-scfg-msi.o
obj-$(CONFIG_EZNPS_GIC) += irq-eznps.o
obj-$(CONFIG_ARCH_ASPEED) += irq-aspeed-vic.o
obj-$(CONFIG_STM32_EXTI) += irq-stm32-exti.o
+obj-$(CONFIG_MESON_GPIO_IRQ) += irq-meson-gpio.o
diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c
new file mode 100644
index 000000000000..869b4df8c483
--- /dev/null
+++ b/drivers/irqchip/irq-meson-gpio.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ * Copyright (c) 2016 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License 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/>.
+ * The full GNU General Public License is included in this distribution
+ * in the file called COPYING.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define IRQ_FREE (-1)
+
+#define REG_EDGE_POL 0x00
+#define REG_PIN_03_SEL 0x04
+#define REG_PIN_47_SEL 0x08
+#define REG_FILTER_SEL 0x0c
+
+#define REG_EDGE_POL_MASK(x) (BIT(x) | BIT(16 + (x)))
+#define REG_EDGE_POL_EDGE(x) BIT(x)
+#define REG_EDGE_POL_LOW(x) BIT(16 + (x))
+#define REG_PIN_SEL_SHIFT(x) (((x) % 4) * 8)
+#define REG_FILTER_SEL_SHIFT(x) ((x) * 4)
+
+struct meson_gpio_irq_params {
+ unsigned int nhwirq;
+ irq_hw_number_t *source;
+ int nsource;
+};
+
+struct meson_gpio_irq_domain {
+ void __iomem *base;
+ int *map;
+ const struct meson_gpio_irq_params *params;
+};
+
+struct meson_gpio_irq_chip_data {
+ void __iomem *base;
+ int index;
+};
+
+static irq_hw_number_t meson_parent_hwirqs[] = {
+ 64, 65, 66, 67, 68, 69, 70, 71,
+};
+
+static const struct meson_gpio_irq_params meson8_params = {
+ .nhwirq = 134,
+ .source = meson_parent_hwirqs,
+ .nsource = ARRAY_SIZE(meson_parent_hwirqs),
+};
+
+static const struct meson_gpio_irq_params meson8b_params = {
+ .nhwirq = 119,
+ .source = meson_parent_hwirqs,
+ .nsource = ARRAY_SIZE(meson_parent_hwirqs),
+};
+
+static const struct meson_gpio_irq_params meson_gxbb_params = {
+ .nhwirq = 133,
+ .source = meson_parent_hwirqs,
+ .nsource = ARRAY_SIZE(meson_parent_hwirqs),
+};
+
+static const struct of_device_id meson_irq_gpio_matches[] = {
+ {
+ .compatible = "amlogic,meson8-gpio-intc",
+ .data = &meson8_params
+ },
+ {
+ .compatible = "amlogic,meson8b-gpio-intc",
+ .data = &meson8b_params
+ },
+ {
+ .compatible = "amlogic,meson-gxbb-gpio-intc",
+ .data = &meson_gxbb_params
+ },
+ {}
+};
+
+static void meson_gpio_irq_update_bits(void __iomem *base, unsigned int reg,
+ u32 mask, u32 val)
+{
+ u32 tmp;
+
+ tmp = readl(base + reg);
+ tmp &= ~mask;
+ tmp |= val;
+
+ writel(tmp, base + reg);
+}
+
+static int meson_gpio_irq_get_index(struct meson_gpio_irq_domain *domain_data,
+ int hwirq)
+{
+ int i;
+
+ for (i = 0; i < domain_data->params->nsource; i++) {
+ if (domain_data->map[i] == hwirq)
+ return i;
+ }
+
+ return -1;
+}
+
+static int mesion_gpio_irq_map_source(struct meson_gpio_irq_domain *domain_data,
+ irq_hw_number_t hwirq,
+ irq_hw_number_t *source)
+{
+ int index;
+ unsigned int reg;
+
+ index = meson_gpio_irq_get_index(domain_data, IRQ_FREE);
+ if (index < 0) {
+ pr_err("No irq available\n");
+ return -ENOSPC;
+ }
+
+ domain_data->map[index] = hwirq;
+
+ reg = (index < 4) ? REG_PIN_03_SEL : REG_PIN_47_SEL;
+ meson_gpio_irq_update_bits(domain_data->base, reg,
+ 0xff << REG_PIN_SEL_SHIFT(index),
+ hwirq << REG_PIN_SEL_SHIFT(index));
+
+ *source = domain_data->params->source[index];
+
+ pr_debug("hwirq %lu assigned to channel %d - source %lu\n",
+ hwirq, index, *source);
+
+ return index;
+}
+
+static int meson_gpio_irq_type_setup(unsigned int type, void __iomem *base,
+ int index)
+{
+ u32 val = 0;
+
+ type &= IRQ_TYPE_SENSE_MASK;
+
+ if (type == IRQ_TYPE_EDGE_BOTH)
+ return -EINVAL;
+
+ if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+ val |= REG_EDGE_POL_EDGE(index);
+
+ if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING))
+ val |= REG_EDGE_POL_LOW(index);
+
+ meson_gpio_irq_update_bits(base, REG_EDGE_POL,
+ REG_EDGE_POL_MASK(index), val);
+
+ return 0;
+}
+
+static unsigned int meson_gpio_irq_type_output(unsigned int type)
+{
+ unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
+
+ type &= ~IRQ_TYPE_SENSE_MASK;
+
+ /*
+ * If the polarity of interrupt is low, the controller will
+ * invert the signal for gic
+ */
+ if (sense & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
+ type |= IRQ_TYPE_LEVEL_HIGH;
+ else if (sense & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+ type |= IRQ_TYPE_EDGE_RISING;
+
+ return type;
+}
+
+static int meson_gpio_irq_set_type(struct irq_data *data, unsigned int type)
+{
+ struct meson_gpio_irq_chip_data *cd = irq_data_get_irq_chip_data(data);
+ int ret;
+
+ pr_debug("set type of hwirq %lu to %u\n", data->hwirq, type);
+
+ ret = meson_gpio_irq_type_setup(type, cd->base, cd->index);
+ if (ret)
+ return ret;
+
+ return irq_chip_set_type_parent(data,
+ meson_gpio_irq_type_output(type));
+}
+
+static struct irq_chip meson_gpio_irq_chip = {
+ .name = "meson-gpio-irqchip",
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_set_type = meson_gpio_irq_set_type,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+#ifdef CONFIG_SMP
+ .irq_set_affinity = irq_chip_set_affinity_parent,
+#endif
+};
+
+static int meson_gpio_irq_domain_translate(struct irq_domain *domain,
+ struct irq_fwspec *fwspec,
+ unsigned long *hwirq,
+ unsigned int *type)
+{
+ if (is_of_node(fwspec->fwnode)) {
+ if (fwspec->param_count != 2)
+ return -EINVAL;
+
+ *hwirq = fwspec->param[0];
+ *type = fwspec->param[1];
+
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int meson_gpio_irq_allocate_gic_irq(struct irq_domain *domain,
+ unsigned int virq,
+ irq_hw_number_t source,
+ unsigned int type)
+{
+ struct irq_fwspec fwspec;
+
+ if (!irq_domain_get_of_node(domain->parent))
+ return -EINVAL;
+
+ fwspec.fwnode = domain->parent->fwnode;
+ fwspec.param_count = 3;
+ fwspec.param[0] = 0; /* SPI */
+ fwspec.param[1] = source;
+ fwspec.param[2] = meson_gpio_irq_type_output(type);
+
+ return irq_domain_alloc_irqs_parent(domain, virq, 1, &fwspec);
+}
+
+static int meson_gpio_irq_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs,
+ void *data)
+{
+ struct irq_fwspec *fwspec = data;
+ struct meson_gpio_irq_domain *domain_data = domain->host_data;
+ struct meson_gpio_irq_chip_data *cd;
+ unsigned long hwirq, source;
+ unsigned int type;
+ int i, index, ret;
+
+ ret = meson_gpio_irq_domain_translate(domain, fwspec, &hwirq, &type);
+ if (ret)
+ return ret;
+
+ pr_debug("irq %d, nr_irqs %d, hwirqs %lu\n", virq, nr_irqs, hwirq);
+
+ for (i = 0; i < nr_irqs; i++) {
+ index = mesion_gpio_irq_map_source(domain_data, hwirq + i,
+ &source);
+ if (index < 0)
+ return index;
+
+ ret = meson_gpio_irq_type_setup(type, domain_data->base,
+ index);
+ if (ret)
+ return ret;
+
+ cd = kzalloc(sizeof(*cd), GFP_KERNEL);
+ if (!cd)
+ return -ENOMEM;
+
+ cd->base = domain_data->base;
+ cd->index = index;
+
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &meson_gpio_irq_chip, cd);
+
+ ret = meson_gpio_irq_allocate_gic_irq(domain, virq + i,
+ source, type);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void meson_gpio_irq_domain_free(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs)
+{
+ struct meson_gpio_irq_domain *domain_data = domain->host_data;
+ struct meson_gpio_irq_chip_data *cd;
+ struct irq_data *irq_data;
+ int i;
+
+ for (i = 0; i < nr_irqs; i++) {
+ irq_data = irq_domain_get_irq_data(domain, virq + i);
+ cd = irq_data_get_irq_chip_data(irq_data);
+
+ domain_data->map[cd->index] = IRQ_FREE;
+ kfree(cd);
+ }
+
+ irq_domain_free_irqs_parent(domain, virq, nr_irqs);
+
+}
+
+static const struct irq_domain_ops meson_gpio_irq_domain_ops = {
+ .alloc = meson_gpio_irq_domain_alloc,
+ .free = meson_gpio_irq_domain_free,
+ .translate = meson_gpio_irq_domain_translate,
+};
+
+static int __init
+meson_gpio_irq_init_domain(struct device_node *node,
+ struct meson_gpio_irq_domain *domain_data,
+ const struct meson_gpio_irq_params *params)
+{
+ int i;
+ int nsource = params->nsource;
+ int *map;
+
+ map = kcalloc(nsource, sizeof(*map), GFP_KERNEL);
+ if (!map)
+ return -ENOMEM;
+
+ for (i = 0; i < nsource; i++)
+ map[i] = IRQ_FREE;
+
+ domain_data->map = map;
+ domain_data->params = params;
+
+ return 0;
+}
+
+static int __init meson_gpio_irq_of_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *domain, *parent_domain;
+ const struct of_device_id *match;
+ const struct meson_gpio_irq_params *params;
+ struct meson_gpio_irq_domain *domain_data;
+ int ret;
+
+ match = of_match_node(meson_irq_gpio_matches, node);
+ if (!match)
+ return -ENODEV;
+ params = match->data;
+
+ if (!parent) {
+ pr_err("missing parent interrupt node\n");
+ return -ENODEV;
+ }
+
+ parent_domain = irq_find_host(parent);
+ if (!parent_domain) {
+ pr_err("unable to obtain parent domain\n");
+ return -ENXIO;
+ }
+
+ domain_data = kzalloc(sizeof(*domain_data), GFP_KERNEL);
+ if (!domain_data)
+ return -ENOMEM;
+
+ domain_data->base = of_iomap(node, 0);
+ if (!domain_data->base) {
+ ret = -ENOMEM;
+ goto out_free_dev;
+ }
+
+ ret = meson_gpio_irq_init_domain(node, domain_data, params);
+ if (ret < 0)
+ goto out_free_dev_content;
+
+ domain = irq_domain_add_hierarchy(parent_domain, 0, params->nhwirq,
+ node, &meson_gpio_irq_domain_ops,
+ domain_data);
+
+ if (!domain) {
+ pr_err("failed to allocated domain\n");
+ ret = -ENOMEM;
+ goto out_free_dev_content;
+ }
+
+ pr_info("%d to %d gpio interrupt mux initialized\n",
+ params->nhwirq, params->nsource);
+
+ return 0;
+
+out_free_dev_content:
+ kfree(domain_data->map);
+ iounmap(domain_data->base);
+
+out_free_dev:
+ kfree(domain_data);
+
+ return ret;
+}
+
+IRQCHIP_DECLARE(meson8_gpio_intc, "amlogic,meson8-gpio-intc",
+ meson_gpio_irq_of_init);
+IRQCHIP_DECLARE(meson8b_gpio_intc, "amlogic,meson8b-gpio-intc",
+ meson_gpio_irq_of_init);
+IRQCHIP_DECLARE(gxbb_gpio_intc, "amlogic,meson-gxbb-gpio-intc",
+ meson_gpio_irq_of_init);
--
2.7.4
^ permalink raw reply related
* [PATCH 0/9] irqchip: meson: add support for the gpio interrupt controller
From: Jerome Brunet @ 2016-10-19 10:08 UTC (permalink / raw)
To: linux-arm-kernel
This patch series adds support for the GPIO interrupt controller found
on Amlogic's meson SoC families.
Unlike what the name suggests, this controller is not part of the SoC GPIO
subsystem. It's an indepedent controller which can watch almost all pad of
the SoC and generate and interrupt from it. Some pins, which are not part
of the public datasheet, don't seem to have this capability though.
Hardware wise, the controller is a 256 to 8 multiplexer. It can take up
to 256 input pads and route them to any of 8 GIC's interrupts. There is
also a filter block in the middle to select the appropriate edge or level.
The number of interrupt declared by the irqchip is lowered from 256 to the
actual number of signal routed to the controller on each SoC family. As we
have access to only 8 GIC?s interrupts, these are allocated when an
interrupt is requested from the controller, on a first come, first served
basis.
This series has been tested on Amlogic S905-P200 board with the front
panel power button. Directly passing an IRQ or using gpio_to_irq both work
with this driver.
This work is derived from the previous work of Carlo Caione [1].
Changes since RFC : [2]
* Remove interrupt property in device tree: the controller cannot generate
interrupts on its own and is merely routing the interrupt to the GIC,
therefore it should not use the interrupt property. This data is now
stored directly in the driver, same as the pinctrl data.
* Improve compatibility checking of meson pinctrl on its interrupt parent
to activate gpio_to_irq callback
* Drop IRQ_BOTH hack. Need more work to have an acceptable solution for
this
[1] : http://lkml.kernel.org/r/1448987062-31225-1-git-send-email-carlo at caione.org
[2] : http://lkml.kernel.org/r/1475593708-10526-1-git-send-email-jbrunet at baylibre.com
Jerome Brunet (9):
irqchip: meson: add support for gpio interrupt controller
dt-bindings: interrupt-controller: add DT binding for meson GPIO
interrupt controller
pinctrl: meson: update pinctrl data with gpio irq data
pinctrl: meson: allow gpio to request irq
dt-bindings: pinctrl: meson: update gpio dt-bindings
ARM64: meson: enable MESON_IRQ_GPIO in Kconfig
ARM: meson: enable MESON_IRQ_GPIO in Kconfig for meson8
ARM64: dts: amlogic: enable gpio interrupt controller on gxbb
ARM: dts: amlogic: enable gpio interrupt controller on meson8
.../amlogic,meson-gpio-intc.txt | 31 ++
.../devicetree/bindings/pinctrl/meson,pinctrl.txt | 4 +
arch/arm/boot/dts/meson8.dtsi | 11 +
arch/arm/boot/dts/meson8b.dtsi | 11 +
arch/arm/mach-meson/Kconfig | 2 +
arch/arm64/Kconfig.platforms | 1 +
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 9 +
drivers/irqchip/Kconfig | 9 +
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-meson-gpio.c | 423 +++++++++++++++++++++
drivers/pinctrl/Kconfig | 2 +
drivers/pinctrl/meson/pinctrl-meson-gxbb.c | 24 +-
drivers/pinctrl/meson/pinctrl-meson.c | 77 +++-
drivers/pinctrl/meson/pinctrl-meson.h | 17 +-
drivers/pinctrl/meson/pinctrl-meson8.c | 22 +-
drivers/pinctrl/meson/pinctrl-meson8b.c | 34 +-
16 files changed, 641 insertions(+), 37 deletions(-)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/amlogic,meson-gpio-intc.txt
create mode 100644 drivers/irqchip/irq-meson-gpio.c
--
2.7.4
^ permalink raw reply
* [PATCH V2] gpu/drm/exynos/exynos_hdmi - Unmap region obtained by of_iomap
From: Arvind Yadav @ 2016-10-19 10:04 UTC (permalink / raw)
To: linux-arm-kernel
Free memory mapping, if hdmi_probe is not successful.
Signed-off-by: Arvind Yadav <arvind.yadav.cs@gmail.com>
---
drivers/gpu/drm/exynos/exynos_hdmi.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 2275efe..ba28dec 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -1901,6 +1901,8 @@ err_disable_pm_runtime:
err_hdmiphy:
if (hdata->hdmiphy_port)
put_device(&hdata->hdmiphy_port->dev);
+ if (hdata->regs_hdmiphy)
+ iounmap(hdata->regs_hdmiphy);
err_ddc:
put_device(&hdata->ddc_adpt->dev);
@@ -1923,6 +1925,9 @@ static int hdmi_remove(struct platform_device *pdev)
if (hdata->hdmiphy_port)
put_device(&hdata->hdmiphy_port->dev);
+ if (hdata->regs_hdmiphy)
+ iounmap(hdata->regs_hdmiphy);
+
put_device(&hdata->ddc_adpt->dev);
return 0;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 5/5] cpufreq: retire the Integrator cpufreq driver
From: Linus Walleij @ 2016-10-19 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>
After switching the core module clocks controlling the Integrator
clock frequencies to the common clock framework, defining the
operating points in the device tree, and activating the generic
DT-based CPUfreq driver, we can retire the old Integrator
cpufreq driver.
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/cpufreq/Kconfig.arm | 8 --
drivers/cpufreq/Makefile | 1 -
drivers/cpufreq/integrator-cpufreq.c | 239 -----------------------------------
3 files changed, 248 deletions(-)
delete mode 100644 drivers/cpufreq/integrator-cpufreq.c
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index d89b8afe23b6..fdbc630272b3 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -60,14 +60,6 @@ config ARM_IMX6Q_CPUFREQ
If in doubt, say N.
-config ARM_INTEGRATOR
- tristate "CPUfreq driver for ARM Integrator CPUs"
- depends on ARCH_INTEGRATOR
- default y
- help
- This enables the CPUfreq driver for ARM Integrator CPUs.
- If in doubt, say Y.
-
config ARM_KIRKWOOD_CPUFREQ
def_bool MACH_KIRKWOOD
help
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 0a9b6a093646..7dde82179d62 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_UX500_SOC_DB8500) += dbx500-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
-obj-$(CONFIG_ARM_INTEGRATOR) += integrator-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
obj-$(CONFIG_ARM_MT8173_CPUFREQ) += mt8173-cpufreq.o
obj-$(CONFIG_ARM_OMAP2PLUS_CPUFREQ) += omap-cpufreq.o
diff --git a/drivers/cpufreq/integrator-cpufreq.c b/drivers/cpufreq/integrator-cpufreq.c
deleted file mode 100644
index 79e3ff2771a6..000000000000
--- a/drivers/cpufreq/integrator-cpufreq.c
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright (C) 2001-2002 Deep Blue Solutions Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * CPU support functions
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/cpufreq.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-
-#include <asm/mach-types.h>
-#include <asm/hardware/icst.h>
-
-static void __iomem *cm_base;
-/* The cpufreq driver only use the OSC register */
-#define INTEGRATOR_HDR_OSC_OFFSET 0x08
-#define INTEGRATOR_HDR_LOCK_OFFSET 0x14
-
-static struct cpufreq_driver integrator_driver;
-
-static const struct icst_params lclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 8,
- .vd_max = 132,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-static const struct icst_params cclk_params = {
- .ref = 24000000,
- .vco_max = ICST525_VCO_MAX_5V,
- .vco_min = ICST525_VCO_MIN,
- .vd_min = 12,
- .vd_max = 160,
- .rd_min = 24,
- .rd_max = 24,
- .s2div = icst525_s2div,
- .idx2s = icst525_idx2s,
-};
-
-/*
- * Validate the speed policy.
- */
-static int integrator_verify_policy(struct cpufreq_policy *policy)
-{
- struct icst_vco vco;
-
- cpufreq_verify_within_cpu_limits(policy);
-
- vco = icst_hz_to_vco(&cclk_params, policy->max * 1000);
- policy->max = icst_hz(&cclk_params, vco) / 1000;
-
- vco = icst_hz_to_vco(&cclk_params, policy->min * 1000);
- policy->min = icst_hz(&cclk_params, vco) / 1000;
-
- cpufreq_verify_within_cpu_limits(policy);
- return 0;
-}
-
-
-static int integrator_set_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- cpumask_t cpus_allowed;
- int cpu = policy->cpu;
- struct icst_vco vco;
- struct cpufreq_freqs freqs;
- u_int cm_osc;
-
- /*
- * Save this threads cpus_allowed mask.
- */
- cpus_allowed = current->cpus_allowed;
-
- /*
- * Bind to the specified CPU. When this call returns,
- * we should be running on the right CPU.
- */
- set_cpus_allowed_ptr(current, cpumask_of(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* get current setting */
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator())
- vco.s = (cm_osc >> 8) & 7;
- else if (machine_is_cintegrator())
- vco.s = 1;
- vco.v = cm_osc & 255;
- vco.r = 22;
- freqs.old = icst_hz(&cclk_params, vco) / 1000;
-
- /* icst_hz_to_vco rounds down -- so we need the next
- * larger freq in case of CPUFREQ_RELATION_L.
- */
- if (relation == CPUFREQ_RELATION_L)
- target_freq += 999;
- if (target_freq > policy->max)
- target_freq = policy->max;
- vco = icst_hz_to_vco(&cclk_params, target_freq * 1000);
- freqs.new = icst_hz(&cclk_params, vco) / 1000;
-
- if (freqs.old == freqs.new) {
- set_cpus_allowed_ptr(current, &cpus_allowed);
- return 0;
- }
-
- cpufreq_freq_transition_begin(policy, &freqs);
-
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator()) {
- cm_osc &= 0xfffff800;
- cm_osc |= vco.s << 8;
- } else if (machine_is_cintegrator()) {
- cm_osc &= 0xffffff00;
- }
- cm_osc |= vco.v;
-
- __raw_writel(0xa05f, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
- __raw_writel(cm_osc, cm_base + INTEGRATOR_HDR_OSC_OFFSET);
- __raw_writel(0, cm_base + INTEGRATOR_HDR_LOCK_OFFSET);
-
- /*
- * Restore the CPUs allowed mask.
- */
- set_cpus_allowed_ptr(current, &cpus_allowed);
-
- cpufreq_freq_transition_end(policy, &freqs, 0);
-
- return 0;
-}
-
-static unsigned int integrator_get(unsigned int cpu)
-{
- cpumask_t cpus_allowed;
- unsigned int current_freq;
- u_int cm_osc;
- struct icst_vco vco;
-
- cpus_allowed = current->cpus_allowed;
-
- set_cpus_allowed_ptr(current, cpumask_of(cpu));
- BUG_ON(cpu != smp_processor_id());
-
- /* detect memory etc. */
- cm_osc = __raw_readl(cm_base + INTEGRATOR_HDR_OSC_OFFSET);
-
- if (machine_is_integrator())
- vco.s = (cm_osc >> 8) & 7;
- else
- vco.s = 1;
- vco.v = cm_osc & 255;
- vco.r = 22;
-
- current_freq = icst_hz(&cclk_params, vco) / 1000; /* current freq */
-
- set_cpus_allowed_ptr(current, &cpus_allowed);
-
- return current_freq;
-}
-
-static int integrator_cpufreq_init(struct cpufreq_policy *policy)
-{
-
- /* set default policy and cpuinfo */
- policy->max = policy->cpuinfo.max_freq = 160000;
- policy->min = policy->cpuinfo.min_freq = 12000;
- policy->cpuinfo.transition_latency = 1000000; /* 1 ms, assumed */
-
- return 0;
-}
-
-static struct cpufreq_driver integrator_driver = {
- .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- .verify = integrator_verify_policy,
- .target = integrator_set_target,
- .get = integrator_get,
- .init = integrator_cpufreq_init,
- .name = "integrator",
-};
-
-static int __init integrator_cpufreq_probe(struct platform_device *pdev)
-{
- struct resource *res;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
-
- cm_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!cm_base)
- return -ENODEV;
-
- return cpufreq_register_driver(&integrator_driver);
-}
-
-static int __exit integrator_cpufreq_remove(struct platform_device *pdev)
-{
- return cpufreq_unregister_driver(&integrator_driver);
-}
-
-static const struct of_device_id integrator_cpufreq_match[] = {
- { .compatible = "arm,core-module-integrator"},
- { },
-};
-
-MODULE_DEVICE_TABLE(of, integrator_cpufreq_match);
-
-static struct platform_driver integrator_cpufreq_driver = {
- .driver = {
- .name = "integrator-cpufreq",
- .of_match_table = integrator_cpufreq_match,
- },
- .remove = __exit_p(integrator_cpufreq_remove),
-};
-
-module_platform_driver_probe(integrator_cpufreq_driver,
- integrator_cpufreq_probe);
-
-MODULE_AUTHOR("Russell M. King");
-MODULE_DESCRIPTION("cpufreq driver for ARM Integrator CPUs");
-MODULE_LICENSE("GPL");
--
2.7.4
^ permalink raw reply related
* [PATCH 4/5] ARM: defconfig: turn on the DT cpufreq for Integrator
From: Linus Walleij @ 2016-10-19 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>
The Integrators are now migrated to handle the CPUfreq
scaling using the generic devicetree CPUfreq driver using the
common clock framework and have the required device tree
modifications, so turn off the old driver and turn on the new
generic driver.
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/configs/integrator_defconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/configs/integrator_defconfig b/arch/arm/configs/integrator_defconfig
index 869faae67201..69cb8f1efcea 100644
--- a/arch/arm/configs/integrator_defconfig
+++ b/arch/arm/configs/integrator_defconfig
@@ -26,6 +26,7 @@ CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPUFREQ_DT=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
--
2.7.4
^ permalink raw reply related
* [PATCH 3/5] ARM: dts: Add Integrator/CP cpus node and operating points
From: Linus Walleij @ 2016-10-19 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>
This adds the cpus node to the Integrator/CP device tree so
that we have a proper placeholder to put in the DT-defined
operating points for the generic DT/OPP cpufreq driver,
along with two working operating points.
I have only put in 48 and 50 MHz because going to e.g. 36
MHz hangs the system when CLCD graphics are active.
Presumably the memory bus gets to slow to feed the display
and the systems hangs for this reason. The ideal solution
would be for the display controller to put constraints on
the memory bus frequency, but that need to be a separate
longer-term project.
We define a CPU node since this is required for cpufreq-dt,
however we do not define any compatible string for the CPU
since this architecture has pluggable CPU modules and we
do not know which one will be used. If necessary, the CPU
compatible can be filled in by the boot loader, but for
just cpufreq-dt it is not required.
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/boot/dts/integratorcp.dts | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/arch/arm/boot/dts/integratorcp.dts b/arch/arm/boot/dts/integratorcp.dts
index 1b5e4b006b72..97f38b57a702 100644
--- a/arch/arm/boot/dts/integratorcp.dts
+++ b/arch/arm/boot/dts/integratorcp.dts
@@ -13,6 +13,32 @@
bootargs = "root=/dev/ram0 console=ttyAMA0,38400n8 earlyprintk";
};
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at 0 {
+ device_type = "cpu";
+ /*
+ * Since the board has pluggable CPU modules, we
+ * cannot define a proper compatible here. Let the
+ * boot loader fill in the apropriate compatible
+ * string if necessary.
+ */
+ /* compatible = "arm,arm920t"; */
+ reg = <0>;
+ /*
+ * TBD comment.
+ */
+ /* kHz uV */
+ operating-points = <50000 0
+ 48000 0>;
+ clocks = <&cmcore>;
+ clock-names = "cpu";
+ clock-latency = <1000000>; /* 1 ms */
+ };
+ };
+
/*
* The Integrator/CP overall clocking architecture can be found in
* ARM DUI 0184B page 7-28 "Integrator/CP922T system clocks" which
--
2.7.4
^ permalink raw reply related
* [PATCH 2/5] ARM: dts: Add Integrator/AP cpus node and operating points
From: Linus Walleij @ 2016-10-19 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>
This adds the cpus node to the Integrator/AP device tree so
that we have a proper placeholder to put in the DT-defined
operating points for the generic DT/OPP cpufreq driver,
along with the proper operating points.
The old Integrator cpufreq driver would resolve the max
frequency to 71MHz, and the min frequency to 12 MHz, but
the clock driver can actually handle any frequency inbetween
so I picked a few select frequencies as OPPs. The cpufreq
framework doesn't seem to deal with sliding frequency scales,
only fixed points so 7 OPPs is better than 2 atleast.
We define a CPU node since this is required for cpufreq-dt,
however we do not define any compatible string for the CPU
since this architecture has pluggable CPU modules and we
do not know which one will be used. If necessary, the CPU
compatible can be filled in by the boot loader, but for
just cpufreq-dt it is not required.
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
arch/arm/boot/dts/integratorap.dts | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/arch/arm/boot/dts/integratorap.dts b/arch/arm/boot/dts/integratorap.dts
index 6f16d09dc5a4..e8b249f92fb3 100644
--- a/arch/arm/boot/dts/integratorap.dts
+++ b/arch/arm/boot/dts/integratorap.dts
@@ -10,6 +10,41 @@
compatible = "arm,integrator-ap";
dma-ranges = <0x80000000 0x0 0x80000000>;
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu at 0 {
+ device_type = "cpu";
+ /*
+ * Since the board has pluggable CPU modules, we
+ * cannot define a proper compatible here. Let the
+ * boot loader fill in the apropriate compatible
+ * string if necessary.
+ */
+ /* compatible = "arm,arm926ej-s"; */
+ reg = <0>;
+ /*
+ * The documentation in ARM DUI 0138E page 3-12 states
+ * that the maximum frequency for this clock is 200 MHz
+ * but painful trial-and-error has proved to me that it
+ * is actually just hanging the system above 71 MHz.
+ * Sad but true.
+ */
+ /* kHz uV */
+ operating-points = <71000 0
+ 66000 0
+ 60000 0
+ 48000 0
+ 36000 0
+ 24000 0
+ 12000 0>;
+ clocks = <&cmosc>;
+ clock-names = "cpu";
+ clock-latency = <1000000>; /* 1 ms */
+ };
+ };
+
aliases {
arm,timer-primary = &timer2;
arm,timer-secondary = &timer1;
--
2.7.4
^ permalink raw reply related
* [PATCH 1/5] cpufreq: enable the DT cpufreq driver on the Integrators
From: Linus Walleij @ 2016-10-19 9:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476871154-32243-1-git-send-email-linus.walleij@linaro.org>
This enables the generic DT and OPP-based cpufreq driver on the
ARM Integrator/AP and Integrator/CP.
Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Russell King <linux@armlinux.org.uk>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
drivers/cpufreq/cpufreq-dt-platdev.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 71267626456b..142a6f615e52 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -26,6 +26,9 @@ static const struct of_device_id machines[] __initconst = {
{ .compatible = "allwinner,sun8i-a83t", },
{ .compatible = "allwinner,sun8i-h3", },
+ { .compatible = "arm,integrator-ap", },
+ { .compatible = "arm,integrator-cp", },
+
{ .compatible = "hisilicon,hi6220", },
{ .compatible = "fsl,imx27", },
--
2.7.4
^ permalink raw reply related
* [PATCH 0/5] Switch to the DT cpufreq policy on the Integrator
From: Linus Walleij @ 2016-10-19 9:59 UTC (permalink / raw)
To: linux-arm-kernel
This switches the ARM Integrator/AP and Integrator/CP to use the
Device Tree cpufreq policy with its definition of operating points
using the generic OPP library.
The Integrators does not need to control a regulator to switch
frequency, only a clock. This clock and its device tree bindings
have been defined in the device tree and merged upstream for v4.9.
This approach provides a little better granularity on the
Integrator/AP where I defined a few operating points: before
this change the Integrator would just switch between min speed
(12 MHz) and max speed (71 MHz). Now it can switch between a
few arbitrarily chosen OPPs as in the examples below:
The following tests were made on the Integrator/AP:
/sys/devices/system/cpu/cpufreq/policy0 echo ondemand > scaling_governor
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 24000000 Hz
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 24000000 Hz
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 24000000 Hz --> 12000000 Hz
The switch from 12 to 24 MHz is triggered by as little as using the
command line with the ondemand governor. If we do this:
yes > /dev/null &
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 36000000 Hz
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 36000000 Hz --> 71000000 Hz
pkill yes
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
So the algorithm is indeed using all the OPPs.
Also as a confirmation test to make sure performance is affected by the
speed changes, we set the performance governor and:
echo 12000 > scaling_max_freq
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 71000000 Hz --> 12000000 Hz
time find /sys|sort|uniq > /dev/null
real 0m 45.51s
user 0m 11.15s
sys 0m 26.74s
echo 71000 > scaling_max_freq
cpu cpu0: dev_pm_opp_set_rate: switching OPP: 12000000 Hz --> 71000000 Hz
time find /sys|sort|uniq
> /dev/null
real 0m 9.13s
user 0m 2.35s
sys 0m 5.50s
So it is working.
If people are happy with this approach and approve of the patches
I'd like an ACK from the cpufreq people and then merge the whole set
through ARM SoC.
Linus Walleij (5):
cpufreq: enable the DT cpufreq driver on the Integrators
ARM: dts: Add Integrator/AP cpus node and operating points
ARM: dts: Add Integrator/CP cpus node and operating points
ARM: defconfig: turn on the DT cpufreq for Integrator
cpufreq: retire the Integrator cpufreq driver
arch/arm/boot/dts/integratorap.dts | 35 +++++
arch/arm/boot/dts/integratorcp.dts | 26 ++++
arch/arm/configs/integrator_defconfig | 1 +
drivers/cpufreq/Kconfig.arm | 8 --
drivers/cpufreq/Makefile | 1 -
drivers/cpufreq/cpufreq-dt-platdev.c | 3 +
drivers/cpufreq/integrator-cpufreq.c | 239 ----------------------------------
7 files changed, 65 insertions(+), 248 deletions(-)
delete mode 100644 drivers/cpufreq/integrator-cpufreq.c
--
2.7.4
^ permalink raw reply
* [PATCH] clk: sunxi-ng: sun6i-a31: Force AHB1 clock to use PLL6 as parent
From: Maxime Ripard @ 2016-10-19 9:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018054209.24546-1-wens@csie.org>
On Tue, Oct 18, 2016 at 01:42:09PM +0800, Chen-Yu Tsai wrote:
> On the A31, the DMA engine only works if AHB1 is clocked from PLL6.
> In addition, the hstimer is clocked from AHB1, and if AHB1 is clocked
> from the CPU clock, and cpufreq is working, we get an unstable timer.
>
> Force the AHB1 clock to use PLL6 as its parent. Previously this was done
> in the device tree with the assigned-clocks and assigned-clocks-parent
> bindings. However with this new monolithic driver, the system critical
> clocks aren't exported through the device tree. The alternative is to
> force this setting in the driver before the clocks are registered.
>
> This is also done in newer versions of mainline U-boot. But people still
> using an older version, or even the vendor version, can still hit this
> issue. Hence the need to do it in the kernel as well.
>
> Reported-by: Hans de Goede <hdegoede@redhat.com>
> Reported-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Fixes: c6e6c96d8fa6 ("clk: sunxi-ng: Add A31/A31s clocks")
> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Applied, thanks!
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 801 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161019/bc1a6152/attachment-0001.sig>
^ permalink raw reply
* how to enable suspend to ram for arm-64 bits
From: Pavel Machek @ 2016-10-19 9:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161018104539.GB15639@leverpostej>
On Tue 2016-10-18 11:45:39, Mark Rutland wrote:
> On Tue, Oct 18, 2016 at 12:00:02PM +0200, Pavel Machek wrote:
> > > >b. in arm64, if some platform has its own suspend flow, couldn't it
> > > >adopts arm/match-xxx to register its own global suspend method?
> > >
> > > No, PSCI is highly recommended.
> >
> > Relying on firmware for suspend on x86 was a great disaster, lets not repeat
> > that mistake. arm32 has better powermanagement than x86 ever will (see Nokia N900
> > for example) -- feel free to copy that code from arm32.
>
> Quite frankly, copying hundreds of lines of board-specific code
> (including assembly that won't compile) is unlikely to help.
>
> So far arm64 requires well-defined, standard, reusable interfaces (e.g.
> PSCI). That cleanly separates concerns (e.g. anyone can implement the
> backend without mandatory changes to the kernel), and keeps things
> maintainable.
Either the lowlevel suspend code is stable and bug free, and then
having that code is not a problem. Or the lowlevel suspend code is
complex enough to contain some bugs, and in such case it is better to
debug and update it with kernel.
> ARM publishes and maintains the ARM Trusted Firmware [1], which anyone
> can use and build atop of. It's open source (three-clause BSD with DCO),
> and accepts board ports. You can have a completely open stack,
> regardless of whether part of that stack is firmware.
If something is called "Trusted", it is not trustworthy.
BSD is better than closed source, but it also means that you will not
get the sources from your hw vendor.
Being separate module means it will be never updated.
Being separate module means it will be hard to debug, in area where
debugging is already pretty hard.
Can it do advanced stuff like deep powersaving on N900 idle?
Just don't do it.
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161019/05d8de63/attachment.sig>
^ permalink raw reply
* [PATCH] reset: uniphier: rename MIO reset to SD reset for Pro5, PXs2, LD20 SoCs
From: Philipp Zabel @ 2016-10-19 9:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1476865429-13143-1-git-send-email-yamada.masahiro@socionext.com>
Hi Masahiro,
Am Mittwoch, den 19.10.2016, 17:23 +0900 schrieb Masahiro Yamada:
> I made a mistake as for naming for this block. The MIO block is not
> implemented for these 3 SoCs in the first place. The current naming
> will be a trouble if an SoC with both MIO and SD-ctrl blocks appear
> in the future.
>
> This driver has just been merged in the previous merge window.
> Rename it before the release.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>
> Philipp,
>
> If you do not mind, may I include this in my PR
> along with the "select ARCH_HAS_RESET_CONTROLLER" patches?
Should be fine, I don't see any potential for conflicts with the reset
tree.
Acked-by: Philipp Zabel <p.zabel@pengutronix.de>
regards
Philipp
> .../devicetree/bindings/reset/uniphier-reset.txt | 22 +++++++++++-----------
> drivers/reset/reset-uniphier.c | 16 ++++++++--------
> 2 files changed, 19 insertions(+), 19 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/reset/uniphier-reset.txt b/Documentation/devicetree/bindings/reset/uniphier-reset.txt
> index e6bbfcc..78cd735 100644
> --- a/Documentation/devicetree/bindings/reset/uniphier-reset.txt
> +++ b/Documentation/devicetree/bindings/reset/uniphier-reset.txt
> @@ -19,12 +19,12 @@ Required properties:
> Example:
>
> sysctrl at 61840000 {
> - compatible = "socionext,uniphier-ld20-sysctrl",
> + compatible = "socionext,uniphier-ld11-sysctrl",
> "simple-mfd", "syscon";
> reg = <0x61840000 0x4000>;
>
> reset {
> - compatible = "socionext,uniphier-ld20-reset";
> + compatible = "socionext,uniphier-ld11-reset";
> #reset-cells = <1>;
> };
>
> @@ -32,8 +32,8 @@ Example:
> };
>
>
> -Media I/O (MIO) reset
> ----------------------
> +Media I/O (MIO) reset, SD reset
> +-------------------------------
>
> Required properties:
> - compatible: should be one of the following:
> @@ -41,21 +41,21 @@ Required properties:
> "socionext,uniphier-ld4-mio-reset" - for PH1-LD4 SoC.
> "socionext,uniphier-pro4-mio-reset" - for PH1-Pro4 SoC.
> "socionext,uniphier-sld8-mio-reset" - for PH1-sLD8 SoC.
> - "socionext,uniphier-pro5-mio-reset" - for PH1-Pro5 SoC.
> - "socionext,uniphier-pxs2-mio-reset" - for ProXstream2/PH1-LD6b SoC.
> + "socionext,uniphier-pro5-sd-reset" - for PH1-Pro5 SoC.
> + "socionext,uniphier-pxs2-sd-reset" - for ProXstream2/PH1-LD6b SoC.
> "socionext,uniphier-ld11-mio-reset" - for PH1-LD11 SoC.
> - "socionext,uniphier-ld20-mio-reset" - for PH1-LD20 SoC.
> + "socionext,uniphier-ld20-sd-reset" - for PH1-LD20 SoC.
> - #reset-cells: should be 1.
>
> Example:
>
> mioctrl at 59810000 {
> - compatible = "socionext,uniphier-ld20-mioctrl",
> + compatible = "socionext,uniphier-ld11-mioctrl",
> "simple-mfd", "syscon";
> reg = <0x59810000 0x800>;
>
> reset {
> - compatible = "socionext,uniphier-ld20-mio-reset";
> + compatible = "socionext,uniphier-ld11-mio-reset";
> #reset-cells = <1>;
> };
>
> @@ -80,12 +80,12 @@ Required properties:
> Example:
>
> perictrl at 59820000 {
> - compatible = "socionext,uniphier-ld20-perictrl",
> + compatible = "socionext,uniphier-ld11-perictrl",
> "simple-mfd", "syscon";
> reg = <0x59820000 0x200>;
>
> reset {
> - compatible = "socionext,uniphier-ld20-peri-reset";
> + compatible = "socionext,uniphier-ld11-peri-reset";
> #reset-cells = <1>;
> };
>
> diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
> index 8b2558e..968c3ae 100644
> --- a/drivers/reset/reset-uniphier.c
> +++ b/drivers/reset/reset-uniphier.c
> @@ -154,7 +154,7 @@ struct uniphier_reset_data {
> UNIPHIER_RESET_END,
> };
>
> -const struct uniphier_reset_data uniphier_pro5_mio_reset_data[] = {
> +const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
> UNIPHIER_MIO_RESET_SD(0, 0),
> UNIPHIER_MIO_RESET_SD(1, 1),
> UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
> @@ -360,7 +360,7 @@ static int uniphier_reset_probe(struct platform_device *pdev)
> .compatible = "socionext,uniphier-ld20-reset",
> .data = uniphier_ld20_sys_reset_data,
> },
> - /* Media I/O reset */
> + /* Media I/O reset, SD reset */
> {
> .compatible = "socionext,uniphier-sld3-mio-reset",
> .data = uniphier_sld3_mio_reset_data,
> @@ -378,20 +378,20 @@ static int uniphier_reset_probe(struct platform_device *pdev)
> .data = uniphier_sld3_mio_reset_data,
> },
> {
> - .compatible = "socionext,uniphier-pro5-mio-reset",
> - .data = uniphier_pro5_mio_reset_data,
> + .compatible = "socionext,uniphier-pro5-sd-reset",
> + .data = uniphier_pro5_sd_reset_data,
> },
> {
> - .compatible = "socionext,uniphier-pxs2-mio-reset",
> - .data = uniphier_pro5_mio_reset_data,
> + .compatible = "socionext,uniphier-pxs2-sd-reset",
> + .data = uniphier_pro5_sd_reset_data,
> },
> {
> .compatible = "socionext,uniphier-ld11-mio-reset",
> .data = uniphier_sld3_mio_reset_data,
> },
> {
> - .compatible = "socionext,uniphier-ld20-mio-reset",
> - .data = uniphier_pro5_mio_reset_data,
> + .compatible = "socionext,uniphier-ld20-sd-reset",
> + .data = uniphier_pro5_sd_reset_data,
> },
> /* Peripheral reset */
> {
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox