blob: a3aa4352c74c9d75d870c5bb06ff4420d92ada9f [file] [log] [blame]
/****************************************************************************
* arch/arm/src/nrf53/nrf53_ipc.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <debug.h>
#include <inttypes.h>
#include <stdint.h>
#include <nuttx/arch.h>
#include "arm_internal.h"
#include "nrf53_ipc.h"
#include "hardware/nrf53_ipc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* IPC receive channel configuration */
struct nrf53_ipc_recv_s
{
ipc_callback_t callback;
void *args;
};
/* IPC device */
struct nrf53_ipc_s
{
struct nrf53_ipc_recv_s recv[NRF53_IPC_CHANS];
};
/****************************************************************************
* Private Data
****************************************************************************/
struct nrf53_ipc_s g_nrf53_ipc;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: nrf53_ipc_interrupt
****************************************************************************/
static int nrf53_ipc_interrupt(int irq, void *context, void *args)
{
struct nrf53_ipc_s *dev = args;
uint32_t regval = 0;
int i = 0;
regval = getreg32(NRF53_IPC_INTPEND);
ipcinfo("IPC interrupt 0x%" PRIx32 "\n", regval);
for (i = 0; i < NRF53_IPC_CHANS; i += 1)
{
if (regval & IPC_CHAN_ID(i))
{
if (dev->recv[i].callback)
{
dev->recv[i].callback(i, dev->recv[i].args);
}
/* Clear EVENT */
putreg32(0, NRF53_IPC_EVENTS_RECEIVE(i));
}
}
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: nrf53_ipc_subscribe
****************************************************************************/
void nrf53_ipc_subscribe(int id, ipc_callback_t callback, void *args)
{
struct nrf53_ipc_s *dev = &g_nrf53_ipc;
DEBUGASSERT(id < NRF53_IPC_CHANS);
ipcinfo("IPC subscribe %d\n", id);
/* Register callaback */
dev->recv[id].callback = callback;
dev->recv[id].args = args;
if (callback)
{
/* Register as receive channel and enable interrupts */
putreg32(IPC_CHAN_ID(id), NRF53_IPC_RECEIVE_CNF(id));
putreg32(IPC_CHAN_ID(id), NRF53_IPC_INTENSET);
}
else
{
/* Disable interrupts */
putreg32(IPC_CHAN_ID(id), NRF53_IPC_INTENCLR);
}
}
/****************************************************************************
* Name: nrf53_ipc_signal
****************************************************************************/
void nrf53_ipc_signal(int id)
{
DEBUGASSERT(id < NRF53_IPC_CHANS);
ipcinfo("IPC signal %d\n", id);
putreg32(1, NRF53_IPC_TASKS_SEND(id));
}
/****************************************************************************
* Name: nrf53_ipc_send_cfg
****************************************************************************/
void nrf53_ipc_send_cfg(int id)
{
DEBUGASSERT(id < NRF53_IPC_CHANS);
ipcinfo("IPC send cfg %d\n", id);
/* Enable send event on a single IPC channel */
putreg32(IPC_CHAN_ID(id), NRF53_IPC_SEND_CNF(id));
}
/****************************************************************************
* Name: nrf53_ipc_init
****************************************************************************/
void nrf53_ipc_init(void)
{
struct nrf53_ipc_s *dev = &g_nrf53_ipc;
/* Reset device */
memset(dev, 0, sizeof(struct nrf53_ipc_s));
/* Attach and enable the IRQ */
irq_attach(NRF53_IRQ_IPC, nrf53_ipc_interrupt, dev);
up_enable_irq(NRF53_IRQ_IPC);
}