* [PATCH v4 8/8] ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 48 +++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 88f98f5..3fdb2d7 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -74,6 +74,28 @@
};
};
+ scpi {
+ compatible = "amlogic,meson-gxbb-scpi";
+ mboxes = <&mailbox 1 &mailbox 2>;
+ shmem = <&cpu_scp_lpri &cpu_scp_hpri>;
+
+ clocks {
+ compatible = "arm,scpi-clocks";
+
+ scpi_dvfs: scpi_clocks at 0 {
+ compatible = "arm,scpi-dvfs-clocks";
+ #clock-cells = <1>;
+ clock-indices = <0>;
+ clock-output-names = "vcpu";
+ };
+ };
+
+ scpi_sensors: sensors {
+ compatible = "arm,scpi-sensors";
+ #thermal-sensor-cells = <1>;
+ };
+ };
+
soc {
usb0_phy: phy at c0000000 {
compatible = "amlogic,meson-gxbb-usb2-phy";
@@ -101,6 +123,16 @@
#address-cells = <1>;
#size-cells = <1>;
ranges = <0 0x0 0xc8000000 0x14000>;
+
+ cpu_scp_lpri: scp-shmem at 0 {
+ compatible = "amlogic,meson-gxbb-scp-shmem";
+ reg = <0x13000 0x400>;
+ };
+
+ cpu_scp_hpri: scp-shmem at 200 {
+ compatible = "amlogic,meson-gxbb-scp-shmem";
+ reg = <0x13400 0x400>;
+ };
};
usb0: usb at c9000000 {
@@ -143,6 +175,22 @@
};
};
+&cpu0 {
+ clocks = <&scpi_dvfs 0>;
+};
+
+&cpu1 {
+ clocks = <&scpi_dvfs 0>;
+};
+
+&cpu2 {
+ clocks = <&scpi_dvfs 0>;
+};
+
+&cpu3 {
+ clocks = <&scpi_dvfs 0>;
+};
+
&cbus {
reset: reset-controller at 4404 {
compatible = "amlogic,meson-gxbb-reset";
--
1.9.1
^ permalink raw reply related
* [PATCH v4 7/8] ARM64: dts: meson-gxbb: Add SRAM node
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
Signed-off-by: Neil Armstrong <narmstrong@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 443811b..88f98f5 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -94,6 +94,15 @@
status = "disabled";
};
+ sram: sram at c8000000 {
+ compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
+ reg = <0x0 0xc8000000 0x0 0x14000>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0x0 0xc8000000 0x14000>;
+ };
+
usb0: usb at c9000000 {
compatible = "amlogic,meson-gxbb-usb", "snps,dwc2";
reg = <0x0 0xc9000000 0x0 0x40000>;
--
1.9.1
^ permalink raw reply related
* [PATCH v4 6/8] dt-bindings: Add support for Amlogic GXBB SCPI Interface
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/arm/arm,scpi.txt b/Documentation/devicetree/bindings/arm/arm,scpi.txt
index faa4b44..04bc171 100644
--- a/Documentation/devicetree/bindings/arm/arm,scpi.txt
+++ b/Documentation/devicetree/bindings/arm/arm,scpi.txt
@@ -7,7 +7,7 @@ by Linux to initiate various system control and power operations.
Required properties:
-- compatible : should be "arm,scpi"
+- compatible : should be "arm,scpi" or "amlogic,meson-gxbb-scpi"
- mboxes: List of phandle and mailbox channel specifiers
All the channels reserved by remote SCP firmware for use by
SCPI message protocol should be specified in any order
@@ -60,7 +60,8 @@ A small area of SRAM is reserved for SCPI communication between application
processors and SCP.
Required properties:
-- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno
+- compatible : should be "arm,juno-sram-ns" for Non-secure SRAM on Juno,
+ or "amlogic,meson-gxbb-sram" for Amlogic GXBB SoC.
The rest of the properties should follow the generic mmio-sram description
found in ../../sram/sram.txt
@@ -70,7 +71,8 @@ Each sub-node represents the reserved area for SCPI.
Required sub-node properties:
- reg : The base offset and size of the reserved area with the SRAM
- compatible : should be "arm,juno-scp-shmem" for Non-secure SRAM based
- shared memory on Juno platforms
+ shared memory on Juno platforms or
+ "amlogic,meson-gxbb-scp-shmem" for Amlogic GXBB SoC.
Sensor bindings for the sensors based on SCPI Message Protocol
--------------------------------------------------------------
--
1.9.1
^ permalink raw reply related
* [PATCH v4 5/8] scpi: grow MAX_DVFS_OPPS to 16 entries
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
Since Amlogic SoCs reports more than 8 OPPs per domains, grow the structure
size to 16.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/firmware/arm_scpi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 21fafbe..bc15348 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -70,7 +70,7 @@
#define SCPI_SLOT 0
#define MAX_DVFS_DOMAINS 8
-#define MAX_DVFS_OPPS 8
+#define MAX_DVFS_OPPS 16
#define DVFS_LATENCY(hdr) (le32_to_cpu(hdr) >> 16)
#define DVFS_OPP_COUNT(hdr) ((le32_to_cpu(hdr) >> 8) & 0xff)
--
1.9.1
^ permalink raw reply related
* [PATCH v4 4/8] scpi: Add support for Legacy match table for Amlogic GXBB SoC
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
Add new DT match table to setup the is_legacy boolean value across
the scpi functions.
Add the Amlogic GXBB SoC compatible for platform and as legacy match entry.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/firmware/arm_scpi.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 1fb3bbf..21fafbe 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -895,6 +895,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
return 0;
}
+static const struct of_device_id legacy_scpi_of_match[] = {
+ {.compatible = "amlogic,meson-gxbb-scpi"},
+ {},
+};
+
static int scpi_probe(struct platform_device *pdev)
{
int count, idx, ret;
@@ -907,6 +912,9 @@ static int scpi_probe(struct platform_device *pdev)
if (!scpi_info)
return -ENOMEM;
+ if (of_match_device(legacy_scpi_of_match, &pdev->dev))
+ scpi_info->is_legacy = true;
+
count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
if (count < 0) {
dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
@@ -1009,6 +1017,7 @@ static int scpi_probe(struct platform_device *pdev)
static const struct of_device_id scpi_of_match[] = {
{.compatible = "arm,scpi"},
+ {.compatible = "amlogic,meson-gxbb-scpi"},
{},
};
--
1.9.1
^ permalink raw reply related
* [PATCH v4 3/8] scpi: Do not fail if get_capabilities is not implemented
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
On Amlogic SCPI legacy implementation, the GET_CAPABILITIES is not
supported, failover by using 0.0.0 version.
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/firmware/arm_scpi.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 6244eb1..1fb3bbf 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -807,6 +807,10 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
info->protocol_version = le32_to_cpu(caps.protocol_version);
info->firmware_version = le32_to_cpu(caps.platform_version);
}
+ /* Ignore error if not implemented */
+ if (scpi_info->is_legacy && ret == -EOPNOTSUPP)
+ return 0;
+
return ret;
}
--
1.9.1
^ permalink raw reply related
* [PATCH v4 2/8] scpi: Add alternative legacy structures, functions and macros
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
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
@@ -50,13 +50,20 @@
#define CMD_TOKEN_ID_MASK 0xff
#define CMD_DATA_SIZE_SHIFT 16
#define CMD_DATA_SIZE_MASK 0x1ff
+#define CMD_LEGACY_DATA_SIZE_SHIFT 20
+#define CMD_LEGACY_DATA_SIZE_MASK 0x1ff
#define PACK_SCPI_CMD(cmd_id, tx_sz) \
((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
(((tx_sz) & CMD_DATA_SIZE_MASK) << CMD_DATA_SIZE_SHIFT))
#define ADD_SCPI_TOKEN(cmd, token) \
((cmd) |= (((token) & CMD_TOKEN_ID_MASK) << CMD_TOKEN_ID_SHIFT))
+#define PACK_LEGACY_SCPI_CMD(cmd_id, tx_sz) \
+ ((((cmd_id) & CMD_ID_MASK) << CMD_ID_SHIFT) | \
+ (((tx_sz) & CMD_LEGACY_DATA_SIZE_MASK) << CMD_LEGACY_DATA_SIZE_SHIFT))
#define CMD_SIZE(cmd) (((cmd) >> CMD_DATA_SIZE_SHIFT) & CMD_DATA_SIZE_MASK)
+#define CMD_LEGACY_SIZE(cmd) (((cmd) >> CMD_LEGACY_DATA_SIZE_SHIFT) & \
+ CMD_LEGACY_DATA_SIZE_MASK)
#define CMD_UNIQ_MASK (CMD_TOKEN_ID_MASK << CMD_TOKEN_ID_SHIFT | CMD_ID_MASK)
#define CMD_XTRACT_UNIQ(cmd) ((cmd) & CMD_UNIQ_MASK)
@@ -133,6 +140,61 @@ enum scpi_std_cmd {
SCPI_CMD_COUNT
};
+/* SCPI Legacy Commands */
+enum legacy_scpi_std_cmd {
+ LEGACY_SCPI_CMD_INVALID = 0x00,
+ LEGACY_SCPI_CMD_SCPI_READY = 0x01,
+ LEGACY_SCPI_CMD_SCPI_CAPABILITIES = 0x02,
+ LEGACY_SCPI_CMD_EVENT = 0x03,
+ LEGACY_SCPI_CMD_SET_CSS_PWR_STATE = 0x04,
+ LEGACY_SCPI_CMD_GET_CSS_PWR_STATE = 0x05,
+ LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT = 0x06,
+ LEGACY_SCPI_CMD_GET_PWR_STATE_STAT = 0x07,
+ LEGACY_SCPI_CMD_SYS_PWR_STATE = 0x08,
+ LEGACY_SCPI_CMD_L2_READY = 0x09,
+ LEGACY_SCPI_CMD_SET_AP_TIMER = 0x0a,
+ LEGACY_SCPI_CMD_CANCEL_AP_TIME = 0x0b,
+ LEGACY_SCPI_CMD_DVFS_CAPABILITIES = 0x0c,
+ LEGACY_SCPI_CMD_GET_DVFS_INFO = 0x0d,
+ LEGACY_SCPI_CMD_SET_DVFS = 0x0e,
+ LEGACY_SCPI_CMD_GET_DVFS = 0x0f,
+ LEGACY_SCPI_CMD_GET_DVFS_STAT = 0x10,
+ LEGACY_SCPI_CMD_SET_RTC = 0x11,
+ LEGACY_SCPI_CMD_GET_RTC = 0x12,
+ LEGACY_SCPI_CMD_CLOCK_CAPABILITIES = 0x13,
+ LEGACY_SCPI_CMD_SET_CLOCK_INDEX = 0x14,
+ LEGACY_SCPI_CMD_SET_CLOCK_VALUE = 0x15,
+ LEGACY_SCPI_CMD_GET_CLOCK_VALUE = 0x16,
+ LEGACY_SCPI_CMD_PSU_CAPABILITIES = 0x17,
+ LEGACY_SCPI_CMD_SET_PSU = 0x18,
+ LEGACY_SCPI_CMD_GET_PSU = 0x19,
+ LEGACY_SCPI_CMD_SENSOR_CAPABILITIES = 0x1a,
+ LEGACY_SCPI_CMD_SENSOR_INFO = 0x1b,
+ LEGACY_SCPI_CMD_SENSOR_VALUE = 0x1c,
+ LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC = 0x1d,
+ LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS = 0x1e,
+ LEGACY_SCPI_CMD_SENSOR_ASYNC_VALUE = 0x1f,
+ LEGACY_SCPI_CMD_COUNT
+};
+
+/* List all commands that are required to go through the high priority link */
+static int legacy_hpriority_cmds[] = {
+ LEGACY_SCPI_CMD_GET_CSS_PWR_STATE,
+ LEGACY_SCPI_CMD_CFG_PWR_STATE_STAT,
+ LEGACY_SCPI_CMD_GET_PWR_STATE_STAT,
+ LEGACY_SCPI_CMD_SET_DVFS,
+ LEGACY_SCPI_CMD_GET_DVFS,
+ LEGACY_SCPI_CMD_SET_RTC,
+ LEGACY_SCPI_CMD_GET_RTC,
+ LEGACY_SCPI_CMD_SET_CLOCK_INDEX,
+ LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+ LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+ LEGACY_SCPI_CMD_SET_PSU,
+ LEGACY_SCPI_CMD_GET_PSU,
+ LEGACY_SCPI_CMD_SENSOR_CFG_PERIODIC,
+ LEGACY_SCPI_CMD_SENSOR_CFG_BOUNDS,
+};
+
/* List all commands used by this driver, used as indexes */
enum scpi_drv_cmds {
CMD_SCPI_CAPABILITIES = 0,
@@ -165,6 +227,21 @@ enum scpi_drv_cmds {
SCPI_CMD_GET_DEVICE_PWR_STATE,
};
+static int scpi_legacy_commands[CMD_MAX_COUNT] = {
+ LEGACY_SCPI_CMD_SCPI_CAPABILITIES,
+ -1, /* GET_CLOCK_INFO */
+ LEGACY_SCPI_CMD_GET_CLOCK_VALUE,
+ LEGACY_SCPI_CMD_SET_CLOCK_VALUE,
+ LEGACY_SCPI_CMD_GET_DVFS,
+ LEGACY_SCPI_CMD_SET_DVFS,
+ LEGACY_SCPI_CMD_GET_DVFS_INFO,
+ LEGACY_SCPI_CMD_SENSOR_CAPABILITIES,
+ LEGACY_SCPI_CMD_SENSOR_INFO,
+ LEGACY_SCPI_CMD_SENSOR_VALUE,
+ -1, /* SET_DEVICE_PWR_STATE */
+ -1, /* GET_DEVICE_PWR_STATE */
+};
+
struct scpi_xfer {
u32 slot; /* has to be first element */
u32 cmd;
@@ -187,14 +264,17 @@ struct scpi_chan {
struct scpi_xfer *xfers;
spinlock_t rx_lock; /* locking for the rx pending list */
struct mutex xfers_lock;
+ struct mutex legacy_lock;
u8 token;
};
struct scpi_drvinfo {
u32 protocol_version;
u32 firmware_version;
+ bool is_legacy;
int num_chans;
int *scpi_cmds;
+ DECLARE_BITMAP(cmd_priority, LEGACY_SCPI_CMD_COUNT);
atomic_t next_chan;
struct scpi_ops *scpi_ops;
struct scpi_chan *channels;
@@ -211,6 +291,11 @@ struct scpi_shared_mem {
u8 payload[0];
} __packed;
+struct legacy_scpi_shared_mem {
+ __le32 status;
+ u8 payload[0];
+} __packed;
+
struct scp_capabilities {
__le32 protocol_version;
__le32 event_version;
@@ -236,6 +321,12 @@ struct clk_set_value {
__le32 rate;
} __packed;
+struct legacy_clk_set_value {
+ __le32 rate;
+ __le16 id;
+ __le16 reserved;
+} __packed;
+
struct dvfs_info {
__le32 header;
struct {
@@ -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 */
+ len = match->rx_len;
+
+ match->status = le32_to_cpu(mem->status);
+ memcpy_fromio(match->rx_buf, mem->payload, 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);
+ }
- match->status = le32_to_cpu(mem->status);
- memcpy_fromio(match->rx_buf, mem->payload, len);
if (match->rx_len > len)
memset(match->rx_buf + len, 0, match->rx_len - len);
+
complete(&match->done);
}
spin_unlock_irqrestore(&ch->rx_lock, flags);
@@ -331,7 +447,12 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
{
struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
struct scpi_shared_mem *mem = ch->rx_payload;
- u32 cmd = le32_to_cpu(mem->command);
+ u32 cmd;
+
+ if (scpi_info->is_legacy)
+ cmd = *(u32 *)msg;
+ 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;
spin_lock_irqsave(&ch->rx_lock, flags);
list_add_tail(&t->node, &ch->rx_pending);
spin_unlock_irqrestore(&ch->rx_lock, flags);
}
- mem->command = cpu_to_le32(t->cmd);
+
+ if (!scpi_info->is_legacy)
+ mem->command = cpu_to_le32(t->cmd);
}
static struct scpi_xfer *get_scpi_xfer(struct scpi_chan *ch)
@@ -396,21 +526,37 @@ static int scpi_send_message(unsigned int offset, void *tx_buf,
cmd = scpi_info->scpi_cmds[offset];
- chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
+ if (scpi_info->is_legacy)
+ chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0;
+ else
+ chan = atomic_inc_return(&scpi_info->next_chan) %
+ scpi_info->num_chans;
scpi_chan = scpi_info->channels + chan;
msg = get_scpi_xfer(scpi_chan);
if (!msg)
return -ENOMEM;
- msg->slot = BIT(SCPI_SLOT);
- msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+ if (scpi_info->is_legacy) {
+ msg->cmd = PACK_LEGACY_SCPI_CMD(cmd, tx_len);
+ msg->slot = msg->cmd;
+ } else {
+ msg->slot = BIT(SCPI_SLOT);
+ msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+ }
msg->tx_buf = tx_buf;
msg->tx_len = tx_len;
msg->rx_buf = rx_buf;
msg->rx_len = rx_len;
init_completion(&msg->done);
+ /* 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.
+ */
+ 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;
@@ -474,6 +624,18 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
&stat, sizeof(stat));
}
+static int legacy_scpi_clk_set_val(u16 clk_id, unsigned long rate)
+{
+ int stat;
+ struct legacy_clk_set_value clk = {
+ .id = cpu_to_le16(clk_id),
+ .rate = cpu_to_le32(rate)
+ };
+
+ return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+ &stat, sizeof(stat));
+}
+
static int scpi_dvfs_get_idx(u8 domain)
{
int ret;
@@ -525,7 +687,6 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
info->count = DVFS_OPP_COUNT(buf.header);
info->latency = DVFS_LATENCY(buf.header) * 1000; /* uS to nS */
-
info->opps = kcalloc(info->count, sizeof(*opp), GFP_KERNEL);
if (!info->opps) {
kfree(info);
@@ -580,9 +741,13 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
&buf, sizeof(buf));
- if (!ret)
- *val = (u64)le32_to_cpu(buf.hi_val) << 32 |
- le32_to_cpu(buf.lo_val);
+ if (!ret) {
+ if (scpi_info->is_legacy)
+ *val = (u64)le32_to_cpu(buf.lo_val);
+ else
+ *val = (u64)le32_to_cpu(buf.hi_val) << 32 |
+ le32_to_cpu(buf.lo_val);
+ }
return ret;
}
@@ -781,6 +946,7 @@ static int scpi_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&pchan->xfers_list);
spin_lock_init(&pchan->rx_lock);
mutex_init(&pchan->xfers_lock);
+ mutex_init(&pchan->legacy_lock);
ret = scpi_alloc_xfer_list(dev, pchan);
if (!ret) {
@@ -804,6 +970,17 @@ static int scpi_probe(struct platform_device *pdev)
scpi_info->scpi_cmds = scpi_std_commands;
+ if (scpi_info->is_legacy) {
+ /* Replace with legacy variants */
+ scpi_ops.clk_set_val = legacy_scpi_clk_set_val;
+ scpi_info->scpi_cmds = scpi_legacy_commands;
+
+ /* Fill priority bitmap */
+ for (idx = 0; idx < ARRAY_SIZE(legacy_hpriority_cmds); idx++)
+ set_bit(legacy_hpriority_cmds[idx],
+ scpi_info->cmd_priority);
+ }
+
ret = scpi_init_versions(scpi_info);
if (ret) {
dev_err(dev, "incorrect or no SCP firmware found\n");
--
1.9.1
^ permalink raw reply related
* [PATCH v4 1/8] scpi: Add cmd indirection table to prepare for legacy commands
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475652814-30619-1-git-send-email-narmstrong@baylibre.com>
From: Sudeep Holla <sudeep.holla@arm.com>
Add indirection table to permit multiple command values for legacy support.
[narmstrong at baylibre.com: Added cmd check in scpi_send_message]
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
---
drivers/firmware/arm_scpi.c | 81 +++++++++++++++++++++++++++++++++++----------
1 file changed, 64 insertions(+), 17 deletions(-)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index ce2bc2a..498afa0 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -99,6 +99,7 @@ enum scpi_error_codes {
SCPI_ERR_MAX
};
+/* SCPI Standard commands */
enum scpi_std_cmd {
SCPI_CMD_INVALID = 0x00,
SCPI_CMD_SCPI_READY = 0x01,
@@ -132,6 +133,38 @@ enum scpi_std_cmd {
SCPI_CMD_COUNT
};
+/* List all commands used by this driver, used as indexes */
+enum scpi_drv_cmds {
+ CMD_SCPI_CAPABILITIES = 0,
+ CMD_GET_CLOCK_INFO,
+ CMD_GET_CLOCK_VALUE,
+ CMD_SET_CLOCK_VALUE,
+ CMD_GET_DVFS,
+ CMD_SET_DVFS,
+ CMD_GET_DVFS_INFO,
+ CMD_SENSOR_CAPABILITIES,
+ CMD_SENSOR_INFO,
+ CMD_SENSOR_VALUE,
+ CMD_SET_DEVICE_PWR_STATE,
+ CMD_GET_DEVICE_PWR_STATE,
+ CMD_MAX_COUNT,
+};
+
+static int scpi_std_commands[CMD_MAX_COUNT] = {
+ SCPI_CMD_SCPI_CAPABILITIES,
+ SCPI_CMD_GET_CLOCK_INFO,
+ SCPI_CMD_GET_CLOCK_VALUE,
+ SCPI_CMD_SET_CLOCK_VALUE,
+ SCPI_CMD_GET_DVFS,
+ SCPI_CMD_SET_DVFS,
+ SCPI_CMD_GET_DVFS_INFO,
+ SCPI_CMD_SENSOR_CAPABILITIES,
+ SCPI_CMD_SENSOR_INFO,
+ SCPI_CMD_SENSOR_VALUE,
+ SCPI_CMD_SET_DEVICE_PWR_STATE,
+ SCPI_CMD_GET_DEVICE_PWR_STATE,
+};
+
struct scpi_xfer {
u32 slot; /* has to be first element */
u32 cmd;
@@ -161,6 +194,7 @@ struct scpi_drvinfo {
u32 protocol_version;
u32 firmware_version;
int num_chans;
+ int *scpi_cmds;
atomic_t next_chan;
struct scpi_ops *scpi_ops;
struct scpi_chan *channels;
@@ -344,14 +378,24 @@ static void put_scpi_xfer(struct scpi_xfer *t, struct scpi_chan *ch)
mutex_unlock(&ch->xfers_lock);
}
-static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
- void *rx_buf, unsigned int rx_len)
+static int scpi_send_message(unsigned int offset, void *tx_buf,
+ unsigned int tx_len, void *rx_buf,
+ unsigned int rx_len)
{
int ret;
u8 chan;
+ u8 cmd;
struct scpi_xfer *msg;
struct scpi_chan *scpi_chan;
+ if (offset >= CMD_MAX_COUNT || !scpi_info->scpi_cmds)
+ return -EINVAL;
+
+ if (scpi_info->scpi_cmds[offset] < 0)
+ return -EOPNOTSUPP;
+
+ cmd = scpi_info->scpi_cmds[offset];
+
chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
scpi_chan = scpi_info->channels + chan;
@@ -397,7 +441,7 @@ static u32 scpi_get_version(void)
struct clk_get_info clk;
__le16 le_clk_id = cpu_to_le16(clk_id);
- ret = scpi_send_message(SCPI_CMD_GET_CLOCK_INFO, &le_clk_id,
+ ret = scpi_send_message(CMD_GET_CLOCK_INFO, &le_clk_id,
sizeof(le_clk_id), &clk, sizeof(clk));
if (!ret) {
*min = le32_to_cpu(clk.min_rate);
@@ -412,8 +456,9 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
struct clk_get_value clk;
__le16 le_clk_id = cpu_to_le16(clk_id);
- ret = scpi_send_message(SCPI_CMD_GET_CLOCK_VALUE, &le_clk_id,
+ ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
sizeof(le_clk_id), &clk, sizeof(clk));
+
return ret ? ret : le32_to_cpu(clk.rate);
}
@@ -425,7 +470,7 @@ static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
.rate = cpu_to_le32(rate)
};
- return scpi_send_message(SCPI_CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
+ return scpi_send_message(CMD_SET_CLOCK_VALUE, &clk, sizeof(clk),
&stat, sizeof(stat));
}
@@ -434,8 +479,9 @@ static int scpi_dvfs_get_idx(u8 domain)
int ret;
u8 dvfs_idx;
- ret = scpi_send_message(SCPI_CMD_GET_DVFS, &domain, sizeof(domain),
+ ret = scpi_send_message(CMD_GET_DVFS, &domain, sizeof(domain),
&dvfs_idx, sizeof(dvfs_idx));
+
return ret ? ret : dvfs_idx;
}
@@ -444,7 +490,7 @@ static int scpi_dvfs_set_idx(u8 domain, u8 index)
int stat;
struct dvfs_set dvfs = {domain, index};
- return scpi_send_message(SCPI_CMD_SET_DVFS, &dvfs, sizeof(dvfs),
+ return scpi_send_message(CMD_SET_DVFS, &dvfs, sizeof(dvfs),
&stat, sizeof(stat));
}
@@ -468,9 +514,8 @@ static struct scpi_dvfs_info *scpi_dvfs_get_info(u8 domain)
if (scpi_info->dvfs[domain]) /* data already populated */
return scpi_info->dvfs[domain];
- ret = scpi_send_message(SCPI_CMD_GET_DVFS_INFO, &domain, sizeof(domain),
+ ret = scpi_send_message(CMD_GET_DVFS_INFO, &domain, sizeof(domain),
&buf, sizeof(buf));
-
if (ret)
return ERR_PTR(ret);
@@ -503,8 +548,8 @@ static int scpi_sensor_get_capability(u16 *sensors)
struct sensor_capabilities cap_buf;
int ret;
- ret = scpi_send_message(SCPI_CMD_SENSOR_CAPABILITIES, NULL, 0, &cap_buf,
- sizeof(cap_buf));
+ ret = scpi_send_message(CMD_SENSOR_CAPABILITIES, NULL, 0,
+ &cap_buf, sizeof(cap_buf));
if (!ret)
*sensors = le16_to_cpu(cap_buf.sensors);
@@ -517,7 +562,7 @@ static int scpi_sensor_get_info(u16 sensor_id, struct scpi_sensor_info *info)
struct _scpi_sensor_info _info;
int ret;
- ret = scpi_send_message(SCPI_CMD_SENSOR_INFO, &id, sizeof(id),
+ ret = scpi_send_message(CMD_SENSOR_INFO, &id, sizeof(id),
&_info, sizeof(_info));
if (!ret) {
memcpy(info, &_info, sizeof(*info));
@@ -533,7 +578,7 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
struct sensor_value buf;
int ret;
- ret = scpi_send_message(SCPI_CMD_SENSOR_VALUE, &id, sizeof(id),
+ ret = scpi_send_message(CMD_SENSOR_VALUE, &id, sizeof(id),
&buf, sizeof(buf));
if (!ret)
*val = (u64)le32_to_cpu(buf.hi_val) << 32 |
@@ -548,8 +593,8 @@ static int scpi_device_get_power_state(u16 dev_id)
u8 pstate;
__le16 id = cpu_to_le16(dev_id);
- ret = scpi_send_message(SCPI_CMD_GET_DEVICE_PWR_STATE, &id,
- sizeof(id), &pstate, sizeof(pstate));
+ ret = scpi_send_message(CMD_GET_DEVICE_PWR_STATE, &id, sizeof(id),
+ &pstate, sizeof(pstate));
return ret ? ret : pstate;
}
@@ -561,7 +606,7 @@ static int scpi_device_set_power_state(u16 dev_id, u8 pstate)
.pstate = pstate,
};
- return scpi_send_message(SCPI_CMD_SET_DEVICE_PWR_STATE, &dev_set,
+ return scpi_send_message(CMD_SET_DEVICE_PWR_STATE, &dev_set,
sizeof(dev_set), &stat, sizeof(stat));
}
@@ -591,7 +636,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
int ret;
struct scp_capabilities caps;
- ret = scpi_send_message(SCPI_CMD_SCPI_CAPABILITIES, NULL, 0,
+ ret = scpi_send_message(CMD_SCPI_CAPABILITIES, NULL, 0,
&caps, sizeof(caps));
if (!ret) {
info->protocol_version = le32_to_cpu(caps.protocol_version);
@@ -757,6 +802,8 @@ static int scpi_probe(struct platform_device *pdev)
scpi_info->num_chans = count;
platform_set_drvdata(pdev, scpi_info);
+ scpi_info->scpi_cmds = scpi_std_commands;
+
ret = scpi_init_versions(scpi_info);
if (ret) {
dev_err(dev, "incorrect or no SCP firmware found\n");
--
1.9.1
^ permalink raw reply related
* [PATCH v4 0/8] Add support for legacy SCPI protocol
From: Neil Armstrong @ 2016-10-05 7:33 UTC (permalink / raw)
To: linux-arm-kernel
This patchset aims to support the legacy SCPI firmware implementation that was
delivered as early technology preview for the JUNO platform.
Finally a stable, maintained and public implementation for the SCPI protocol
has been upstreamed part of the JUNO support and it is the recommended way
of implementing SCP communication on ARMv8 platforms.
The Amlogic GXBB platform is using this legacy protocol, as the RK3368 & RK3399
platforms. This patchset will only add support for Amlogic GXBB SoC.
This patchset add support for the legacy protocol in the arm_scpi.c file,
avoiding code duplication.
Last RFC discution tread can be found at : https://lkml.org/lkml/2016/8/9/210
Changes since v3 at : http://lkml.kernel.org/r/1473262477-18045-1-git-send-email-narmstrong at baylibre.com
- Changed back author to Sudeep Holla for first patch
- Merged legacy functions to scpi_send_message, tx_prepare and handle_remote_message
- Added legacy locking scheme
- Merged back legacy_scpi_sensor_get_value into scpi_sensor_get_value
- Rebased on linux-next-20161004 with patchset [1]
Changes since v2 at : http://lkml.kernel.org/r/1471952816-30877-1-git-send-email-narmstrong at baylibre.com
- Added command indirection table and use it in each commands
- Added bitmap for high priority commands
- Cleaned up legacy tx_prepare/handle_message to align to standard functions
- Dropped legacy_scpi_ops
Changes since v1 at : http://lkml.kernel.org/r/1471515066-3626-1-git-send-email-narmstrong at baylibre.com
- Dropped vendor_send_message and rockchip vendor mechanism patches
- Merged alternate functions into main functions using is_legacy boolean
- Added DT match table to set is_legacy to true
- Kept alternate scpi_ops structure for legacy
[1] http://lkml.kernel.org/r/1475595430-30075-1-git-send-email-narmstrong at baylibre.com
Neil Armstrong (7):
scpi: Add alternative legacy structures, functions and macros
scpi: Do not fail if get_capabilities is not implemented
scpi: Add support for Legacy match table for Amlogic GXBB SoC
scpi: grow MAX_DVFS_OPPS to 16 entries
dt-bindings: Add support for Amlogic GXBB SCPI Interface
ARM64: dts: meson-gxbb: Add SRAM node
ARM64: dts: meson-gxbb: Add SCPI with cpufreq & sensors Nodes
Sudeep Holla (1):
scpi: Add cmd indirection table to prepare for legacy commands
Documentation/devicetree/bindings/arm/arm,scpi.txt | 8 +-
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi | 57 ++++
drivers/firmware/arm_scpi.c | 317 ++++++++++++++++++---
3 files changed, 339 insertions(+), 43 deletions(-)
--
1.9.1
^ permalink raw reply
* [PATCH v7 21/22] iommu/dma: Add support for mapping MSIs
From: Nipun Gupta @ 2016-10-05 7:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2273af20d844bd618c6a90b57e639700328ebf7f.1473695704.git.robin.murphy@arm.com>
> -----Original Message-----
> From: iommu-bounces at lists.linux-foundation.org [mailto:iommu-
> bounces at lists.linux-foundation.org] On Behalf Of Robin Murphy
> Sent: Monday, September 12, 2016 21:44
> To: will.deacon at arm.com; joro at 8bytes.org; iommu at lists.linux-
> foundation.org; linux-arm-kernel at lists.infradead.org
> Cc: devicetree at vger.kernel.org; punit.agrawal at arm.com;
> thunder.leizhen at huawei.com
> Subject: [PATCH v7 21/22] iommu/dma: Add support for mapping MSIs
>
> When an MSI doorbell is located downstream of an IOMMU, attaching devices
> to a DMA ops domain and switching on translation leads to a rude shock when
> their attempt to write to the physical address returned by the irqchip driver
> faults (or worse, writes into some already-mapped
> buffer) and no interrupt is forthcoming.
>
> Address this by adding a hook for relevant irqchip drivers to call from their
> compose_msi_msg() callback, to swizzle the physical address with an
> appropriatly-mapped IOVA for any device attached to one of our DMA ops
> domains.
>
> Acked-by: Thomas Gleixner <tglx@linutronix.de>
> Acked-by: Marc Zyngier <marc.zyngier@arm.com>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> drivers/iommu/dma-iommu.c | 136
> ++++++++++++++++++++++++++++++++++-----
> drivers/irqchip/irq-gic-v2m.c | 3 +
> drivers/irqchip/irq-gic-v3-its.c | 3 +
> include/linux/dma-iommu.h | 9 +++
> 4 files changed, 136 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index
> 00c8a08d56e7..4329d18080cf 100644
> --- a/drivers/iommu/dma-iommu.c
> +++ b/drivers/iommu/dma-iommu.c
> @@ -25,10 +25,28 @@
> #include <linux/huge_mm.h>
> #include <linux/iommu.h>
> #include <linux/iova.h>
> +#include <linux/irq.h>
> #include <linux/mm.h>
> #include <linux/scatterlist.h>
> #include <linux/vmalloc.h>
>
> +struct iommu_dma_msi_page {
> + struct list_head list;
> + dma_addr_t iova;
> + phys_addr_t phys;
> +};
> +
> +struct iommu_dma_cookie {
> + struct iova_domain iovad;
> + struct list_head msi_page_list;
> + spinlock_t msi_lock;
> +};
> +
> +static inline struct iova_domain *cookie_iovad(struct iommu_domain
> +*domain) {
> + return &((struct iommu_dma_cookie *)domain->iova_cookie)->iovad; }
> +
> int iommu_dma_init(void)
> {
> return iova_cache_get();
> @@ -43,15 +61,19 @@ int iommu_dma_init(void)
> */
> int iommu_get_dma_cookie(struct iommu_domain *domain) {
> - struct iova_domain *iovad;
> + struct iommu_dma_cookie *cookie;
>
> if (domain->iova_cookie)
> return -EEXIST;
>
> - iovad = kzalloc(sizeof(*iovad), GFP_KERNEL);
> - domain->iova_cookie = iovad;
> + cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
> + if (!cookie)
> + return -ENOMEM;
>
> - return iovad ? 0 : -ENOMEM;
> + spin_lock_init(&cookie->msi_lock);
> + INIT_LIST_HEAD(&cookie->msi_page_list);
> + domain->iova_cookie = cookie;
> + return 0;
> }
> EXPORT_SYMBOL(iommu_get_dma_cookie);
>
> @@ -63,14 +85,20 @@ EXPORT_SYMBOL(iommu_get_dma_cookie);
> */
> void iommu_put_dma_cookie(struct iommu_domain *domain) {
> - struct iova_domain *iovad = domain->iova_cookie;
> + struct iommu_dma_cookie *cookie = domain->iova_cookie;
> + struct iommu_dma_msi_page *msi, *tmp;
>
> - if (!iovad)
> + if (!cookie)
> return;
>
> - if (iovad->granule)
> - put_iova_domain(iovad);
> - kfree(iovad);
> + if (cookie->iovad.granule)
> + put_iova_domain(&cookie->iovad);
> +
> + list_for_each_entry_safe(msi, tmp, &cookie->msi_page_list, list) {
> + list_del(&msi->list);
> + kfree(msi);
> + }
> + kfree(cookie);
> domain->iova_cookie = NULL;
> }
> EXPORT_SYMBOL(iommu_put_dma_cookie);
> @@ -88,7 +116,7 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
> */
> int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t
> base, u64 size) {
> - struct iova_domain *iovad = domain->iova_cookie;
> + struct iova_domain *iovad = cookie_iovad(domain);
> unsigned long order, base_pfn, end_pfn;
>
> if (!iovad)
> @@ -155,7 +183,7 @@ int dma_direction_to_prot(enum dma_data_direction
> dir, bool coherent) static struct iova *__alloc_iova(struct iommu_domain
> *domain, size_t size,
> dma_addr_t dma_limit)
> {
> - struct iova_domain *iovad = domain->iova_cookie;
> + struct iova_domain *iovad = cookie_iovad(domain);
> unsigned long shift = iova_shift(iovad);
> unsigned long length = iova_align(iovad, size) >> shift;
>
> @@ -171,7 +199,7 @@ static struct iova *__alloc_iova(struct iommu_domain
> *domain, size_t size,
> /* The IOVA allocator knows what we mapped, so just unmap whatever that
> was */ static void __iommu_dma_unmap(struct iommu_domain *domain,
> dma_addr_t dma_addr) {
> - struct iova_domain *iovad = domain->iova_cookie;
> + struct iova_domain *iovad = cookie_iovad(domain);
> unsigned long shift = iova_shift(iovad);
> unsigned long pfn = dma_addr >> shift;
> struct iova *iova = find_iova(iovad, pfn); @@ -294,7 +322,7 @@ struct
> page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
> void (*flush_page)(struct device *, const void *, phys_addr_t)) {
> struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> - struct iova_domain *iovad = domain->iova_cookie;
> + struct iova_domain *iovad = cookie_iovad(domain);
> struct iova *iova;
> struct page **pages;
> struct sg_table sgt;
> @@ -386,7 +414,7 @@ dma_addr_t iommu_dma_map_page(struct device
> *dev, struct page *page, {
> dma_addr_t dma_addr;
> struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> - struct iova_domain *iovad = domain->iova_cookie;
> + struct iova_domain *iovad = cookie_iovad(domain);
> phys_addr_t phys = page_to_phys(page) + offset;
> size_t iova_off = iova_offset(iovad, phys);
> size_t len = iova_align(iovad, size + iova_off); @@ -495,7 +523,7 @@
> int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
> int nents, int prot)
> {
> struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> - struct iova_domain *iovad = domain->iova_cookie;
> + struct iova_domain *iovad = cookie_iovad(domain);
> struct iova *iova;
> struct scatterlist *s, *prev = NULL;
> dma_addr_t dma_addr;
> @@ -587,3 +615,81 @@ int iommu_dma_mapping_error(struct device *dev,
> dma_addr_t dma_addr) {
> return dma_addr == DMA_ERROR_CODE;
> }
> +
> +static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device
> *dev,
> + phys_addr_t msi_addr, struct iommu_domain *domain) {
> + struct iommu_dma_cookie *cookie = domain->iova_cookie;
> + struct iommu_dma_msi_page *msi_page;
> + struct iova_domain *iovad = &cookie->iovad;
> + struct iova *iova;
> + int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
> +
> + msi_addr &= ~(phys_addr_t)iova_mask(iovad);
> + list_for_each_entry(msi_page, &cookie->msi_page_list, list)
> + if (msi_page->phys == msi_addr)
> + return msi_page;
> +
> + msi_page = kzalloc(sizeof(*msi_page), GFP_ATOMIC);
> + if (!msi_page)
> + return NULL;
> +
> + iova = __alloc_iova(domain, iovad->granule, dma_get_mask(dev));
I think this should be 'iova = __alloc_iova(domain, iovad->granule, dma_get_mask(dev));'
as __alloc_iova takes input parameter as 'struct iova_domain *'
Regards,
Nipun
> + if (!iova)
> + goto out_free_page;
> +
> + msi_page->phys = msi_addr;
> + msi_page->iova = iova_dma_addr(iovad, iova);
> + if (iommu_map(domain, msi_page->iova, msi_addr, iovad->granule,
> prot))
> + goto out_free_iova;
> +
> + INIT_LIST_HEAD(&msi_page->list);
> + list_add(&msi_page->list, &cookie->msi_page_list);
> + return msi_page;
> +
> +out_free_iova:
> + __free_iova(iovad, iova);
> +out_free_page:
> + kfree(msi_page);
> + return NULL;
> +}
> +
> +void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg) {
> + struct device *dev = msi_desc_to_dev(irq_get_msi_desc(irq));
> + struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
> + struct iommu_dma_cookie *cookie;
> + struct iommu_dma_msi_page *msi_page;
> + phys_addr_t msi_addr = (u64)msg->address_hi << 32 | msg->address_lo;
> + unsigned long flags;
> +
> + if (!domain || !domain->iova_cookie)
> + return;
> +
> + cookie = domain->iova_cookie;
> +
> + /*
> + * We disable IRQs to rule out a possible inversion against
> + * irq_desc_lock if, say, someone tries to retarget the affinity
> + * of an MSI from within an IPI handler.
> + */
> + spin_lock_irqsave(&cookie->msi_lock, flags);
> + msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
> + spin_unlock_irqrestore(&cookie->msi_lock, flags);
> +
> + if (WARN_ON(!msi_page)) {
> + /*
> + * We're called from a void callback, so the best we can do is
> + * 'fail' by filling the message with obviously bogus values.
> + * Since we got this far due to an IOMMU being present, it's
> + * not like the existing address would have worked anyway...
> + */
> + msg->address_hi = ~0U;
> + msg->address_lo = ~0U;
> + msg->data = ~0U;
> + } else {
> + msg->address_hi = upper_32_bits(msi_page->iova);
> + msg->address_lo &= iova_mask(&cookie->iovad);
> + msg->address_lo += lower_32_bits(msi_page->iova);
> + }
> +}
> diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c index
> 35eb7ac5d21f..863e073c6f7f 100644
> --- a/drivers/irqchip/irq-gic-v2m.c
> +++ b/drivers/irqchip/irq-gic-v2m.c
> @@ -16,6 +16,7 @@
> #define pr_fmt(fmt) "GICv2m: " fmt
>
> #include <linux/acpi.h>
> +#include <linux/dma-iommu.h>
> #include <linux/irq.h>
> #include <linux/irqdomain.h>
> #include <linux/kernel.h>
> @@ -108,6 +109,8 @@ static void gicv2m_compose_msi_msg(struct irq_data
> *data, struct msi_msg *msg)
>
> if (v2m->flags & GICV2M_NEEDS_SPI_OFFSET)
> msg->data -= v2m->spi_offset;
> +
> + iommu_dma_map_msi_msg(data->irq, msg);
> }
>
> static struct irq_chip gicv2m_irq_chip = { diff --git a/drivers/irqchip/irq-gic-v3-
> its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 36b9c28a5c91..98ff669d5962 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -18,6 +18,7 @@
> #include <linux/bitmap.h>
> #include <linux/cpu.h>
> #include <linux/delay.h>
> +#include <linux/dma-iommu.h>
> #include <linux/interrupt.h>
> #include <linux/log2.h>
> #include <linux/mm.h>
> @@ -655,6 +656,8 @@ static void its_irq_compose_msi_msg(struct irq_data
> *d, struct msi_msg *msg)
> msg->address_lo = addr & ((1UL << 32) - 1);
> msg->address_hi = addr >> 32;
> msg->data = its_get_event_id(d);
> +
> + iommu_dma_map_msi_msg(d->irq, msg);
> }
>
> static struct irq_chip its_irq_chip = { diff --git a/include/linux/dma-iommu.h
> b/include/linux/dma-iommu.h index 81c5c8d167ad..5ee806e41b5c 100644
> --- a/include/linux/dma-iommu.h
> +++ b/include/linux/dma-iommu.h
> @@ -21,6 +21,7 @@
>
> #ifdef CONFIG_IOMMU_DMA
> #include <linux/iommu.h>
> +#include <linux/msi.h>
>
> int iommu_dma_init(void);
>
> @@ -62,9 +63,13 @@ void iommu_dma_unmap_sg(struct device *dev, struct
> scatterlist *sg, int nents, int iommu_dma_supported(struct device *dev, u64
> mask); int iommu_dma_mapping_error(struct device *dev, dma_addr_t
> dma_addr);
>
> +/* The DMA API isn't _quite_ the whole story, though... */ void
> +iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
> +
> #else
>
> struct iommu_domain;
> +struct msi_msg;
>
> static inline int iommu_dma_init(void)
> {
> @@ -80,6 +85,10 @@ static inline void iommu_put_dma_cookie(struct
> iommu_domain *domain) { }
>
> +static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
> +{ }
> +
> #endif /* CONFIG_IOMMU_DMA */
> #endif /* __KERNEL__ */
> #endif /* __DMA_IOMMU_H */
> --
> 2.8.1.dirty
>
> _______________________________________________
> iommu mailing list
> iommu at lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu
^ permalink raw reply
* [PATCH v2 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Peter Ujfalusi @ 2016-10-05 6:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <e9c3108e-ffd1-472a-a2d3-2948665de217@ti.com>
On 10/05/16 09:21, Mugunthan V N wrote:
> On Tuesday 04 October 2016 02:02 PM, Peter Ujfalusi wrote:
>> On 10/03/16 16:03, Mugunthan V N wrote:
>>> +static int tiadc_request_dma(struct platform_device *pdev,
>>> + struct tiadc_device *adc_dev)
>>> +{
>>> + struct tiadc_dma *dma = &adc_dev->dma;
>>> + dma_cap_mask_t mask;
>>> +
>>> + /* Default slave configuration parameters */
>>> + dma->conf.direction = DMA_DEV_TO_MEM;
>>> + dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
>>> + dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
>>> +
>>> + dma_cap_zero(mask);
>>> + dma_cap_set(DMA_CYCLIC, mask);
>>> +
>>> + /* Get a channel for RX */
>>> + dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
>>> + if (!dma->chan)
>>> + return -ENODEV;
>>
>> dma_request_chan() ERR_PTR in case of failure, never NULL. You should reuse
>> the returned error code to support deferred probing.
>
> Will fix this in v3.
>
>>
>>> +
>>> + /* RX buffer */
>>> + dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>>> + &dma->addr, GFP_KERNEL);
>>> + if (!dma->buf)
>>> + goto err;
>>> +
>>> + return 0;
>>> +err:
>>> + dma_release_channel(dma->chan);
>>> +
>>> + return -ENOMEM;
>>> +}
>>> +
>>> static int tiadc_parse_dt(struct platform_device *pdev,
>>> struct tiadc_device *adc_dev)
>>> {
>>> @@ -512,8 +639,14 @@ static int tiadc_probe(struct platform_device *pdev)
>>>
>>> platform_set_drvdata(pdev, indio_dev);
>>>
>>> + err = tiadc_request_dma(pdev, adc_dev);
>>> + if (err && err != -ENODEV)
>>> + goto err_dma;
>>
>> You should handle the deferred probing for DMA channel.
>
> + dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
> + if (IS_ERR(dma->chan)) {
> + int ret = PTR_ERR(dma->chan);
> +
> + dma->chan = NULL;
> + return ret;
You don't need the 'ret' variable:
return PTR_ERR(dma->chan);
> + }
>
> With this probe defer will be taken care and ADC will continue without
> DMA when request channel returns -ENODEV.
I would rather have explicit check for deferred probe:
err = tiadc_request_dma(pdev, adc_dev);
if (err && err == -EPROBE_DEFER)
goto err_dma;
--
P?ter
^ permalink raw reply
* [PATCH v2 2/4] drivers: iio: ti_am335x_adc: add dma support
From: Mugunthan V N @ 2016-10-05 6:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <0ff2c6ef-3fa1-dc8b-fb6e-1a4dcfea8ea9@ti.com>
On Tuesday 04 October 2016 02:02 PM, Peter Ujfalusi wrote:
> On 10/03/16 16:03, Mugunthan V N wrote:
>> +static int tiadc_request_dma(struct platform_device *pdev,
>> + struct tiadc_device *adc_dev)
>> +{
>> + struct tiadc_dma *dma = &adc_dev->dma;
>> + dma_cap_mask_t mask;
>> +
>> + /* Default slave configuration parameters */
>> + dma->conf.direction = DMA_DEV_TO_MEM;
>> + dma->conf.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
>> + dma->conf.src_addr = adc_dev->mfd_tscadc->tscadc_phys_base + REG_FIFO1;
>> +
>> + dma_cap_zero(mask);
>> + dma_cap_set(DMA_CYCLIC, mask);
>> +
>> + /* Get a channel for RX */
>> + dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
>> + if (!dma->chan)
>> + return -ENODEV;
>
> dma_request_chan() ERR_PTR in case of failure, never NULL. You should reuse
> the returned error code to support deferred probing.
Will fix this in v3.
>
>> +
>> + /* RX buffer */
>> + dma->buf = dma_alloc_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>> + &dma->addr, GFP_KERNEL);
>> + if (!dma->buf)
>> + goto err;
>> +
>> + return 0;
>> +err:
>> + dma_release_channel(dma->chan);
>> +
>> + return -ENOMEM;
>> +}
>> +
>> static int tiadc_parse_dt(struct platform_device *pdev,
>> struct tiadc_device *adc_dev)
>> {
>> @@ -512,8 +639,14 @@ static int tiadc_probe(struct platform_device *pdev)
>>
>> platform_set_drvdata(pdev, indio_dev);
>>
>> + err = tiadc_request_dma(pdev, adc_dev);
>> + if (err && err != -ENODEV)
>> + goto err_dma;
>
> You should handle the deferred probing for DMA channel.
+ dma->chan = dma_request_chan(adc_dev->mfd_tscadc->dev, "fifo1");
+ if (IS_ERR(dma->chan)) {
+ int ret = PTR_ERR(dma->chan);
+
+ dma->chan = NULL;
+ return ret;
+ }
With this probe defer will be taken care and ADC will continue without
DMA when request channel returns -ENODEV.
Regards
Mugunthan V N
>
>> +
>> return 0;
>>
>> +err_dma:
>> + iio_device_unregister(indio_dev);
>> err_buffer_unregister:
>> tiadc_iio_buffered_hardware_remove(indio_dev);
>> err_free_channels:
>> @@ -525,8 +658,14 @@ static int tiadc_remove(struct platform_device *pdev)
>> {
>> struct iio_dev *indio_dev = platform_get_drvdata(pdev);
>> struct tiadc_device *adc_dev = iio_priv(indio_dev);
>> + struct tiadc_dma *dma = &adc_dev->dma;
>> u32 step_en;
>>
>> + if (dma->chan) {
>> + dma_free_coherent(dma->chan->device->dev, DMA_BUFFER_SIZE,
>> + dma->buf, dma->addr);
>> + dma_release_channel(dma->chan);
>> + }
>> iio_device_unregister(indio_dev);
>> tiadc_iio_buffered_hardware_remove(indio_dev);
>> tiadc_channels_remove(indio_dev);
>> diff --git a/include/linux/mfd/ti_am335x_tscadc.h b/include/linux/mfd/ti_am335x_tscadc.h
>> index e45a208..b9a53e0 100644
>> --- a/include/linux/mfd/ti_am335x_tscadc.h
>> +++ b/include/linux/mfd/ti_am335x_tscadc.h
>> @@ -23,6 +23,8 @@
>> #define REG_IRQENABLE 0x02C
>> #define REG_IRQCLR 0x030
>> #define REG_IRQWAKEUP 0x034
>> +#define REG_DMAENABLE_SET 0x038
>> +#define REG_DMAENABLE_CLEAR 0x03c
>> #define REG_CTRL 0x040
>> #define REG_ADCFSM 0x044
>> #define REG_CLKDIV 0x04C
>> @@ -36,6 +38,7 @@
>> #define REG_FIFO0THR 0xE8
>> #define REG_FIFO1CNT 0xF0
>> #define REG_FIFO1THR 0xF4
>> +#define REG_DMA1REQ 0xF8
>> #define REG_FIFO0 0x100
>> #define REG_FIFO1 0x200
>>
>> @@ -126,6 +129,10 @@
>> #define FIFOREAD_DATA_MASK (0xfff << 0)
>> #define FIFOREAD_CHNLID_MASK (0xf << 16)
>>
>> +/* DMA ENABLE/CLEAR Register */
>> +#define DMA_FIFO0 BIT(0)
>> +#define DMA_FIFO1 BIT(1)
>> +
>> /* Sequencer Status */
>> #define SEQ_STATUS BIT(5)
>> #define CHARGE_STEP 0x11
>>
>
>
^ permalink raw reply
* [PATCH] ARM: dts: rockchip: Reserve unusable memory region on rk3066
From: Paweł Jarosz @ 2016-10-05 6:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6239b970-09d3-f7ee-e6f5-c019eaedb725@rock-chips.com>
Hi
W dniu 05.10.2016 o 04:27, Huang, Tao pisze:
> Hi, Pawe?:
> On 2016?10?01? 22:09, =?UTF-8?q?Pawe=C5=82=20Jarosz?= wrote:
>> For some reason accessing memory region above 0xfe000000 freezes
>> system on rk3066. There is similiar bug on later rockchip soc (rk3288)
> RK3066 only support 2GB memory from 0x60000000 to 0xE0000000, can not access
> above 0xfe000000. I think you mean 0x9F000000?
Yes i meant 0x9F00000. Sorry for that.
> I don't remember RK3066 has such limit. I will double check with our IC
> design team.
> Do you know which master can not access this memory area
> [0x9F000000~0xA0000000)?
I don't.
> Could you please tell which board you're using (and how much memory it has)
Rikomagic MK808 1GB RAM
Thanks
Pawel
^ permalink raw reply
* [PATCH 07/14] ASoC: Add sun8i audio card
From: Code Kipper @ 2016-10-05 6:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <33d641ff43f0c0349cdfa2cdbbfdcdde66205596.1475571575.git.mylene.josserand@free-electrons.com>
On 4 October 2016 at 11:46, Myl?ne Josserand
<mylene.josserand@free-electrons.com> wrote:
> Add the audio card for sun8i SoC. This card links the codec driver
> (digital part) with the DAI driver. The analog codec driver is
> added as an aux_device.
>
> Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
> ---
> sound/soc/sunxi/Kconfig | 14 +++++++
> sound/soc/sunxi/Makefile | 1 +
> sound/soc/sunxi/sun8i.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 116 insertions(+)
> create mode 100644 sound/soc/sunxi/sun8i.c
>
> diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig
> index 9e287b0..7b97395 100644
> --- a/sound/soc/sunxi/Kconfig
> +++ b/sound/soc/sunxi/Kconfig
> @@ -27,6 +27,20 @@ config SND_SUN4I_SPDIF
> Say Y or M to add support for the S/PDIF audio block in the Allwinner
> A10 and affiliated SoCs.
>
> +config SND_SUN8I
> + tristate "Allwinner SUN6I/SUN8I audio card support"
> + select SND_SUN8I_CODEC
> + select SND_SUN4I_I2S
> + select SND_SUN8I_CODEC_ANALOG
> + select REGMAP_MMIO
> + help
> + This option enables the audio card for Allwinner A33 (sun8i) SoC.
> + It enables the DAI driver (SND_SUN4I_I2S), the digital audio
> + codec driver (SND_SUN8I_CODEC) and the analog codec driver
> + (SND_SUN8I_CODEC_ANALOG).
> +
> + Say Y or M if you want to add sun8i/6i card support
> +
> config SND_SUN8I_CODEC
> tristate "Allwinner SUN8I audio codec"
> select REGMAP_MMIO
> diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile
> index 1da63d3..7f1bab9 100644
> --- a/sound/soc/sunxi/Makefile
> +++ b/sound/soc/sunxi/Makefile
> @@ -1,5 +1,6 @@
> obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o
> obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o
> obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o
> +obj-$(CONFIG_SND_SUN8I) += sun8i.o
> obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o
> obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o
> diff --git a/sound/soc/sunxi/sun8i.c b/sound/soc/sunxi/sun8i.c
> new file mode 100644
> index 0000000..565cd88
> --- /dev/null
> +++ b/sound/soc/sunxi/sun8i.c
> @@ -0,0 +1,101 @@
> +/*
> + * ALSA SoC driver for Allwinner sun8i SoC
> + *
> + * Copyright (C) 2016 Myl?ne Josserand <mylene.josserand@free-electrons.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/firmware.h>
> +#include <linux/module.h>
> +
> +#include <sound/soc.h>
> +
> +static struct snd_soc_aux_dev sun8i_audio_prcm_aux_devs[] = {
> + {
> + .name = "sun8i-codec-analog",
> + .codec_name = "sun8i-codec-analog.0",
> + },
> +};
> +
> +static struct snd_soc_dai_link sun8i_dai_link = {
> + .name = "sun4i-i2s",
> + .stream_name = "Playback",
> + .codec_dai_name = "sun8i",
> + .dai_fmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S |
> + SND_SOC_DAIFMT_CBM_CFM,
> +};
> +
> +static struct snd_soc_card sun8i_card = {
> + .name = "sun8i-card",
> + .owner = THIS_MODULE,
> + .dai_link = &sun8i_dai_link,
> + .num_links = 1,
> + .aux_dev = sun8i_audio_prcm_aux_devs,
> + .num_aux_devs = ARRAY_SIZE(sun8i_audio_prcm_aux_devs),
> +};
> +
> +static int sun8i_probe(struct platform_device *pdev)
> +{
> + struct snd_soc_dai_link *link = &sun8i_dai_link;
> + struct device_node *np = pdev->dev.of_node;
> + int ret;
> +
> + /* register the soc card */
> + sun8i_card.dev = &pdev->dev;
> +
> + /* Retrieve the audio-codec from DT */
> + link->codec_of_node = of_parse_phandle(np, "allwinner,audio-codec", 0);
> + if (!link->codec_of_node) {
> + dev_err(&pdev->dev, "Missing audio codec\n");
> + return -EINVAL;
> + }
> +
> + /* Retrieve DAI from DT */
> + link->cpu_of_node = of_parse_phandle(np, "allwinner,i2s-controller", 0);
Now that I've spent some time trying to add my changes for the H3
ontop of your code, I think this file should be more generic and rely
on the dtsi more. It's pretty A33 specific but with little effort it
can be worked to cover all of the sun8i type drivers. I would change
"allwinner,i2s-controller" to "allwinner,audio-dai" for starters and
then maybe pull in some info for the dai-link from the dtsi.
CK
> + if (!link->cpu_of_node) {
> + dev_err(&pdev->dev, "Missing I2S controller\n");
> + return -EINVAL;
> + }
> +
> + link->platform_of_node = link->cpu_of_node;
> +
> + /* Register the sound card */
> + ret = devm_snd_soc_register_card(&pdev->dev, &sun8i_card);
> + if (ret) {
> + dev_err(&pdev->dev,
> + "Soc register card failed %d\n", ret);
> + return ret;
> + }
> +
> + return ret;
> +}
> +
> +static const struct of_device_id sun8i_of_match[] = {
> + { .compatible = "allwinner,sun8i-audio", },
> + {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, sun8i_of_match);
> +
> +static struct platform_driver sun8i_card_driver = {
> + .probe = sun8i_probe,
> + .driver = {
> + .name = "sun8i-audio",
> + .of_match_table = sun8i_of_match,
> + },
> +};
> +
> +module_platform_driver(sun8i_card_driver);
> +
> +MODULE_AUTHOR("Myl?ne Josserand <mylene.josserand@free-electrons.com>");
> +MODULE_DESCRIPTION("Allwinner sun8i machine ASoC driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.9.3
>
^ permalink raw reply
* [PATCH v26 0/7] arm64: add kdump support
From: AKASHI Takahiro @ 2016-10-05 5:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <70ca1b97-8de4-921f-0cef-e02a88691ccd@caviumnetworks.com>
Manish,
On Tue, Oct 04, 2016 at 06:53:28PM +0530, Manish Jaggi wrote:
>
> On 10/04/2016 04:23 PM, James Morse wrote:
> > Hi Manish,
> >
> > On 04/10/16 11:05, Manish Jaggi wrote:
> >> On 10/04/2016 03:16 PM, James Morse wrote:
> >>> On 03/10/16 13:41, Manish Jaggi wrote:
> >>>> On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> >>>>> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
> >>>>>> First kernel is booted with mem=2G crashkernel=1G command line option.
> >>>>>> While the system has 64G memory.
> >>>
> >>>>> Are you saying that "mem=..." doesn't have any effect?
> >>>> What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
> >>>> the memory for second kernel has to be withing the crashkernel size.
> >>>> As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
> >>>> much more than the first kernel had in first place.
> >>>
> >>> So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
> >>> to the kdump kernel, this is the expected behaviour. The
> >>> DT:/reserved-memory/crash_dump describes the memory not to use.
> >>>
> >>> On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
> >>> arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
> >>> nor kexec-tools know about the top 62G.
> >>> When you run kexec-tools, it describes what it sees in /proc/iomem in the
> >>> DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.
> >>>
> >>> When we crash and reboot, the crash kernel discovers all 64G of memory from the
> >>> EFI memory map.
> >
> >> So the iomem and meminfo should be same or different for the second kernel?
> >> Also i assumed that crashkernel=1G should restrict the second kernels to 1G.
> >
> > Not with v26 of this series. What should it do with the 62G of memory that was
> > removed by booting with 'mem=2G'? It isn't part of the crashkernel reserved
> > area, and it isn't part of the vmcore described in elfcorehdr either...
> >
> >
> >> This is my understanding from the description. It should not require a second mem= option
> >
> >>> kexec-tools described the 1G of memory that the first kernel was using in the
> >>> DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
> >>> reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.
> >>>
> >>> This may change with the next version of kdump if it switches back to using
> >>> DT:/chosen/linux,usable-memory-range.
> >>> If you need v26 to avoid the top 62G of memory, you need to provide the same
> >>> 'mem=' to the first and second kernel.
> >
> >> If I provide for second kernel, I dont see any prints after Bye.
> >> Have you tired this anytime?
> >
> > Yes, on juno-r1 passing 'mem=2G' to both the first and second kernel causes only
> > the first 2G of memory to be used with this pattern:
> > first kernel: [1G used for linux] [1G reserved for Crash kernel] [6G memory
> > hidden]
> > kdump kernel: [1G vmcore] [1G used for linux] [6G memory hidden]
> >
> >
> Oh, ok!
> I was giving mem=1G to crashkernel to test. with mem=2G it works.
I didn't know that you specified "mem=1G" in our local discussions ...
> >>>>>> 1.2 Live crash dump fails with error
> >>>
> >>> ... do we expect this to work? I don't think it has anything to do with this
> >>> series...
> >>>
> >> Why it should not?
> >> I saved the vmcore file while in second kernel. Since crash without vmcore file didnt run,
> >> Tried with vmcore file and it worked. Its just that if you want to boot a second kernel
> >> with read only file system without network live crash dump analysis is handy.
> >
> > Ah, you want to run /usr/bin/crash with the kdump boot of linux. You still need
> > to tell it where to find the memory image: "crash /path/to/vmlinux /proc/vmcore"
> > should do the trick.
> >
> We should fix the documentation of kdump them.
> Since it is not supported, it should be removed.
Remove what?
And can you please double-check if you still have any problem
on a live system or with a saved core file?
(except for "mem=" stuff)
-Takahiro AKASHI
> > Thanks,
> >
> > James
> >
^ permalink raw reply
* [PATCH v26 0/7] arm64: add kdump support
From: AKASHI Takahiro @ 2016-10-05 5:41 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <57F37A73.3030105@arm.com>
On Tue, Oct 04, 2016 at 10:46:27AM +0100, James Morse wrote:
> Hi Manish,
>
> On 03/10/16 13:41, Manish Jaggi wrote:
> > On 10/03/2016 04:34 PM, AKASHI Takahiro wrote:
> >> On Mon, Oct 03, 2016 at 01:24:34PM +0530, Manish Jaggi wrote:
> >>> With the v26 kdump and v3 kexec-tools and top of tree crash.git, below are the tests done
> >>> Attached is a patch in crash.git (symbols.c) to make crash utility work on my setup.
> >>> Can you please have a look and provide your comments.
> >>>
> >>> To generate a panic, i have a kernel module which on init calls panic.
>
> ... modules ... I haven't tested that. I bet it causes some problems!
> We probably need to include module_alloc_base as an elf note in the vmcore file...
No, I don't think so :)
I created some test module as Manish implied and tested kdump:
(My kernel here even enables KASLR.)
===8<===
$ crash vmlinux vmcore
...
please wait... (gathering module symbol data)
...
crash> mod -S
MODULE NAME SIZE OBJECT FILE
ffff04d78f4b8000 testmod 16384 /opt/buildroot/15.11_64/root/kexec/testmod.ko
crash> bt
PID: 1102 TASK: ffffb4da8e910000 CPU: 0 COMMAND: "insmod"
#0 [ffffb4da8e9afa30] __crash_kexec at ffff0e0045020a54
#1 [ffffb4da8e9afb90] panic at ffff0e004505523c
#2 [ffffb4da8e9afc50] testmod_init at ffff04d78f4b6014 [testmod]
#3 [ffffb4da8e9afb40] do_one_initcall at ffff0e0044f7333c
--- <Exception in user> ---
PC: 0000000a LR: 00000000 SP: ffff04d78f4b6000 PSTATE: 7669726420656c75
X12: ffffb4da8e9ac000 X11: ffff04d78f4b6018 X10: ffffb4da8e9afc50 X9: 20676e6973756143
X8: 00000000 X7: ffff0e0045e5ce00 X6: ffff0e0045e5c000 X5: 600001c5
X4: ffff0e0045020a58 X3: ffffb4da8e9afa30 X2: ffff0e004502098c X1: ffffb4da8e9afa30
X0: 00000124
crash> disas testmod_init
Dump of assembler code for function testmod_init:
0xffff04d78f4b6000 <+0>: stp x29, x30, [sp,#-16]!
0xffff04d78f4b6004 <+4>: mov x29, sp
0xffff04d78f4b6008 <+8>: ldr x0, 0xffff04d78f4b6018
0xffff04d78f4b600c <+12>: bl 0xffff04d78f4b6090
0xffff04d78f4b6010 <+16>: ldr x0, 0xffff04d78f4b6020
0xffff04d78f4b6014 <+20>: bl 0xffff04d78f4b6080
End of assembler dump.
===>8===
(I see some issue in disassembled code, though.)
>
>
> >>> First kernel is booted with mem=2G crashkernel=1G command line option.
> >>> While the system has 64G memory.
>
> >> Are you saying that "mem=..." doesn't have any effect?
> > What I am saying it that If the first kernel is booted using mem= option and crashkernel= option
> > the memory for second kernel has to be withing the crashkernel size.
> > As per /proc/iomem System RAM the information is correct, but the /proc/meminfo is showing total memory
> > much more than the first kernel had in first place.
>
> So your second crashkernel has 63G of memory? Unless you provide the same 'mem='
> to the kdump kernel, this is the expected behaviour. The
> DT:/reserved-memory/crash_dump describes the memory not to use.
>
> On your first boot with 'mem=2G' memblock_mem_limit_remove_map() called from
> arm64_memblock_init() removed the top 62G of memory. Neither the first kernel
> nor kexec-tools know about the top 62G.
> When you run kexec-tools, it describes what it sees in /proc/iomem in the
> DT:/reserved-memory/crash_dump, which is just the remaining 1G of memory.
>
> When we crash and reboot, the crash kernel discovers all 64G of memory from the
> EFI memory map.
> kexec-tools described the 1G of memory that the first kernel was using in the
> DT:/reserved-memory/crash_dump node, so early_init_fdt_scan_reserved_mem()
> reserves the 1G of memory the first kernel used. This leaves us with 63G of memory.
Thank you very much for elaborating this on behalf of myself!
> This may change with the next version of kdump if it switches back to using
> DT:/chosen/linux,usable-memory-range.
Indeed.
We need to talk to Rob.
Thanks,
-Takahiro AKASHI
> If you need v26 to avoid the top 62G of memory, you need to provide the same
> 'mem=' to the first and second kernel.
>
>
> >>> 1.2 Live crash dump fails with error
>
> ... do we expect this to work? I don't think it has anything to do with this
> series...
>
>
> Thanks,
>
> James
>
^ permalink raw reply
* Coresight ETF trace dump failed in Juno r1 with 4.8-rc8
From: Venkatesh Vivekanandan @ 2016-10-05 5:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <434a0256-de86-c1f0-0dc3-a38f55596e8e@arm.com>
On Tue, Oct 4, 2016 at 7:59 PM, Suzuki K Poulose <Suzuki.Poulose@arm.com> wrote:
> On 04/10/16 06:37, Venkatesh Vivekanandan wrote:
>>
>> On Mon, Oct 3, 2016 at 6:44 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>>
>>> Hi Venkatesh,
>>>
>>> On 03/10/16 12:36, Venkatesh Vivekanandan wrote:
>>>>
>>>>
>>>> Hi All,
>>>>
>>>> I am trying to collect ETF trace from Juno R1 and could see "cpu
>>>> stall" while dumping the trace. Attached is the log of sequence
>>>> followed. Was trying to collect the trace data from hardware and see
>>>> if it is any valid data. Am I missing anything here?.
>>>>
>>>
>>> There are few fixes from me and Suzuki queued for v4.9.
>>> Can you check if this issue persists even on linux-next ?
>>
>>
>> Issue is the same in linux-next as well. Please find the attached log.
>>
>> linaro-test [rc=0]# dd if=/dev/20010000.etf of=/cstrace.bin bs=1
>> [ 120.009698] INFO: rcu_preempt detected stalls on CPUs/tasks:
>> [ 120.015307] 2-...: (1 GPs behind) idle=f11/140000000000000/0
>> softirq=224/224 fqs=1903
>> [ 120.023226] (detected by 1, t=5255 jiffies, g=-1, c=-2, q=19)
>> [ 120.029001] Task dump for CPU 2:
>> [ 120.032190] dd R running task 0 1270 1267
>> 0x00000002
>> [ 120.039172] Call trace:
>> [ 120.041594] [<ffff000008085534>] __switch_to+0xc8/0xd4
>> [ 120.046675] [<0000000000020000>] 0x20000
>>
>> Steps followed,
>> # git clone
>> git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
>> linux-next
>> # cd linux-next
>> # make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- defconfig
>> # make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig <---
>> enable coresight
>> # make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j8 Image
>> # make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs
>> # arch/arm64/boot/Image <--- copied this kernel
>> # arch/arm64/boot/dts/arm/juno-r1.dtb <--- copied this dtb
>>
>> Top commit in linux-next is,
>>
>> commit c7d3b912180a9bb0733e5cfab84e5a7493dd3599
>> Author: Stephen Rothwell <sfr@canb.auug.org.au>
>> Date: Tue Oct 4 14:52:03 2016 +1100
>>
>> Add linux-next specific files for 20161004
>
>
> Can't reproduce it here either.
>
> root at localhost:/sys/bus/coresight/devices# echo 1 > 20010000.etf/enable_sink
> root at localhost:/sys/bus/coresight/devices# echo 1 >
> 22140000.etm/enable_source
> root at localhost:/sys/bus/coresight/devices# dd if=/dev/20010000.etf bs=1
> of=/root/etr.bin
> 65536+0 records in
> 65536+0 records out
> 65536 bytes (66 kB) copied, 0.227546 s, 288 kB/s
> root at localhost:/sys/bus/coresight/devices# dd if=/dev/20010000.etf bs=1
> of=/root/etr.bin
> 65536+0 records in
> 65536+0 records out
> 65536 bytes (66 kB) copied, 0.233527 s, 281 kB/s
> root at localhost:/sys/bus/coresight/devices# echo 0 > 20010000.etf/enable_sink
> root at localhost:/sys/bus/coresight/devices# dd if=/dev/20010000.etf bs=1
> of=/root/etr.bin
> 65536+0 records in
> 65536+0 records out
> 65536 bytes (66 kB) copied, 0.474943 s, 138 kB/s
>
> FWIW, here is my firmware version :
>
> NOTICE: Booting Trusted Firmware
> NOTICE: BL1: v1.1(release):e04723e21362
> NOTICE: BL1: Built : 15:39:56, Sep 1 2015
> NOTICE: BL1: Booting BL2
> NOTICE: BL2: v1.1(release):e04723e21362
> NOTICE: BL2: Built : 15:42:30, Sep 1 2015
> NOTICE: BL1: Booting BL3-1
> NOTICE: BL3-1: v1.1(release):604d5da6f2aa
> NOTICE: BL3-1: Built : 14:50:36, Sep 10 2015
> UEFI firmware (version ea31f8e built at 16:35:17 on Aug 5 2015)
>
Hang is seen while trying to dump trace _after_ disabling the ETM
source. Is it not supposed to work?.
It works fine, when dumped before disabling ETM source. Please find
the log below.
linaro-test [rc=0]# echo 1 > 20010000.etf/enable_sink
linaro-test [rc=0]# echo 1 > 22140000.etm/enable_source
[ 91.792145] coresight-tmc 20010000.etf: TMC-ETB/ETF enabled
[ 91.797719] coresight-funnel 20040000.main-funnel: FUNNEL inport 0 enabled
[ 91.804552] coresight-funnel 220c0000.cluster0-funnel: FUNNEL
inport 1 enabled
[ 91.815990] coresight-etm4x 22140000.etm: ETM tracing enabled
linaro-test [rc=0]# dd if=/dev/20010000.etf of=/cstrace.bin bs=1
[ 108.105492] coresight-tmc 20010000.etf: TMC read start
[ 108.404335] coresight-tmc 20010000.etf: TMC read end
65536+0 records in
65536+0 records out
linaro-test [rc=0]# echo 0 > 20010000.etf/enable_sink
linaro-test [rc=0]# dd if=/dev/20010000.etf of=/cstrace.bin bs=1
[ 125.069740] coresight-tmc 20010000.etf: TMC read start
[ 125.184370] coresight-tmc 20010000.etf: TMC read end
65536+0 records in
65536+0 records out
linaro-test [rc=0]# echo 0 > 22140000.etm/enable_source
[ 140.271163] coresight-etm4x 22140000.etm: ETM tracing disabled
[ 140.276964] coresight-funnel 220c0000.cluster0-funnel: FUNNEL
inport 1 disabled
[ 140.284211] coresight-funnel 20040000.main-funnel: FUNNEL inport 0 disabled
[ 140.291128] coresight-tmc 20010000.etf: TMC-ETB/ETF disabled
linaro-test [rc=0]# dd if=/dev/20010000.etf of=/cstrace.bin bs=1
<---- It hangs here...
My firmware version,
NOTICE: Booting Trusted Firmware
NOTICE: BL1: v1.1(debug):4a1dcde
NOTICE: BL1: Built : 17:54:40, Nov 24 2015
NOTICE: BL1: Booting BL2
NOTICE: BL2: v1.1(debug):4a1dcde
NOTICE: BL2: Built : 17:54:40, Nov 24 2015
NOTICE: BL1: Booting BL3-1
NOTICE: BL3-1: v1.1(debug):4a1dcde
NOTICE: BL3-1: Built : 17:54:40, Nov 24 2015
UEFI firmware (version 9ed6f7e built@17:54:28 on Nov 24 2015)
>
> Cheers
> Suzuki
>
^ permalink raw reply
* PROBLEM: DWC3 USB 3.0 not working on Odroid-XU4 with Exynos 5422
From: Vivek Gautam @ 2016-10-05 4:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CANAwSgQ2j+NtDwgn972-1UdY=j4DEsB+0d7VdhoC9i9WHRc9yQ@mail.gmail.com>
Hi Anand,
On Tue, Oct 4, 2016 at 8:39 PM, Anand Moon <linux.amoon@gmail.com> wrote:
> Hi Vivek,
>
[snip]
>
> What I feel is that their need to be some reset of usb phy so that
> device are assigned to respective bus ports.
The phy resets are what we do in the phy-exynos5-usbdrd driver. In
addition to what we
have currently in this phy driver, we just need the phy calibration
patch [1] for phy configurations.
[1] https://lkml.org/lkml/2015/2/2/259
> odroid at odroid:~$ lsusb -t
> /: Bus 06.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
> /: Bus 05.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
> |__ Port 1: Dev 3, If 0, Class=Vendor Specific Class, Driver=r8152, 480M
This shows the ethernet device gets detected on the high-speed port of one
of the controller.
The lsusb output for kernel v4.7.x posted by Michael show that the
ethernet device got detected on super-speed port of the controller.
So, there seems to be a difference between the two.
Or, is this how it is behaving ?
Is this lsusb output on 4.8 kernel with the patch [1] ?
> /: Bus 04.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 5000M
> |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 5000M
> |__ Port 1: Dev 3, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
> |__ Port 2: Dev 4, If 0, Class=Mass Storage, Driver=usb-storage, 5000M
> /: Bus 03.Port 1: Dev 1, Class=root_hub, Driver=xhci-hcd/1p, 480M
> |__ Port 1: Dev 2, If 0, Class=Hub, Driver=hub/2p, 480M
> /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=exynos-ohci/3p, 12M
> /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=exynos-ehci/3p, 480M
> |__ Port 1: Dev 3, If 0, Class=Mass Storage, Driver=usb-storage, 480M
>
>
> Bus 06.Port should register the Realtek Ethernet r8153 device.
> But I am not able to trace out how it's should happen.
If i understand, below is how the configuration looks like on the board?
+-----------------------+
+------>| |
| | Bus 6 |-------+
+-----------+ | (super-speed) | |
| | +-----------------------+ |
|Controller | | --------> Ethernet device
| 2 | |
| | +-----------------------+ |
+-----------+ | | |
| | Bus 5 |-------+
+------>| (high-speed) |
+-----------------------+
+-----------------------+
+------>| |
| | Bus 4 |-------+
+-----------+ | (super-speed) | |
| | +-----------------------+ |
|Controller | | --------> (On board
hub ?? _OR_ external hub with downstream devices) ???
| 1 | |
| | +-----------------------+ |
+-----------+ | | |
| | Bus 3 |-------+
+------>| (high-speed) |
+-----------------------+
Thanks
Vivek
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
^ permalink raw reply
* [PATCH v14 2/4] CMDQ: Mediatek CMDQ driver
From: Jassi Brar @ 2016-10-05 3:37 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475636064.21937.25.camel@mtksdaap41>
On 5 October 2016 at 08:24, Horng-Shyang Liao <hs.liao@mediatek.com> wrote:
> On Fri, 2016-09-30 at 17:47 +0800, Horng-Shyang Liao wrote:
>> On Fri, 2016-09-30 at 17:11 +0800, CK Hu wrote:
>
> After I trace mailbox driver, I realize that CMDQ driver cannot use
> tx_done.
>
> CMDQ clients will flush many tasks into CMDQ driver, and then CMDQ
> driver will apply these tasks into GCE HW "immediately". These tasks,
> which are queued in GCE HW, may not execute immediately since they
> may need to wait event(s), e.g. vsync.
>
> However, in mailbox driver, mailbox uses a software buffer to queue
> sent messages. It only sends next message until previous message is
> done. This cannot fulfill CMDQ's requirement.
>
I understand
a) GCE HW can internally queue many tasks in some 'FIFO'
b) Execution of some task may have to wait until some external event
occurs (like vsync)
c) GCE does not generate irq/flag for each task executed (?)
If so, may be your tx_done should return 'true' so long as the GCE HW
can accept tasks in its 'FIFO'. For mailbox api, any task that is
queued on GCE, is assumed to be transmitted.
> Quote some code from mailbox driver. Please notice "active_req" part.
>
> static void msg_submit(struct mbox_chan *chan)
> {
> ...
> if (!chan->msg_count || chan->active_req)
> goto exit;
> ...
> err = chan->mbox->ops->send_data(chan, data);
> if (!err) {
> chan->active_req = data;
> chan->msg_count--;
> }
> ...
> }
>
> static void tx_tick(struct mbox_chan *chan, int r)
> {
> ...
> spin_lock_irqsave(&chan->lock, flags);
> mssg = chan->active_req;
> chan->active_req = NULL;
> spin_unlock_irqrestore(&chan->lock, flags);
> ...
> }
>
> Current workable CMDQ driver uses mbox_client_txdone() to prevent
> this issue, and then uses self callback functions to handle done tasks.
>
> int cmdq_task_flush_async(struct cmdq_client *client, struct cmdq_task
> *task, cmdq_async_flush_cb cb, void *data)
> {
> ...
> mbox_send_message(client->chan, task);
> /* We can send next task immediately, so just call txdone. */
> mbox_client_txdone(client->chan, 0);
> ...
> }
>
> Another solution is to use rx_callback; i.e. CMDQ mailbox controller
> call mbox_chan_received_data() when CMDQ task is done. But, this may
> violate the design of mailbox. What do you think?
>
If my point (c) above does not hold, maybe look at implementing
tx_done() callback and submit next task from the callback of last
done.
^ permalink raw reply
* [PATCH v2 3/4] ARM: dts: dra72-evm-revc: fix correct phy delay and impedance settings
From: Mugunthan V N @ 2016-10-05 3:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a4ef7fc1-73f7-7136-0d60-6ce8a8ff33b9@ti.com>
On Tuesday 04 October 2016 06:41 PM, Lokesh Vutla wrote:
>
> On Tuesday 04 October 2016 06:26 PM, Mugunthan V N wrote:
>> > The default impedance settings of the phy is not the optimal
>> > value, due to this the second ethernet is not working. Fix it
>> > with correct values which makes the second ethernet port to work.
>> >
>> > Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
>> > ---
>> > arch/arm/boot/dts/dra72-evm-revc.dts | 2 ++
>> > 1 file changed, 2 insertions(+)
>> >
>> > diff --git a/arch/arm/boot/dts/dra72-evm-revc.dts b/arch/arm/boot/dts/dra72-evm-revc.dts
>> > index f9cfd3b..d626cd7 100644
>> > --- a/arch/arm/boot/dts/dra72-evm-revc.dts
>> > +++ b/arch/arm/boot/dts/dra72-evm-revc.dts
>> > @@ -62,6 +62,7 @@
>> > ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
>> > ti,tx-internal-delay = <DP83867_RGMIIDCTL_1_NS>;
>> > ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_8_B_NIB>;
>> > + ti,min-output-imepdance;
> s/imepdance/impedance
>
Thanks for quick catch. Will fix this in v3.
Regards
Mugunthan V N
^ permalink raw reply
* [PATCH v2 2/4] net: phy: dp83867: add support for MAC impedance configuration
From: Mugunthan V N @ 2016-10-05 3:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161004131032.GL11677@lunn.ch>
On Tuesday 04 October 2016 06:40 PM, Andrew Lunn wrote:
>> + if (of_property_read_bool(of_node, "ti,max-output-imepdance"))
>> + dp83867->io_impedance = DP83867_IO_MUX_CFG_IO_IMPEDANCE_MAX;
>> + else if (of_property_read_bool(of_node, "ti,min-output-imepdance"))
>
> Did you really test this? Or did you make the same typos in your device
> tree file?
>
I have tested this and attached the log in cover letter. Since there is
a typo error on both dts and driver it worked as expected. Will send a
v3 ASAP.
Regards
Mugunthan V N
^ permalink raw reply
* [PATCH 08/14] dt-bindings: sound: Add sun8i analog codec documentation
From: Chen-Yu Tsai @ 2016-10-05 2:59 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161004162430.GQ5228@lukather>
On Wed, Oct 5, 2016 at 12:24 AM, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Tue, Oct 04, 2016 at 11:46:21AM +0200, Myl?ne Josserand wrote:
>> Add the documentation for dt-binding of the analog audiocodec
>> driver for SUN8I SoC.
>>
>> Signed-off-by: Myl?ne Josserand <mylene.josserand@free-electrons.com>
>> ---
>> .../devicetree/bindings/sound/sun8i-codec-analog.txt | 20 ++++++++++++++++++++
>> 1 file changed, 20 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
>>
>> diff --git a/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
>> new file mode 100644
>> index 0000000..a03ec20
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/sound/sun8i-codec-analog.txt
>> @@ -0,0 +1,20 @@
>> +* Allwinner A23/A33 Analog Codec
>> +
>> +This codec must be handled as a PRCM subnode.
>
> Like Mark was saying, you should probably reference the sun6i-prcm.txt
> binding here
>
>> +Required properties:
>> +- compatible: must be either "allwinner,sun8i-codec-analog"
>
> Our compatible prefix is <family>-<soc>, and using the older SoC that
> introduced that block.
>
> In this case, that would be sun6i-a31, I think?
sun6i-a31s actually, but a31s has extra line out controls,
so the right one would be sun8i-a23. Both are listed in my
original driver.
ChenYu
>
> Thanks,
> Maxime
>
> --
> Maxime Ripard, Free Electrons
> Embedded Linux and Kernel engineering
> http://free-electrons.com
^ permalink raw reply
* [PATCH v14 2/4] CMDQ: Mediatek CMDQ driver
From: Horng-Shyang Liao @ 2016-10-05 2:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475228829.3658.1.camel@mtksdaap41>
On Fri, 2016-09-30 at 17:47 +0800, Horng-Shyang Liao wrote:
> On Fri, 2016-09-30 at 17:11 +0800, CK Hu wrote:
> > Hi, HS:
> >
> > One comment inline
> >
> > On Fri, 2016-09-30 at 16:56 +0800, Horng-Shyang Liao wrote:
> > > Hi CK,
> > >
> > > Please see my inline reply.
> > >
> > > On Fri, 2016-09-30 at 11:06 +0800, CK Hu wrote:
> > > > Hi, HS:
> > > >
> > > > On Mon, 2016-09-05 at 09:44 +0800, HS Liao wrote:
> > > > > This patch is first version of Mediatek Command Queue(CMDQ) driver. The
> > > > > CMDQ is used to help write registers with critical time limitation,
> > > > > such as updating display configuration during the vblank. It controls
> > > > > Global Command Engine (GCE) hardware to achieve this requirement.
> > > > > Currently, CMDQ only supports display related hardwares, but we expect
> > > > > it can be extended to other hardwares for future requirements.
> > > > >
> > > > > Signed-off-by: HS Liao <hs.liao@mediatek.com>
> > > > > Signed-off-by: CK Hu <ck.hu@mediatek.com>
> > > > > ---
> > > >
> > > > [snip...]
> > > >
> > > > > +
> > > > > +struct cmdq_task {
> > > > > + struct cmdq *cmdq;
> > > > > + struct list_head list_entry;
> > > > > + void *va_base;
> > > > > + dma_addr_t pa_base;
> > > > > + size_t cmd_buf_size; /* command occupied size */
> > > > > + size_t buf_size; /* real buffer size */
> > > > > + bool finalized;
> > > > > + struct cmdq_thread *thread;
> > > >
> > > > I think thread info could be removed from cmdq_task. Only
> > > > cmdq_task_handle_error() and cmdq_task_insert_into_thread() use
> > > > task->thread and caller of both function has the thread info. So you
> > > > could just pass thread info into these two function and remove thread
> > > > info in cmdq_task.
> > >
> > > This modification will remove 1 pointer but add 2 pointers. Moreover,
> > > more pointers will need to be delivered between functions for future
> > > extension. IMHO, it would be better to keep thread pointer inside
> > > cmdq_task.
> > >
> > > > > + struct cmdq_task_cb cb;
> > > >
> > > > I think this callback function is equal to mailbox client tx_done
> > > > callback. It's better to use already-defined interface rather than
> > > > creating your own.
> > >
> > > This is because CMDQ driver allows different callback functions for
> > > different tasks, but mailbox only allows one callback function per
> > > channel. But, I think I can add a wrapper for tx_done to call CMDQ
> > > callback functions. So, I will use tx_done in CMDQ v15.
> >
> > Up to now, one callback function for one channel is enough for DRM. So
> > 'different callback function for different sent-message' looks like an
> > advanced function. Maybe you should not include it in first patch.
> >
> > Regards,
> > CK
>
> Hi CK,
>
> OK. I will do it.
>
> Thanks,
> HS
>
> [snip...]
Hi CK,
After I trace mailbox driver, I realize that CMDQ driver cannot use
tx_done.
CMDQ clients will flush many tasks into CMDQ driver, and then CMDQ
driver will apply these tasks into GCE HW "immediately". These tasks,
which are queued in GCE HW, may not execute immediately since they
may need to wait event(s), e.g. vsync.
However, in mailbox driver, mailbox uses a software buffer to queue
sent messages. It only sends next message until previous message is
done. This cannot fulfill CMDQ's requirement.
Quote some code from mailbox driver. Please notice "active_req" part.
static void msg_submit(struct mbox_chan *chan)
{
...
if (!chan->msg_count || chan->active_req)
goto exit;
...
err = chan->mbox->ops->send_data(chan, data);
if (!err) {
chan->active_req = data;
chan->msg_count--;
}
...
}
static void tx_tick(struct mbox_chan *chan, int r)
{
...
spin_lock_irqsave(&chan->lock, flags);
mssg = chan->active_req;
chan->active_req = NULL;
spin_unlock_irqrestore(&chan->lock, flags);
...
}
Current workable CMDQ driver uses mbox_client_txdone() to prevent
this issue, and then uses self callback functions to handle done tasks.
int cmdq_task_flush_async(struct cmdq_client *client, struct cmdq_task
*task, cmdq_async_flush_cb cb, void *data)
{
...
mbox_send_message(client->chan, task);
/* We can send next task immediately, so just call txdone. */
mbox_client_txdone(client->chan, 0);
...
}
Another solution is to use rx_callback; i.e. CMDQ mailbox controller
call mbox_chan_received_data() when CMDQ task is done. But, this may
violate the design of mailbox. What do you think?
Thanks,
HS
Hi Jassi,
Do you have any suggestion about previous situation?
Thanks,
HS
^ permalink raw reply
* [PATCH] clk: lpc32xx: fix pwm clock divider computation
From: Vladimir Zapolskiy @ 2016-10-05 2:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474915467-11101-1-git-send-email-slemieux.tyco@gmail.com>
Hi Sylvain,
On 26.09.2016 21:44, Sylvain Lemieux wrote:
> From: Sylvain Lemieux <slemieux@tycoint.com>
>
> A zero value in the PWM clock divider register
> (PWM1_FREQ/PWM2_FREQ) turn off the PWM clock.
>
> The "CLK_DIVIDER_ALLOW_ZERO" option is used for hardware that handle
> the zero divider by not modifying their clock input (i.e. bypass).
> See "/include/linux/clk-provider.h" for details.
the problem is that the divider value is not set to some non-zero
value when the clock is enabled, right?
I think it does not matter if the clock rate value is set to parent
clock rate or any other value when divider is 0 *and* clock is gated.
Enabling or disabling a clock is a gate control, so I suggest two
alternative options at your choice (my preference is option 2):
1) add a custom clk_pwm_gate_enable(), clk_pwm_gate_disable() and
clk_pwm_gate_is_enabled() functions combined under lpc32xx_clk_pwm_gate_ops.
Next instead of adding one more define for a single exception
please reassign .ops for two PWM clocks in runtime in
lpc32xx_clk_init() function before calling lpc32xx_clk_register()
in a loop.
But this option is too invasive, a simpler solution is below.
2) in lpc32xx_clk_init() before clock registrations check for zero
dividers of PWM clocks, then if a divider is 0 and clock is gated
set divider to 1, if the divider is 0 and clock is not gated then
gate the clock and set divider to 1, in other cases do nothing.
> Remove the CLK_DIVIDER_ALLOW_ZERO option and add support to handle
> the clock rate computation of the PWM clock divider 0 value.
>
> Signed-off-by: Sylvain Lemieux <slemieux@tycoint.com>
> ---
> Note:
> * Should we include a new CLK_DIVIDER option for this case
> (i.e. clock off when zero ) in "clk-provider.h"?
>
> drivers/clk/nxp/clk-lpc32xx.c | 52 +++++++++++++++++++++++++++++++++++++++----
> 1 file changed, 48 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c
> index 34c9735..3ca3a14 100644
> --- a/drivers/clk/nxp/clk-lpc32xx.c
> +++ b/drivers/clk/nxp/clk-lpc32xx.c
> @@ -959,6 +959,25 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
> divider->flags);
> }
>
> +static unsigned long clk_divider_pwm_recalc_rate(struct clk_hw *hw,
> + unsigned long parent_rate)
> +{
> + struct lpc32xx_clk_div *divider = to_lpc32xx_div(hw);
> + unsigned int val;
> +
> + regmap_read(clk_regmap, divider->reg, &val);
> +
> + val >>= divider->shift;
> + val &= div_mask(divider->width);
> +
> + /* Handle 0 divider -> PWM clock is off. */
> + if(val == 0)
No space in front of the open parenthesis.
> + return 0;
> +
> + return divider_recalc_rate(hw, parent_rate, val, divider->table,
> + divider->flags);
> +}
> +
> static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
> unsigned long *prate)
> {
> @@ -999,6 +1018,12 @@ static const struct clk_ops lpc32xx_clk_divider_ops = {
> .set_rate = clk_divider_set_rate,
> };
>
> +static const struct clk_ops lpc32xx_clk_pwm_divider_ops = {
> + .recalc_rate = clk_divider_pwm_recalc_rate,
> + .round_rate = clk_divider_round_rate,
> + .set_rate = clk_divider_set_rate,
> +};
> +
> static u8 clk_mux_get_parent(struct clk_hw *hw)
> {
> struct lpc32xx_clk_mux *mux = to_lpc32xx_mux(hw);
> @@ -1151,6 +1176,25 @@ struct clk_hw_proto {
> }, \
> }
>
> +#define LPC32XX_DEFINE_PWM_DIV(_idx, _reg, _shift, _width, _tab, _fl) \
> +[CLK_PREFIX(_idx)] = { \
> + .type = CLK_DIV, \
> + { \
> + .hw0 = { \
> + .ops = &lpc32xx_clk_pwm_divider_ops, \
> + { \
> + .div = { \
> + .reg = LPC32XX_CLKPWR_ ## _reg, \
> + .shift = (_shift), \
> + .width = (_width), \
> + .table = (_tab), \
> + .flags = (_fl), \
> + }, \
> + }, \
> + }, \
> + }, \
> +}
> +
> #define LPC32XX_DEFINE_GATE(_idx, _reg, _bit, _flags) \
> [CLK_PREFIX(_idx)] = { \
> .type = CLK_GATE, \
> @@ -1281,14 +1325,14 @@ static struct clk_hw_proto clk_hw_proto[LPC32XX_CLK_HW_MAX] = {
> LPC32XX_DEFINE_GATE(MCPWM, TIMCLK_CTRL1, 6, 0),
>
> LPC32XX_DEFINE_MUX(PWM1_MUX, PWMCLK_CTRL, 1, 0x1, NULL, 0),
> - LPC32XX_DEFINE_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL,
> - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
> + LPC32XX_DEFINE_PWM_DIV(PWM1_DIV, PWMCLK_CTRL, 4, 4, NULL,
> + CLK_DIVIDER_ONE_BASED),
> LPC32XX_DEFINE_GATE(PWM1_GATE, PWMCLK_CTRL, 0, 0),
> LPC32XX_DEFINE_COMPOSITE(PWM1, PWM1_MUX, PWM1_DIV, PWM1_GATE),
>
> LPC32XX_DEFINE_MUX(PWM2_MUX, PWMCLK_CTRL, 3, 0x1, NULL, 0),
> - LPC32XX_DEFINE_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL,
> - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO),
> + LPC32XX_DEFINE_PWM_DIV(PWM2_DIV, PWMCLK_CTRL, 8, 4, NULL,
> + CLK_DIVIDER_ONE_BASED),
> LPC32XX_DEFINE_GATE(PWM2_GATE, PWMCLK_CTRL, 2, 0),
> LPC32XX_DEFINE_COMPOSITE(PWM2, PWM2_MUX, PWM2_DIV, PWM2_GATE),
>
>
--
With best wishes,
Vladimir
^ permalink raw reply
* [PATCH] ARM: dts: rockchip: Reserve unusable memory region on rk3066
From: Huang, Tao @ 2016-10-05 2:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161001140939.GA31220@vaio-ubuntu>
Hi, Pawe?:
On 2016?10?01? 22:09, =?UTF-8?q?Pawe=C5=82=20Jarosz?= wrote:
> For some reason accessing memory region above 0xfe000000 freezes
> system on rk3066. There is similiar bug on later rockchip soc (rk3288)
RK3066 only support 2GB memory from 0x60000000 to 0xE0000000, can not access
above 0xfe000000. I think you mean 0x9F000000?
> solved same way.
>
> Signed-off-by: Pawe? Jarosz <paweljarosz3691@gmail.com>
> ---
> arch/arm/boot/dts/rk3066a.dtsi | 13 +++++++++++++
> 1 file changed, 13 insertions(+)
>
> diff --git a/arch/arm/boot/dts/rk3066a.dtsi b/arch/arm/boot/dts/rk3066a.dtsi
> index 0d0dae3..44c8956 100644
> --- a/arch/arm/boot/dts/rk3066a.dtsi
> +++ b/arch/arm/boot/dts/rk3066a.dtsi
> @@ -93,6 +93,19 @@
> };
> };
>
> + reserved-memory {
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges;
> + /*
> + * The rk3066 cannot use the memory area above 0x9F000000
> + * for some unknown reason.
> + */
I don't remember RK3066 has such limit. I will double check with our IC
design team.
Do you know which master can not access this memory area
[0x9F000000~0xA0000000)?
> + unusable at 9F000000 {
> + reg = <0x9F000000 0x1000000>;
> + };
> + };
> +
> i2s0: i2s at 10118000 {
> compatible = "rockchip,rk3066-i2s";
> reg = <0x10118000 0x2000>;
^ 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