diff --git a/arch/arm/src/cxd56xx/cxd56_adc.c b/arch/arm/src/cxd56xx/cxd56_adc.c index 728a01bebd..9f3ecdabd4 100644 --- a/arch/arm/src/cxd56xx/cxd56_adc.c +++ b/arch/arm/src/cxd56xx/cxd56_adc.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -172,6 +173,8 @@ struct cxd56adc_dev_s struct scufifo_wm_s *wm; /* water mark */ struct math_filter_s *filter; /* math filter */ struct scuev_notify_s * notify; /* notify */ + sem_t exclsem; /* exclusive semaphore */ + int crefs; /* reference count */ }; /**************************************************************************** @@ -218,6 +221,7 @@ static struct cxd56adc_dev_s g_lpadc0priv = .wm = NULL, .filter = NULL, .notify = NULL, + .crefs = 0, }; #endif @@ -233,6 +237,7 @@ static struct cxd56adc_dev_s g_lpadc1priv = .wm = NULL, .filter = NULL, .notify = NULL, + .crefs = 0, }; #endif @@ -248,6 +253,7 @@ static struct cxd56adc_dev_s g_lpadc2priv = .wm = NULL, .filter = NULL, .notify = NULL, + .crefs = 0, }; #endif @@ -263,6 +269,7 @@ static struct cxd56adc_dev_s g_lpadc3priv = .wm = NULL, .filter = NULL, .notify = NULL, + .crefs = 0, }; #endif @@ -278,6 +285,7 @@ static struct cxd56adc_dev_s g_hpadc0priv = .wm = NULL, .filter = NULL, .notify = NULL, + .crefs = 0, }; #endif @@ -293,6 +301,7 @@ static struct cxd56adc_dev_s g_hpadc1priv = .wm = NULL, .filter = NULL, .notify = NULL, + .crefs = 0, }; #endif @@ -703,9 +712,23 @@ static int cxd56_adc_open(FAR struct file *filep) int type; DEBUGASSERT(priv != NULL); - DEBUGASSERT(priv->seq == NULL); DEBUGASSERT(priv->ch < CH_MAX); + /* Increment reference counter */ + + nxsem_wait_uninterruptible(&priv->exclsem); + + priv->crefs++; + DEBUGASSERT(priv->crefs > 0); + + if (priv->crefs > 1) + { + nxsem_post(&priv->exclsem); + return OK; + } + + DEBUGASSERT(priv->seq == NULL); + type = SCU_BUS_LPADC0 + priv->ch; /* Open sequencer */ @@ -713,6 +736,7 @@ static int cxd56_adc_open(FAR struct file *filep) priv->seq = seq_open(SEQ_TYPE_NORMAL, type); if (!priv->seq) { + nxsem_post(&priv->exclsem); return -ENOENT; } @@ -725,11 +749,14 @@ static int cxd56_adc_open(FAR struct file *filep) ret = set_ofstgain(priv); if (ret < 0) { + nxsem_post(&priv->exclsem); return ret; } ainfo("open ch%d freq%d scufifo%d\n", priv->ch, priv->freq, priv->fsize); + nxsem_post(&priv->exclsem); + return OK; } @@ -750,6 +777,19 @@ static int cxd56_adc_close(FAR struct file *filep) DEBUGASSERT(priv->seq != NULL); DEBUGASSERT(priv->ch < CH_MAX); + /* Decrement reference counter */ + + nxsem_wait_uninterruptible(&priv->exclsem); + + DEBUGASSERT(priv->crefs > 0); + priv->crefs--; + + if (priv->crefs > 0) + { + nxsem_post(&priv->exclsem); + return OK; + } + /* Close sequencer */ seq_close(priv->seq); @@ -773,6 +813,8 @@ static int cxd56_adc_close(FAR struct file *filep) priv->notify = NULL; } + nxsem_post(&priv->exclsem); + return OK; } @@ -1058,6 +1100,7 @@ int cxd56_adcinitialize(void) return ret; } + nxsem_init(&g_lpadc0priv.exclsem, 0, 1); #endif #if defined (CONFIG_CXD56_LPADC1) || defined (CONFIG_CXD56_LPADC0_1) || defined (CONFIG_CXD56_LPADC_ALL) ret = register_driver("/dev/lpadc1", &g_adcops, 0666, &g_lpadc1priv); @@ -1067,6 +1110,7 @@ int cxd56_adcinitialize(void) return ret; } + nxsem_init(&g_lpadc1priv.exclsem, 0, 1); #endif #if defined (CONFIG_CXD56_LPADC2) || defined (CONFIG_CXD56_LPADC_ALL) ret = register_driver("/dev/lpadc2", &g_adcops, 0666, &g_lpadc2priv); @@ -1076,6 +1120,7 @@ int cxd56_adcinitialize(void) return ret; } + nxsem_init(&g_lpadc2priv.exclsem, 0, 1); #endif #if defined (CONFIG_CXD56_LPADC3) || defined (CONFIG_CXD56_LPADC_ALL) ret = register_driver("/dev/lpadc3", &g_adcops, 0666, &g_lpadc3priv); @@ -1085,6 +1130,7 @@ int cxd56_adcinitialize(void) return ret; } + nxsem_init(&g_lpadc3priv.exclsem, 0, 1); #endif #ifdef CONFIG_CXD56_HPADC0 ret = register_driver("/dev/hpadc0", &g_adcops, 0666, &g_hpadc0priv); @@ -1094,6 +1140,7 @@ int cxd56_adcinitialize(void) return ret; } + nxsem_init(&g_hpadc0priv.exclsem, 0, 1); #endif #ifdef CONFIG_CXD56_HPADC1 ret = register_driver("/dev/hpadc1", &g_adcops, 0666, &g_hpadc1priv); @@ -1103,6 +1150,7 @@ int cxd56_adcinitialize(void) return ret; } + nxsem_init(&g_hpadc1priv.exclsem, 0, 1); #endif return ret;