Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IPC: IPM: Add ipm adsp driver & sanitycheck #22724

Closed
wants to merge 15 commits into from

Conversation

finikorg
Copy link
Collaborator

@finikorg finikorg commented Feb 11, 2020

Add IPM ADSP driver, DT configuration, ipm_echo sample, IPM console and documentation.
Added sanitycheck support for device-testing of up_squared_adsp.

Testing:
Build sample with

$ west build -p -b up_squared_adsp zephyr/samples/hello_world/

Flash with command

$ west flash zephyr/boards/xtensa/up_squared_adsp/tools/up_squared_adsp_flash.sh <!KEY>

Open simplest polling mailbox terminal with

$ sudo boards/xtensa/up_squared_adsp/tools/mbterm.py 
*** Booting Zephyr OS build zephyr-v2.2.0-1620-g4484b8eff384  ***
Hello World! up_squared_adsp

Try sanitycheck as superuser with

# sanitycheck -M -c -p up_squared_adsp --device-test \
   --west-flash="zephyr/boards/xtensa/up_squared_adsp/tools/up_squared_adsp_flash.sh, otc_private_key.pem" \
   --device-serial-pty zephyr/boards/xtensa/up_squared_adsp/tools/mbterm.py

Running as regular user with ambient (more about ambient: #22724 (comment))

$ ~/work/ambient/set_ambient zephyr/scripts/sanitycheck -M -c -p up_squared_adsp --device-test \
  --west-flash="zephyr/boards/xtensa/up_squared_adsp/tools/up_squared_adsp_flash.sh, otc_private_key.pem" \
  --device-serial-pty zephyr/boards/xtensa/up_squared_adsp/tools/mbterm.py -v

@finikorg finikorg added the area: IPC Inter-Process Communication label Feb 11, 2020
@zephyrbot zephyrbot added the area: Samples Samples label Feb 11, 2020
@zephyrbot
Copy link
Collaborator

zephyrbot commented Feb 11, 2020

All checks are passing now.

Tip: The bot edits this comment instead of posting a new one, so you can check the comment's history to see earlier messages.

@dcpleung
Copy link
Member

Could you squash the two sample commits together?

@finikorg finikorg force-pushed the ipm branch 3 times, most recently from cf0212b to 80f7765 Compare February 12, 2020 13:38
drivers/ipm/ipm_adsp.c Outdated Show resolved Hide resolved
Copy link
Contributor

@andyross andyross left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some notes on first reading. Is there a host-side driver integration somewhere?

/* IPC Target Busy Interrupt Enable (IPCTBIE) */
if (dipct & IPC_DIPCT_BUSY && dipcctl & IPC_DIPCCTL_IPCTBIE) {
/* Mask Busy interrupt */
ipc_write(IPC_DIPCCTL, dipcctl & ~IPC_DIPCCTL_IPCTBIE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So... you're in the ISR here already. Why is this masking the interrupt it's servicing? I'm guessing that this is either needless, or what is happening here is you're masking delivery of the interrupt to the OTHER side of the IPM channel while the shared state is indeterminate, in which case you really need a comment here (and probably need some other locking I'm guessing?). Or maybe the mask/unmask sequence is needed to properly ACK the interrupt? Same thing, needs a comment.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not have good documentation for this, only register description. I have followed what SOF is doing for IPC IRQ handler:
https://github.com/thesofproject/sof/blob/3dd843a46defd5234a517991a7c0049c66233b1d/src/drivers/intel/cavs/ipc.c#L64-L137
I will add more comments.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I cast my mind back, we cant clear this IRQ until we have finished processing the IPC (which may take some time) hence the mask. Clearing could also interrupt the host on some HW too. So short term this flow is fine as it survives 25k flood IPC pings. Long term we should be operating a msg queue where we can clear the IRQ and process the IPC offline (and allow other IPC to be sent).

if (dipcie & IPC_DIPCIE_DONE && dipcctl & IPC_DIPCCTL_IPCIDIE) {
/* Mask Done interrupt */
ipc_write(IPC_DIPCCTL,
ipc_read(IPC_DIPCCTL) & ~IPC_DIPCCTL_IPCIDIE);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above. Need clarity on what is being masked and why.

}

memcpy((void *)IPM_ADSP_MAILBOX_OUT, data, size);
SOC_DCACHE_FLUSH((void *)IPM_ADSP_MAILBOX_OUT, size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that this is an app-visible API, you almost certainly want to check size vs. MAILBOX_OUT_SIZE to avoid scribbling over shared areas and potentially confusing/crashing the host kernel. Or at the very least check it in an __ASSERT().

So this supports only one message at a time? A quick grep says that the outbox region is 4k, I think, so it seems like some queuing ability would really improve things.

Copy link
Collaborator Author

@finikorg finikorg Feb 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About queuing. API mentions:

* finishes. If there is deferred processing on the remote side,
* or you would like to queue outgoing messages and wait on an
* event/semaphore, you can implement that in a high-level driver

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or at the very least check it in an __ASSERT().

Added BUILD_ASSERT.

/* Use zero copy */
data->callback(data->callback_ctx,
dipct & IPC_DIPCI_MSG_MASK,
(void *)IPM_ADSP_MAILBOX_IN);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment to the send side: this supports only one message in the buffer at a time. But this buffer is 8k, and IPM is designed to be asynchronous, so some queing ability would definitely be possible and a good idea.

static int console_out(int c)
{
/* Send character with busy wait */
ipm_send(ipm_console_device, 1, c & ~BIT(31), NULL, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, excellent example of why you want queuing in this driver. This is going to stall waiting on the other side to take an interrupt and clear the busy flat for... every... byte... of... log... output... Some linux driver developer is going to be coming at you with a shiv made from the shards of a smartphone screen.

FWIW: accumulating a local line buffer and flushing when it gets full or on newline would be a very reasonable workaround too.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took it initially from drivers/console/ipm_console_sender.c

ipm_send(ipm_console_device, 1, character, NULL, 0);

I think we can just send without busy wait. If we get BUSY we can just drop the character.

For the testing it was easier to set this flag to verify that it works.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have now immediate log with line buffer and another option using message queue msgq.

@finikorg
Copy link
Collaborator Author

Some notes on first reading. Is there a host-side driver integration somewhere?

For the host side I use devmem2, in this patch set there is README
https://github.com/finikorg/zephyr/tree/ipm/samples/subsys/ipc/ipm_echo

@zephyrbot zephyrbot added area: API Changes to public APIs area: Tests Issues related to a particular existing or missing test labels Feb 14, 2020
@finikorg finikorg force-pushed the ipm branch 2 times, most recently from 49df5c4 to 30678b8 Compare February 14, 2020 13:10
Copy link
Collaborator

@lgirdwood lgirdwood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in general we need to look at de-duplicating code in APL and S1000 ADSP to create a SoC family for all CAVS IP versions.

}

static int ipm_adsp_send(struct device *dev, int wait, u32_t id,
const void *data, int size)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really have the IPC IP programming flows under the SoC family since this function will be used by all CAVS v1.5 DSPs and not just APL..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment I have access only to up_squared board, so it is the only one supported platform. I can test it also on other platforms when they become available.
BTW: How the code would be different for other SOCs?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best to have a look at the IPC drivers in SOF, but generally the IPC doorbell HW has changed between 1st gen (BYT, CHT), 2nd gen (HSW, BDW), 3rd ((SKL - APL), 4th (CNL+). I've started some work on this now, will send a patch for you to review hopefully tomorrow.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the difference with CAVS_VERSION_1_5 and others in https://github.com/thesofproject/sof/blob/master/src/drivers/intel/cavs/ipc.c
I can add support for other boards but I have only up_squared_adsp.

@@ -78,6 +78,14 @@ static void prepare_host_windows(void)
SOC_DCACHE_FLUSH((void *)(HP_SRAM_WIN0_BASE + SRAM_REG_FW_END),
HP_SRAM_WIN0_SIZE - SRAM_REG_FW_END);

if (IS_ENABLED(CONFIG_IPM_ADSP)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking long term we should build the extended FW boot data (i.e. data we send to host about window mappings and some FW capabilities via DT). Any thoughts on this, not something we need immediately but worth considering ?

Copy link
Collaborator Author

@finikorg finikorg Feb 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment we send window mappings:

/*
* Sends the firmware ready message so the firmware loader can
* map the host windows.
*/
static void send_fw_ready(void)
{
memcpy((void *)MAILBOX_DSPBOX_BASE,
&fw_ready_apl, sizeof(fw_ready_apl));
memcpy((void *)(MAILBOX_DSPBOX_BASE + sizeof(fw_ready_apl)),
&sram_window, sizeof(sram_window));
SOC_DCACHE_FLUSH((void *)MAILBOX_DSPBOX_BASE, MAILBOX_DSPBOX_SIZE);
ipc_write(IPC_DIPCIE, 0);
ipc_write(IPC_DIPCI, (0x80000000 | ADSP_IPC_FW_READY));
}

On the host side we use https://github.com/thesofproject/sof-diagnostic-driver which does not use it much.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Linux and the diagnostic driver read this data as part of their IPC init, since mailbox sizes, access etc and IPC HW varies between the SoCs so I dont think there is anything stopping the DT upgrade when time permits.

@github-actions github-actions bot added has-conflicts Issue/PR has conflicts with another issue/PR and removed has-conflicts Issue/PR has conflicts with another issue/PR labels Jul 2, 2020
finikorg added 15 commits August 5, 2020 16:35
Add bindings for ADSP mailbox.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add mailbox to the board DTS.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add IPM driver for ADSP.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add IPM echo sample echoing data over IPM. Add documentation for
the sample.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add console over Inter Processor Mailboxes (IPM).
This is useful for AMP processors like ADSP found on up_squared board.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add @finikorg as codeowner for ipm_adsp driver and ipm_console.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Use for IPC with firmware loader IPM API.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add defaults for IPM_ADSP and IPM_CONSOLE when IPM and CONSOLE are
enabled.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add by default IPM console for up_squared_adsp board, used for sanity
checks.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add tool which can access ADSP console over IPM using Python device
library and polling Doorbell registers.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Add message queue to console in CONFIG_IPM_CONSOLE_IMMEDIATE is not
selected.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
For CONFIG_LOG_BACKEND_RB logs are printed to the ring buffer in memory,
so special tools are needed to read those logs.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Use line buffer to store characters before sending over IPM.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Update terminal tool to use line buffer read instead of one charcter
over IPM.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
Update permissions for mmap.

Signed-off-by: Andrei Emeltchenko <andrei.emeltchenko@intel.com>
@dcpleung
Copy link
Member

??? I thought the driver has already been merged.

@finikorg
Copy link
Collaborator Author

??? I thought the driver has already been merged.

I have split this PR to small chunks, IPM driver was merged, remaining are console over IPM and tools.

@finikorg
Copy link
Collaborator Author

finikorg commented Sep 7, 2020

The PR was split to smaller logical entities and merged upstream. Closing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: API Changes to public APIs area: Bluetooth area: Boards area: Devicetree Binding PR modifies or adds a Device Tree binding area: Devicetree area: Documentation area: IPC Inter-Process Communication area: Samples Samples area: Sanitycheck Sanitycheck has been renamed to Twister area: Tests Issues related to a particular existing or missing test has-conflicts Issue/PR has conflicts with another issue/PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants