Skip to content

Commit

Permalink
os/arch/arm/src/amebasmart: I2C/I2S integrate with PM
Browse files Browse the repository at this point in the history
- Prepare pre/post sleep process for I2C/I2S
  • Loading branch information
edwakuwaku committed May 21, 2024
1 parent cf41d8a commit 8aa2f0a
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 1 deletion.
47 changes: 47 additions & 0 deletions os/arch/arm/src/amebasmart/amebasmart_i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -1226,3 +1226,50 @@ int up_i2creset(FAR struct i2c_dev_s *dev)
return 0;
}
#endif /* CONFIG_I2C_RESET */

/****************************************************************************
* Name: rtk_i2c_suspend/resume
*
* Description:
* Suspend or resume i2c peripherals for/from sleep modes.
*
****************************************************************************/

#ifdef CONFIG_PM
static uint32_t rtk_i2c_suspend(uint32_t expected_idle_time, void *param)
{
(void)expected_idle_time;
(void)param;

/* Need to destroy semaphore and release i2c object to prevent memory leak */
#ifdef CONFIG_AMEBASMART_I2C1
up_i2cuninitialize(&amebasmart_i2c1_priv);
#endif
#ifdef CONFIG_AMEBASMART_I2C2
up_i2cuninitialize(&amebasmart_i2c2_priv);
#endif
return 1;
}

static uint32_t rtk_i2c_resume(uint32_t expected_idle_time, void *param)
{
(void)expected_idle_time;
(void)param;
/* For PG Sleep, I2C 1/2 HW will be lost power, thus a reinitialization is required here
I2C0 is under SYSON block, so it will not require to be reinitialized*/
#ifdef CONFIG_AMEBASMART_I2C1
(void) up_i2cinitialize(1);
#endif
#ifdef CONFIG_AMEBASMART_I2C2
(void) up_i2cinitialize(2);
#endif
return 1;
}
#endif

#ifdef CONFIG_PM
void i2c_pminitialize(void)
{
pmu_register_sleep_callback(PMU_I2C_DEVICE, (PSM_HOOK_FUN)rtk_i2c_suspend, NULL, (PSM_HOOK_FUN)rtk_i2c_resume, NULL);
}
#endif
88 changes: 87 additions & 1 deletion os/arch/arm/src/amebasmart/amebasmart_i2s.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
#include <tinyara/wqueue.h>
#include <tinyara/audio/audio.h>
#include <tinyara/audio/i2s.h>
#ifdef CONFIG_AUDIO_ALC1019
#include <tinyara/audio/alc1019.h>
#endif

#include "irq/irq.h"

Expand Down Expand Up @@ -1706,7 +1709,7 @@ static int i2s_allocate_wd(struct amebasmart_i2s_s *priv)
****************************************************************************/

/****************************************************************************
* Name:
* Name: amebasmart_i2s_initialize
*
* Description:
* Initialize the selected i2s port
Expand Down Expand Up @@ -1809,3 +1812,86 @@ struct i2s_dev_s *amebasmart_i2s_initialize(uint16_t port)
}
#endif /* I2S_HAVE_RX || I2S_HAVE_TX */
#endif /* CONFIG_AUDIO */

#ifdef CONFIG_PM
static void amebasmart_i2s_reinitialize(uint16_t port)
{
struct amebasmart_i2s_config_s *hw_config_s = NULL;
struct amebasmart_i2s_s *priv;

/* Assign HW configuration */
if (port == I2S_NUM_2) {
hw_config_s = (struct amebasmart_i2s_config_s *)&amebasmart_i2s2_config;
} else if (port == I2S_NUM_3) {
hw_config_s = (struct amebasmart_i2s_config_s *)&amebasmart_i2s3_config;
} else {
i2serr("Please select I2S2 or I2S3 bus\n");
return NULL;
}

/* If we the I2S structure is NULL, we should have faced some problem */
DEBUGASSERT(g_i2sdevice[port] == NULL);

priv = g_i2sdevice[port];

/* Get default configuration */
i2s_getdefaultconfig(priv);

/* I2s object reinitialization */
i2s_init(&priv->i2s_object, hw_config_s->i2s_sclk_pin, hw_config_s->i2s_ws_pin, hw_config_s->i2s_sd_tx_pin, hw_config_s->i2s_sd_rx_pin, hw_config_s->i2s_mclk_pin);

/* Initialize buffering */
#if defined(I2S_HAVE_TX) && (0 < I2S_HAVE_TX)
i2s_set_dma_buffer(&priv->i2s_object, (char *)priv->i2s_tx_buf, NULL, I2S_DMA_PAGE_NUM, I2S_DMA_PAGE_SIZE); /* Allocate DMA Buffer for TX */
#endif

/* configures IRQ */
#if defined(I2S_HAVE_RX) && (0 < I2S_HAVE_RX)
priv->rx_isr_handler = (i2s_irq_handler)&i2s_transfer_rx_handleirq;
#endif

#if defined(I2S_HAVE_TX) && (0 < I2S_HAVE_TX)
priv->tx_isr_handler = (i2s_irq_handler)&i2s_transfer_tx_handleirq;
#endif

ret = amebasmart_i2s_isr_initialize(priv);
if (ret != OK) {
i2serr("I2S initialize: isr fails\n");
goto errout_with_alloc;
}

i2s_disable(&priv->i2s_object);
}

static uint32_t rtk_i2s_suspend(uint32_t expected_idle_time, void *param)
{
(void)expected_idle_time;
(void)param;
/* Nothing to do here */

return 1;
}

static uint32_t rtk_i2s_resume(uint32_t expected_idle_time, void *param)
{
(void)expected_idle_time;
(void)param;

/* For PG Sleep, I2S HW will be lost power, thus a reinitialization is required here */
#ifdef CONFIG_AMEBASMART_I2S2
amebasmart_i2s_reinitialize(I2S_NUM_2);
#endif
#ifdef CONFIG_AMEBASMART_I2S3
amebasmart_i2s_reinitialize(I2S_NUM_3);
#endif

return 1;
}
#endif

#ifdef CONFIG_PM
void i2s_pminitialize(void)
{
pmu_register_sleep_callback(PMU_I2S_DEVICE, (PSM_HOOK_FUN)rtk_i2s_suspend, NULL, (PSM_HOOK_FUN)rtk_i2s_resume, NULL);
}
#endif

0 comments on commit 8aa2f0a

Please sign in to comment.