diff options
author | Suren A. Chilingaryan <csa@suren.me> | 2015-08-05 21:18:05 +0200 |
---|---|---|
committer | Suren A. Chilingaryan <csa@suren.me> | 2015-08-05 21:18:05 +0200 |
commit | 3e4b1ebf881a61900c4bab96dc7a7f3963b6d891 (patch) | |
tree | 95fbb89669ebb961f97e2df9ef80d94afb24ecb6 /cmosis.c | |
parent | ff82489cba07d124ca76ac9ce78e70c73cad9317 (diff) | |
download | ipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.tar.gz ipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.tar.bz2 ipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.tar.xz ipecamera-3e4b1ebf881a61900c4bab96dc7a7f3963b6d891.zip |
Serialize access to CMOSIS registers
Diffstat (limited to 'cmosis.c')
-rw-r--r-- | cmosis.c | 75 |
1 files changed, 68 insertions, 7 deletions
@@ -1,5 +1,7 @@ #define _BSD_SOURCE #define _IPECAMERA_MODEL_C +#include <stdio.h> +#include <stdlib.h> #include <sys/time.h> #include <unistd.h> #include <assert.h> @@ -7,6 +9,8 @@ #include <pcilib.h> #include <pcilib/tools.h> #include <pcilib/error.h> +#include <pcilib/locking.h> +#include <pcilib/model.h> #include "cmosis.h" #include "private.h" @@ -25,13 +29,51 @@ //#define IPECAMERA_RETRY_ERRORS #define IPECAMERA_MULTIREAD -int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value) { + +typedef struct ipecamera_cmosis_context_s ipecamera_cmosis_context_t; + +struct ipecamera_cmosis_context_s { + pcilib_register_bank_context_t bank_ctx; /**< the bank context associated with the software registers */ + pcilib_lock_t *lock; /**< the lock to serialize access through GPIO */ +}; + +void ipecamera_cmosis_close(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx) { + ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx; + + if (bank_ctx->lock) + pcilib_return_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, bank_ctx->lock); + free(bank_ctx); +} + +pcilib_register_bank_context_t* ipecamera_cmosis_open(pcilib_t *ctx, pcilib_register_bank_t bank, const char* model, const void *args) { + int err; + ipecamera_cmosis_context_t *bank_ctx; + + bank_ctx = calloc(1, sizeof(ipecamera_cmosis_context_t)); + if (!bank_ctx) { + pcilib_error("Memory allocation for bank context has failed"); + return NULL; + } + + bank_ctx->lock = pcilib_get_lock(ctx, PCILIB_LOCK_FLAGS_DEFAULT, "cmosis"); + if (!bank_ctx->lock) { + ipecamera_cmosis_close(ctx, (pcilib_register_bank_context_t*)bank_ctx); + pcilib_error("Failed to initialize a lock to protect CMOSIS register bank"); + return NULL; + } + + return (pcilib_register_bank_context_t*)bank_ctx; +} + +int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t *value) { + int err; uint32_t val, tmp[4]; char *wr, *rd; struct timeval start; int retries = RETRIES; - const pcilib_register_bank_description_t *bank = bank_ctx->bank; - + ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx; + const pcilib_register_bank_description_t *bank = reg_bank_ctx->bank; + assert(addr < 128); wr = pcilib_resolve_register_address(ctx, bank->bar, bank->write_addr); @@ -42,6 +84,12 @@ int ipecamera_cmosis_read(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ct } retry: + err = pcilib_lock(bank_ctx->lock); + if (err) { + pcilib_error("Error (%i) obtaining a lock to serialize access to CMOSIS registers ", err); + return err; + } + val = (addr << 8); ipecamera_datacpy(wr, &val, bank); @@ -71,15 +119,18 @@ retry: } #endif /* IPECAMERA_MULTIREAD */ + pcilib_unlock(bank_ctx->lock); + if ((val & READ_READY_BIT) == 0) { if (--retries > 0) { pcilib_warning("Timeout reading register value (CMOSIS %lu, status: %lx), retrying (try %i of %i)...", addr, val, RETRIES - retries, RETRIES); goto retry; } + pcilib_error("Timeout reading register value (CMOSIS %lu, status: %lx)", addr, val); return PCILIB_ERROR_TIMEOUT; } - + if (val & READ_ERROR_BIT) { #ifdef IPECAMERA_RETRY_ERRORS if (--retries > 0) { @@ -109,12 +160,14 @@ retry: return 0; } -int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value) { +int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *reg_bank_ctx, pcilib_register_addr_t addr, pcilib_register_value_t value) { + int err; uint32_t val, tmp[4]; char *wr, *rd; struct timeval start; int retries = RETRIES; - const pcilib_register_bank_description_t *bank = bank_ctx->bank; + ipecamera_cmosis_context_t *bank_ctx = (ipecamera_cmosis_context_t*)reg_bank_ctx; + const pcilib_register_bank_description_t *bank = reg_bank_ctx->bank; assert(addr < 128); assert(value < 256); @@ -127,6 +180,12 @@ int ipecamera_cmosis_write(pcilib_t *ctx, pcilib_register_bank_context_t *bank_c } retry: + err = pcilib_lock(bank_ctx->lock); + if (err) { + pcilib_error("Error (%i) obtaining a lock to serialize access to CMOSIS registers ", err); + return err; + } + val = WRITE_BIT|(addr << 8)|(value&0xFF); ipecamera_datacpy(wr, &val, bank); @@ -154,6 +213,8 @@ retry: } #endif /* IPECAMERA_MULTIREAD */ + pcilib_unlock(bank_ctx->lock); + if ((val & READ_READY_BIT) == 0) { #ifdef IPECAMERA_RETRY_ERRORS if (--retries > 0) { @@ -186,7 +247,7 @@ retry: pcilib_error("Address verification failed during register write (CMOSIS %lu, value: %lu, status: %lx)", addr, value, val); return PCILIB_ERROR_VERIFY; } - + if ((val&0xFF) != value) { pcilib_error("Value verification failed during register read (CMOSIS %lu, value: %lu != %lu)", addr, val/*&ipecamera_bit_mask[bits]*/, value); return PCILIB_ERROR_VERIFY; |