From 59af2cc58e37481f176cbea96e6a59e70a9f5598 Mon Sep 17 00:00:00 2001 From: Javier Jalle Date: Tue, 7 Mar 2017 13:59:09 +0100 Subject: leon, grspw_router: Changed driver C API SMP safe by spin-lock protection and semaphore. On spin-lock per SpW/AMBA port to allow multiple parallel register operations per port. A common semaphore for general SpW router configuration such as routing table. Move to a C API instead of using the I/O Manager. The SpW router driver does not perform any I/O only management of the router. Update #2355. --- .../lib/libbsp/sparc/shared/include/grspw_router.h | 342 ++- c/src/lib/libbsp/sparc/shared/spw/grspw_router.c | 2324 +++++++++++++++++--- 2 files changed, 2246 insertions(+), 420 deletions(-) diff --git a/c/src/lib/libbsp/sparc/shared/include/grspw_router.h b/c/src/lib/libbsp/sparc/shared/include/grspw_router.h index 4a5b5fe2f3..aa9086a449 100644 --- a/c/src/lib/libbsp/sparc/shared/include/grspw_router.h +++ b/c/src/lib/libbsp/sparc/shared/include/grspw_router.h @@ -1,7 +1,7 @@ /* * GRSPW ROUTER APB-Register Driver. * - * COPYRIGHT (c) 2010. + * COPYRIGHT (c) 2010-2017. * Cobham Gaisler AB. * * The license and distribution terms for this file may be @@ -12,17 +12,44 @@ #ifndef __GRSPW_ROUTER_H__ #define __GRSPW_ROUTER_H__ +#ifdef __cplusplus +extern "C" { +#endif + +/* Maximum number of ROUTER devices supported by driver */ +#define ROUTER_MAX 2 + +#define ROUTER_ERR_OK 0 +#define ROUTER_ERR_EINVAL -1 +#define ROUTER_ERR_ERROR -2 +#define ROUTER_ERR_TOOMANY -3 +#define ROUTER_ERR_IMPLEMENTED -4 + /* Hardware Information */ struct router_hw_info { - unsigned char nports_spw; - unsigned char nports_amba; - unsigned char nports_fifo; - char timers_avail; - char pnp_avail; - unsigned char ver_major; - unsigned char ver_minor; - unsigned char ver_patch; - unsigned char iid; + uint8_t nports_spw; + uint8_t nports_amba; + uint8_t nports_fifo; + int8_t srouting; + int8_t pnp_enable; + int8_t timers_avail; + int8_t pnp_avail; + uint8_t ver_major; + uint8_t ver_minor; + uint8_t ver_patch; + uint8_t iid; + + /* Router capabilities */ + uint8_t amba_port_fifo_size; + uint8_t spw_port_fifo_size; + uint8_t rmap_maxdlen; + int8_t aux_async; + int8_t aux_dist_int_support; + int8_t dual_port_support; + int8_t dist_int_support; + int8_t spwd_support; + uint8_t pktcnt_support; + uint8_t charcnt_support; }; #define ROUTER_FLG_CFG 0x01 @@ -33,75 +60,280 @@ struct router_hw_info { #define ROUTER_FLG_ALL 0x1f /* All Above Flags */ struct router_config { - unsigned int flags; /* Determine what configuration should be updated */ + uint32_t flags; /* Determine what configuration should be updated */ /* Router Configuration Register */ - unsigned int config; + uint32_t config; /* Set Instance ID */ - unsigned char iid; + uint8_t iid; /* SpaceWire Link Initialization Clock Divisor */ - unsigned char idiv; + uint8_t idiv; - /* Timer Prescaler and Reload */ - unsigned int timer_prescaler; - unsigned int timer_reload[32]; + /* Timer Prescaler */ + uint32_t timer_prescaler; }; -/* Logical routing table */ -struct router_routes { - unsigned int route[224]; +/* Routing table address control */ +struct router_route_acontrol { + uint32_t control[31]; + uint32_t control_logical[224]; }; -/* Port Setup, see register definitions for "Port setup register" */ -struct router_ps { - unsigned int ps[31]; /* Port Setup for ports 1-31 */ - unsigned int ps_logical[224]; /* Port setup for locgical addresses 32-255 */ +/* Routing table port mapping */ +struct router_route_portmap { + uint32_t pmap[31]; /* Port Setup for ports 1-31 */ + uint32_t pmap_logical[224]; /* Port setup for locgical addresses 32-255 */ +}; + +/* Routing table */ +#define ROUTER_ROUTE_FLG_MAP 0x01 +#define ROUTER_ROUTE_FLG_CTRL 0x02 +#define ROUTER_ROUTE_FLG_ALL 0x3 /* All Above Flags */ +struct router_routing_table { + uint32_t flags; /* Determine what configuration should be updated */ + + struct router_route_acontrol acontrol; + struct router_route_portmap portmap; }; /* Set/Get Port Control/Status */ -#define ROUTER_PORTFLG_SET_CTRL 0x01 -#define ROUTER_PORTFLG_GET_CTRL 0x02 -#define ROUTER_PORTFLG_SET_STS 0x04 -#define ROUTER_PORTFLG_GET_STS 0x08 +#define ROUTER_PORT_FLG_SET_CTRL 0x01 +#define ROUTER_PORT_FLG_GET_CTRL 0x02 +#define ROUTER_PORT_FLG_SET_STS 0x04 +#define ROUTER_PORT_FLG_GET_STS 0x08 +#define ROUTER_PORT_FLG_SET_CTRL2 0x10 +#define ROUTER_PORT_FLG_GET_CTRL2 0x20 +#define ROUTER_PORT_FLG_SET_TIMER 0x40 +#define ROUTER_PORT_FLG_GET_TIMER 0x80 +#define ROUTER_PORT_FLG_SET_PKTLEN 0x100 +#define ROUTER_PORT_FLG_GET_PKTLEN 0x200 struct router_port { - unsigned int flag; - int port; - unsigned int ctrl; - unsigned int sts; + uint32_t flag; + /* Port control */ + uint32_t ctrl; + /* Port status */ + uint32_t sts; + /* Port control 2 */ + uint32_t ctrl2; + /* Timer Reload */ + uint32_t timer_reload; + /* Maximum packet length */ + uint32_t packet_length; }; -/* Get Hardware support/information available */ -#define GRSPWR_IOCTL_HWINFO 0x01 /* OUT: struct router_hw_info */ +/* Register GRSPW Router driver to Driver Manager */ +void router_register_drv(void); -/* Router Configuration */ -#define GRSPWR_IOCTL_CFG_SET 0x02 /* IN: struct router_config */ -#define GRSPWR_IOCTL_CFG_GET 0x03 /* OUT: struct router_config */ +extern void *router_open(unsigned int dev_no); +extern int router_close(void *d); +extern int router_print(void *d); +extern int router_hwinfo_get(void *d, struct router_hw_info *hwinfo); -/* Routes */ -#define GRSPWR_IOCTL_ROUTES_SET 0x04 /* IN: struct router_routes */ -#define GRSPWR_IOCTL_ROUTES_GET 0x05 /* OUT: struct router_routes */ +/* Router general config */ +extern int router_config_set(void *d, struct router_config *cfg); +extern int router_config_get(void *d, struct router_config *cfg); -/* Port Setup */ -#define GRSPWR_IOCTL_PS_SET 0x06 /* IN: struct router_ps */ -#define GRSPWR_IOCTL_PS_GET 0x07 /* OUT: struct router_ps */ +/* Routing table config */ +extern int router_routing_table_set(void *d, + struct router_routing_table *cfg); +extern int router_routing_table_get(void *d, + struct router_routing_table *cfg); -/* Set configuration write enable */ -#define GRSPWR_IOCTL_WE_SET 0x08 /* INT: int */ +/* Router Set/Get Port configuration */ +extern int router_port_ioc(void *d, int port, struct router_port *cfg); -/* Set/Get Port Control/Status */ -#define GRSPWR_IOCTL_PORT 0x09 /* IN/OUT: struct router_port */ +/* Read Port Control register */ +extern int router_port_ctrl_get(void *d, int port, uint32_t *ctrl); +/* Read Port Control2 register */ +extern int router_port_ctrl2_get(void *d, int port, uint32_t *ctrl2); +/* Write Port Control Register */ +extern int router_port_ctrl_set(void *d, int port, uint32_t ctrl); +/* Write Port Control2 Register */ +extern int router_port_ctrl2_set(void *d, int port, uint32_t ctrl2); +/* Set Timer Reload Value for a specific port */ +extern int router_port_treload_set(void *d, int port, uint32_t reload); +/* Get Timer Reload Value for a specific port */ +extern int router_port_treload_get(void *d, int port, uint32_t *reload); +/* Get Maximum packet length for a specific port */ +extern int router_port_maxplen_get(void *d, int port, uint32_t *length); +/* Set Maximum packet length for a specific port */ +extern int router_port_maxplen_set(void *d, int port, uint32_t length); -/* Set Router Configuration/Status Register */ -#define GRSPWR_IOCTL_CFGSTS_SET 0x0a /* IN: unsigned int */ -/* Get Router Configuration/Status Register */ -#define GRSPWR_IOCTL_CFGSTS_GET 0x0b /* OUT: unsigned int */ +/* Check Port Status register and clear errors if there are */ +extern int router_port_status(void *d, int port, uint32_t *sts); -/* Get Current Time-Code Register */ -#define GRSPWR_IOCTL_TC_GET 0x0c /* OUT: unsigned int */ +#define ROUTER_LINK_STATUS_ERROR_RESET 0 +#define ROUTER_LINK_STATUS_ERROR_WAIT 1 +#define ROUTER_LINK_STATUS_READY 2 +#define ROUTER_LINK_STATUS_STARTED 3 +#define ROUTER_LINK_STATUS_CONNECTING 4 +#define ROUTER_LINK_STATUS_RUN_STATE 5 +/* Get Link status */ +extern int router_port_link_status(void *d, int port); +/* Operate a Link */ +extern int router_port_enable(void *d, int port); +extern int router_port_disable(void *d, int port); +extern int router_port_link_stop(void *d, int port); +extern int router_port_link_start(void *d, int port); +extern int router_port_link_receive_spill(void *d, int port); +extern int router_port_link_transmit_reset(void *d, int port); -/* Register GRSPW Router driver to Driver Manager */ -void router_register_drv (void); +/* Get port credit counter register */ +extern int router_port_cred_get(void *d, int port, uint32_t *cred); + +/* + * ROUTER RTACTRL register fields + */ +#define RTACTRL_SR (0x1 << RTACTRL_SR_BIT) +#define RTACTRL_EN (0x1 << RTACTRL_EN_BIT) +#define RTACTRL_PR (0x1 << RTACTRL_PR_BIT) +#define RTACTRL_HD (0x1 << RTACTRL_HD_BIT) + +#define RTACTRL_SR_BIT 3 +#define RTACTRL_EN_BIT 2 +#define RTACTRL_PR_BIT 1 +#define RTACTRL_HD_BIT 0 + +/* Individual route modification */ +#define ROUTER_ROUTE_PACKETDISTRIBUTION_ENABLE (0x1 << 16) +#define ROUTER_ROUTE_PACKETDISTRIBUTION_DISABLE (0x0 << 16) +#define ROUTER_ROUTE_SPILLIFNOTREADY_ENABLE RTACTRL_SR +#define ROUTER_ROUTE_SPILLIFNOTREADY_DISABLE 0 +#define ROUTER_ROUTE_ENABLE RTACTRL_EN +#define ROUTER_ROUTE_DISABLE 0 +#define ROUTER_ROUTE_PRIORITY_HIGH RTACTRL_PR +#define ROUTER_ROUTE_PRIORITY_LOW 0 +#define ROUTER_ROUTE_HEADERDELETION_ENABLE RTACTRL_HD +#define ROUTER_ROUTE_HEADERDELETION_DISABLE 0 +struct router_route { + uint8_t from_address; + uint8_t to_port[32]; + int count; + int options; +}; +extern int router_route_set(void *d, struct router_route *route); +extern int router_route_get(void *d, struct router_route *route); + +/* Router configuration port write enable */ +extern int router_write_enable(void *d); +extern int router_write_disable(void *d); + +/* Router reset */ +extern int router_reset(void *d); + +/* Set Instance ID */ +extern int router_instance_set(void *d, uint8_t iid); +/* Get Instance ID */ +extern int router_instance_get(void *d, uint8_t *iid); + +/* Set SpaceWire Link Initialization Clock Divisor */ +extern int router_idiv_set(void *d, uint8_t idiv); +/* Get SpaceWire Link Initialization Clock Divisor */ +extern int router_idiv_get(void *d, uint8_t *idiv); + +/* Set Timer Prescaler */ +extern int router_tpresc_set(void *d, uint32_t prescaler); +/* Get Timer Prescaler */ +extern int router_tpresc_get(void *d, uint32_t *prescaler); + +/* Set/get Router configuration */ +extern int router_cfgsts_set(void *d, uint32_t cfgsts); +extern int router_cfgsts_get(void *d, uint32_t *cfgsts); + +/* Router timecode */ +extern int router_tc_enable(void *d); +extern int router_tc_disable(void *d); +extern int router_tc_reset(void *d); +extern int router_tc_get(void *d); + +/* Router Interrupts */ +/* + * ROUTER IMASK register fields + */ +#define IMASK_PE (0x1 << IMASK_PE_BIT) +#define IMASK_SR (0x1 << IMASK_SR_BIT) +#define IMASK_RS (0x1 << IMASK_RS_BIT) +#define IMASK_TT (0x1 << IMASK_TT_BIT) +#define IMASK_PL (0x1 << IMASK_PL_BIT) +#define IMASK_TS (0x1 << IMASK_TS_BIT) +#define IMASK_AC (0x1 << IMASK_AC_BIT) +#define IMASK_RE (0x1 << IMASK_RE_BIT) +#define IMASK_IA (0x1 << IMASK_IA_BIT) +#define IMASK_LE (0x1 << IMASK_LE_BIT) +#define IMASK_ME (0x1 << IMASK_ME_BIT) +#define IMASK_ALL ( IMASK_PE | IMASK_SR | IMASK_RS | IMASK_TT \ + IMASK_PL | IMASK_TS | IMASK_AC | IMASK_RE | IMASK_IA \ + IMASK_LE | IMASK_ME) + +#define IMASK_PE_BIT 10 +#define IMASK_SR_BIT 9 +#define IMASK_RS_BIT 8 +#define IMASK_TT_BIT 7 +#define IMASK_PL_BIT 6 +#define IMASK_TS_BIT 5 +#define IMASK_AC_BIT 4 +#define IMASK_RE_BIT 3 +#define IMASK_IA_BIT 2 +#define IMASK_LE_BIT 1 +#define IMASK_ME_BIT 0 + +#define ROUTER_INTERRUPT_ALL IMASK_ALL +#define ROUTER_INTERRUPT_SPWPNP_ERROR IMASK_PE +#define ROUTER_INTERRUPT_SPILLED IMASK_SR +#define ROUTER_INTERRUPT_RUNSTATE IMASK_RS +#define ROUTER_INTERRUPT_TC_TRUNCATION IMASK_TT +#define ROUTER_INTERRUPT_PACKET_TRUNCATION IMASK_PL +#define ROUTER_INTERRUPT_TIMEOUT IMASK_TS +#define ROUTER_INTERRUPT_CFGPORT IMASK_AC +#define ROUTER_INTERRUPT_RMAP_ERROR IMASK_RE +#define ROUTER_INTERRUPT_INVALID_ADDRESS IMASK_IA +#define ROUTER_INTERRUPT_LINK_ERROR IMASK_LE +#define ROUTER_INTERRUPT_MEMORY_ERROR IMASK_ME +extern int router_port_interrupt_unmask(void *d, int port); +extern int router_port_interrupt_mask(void *d, int port); +extern int router_interrupt_unmask(void *d, int options); +extern int router_interrupt_mask(void *d, int options); + +/* Router Interrupt code generation */ +/* + * ROUTER ICODEGEN register fields + */ +#define ICODEGEN_UA (0x1 << ICODEGEN_UA_BIT) +#define ICODEGEN_AH (0x1 << ICODEGEN_AH_BIT) +#define ICODEGEN_IT (0x1 << ICODEGEN_IT_BIT) +#define ICODEGEN_TE (0x1 << ICODEGEN_TE_BIT) +#define ICODEGEN_EN (0x1 << ICODEGEN_EN_BIT) +#define ICODEGEN_IN (0x1f << ICODEGEN_IN_BIT) + +#define ICODEGEN_UA_BIT 20 +#define ICODEGEN_AH_BIT 19 +#define ICODEGEN_IT_BIT 18 +#define ICODEGEN_TE_BIT 17 +#define ICODEGEN_EN_BIT 16 +#define ICODEGEN_IN_BIT 0 + +#define ROUTER_ICODEGEN_ITYPE_EDGE ICODEGEN_IT +#define ROUTER_ICODEGEN_ITYPE_LEVEL 0 +#define ROUTER_ICODEGEN_AUTOUNACK_ENABLE ICODEGEN_UA +#define ROUTER_ICODEGEN_AUTOUNACK_DISABLE 0 +#define ROUTER_ICODEGEN_AUTOACK_ENABLE ICODEGEN_AH +#define ROUTER_ICODEGEN_AUTOACK_DISABLE 0 +extern int router_icodegen_enable(void *d, uint8_t intn, uint32_t aitimer, + int options); +extern int router_icodegen_disable(void *d); + +/* Router interrupt change timers */ +extern int router_isrctimer_set(void *d, uint32_t reloadvalue); +extern int router_isrctimer_get(void *d, uint32_t *reloadvalue); + +/* Router interrupt timers */ +extern int router_isrtimer_set(void *d, uint32_t reloadvalue); +extern int router_isrtimer_get(void *d, uint32_t *reloadvalue); + +#ifdef __cplusplus +} +#endif #endif diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c b/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c index 2bd9c720bb..c98dcc49f1 100644 --- a/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c +++ b/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c @@ -1,6 +1,6 @@ /* GRSPW ROUTER APB-Register Driver. * - * COPYRIGHT (c) 2010. + * COPYRIGHT (c) 2010-2017. * Cobham Gaisler AB. * * The license and distribution terms for this file may be @@ -12,106 +12,596 @@ #include #include #include +#include +#include /* printk */ #include #include #include -#define ROUTER_DBG(args...) +//#define STATIC +#define STATIC static -#define REG_READ(adr) (*(volatile unsigned int *)(adr)) -#define REG_WRITE(adr, value) (*(volatile unsigned int *)(adr) = (value)) +#define UNUSED __attribute__((unused)) + +//#define DEBUG 1 + +#ifdef DEBUG +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + +#define THREAD_SAFE 1 + +/* Use interrupt lock privmitives compatible with SMP defined in + * RTEMS 4.11.99 and higher. + */ +#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) + +#ifdef THREAD_SAFE +/* map via rtems_interrupt_lock_* API: */ +#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) +#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) +#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) +#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) +#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) +#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) +#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k +#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) +#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock) +#else +#define SPIN_DECLARE(lock) +#define SPIN_INIT(lock, name) +#define SPIN_LOCK(lock, level) +#define SPIN_LOCK_IRQ(lock, level) +#define SPIN_UNLOCK(lock, level) +#define SPIN_UNLOCK_IRQ(lock, level) +#define SPIN_IRQFLAGS(k) +#define SPIN_ISR_IRQFLAGS(k) +#define SPIN_FREE(lock) +#endif + +#else + +#ifdef THREAD_SAFE +#error THREAD SAFE operation not supported on this RTEMS version +#else +#define SPIN_DECLARE(lock) +#define SPIN_INIT(lock, name) +#define SPIN_LOCK(lock, level) +#define SPIN_LOCK_IRQ(lock, level) +#define SPIN_UNLOCK(lock, level) +#define SPIN_UNLOCK_IRQ(lock, level) +#define SPIN_IRQFLAGS(k) +#define SPIN_ISR_IRQFLAGS(k) +#define SPIN_FREE(lock) +#endif + +#ifdef RTEMS_SMP +#error SMP mode not compatible with these interrupt lock primitives +#endif + +#endif + +#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) +#define REG_READ(addr) (*(volatile unsigned int *)(addr)) + + +/* + * ROUTER RTPMAP register fields + */ +#define RTPMAP_PE (0x7fffffff << RTPMAP_PE_BIT) +#define RTPMAP_PD (0x1 << RTPMAP_PD_BIT) + +#define RTPMAP_PE_BIT 1 +#define RTPMAP_PD_BIT 0 + +/* + * ROUTER RTACTRL register fields + * DEFINED IN HEADER + */ + +/* + * ROUTER PCTRL register fields + */ +#define PCTRL_RD (0xff << PCTRL_RD_BIT) +#define PCTRL_ST (0x1 << PCTRL_ST_BIT) +#define PCTRL_SR (0x1 << PCTRL_SR_BIT) +#define PCTRL_AD (0x1 << PCTRL_AD_BIT) +#define PCTRL_LR (0x1 << PCTRL_LR_BIT) +#define PCTRL_PL (0x1 << PCTRL_PL_BIT) +#define PCTRL_TS (0x1 << PCTRL_TS_BIT) +#define PCTRL_IC (0x1 << PCTRL_IC_BIT) +#define PCTRL_ET (0x1 << PCTRL_ET_BIT) +#define PCTRL_NP (0x1 << PCTRL_NP_BIT) +#define PCTRL_PS (0x1 << PCTRL_PS_BIT) +#define PCTRL_BE (0x1 << PCTRL_BE_BIT) +#define PCTRL_DI (0x1 << PCTRL_DI_BIT) +#define PCTRL_TR (0x1 << PCTRL_TR_BIT) +#define PCTRL_PR (0x1 << PCTRL_PR_BIT) +#define PCTRL_TF (0x1 << PCTRL_TF_BIT) +#define PCTRL_RS (0x1 << PCTRL_RS_BIT) +#define PCTRL_TE (0x1 << PCTRL_TE_BIT) +#define PCTRL_CE (0x1 << PCTRL_CE_BIT) +#define PCTRL_AS (0x1 << PCTRL_AS_BIT) +#define PCTRL_LS (0x1 << PCTRL_LS_BIT) +#define PCTRL_LD (0x1 << PCTRL_LD_BIT) + +#define PCTRL_RD_BIT 24 +#define PCTRL_ST_BIT 21 +#define PCTRL_SR_BIT 20 +#define PCTRL_AD_BIT 19 +#define PCTRL_LR_BIT 18 +#define PCTRL_PL_BIT 17 +#define PCTRL_TS_BIT 16 +#define PCTRL_IC_BIT 15 +#define PCTRL_ET_BIT 14 +#define PCTRL_NP_BIT 13 +#define PCTRL_PS_BIT 12 +#define PCTRL_BE_BIT 11 +#define PCTRL_DI_BIT 10 +#define PCTRL_TR_BIT 9 +#define PCTRL_PR_BIT 8 +#define PCTRL_TF_BIT 7 +#define PCTRL_RS_BIT 6 +#define PCTRL_TE_BIT 5 +#define PCTRL_CE_BIT 3 +#define PCTRL_AS_BIT 2 +#define PCTRL_LS_BIT 1 +#define PCTRL_LD_BIT 0 + +/* + * ROUTER PSTSCFG register fields + */ +#define PSTSCFG_EO (0x1 << PSTSCFG_EO_BIT) +#define PSTSCFG_EE (0x1 << PSTSCFG_EE_BIT) +#define PSTSCFG_PL (0x1 << PSTSCFG_PL_BIT) +#define PSTSCFG_TT (0x1 << PSTSCFG_TT_BIT) +#define PSTSCFG_PT (0x1 << PSTSCFG_PT_BIT) +#define PSTSCFG_HC (0x1 << PSTSCFG_HC_BIT) +#define PSTSCFG_PI (0x1 << PSTSCFG_PI_BIT) +#define PSTSCFG_CE (0x1 << PSTSCFG_CE_BIT) +#define PSTSCFG_EC (0xf << PSTSCFG_EC_BIT) +#define PSTSCFG_TS (0x1 << PSTSCFG_TS_BIT) +#define PSTSCFG_ME (0x1 << PSTSCFG_ME_BIT) +#define PSTSCFG_IP (0x1f << PSTSCFG_IP_BIT) +#define PSTSCFG_CP (0x1 << PSTSCFG_CP_BIT) +#define PSTSCFG_PC (0xf << PSTSCFG_PC_BIT) +#define PSTSCFG_WCLEAR (PSTSCFG_EO | PSTSCFG_EE | PSTSCFG_PL | \ + PSTSCFG_TT | PSTSCFG_PT | PSTSCFG_HC | \ + PSTSCFG_PI | PSTSCFG_CE | PSTSCFG_TS | \ + PSTSCFG_ME | PSTSCFG_CP) + +#define PSTSCFG_EO_BIT 31 +#define PSTSCFG_EE_BIT 30 +#define PSTSCFG_PL_BIT 29 +#define PSTSCFG_TT_BIT 28 +#define PSTSCFG_PT_BIT 27 +#define PSTSCFG_HC_BIT 26 +#define PSTSCFG_PI_BIT 25 +#define PSTSCFG_CE_BIT 24 +#define PSTSCFG_EC_BIT 20 +#define PSTSCFG_TS_BIT 18 +#define PSTSCFG_ME_BIT 17 +#define PSTSCFG_IP_BIT 7 +#define PSTSCFG_CP_BIT 4 +#define PSTSCFG_PC_BIT 0 + +/* + * ROUTER PSTS register fields + */ +#define PSTS_PT (0x3 << PSTS_PT_BIT) +#define PSTS_PL (0x1 << PSTS_PL_BIT) +#define PSTS_TT (0x1 << PSTS_TT_BIT) +#define PSTS_RS (0x1 << PSTS_RS_BIT) +#define PSTS_SR (0x1 << PSTS_SR_BIT) +#define PSTS_LR (0x1 << PSTS_LR_BIT) +#define PSTS_SP (0x1 << PSTS_SP_BIT) +#define PSTS_AC (0x1 << PSTS_AC_BIT) +#define PSTS_TS (0x1 << PSTS_TS_BIT) +#define PSTS_ME (0x1 << PSTS_ME_BIT) +#define PSTS_TF (0x1 << PSTS_TF_BIT) +#define PSTS_RE (0x1 << PSTS_RE_BIT) +#define PSTS_LS (0x7 << PSTS_LS_BIT) +#define PSTS_IP (0x1f << PSTS_IP_BIT) +#define PSTS_PR (0x1 << PSTS_PR_BIT) +#define PSTS_PB (0x1 << PSTS_PB_BIT) +#define PSTS_IA (0x1 << PSTS_IA_BIT) +#define PSTS_CE (0x1 << PSTS_CE_BIT) +#define PSTS_ER (0x1 << PSTS_ER_BIT) +#define PSTS_DE (0x1 << PSTS_DE_BIT) +#define PSTS_PE (0x1 << PSTS_PE_BIT) +#define PSTS_WCLEAR (PSTS_PL | PSTS_TT | PSTS_RS | PSTS_SR | \ + PSTS_TS | PSTS_ME | PSTS_IA | PSTS_CE | \ + PSTS_ER | PSTS_DE | PSTS_PE) + +#define PSTS_PT_BIT 30 +#define PSTS_PL_BIT 29 +#define PSTS_TT_BIT 28 +#define PSTS_RS_BIT 27 +#define PSTS_SR_BIT 26 +#define PSTS_LR_BIT 22 +#define PSTS_SP_BIT 21 +#define PSTS_AC_BIT 20 +#define PSTS_TS_BIT 18 +#define PSTS_ME_BIT 17 +#define PSTS_TF_BIT 16 +#define PSTS_RE_BIT 15 +#define PSTS_LS_BIT 12 +#define PSTS_IP_BIT 7 +#define PSTS_PR_BIT 6 +#define PSTS_PB_BIT 5 +#define PSTS_IA_BIT 4 +#define PSTS_CE_BIT 3 +#define PSTS_ER_BIT 2 +#define PSTS_DE_BIT 1 +#define PSTS_PE_BIT 0 + +/* + * ROUTER PTIMER register fields + */ +#define PTIMER_RL (0xffff << PTIMER_RL_BIT) + +#define PTIMER_RL_BIT 0 + +/* + * ROUTER PCTRL2 register fields + */ +#define PCTRL2_SM (0xff << PCTRL2_SM_BIT) +#define PCTRL2_SV (0xff << PCTRL2_SV_BIT) +#define PCTRL2_OR (0x1 << PCTRL2_OR_BIT) +#define PCTRL2_UR (0x1 << PCTRL2_UR_BIT) +#define PCTRL2_AT (0x1 << PCTRL2_AT_BIT) +#define PCTRL2_AR (0x1 << PCTRL2_AR_BIT) +#define PCTRL2_IT (0x1 << PCTRL2_IT_BIT) +#define PCTRL2_IR (0x1 << PCTRL2_IR_BIT) +#define PCTRL2_SD (0x1f << PCTRL2_SD_BIT) +#define PCTRL2_SC (0x1f << PCTRL2_SC_BIT) + +#define PCTRL2_SM_BIT 24 +#define PCTRL2_SV_BIT 16 +#define PCTRL2_OR_BIT 15 +#define PCTRL2_UR_BIT 14 +#define PCTRL2_AT_BIT 12 +#define PCTRL2_AR_BIT 11 +#define PCTRL2_IT_BIT 10 +#define PCTRL2_IR_BIT 9 +#define PCTRL2_SD_BIT 1 +#define PCTRL2_SC_BIT 0 + +/* + * ROUTER RTRCFG register fields + */ +#define RTRCFG_SP (0x1f << RTRCFG_SP_BIT) +#define RTRCFG_AP (0x1f << RTRCFG_AP_BIT) +#define RTRCFG_FP (0x1f << RTRCFG_FP_BIT) +#define RTRCFG_SR (0x1 << RTRCFG_SR_BIT) +#define RTRCFG_PE (0x1 << RTRCFG_PE_BIT) +#define RTRCFG_IC (0x1 << RTRCFG_IC_BIT) +#define RTRCFG_IS (0x1 << RTRCFG_IS_BIT) +#define RTRCFG_IP (0x1 << RTRCFG_IP_BIT) +#define RTRCFG_AI (0x1 << RTRCFG_AI_BIT) +#define RTRCFG_AT (0x1 << RTRCFG_AT_BIT) +#define RTRCFG_IE (0x1 << RTRCFG_IE_BIT) +#define RTRCFG_RE (0x1 << RTRCFG_RE_BIT) +#define RTRCFG_EE (0x1 << RTRCFG_EE_BIT) +#define RTRCFG_LS (0x1 << RTRCFG_LS_BIT) +#define RTRCFG_SA (0x1 << RTRCFG_SA_BIT) +#define RTRCFG_TF (0x1 << RTRCFG_TF_BIT) +#define RTRCFG_ME (0x1 << RTRCFG_ME_BIT) +#define RTRCFG_TA (0x1 << RTRCFG_TA_BIT) +#define RTRCFG_PP (0x1 << RTRCFG_PP_BIT) +#define RTRCFG_WCLEAR (RTRCFG_ME) + +#define RTRCFG_SP_BIT 27 +#define RTRCFG_AP_BIT 22 +#define RTRCFG_FP_BIT 17 +#define RTRCFG_SR_BIT 15 +#define RTRCFG_PE_BIT 14 +#define RTRCFG_IC_BIT 13 +#define RTRCFG_IS_BIT 12 +#define RTRCFG_IP_BIT 11 +#define RTRCFG_AI_BIT 10 +#define RTRCFG_AT_BIT 9 +#define RTRCFG_IE_BIT 8 +#define RTRCFG_RE_BIT 7 +#define RTRCFG_EE_BIT 6 +#define RTRCFG_LS_BIT 5 +#define RTRCFG_SA_BIT 4 +#define RTRCFG_TF_BIT 3 +#define RTRCFG_ME_BIT 2 +#define RTRCFG_TA_BIT 1 +#define RTRCFG_PP_BIT 0 + +/* + * ROUTER TC register fields + */ +#define TC_RE (0x3f << TC_RE_BIT) +#define TC_EN (0x3f << TC_EN_BIT) +#define TC_CF (0x3f << TC_CF_BIT) +#define TC_TC (0x3f << TC_TC_BIT) + +#define TC_RE_BIT 9 +#define TC_EN_BIT 8 +#define TC_CF_BIT 6 +#define TC_TC_BIT 0 + +/* + * ROUTER VER register fields + */ +#define VER_MA (0xff << VER_MA_BIT) +#define VER_MI (0xff << VER_MI_BIT) +#define VER_PA (0xff << VER_PA_BIT) +#define VER_ID (0xff << VER_ID_BIT) + +#define VER_MA_BIT 24 +#define VER_MI_BIT 16 +#define VER_PA_BIT 8 +#define VER_ID_BIT 0 + +/* + * ROUTER IDIV register fields + */ +#define IDIV_ID (0xff << IDIV_ID_BIT) + +#define IDIV_ID_BIT 0 + +/* + * ROUTER CFGWE register fields + */ +#define CFGWE_WE (0x1 << CFGWE_WE_BIT) + +#define CFGWE_WE_BIT 0 + +/* + * ROUTER PRESCALER register fields + */ +#define PRESCALER_RL (0xffff << PRESCALER_RL_BIT) + +#define PRESCALER_RL_BIT 0 + +/* + * ROUTER IMASK register fields + * DEFINED IN HEADER + */ + +/* + * ROUTER ICODEGEN register fields + * DEFINED IN HEADER + */ + +/* + * ROUTER ISRTIMER register fields + */ +#define ISRTIMER_RL (0xffff << ISRTIMER_RL_BIT) + +#define ISRTIMER_RL_BIT 0 + +/* + * ROUTER AITIMER register fields + */ +#define AITIMER_RL (0xffff << AITIMER_RL_BIT) + +#define AITIMER_RL_BIT 0 + +/* + * ROUTER ISRCTIMER register fields + */ +#define ISRCTIMER_RL (0x1f << ISRCTIMER_RL_BIT) + +#define ISRCTIMER_RL_BIT 0 + +/* + * ROUTER CAP register fields + */ +#define CAP_AF (0x3 << CAP_AF_BIT) +#define CAP_PF (0x7 << CAP_PF_BIT) +#define CAP_RM (0x7 << CAP_RM_BIT) +#define CAP_AS (0x1 << CAP_AS_BIT) +#define CAP_AX (0x1 << CAP_AX_BIT) +#define CAP_DP (0x1 << CAP_DP_BIT) +#define CAP_ID (0x1 << CAP_ID_BIT) +#define CAP_SD (0x1 << CAP_SD_BIT) +#define CAP_PC (0x1f << CAP_PC_BIT) +#define CAP_CC (0x1f << CAP_CC_BIT) + +#define CAP_AF_BIT 24 +#define CAP_PF_BIT 29 +#define CAP_RM_BIT 16 +#define CAP_AS_BIT 14 +#define CAP_AX_BIT 13 +#define CAP_DP_BIT 12 +#define CAP_ID_BIT 11 +#define CAP_SD_BIT 10 +#define CAP_PC_BIT 4 +#define CAP_CC_BIT 0 + +/* + * ROUTER PNPVEND register fields + */ +#define PNPVEND_VI (0xffff << PNPVEND_VI_BIT) +#define PNPVEND_PI (0xffff << PNPVEND_PI_BIT) + +#define PNPVEND_VI_BIT 16 +#define PNPVEND_PI_BIT 0 + +/* + * ROUTER PNPUVEND register fields + */ +#define PNPUVEND_VI (0xffff << PNPUVEND_VI_BIT) +#define PNPUVEND_PI (0xffff << PNPUVEND_PI_BIT) + +#define PNPUVEND_VI_BIT 16 +#define PNPUVEND_PI_BIT 0 + +/* + * ROUTER MAXPLEN register fields + */ +#define MAXPLEN_ML (0xffffff << MAXPLEN_ML_BIT) + +#define MAXPLEN_ML_BIT 0 + +/* + * ROUTER CHARO register fields + */ +#define CHARO_OR (0x1 << CHARO_OR_BIT) +#define CHARO_CC (0x7fffffff << CHARO_CC_BIT) + +#define CHARO_OR_BIT 31 +#define CHARO_CC_BIT 0 + +/* + * ROUTER CHARI register fields + */ +#define CHARI_OR (0x1 << CHARI_OR_BIT) +#define CHARI_CC (0x7fffffff << CHARI_CC_BIT) + +#define CHARI_OR_BIT 31 +#define CHARI_CC_BIT 0 + +/* + * ROUTER PKTO register fields + */ +#define PKTO_OR (0x1 << PKTO_OR_BIT) +#define PKTO_CC (0x7fffffff << PKTO_CC_BIT) + +#define PKTO_OR_BIT 31 +#define PKTO_CC_BIT 0 + +/* + * ROUTER PKTI register fields + */ +#define PKTI_OR (0x1 << PKTI_OR_BIT) +#define PKTI_CC (0x7fffffff << PKTI_CC_BIT) + +#define PKTI_OR_BIT 31 +#define PKTI_CC_BIT 0 + +/* + * ROUTER CRED register fields + */ +#define CRED_OC (0x3f << CRED_OC_BIT) +#define CRED_IC (0x3f << CRED_IC_BIT) + +#define CRED_OC_BIT 6 +#define CRED_IC_BIT 0 + +/* + * ROUTER RTRCOMB register fields + */ +#define RTRCOMB_SR (0x1 << RTRCOMB_SR_BIT) +#define RTRCOMB_EN (0x1 << RTRCOMB_EN_BIT) +#define RTRCOMB_PR (0x1 << RTRCOMB_PR_BIT) +#define RTRCOMB_HD (0x1 << RTRCOMB_HD_BIT) +#define RTRCOMB_PE (0x7ffff << RTRCOMB_PE_BIT) +#define RTRCOMB_PD (0x1 << RTRCOMB_PD_BIT) + +#define RTRCOMB_SR_BIT 31 +#define RTRCOMB_EN_BIT 30 +#define RTRCOMB_PR_BIT 29 +#define RTRCOMB_HD_BIT 28 +#define RTRCOMB_PE_BIT 1 +#define RTRCOMB_PD_BIT 0 struct router_regs { unsigned int resv1; /* 0x000 */ unsigned int psetup[255]; /* 0x004 */ - unsigned int resv2[32]; /* 0x400 */ - unsigned int routes[224]; /* 0x480 */ + unsigned int resv2; /* 0x400 */ + unsigned int routes[255]; /* 0x404 */ unsigned int pctrl[32]; /* 0x800 */ unsigned int psts[32]; /* 0x880 */ unsigned int treload[32]; /* 0x900 */ - unsigned int resv3[32]; /* 0x980 */ + unsigned int pctrl2[32]; /* 0x980 */ unsigned int cfgsts; /* 0xA00 */ unsigned int timecode; /* 0xA04 */ unsigned int ver; /* 0xA08 */ unsigned int idiv; /* 0xA0C */ unsigned int cfgwe; /* 0xA10 */ unsigned int tprescaler; /* 0xA14 */ - unsigned int resv4[123]; /* 0xA18 */ - unsigned int charo[31]; /* 0xC04 */ - unsigned int resv5; /* 0xC80 */ + unsigned int imask; /* 0xA18 */ + unsigned int ipmask; /* 0xA1C */ + unsigned int pip; /* 0xA20 */ + unsigned int icodegen; /* 0xA24 */ + unsigned int isr0; /* 0xA28 */ + unsigned int isr1; /* 0xA2C */ + unsigned int isrtimer; /* 0xA30 */ + unsigned int aitimer; /* 0xA34 */ + unsigned int isrctimer; /* 0xA38 */ + unsigned int resv4; /* 0xA3C */ + unsigned int lrunsts; /* 0xA40 */ + unsigned int cap; /* 0xA44 */ + unsigned int resv5[111]; /* 0xA48 */ + unsigned int charo[31]; /* 0xC04 */ /* TODO check GR718 */ + unsigned int resv6; /* 0xC80 */ unsigned int chari[31]; /* 0xC84 */ - unsigned int resv6; /* 0xD00 */ + unsigned int resv7; /* 0xD00 */ unsigned int pkto[31]; /* 0xD04 */ - unsigned int resv7; /* 0xD80 */ + unsigned int resv8; /* 0xD80 */ unsigned int pkti[31]; /* 0xD84 */ + unsigned int maxplen[32]; /* 0xE00 */ + unsigned int resv9; /* 0xE80 */ + unsigned int credcnt[31]; /* 0xE84 */ + unsigned int resv10[64]; /* 0xF00 */ + unsigned int resv11; /* 0x1000 */ + unsigned int rtcomb[255]; /* 0x1004 */ }; struct router_priv { - char devName[32]; struct drvmgr_dev *dev; + + /* ROUTER control registers */ struct router_regs *regs; + + #ifdef THREAD_SAFE + /* ROUTER semaphore */ + rtems_id sem; + #endif + + /* ROUTER driver register */ + char devname[9]; + int index; /* Index in order it was probed */ + int minor; int open; struct router_hw_info hwinfo; int nports; + int irq_init; + + SPIN_DECLARE(plock[32]) + }; -static rtems_device_driver router_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver router_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver router_close( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver router_control( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -#define ROUTER_DRIVER_TABLE_ENTRY \ - { router_initialize, \ - router_open, \ - router_close, \ - NULL, \ - NULL, \ - router_control } - -static void router_hwinfo( - struct router_priv *priv, - struct router_hw_info *hwinfo); - -static rtems_driver_address_table router_driver = ROUTER_DRIVER_TABLE_ENTRY; -static int router_driver_io_registered = 0; -static rtems_device_major_number router_driver_io_major = 0; - -/******************* Driver manager interface ***********************/ +int router_count = 0; +static struct router_priv *priv_tab[ROUTER_MAX]; /* Driver prototypes */ -int router_register_io(rtems_device_major_number *m); + +STATIC int router_init(struct router_priv *priv); +STATIC void router_hwinfo(struct router_priv *priv, + struct router_hw_info *hwinfo); +STATIC int router_acontrol_set(struct router_priv *priv, + struct router_route_acontrol *control); +STATIC int router_acontrol_get(struct router_priv *priv, + struct router_route_acontrol *control); +STATIC int router_portmap_set(struct router_priv *priv, + struct router_route_portmap *pmap); +STATIC int router_portmap_get(struct router_priv *priv, + struct router_route_portmap *pmap); + +/* -IRQ handler */ +void router_isr(void *arg); int router_init2(struct drvmgr_dev *dev); -struct drvmgr_drv_ops router_ops = +struct drvmgr_drv_ops router_ops = { - .init = {NULL, router_init2, NULL, NULL}, + .init = {NULL, router_init2, NULL, NULL}, .remove = NULL, .info = NULL }; -struct amba_dev_id router_ids[] = +struct amba_dev_id router_ids[] = { {VENDOR_GAISLER, GAISLER_SPW_ROUTER}, {0, 0} /* Mark end of table */ @@ -136,427 +626,1531 @@ struct amba_drv_info router_drv_info = void router_register_drv (void) { + DBG("Registering SPW ROUTER driver\n"); drvmgr_drv_register(&router_drv_info.general); } -int router_init2(struct drvmgr_dev *dev) +STATIC void router_hwinfo(struct router_priv *priv, + struct router_hw_info *hwinfo) { - struct router_priv *priv = dev->priv; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - char prefix[32]; - rtems_status_code status; + unsigned int tmp; - if ( priv == NULL ) - return DRVMGR_NOMEM; - priv->dev = dev; + /* Find router info */ + tmp = REG_READ(&priv->regs->cfgsts); + hwinfo->nports_spw = (tmp & RTRCFG_SP) >> RTRCFG_SP_BIT; + hwinfo->nports_amba = (tmp & RTRCFG_AP) >> RTRCFG_AP_BIT; + hwinfo->nports_fifo = (tmp & RTRCFG_FP) >> RTRCFG_FP_BIT; + hwinfo->srouting = (tmp & RTRCFG_SR) >> RTRCFG_SR_BIT; + hwinfo->pnp_enable = (tmp & RTRCFG_PE) >> RTRCFG_PE_BIT; + hwinfo->timers_avail = (tmp & RTRCFG_TA) >> RTRCFG_TA_BIT; + hwinfo->pnp_avail = (tmp & RTRCFG_PP) >> RTRCFG_PP_BIT; - /* Do initialization */ - if ( router_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( router_register_io(&router_driver_io_major) ) { - /* Failed to register I/O driver */ - return DRVMGR_FAIL; - } + tmp = REG_READ(&priv->regs->ver); + hwinfo->ver_major = (tmp & VER_MA) >> VER_MA_BIT; + hwinfo->ver_minor = (tmp & VER_MI) >> VER_MI_BIT; + hwinfo->ver_patch = (tmp & VER_PA) >> VER_PA_BIT; + hwinfo->iid = (tmp & VER_ID) >> VER_ID_BIT; + + /* Find router capabilities */ + tmp = REG_READ(&priv->regs->cap); + hwinfo->amba_port_fifo_size = 4 << ((tmp & CAP_AF) >> CAP_AF_BIT); + hwinfo->spw_port_fifo_size = 16 << ((tmp & CAP_PF) >> CAP_PF_BIT); + hwinfo->rmap_maxdlen = 4 << ((tmp & CAP_RM) >> CAP_RM_BIT); + hwinfo->aux_async = (tmp & CAP_AS) >> CAP_AS_BIT; + hwinfo->aux_dist_int_support = (tmp & CAP_AX) >> CAP_AX_BIT; + hwinfo->dual_port_support = (tmp & CAP_ID) >> CAP_ID_BIT; + hwinfo->dist_int_support = (tmp & CAP_DP) >> CAP_DP_BIT; + hwinfo->spwd_support = (tmp & CAP_SD) >> CAP_SD_BIT; + hwinfo->pktcnt_support = (tmp & CAP_PC) >> CAP_PC_BIT; + hwinfo->charcnt_support = (tmp & CAP_CC) >> CAP_CC_BIT; +} - router_driver_io_registered = 1; - } +STATIC void router_hwinfo_print(struct router_hw_info *hwinfo) +{ + DBG(" -PORTS= SPW: %d, AMBA: %d, FIFO: %d\n", hwinfo->nports_spw, + hwinfo->nports_amba, hwinfo->nports_fifo); + DBG(" -Static routing: %s, Timers: %s\n", + (hwinfo->srouting?"Enabled":"Disabled"), + (hwinfo->timers_avail?"Available":"N/A")); + DBG(" -PnP: %s, %s\n", + (hwinfo->pnp_avail?"Available":"N/A"), + (hwinfo->pnp_enable?"Enabled":"Disabled")); + DBG(" -Version= Major: 0x%02x, Minor: 0x%02x, Patch: 0x%02x, ID: 0x%02x\n", + hwinfo->ver_major, hwinfo->ver_minor, + hwinfo->ver_patch, hwinfo->iid); + DBG(" -Aux: %s, AuxDistInt: %s, DistInt: %s, SPWD: %s, PKTCNT: %s, " + "CHARCNT: %s\n", + (hwinfo->aux_async?"Async":"Sync"), + (hwinfo->aux_dist_int_support?"Supported":"N/A"), + (hwinfo->dist_int_support?"Supported":"N/A"), + (hwinfo->spwd_support?"Supported":"N/A"), + (hwinfo->pktcnt_support?"Supported":"N/A"), + (hwinfo->charcnt_support?"Supported":"N/A")); +} - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return DRVMGR_FAIL; +STATIC int router_acontrol_set(struct router_priv *priv, + struct router_route_acontrol *control) +{ + int i; + for (i=0; i<31; i++) { + REG_WRITE(&priv->regs->routes[i], control->control[i]); } - pnpinfo = &ambadev->info; - priv->regs = (struct router_regs *)pnpinfo->ahb_slv->start[0]; - priv->minor = dev->minor_drv; - - /* Register character device in registered region */ - router_hwinfo(priv, &priv->hwinfo); - priv->open = 0; - priv->nports = priv->hwinfo.nports_spw + priv->hwinfo.nports_amba + - priv->hwinfo.nports_fifo; - if ( (priv->nports < 2) || (priv->nports > 32) ) - return DRVMGR_FAIL; - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/router%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%srouter%d", prefix, dev->minor_bus); + for (i=0; i<224; i++) { + REG_WRITE(&priv->regs->routes[i+31], control->control_logical[i]); } + return ROUTER_ERR_OK; +} - /* Register Device */ - status = rtems_io_register_name(priv->devName, router_driver_io_major, dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; +STATIC int router_acontrol_get(struct router_priv *priv, + struct router_route_acontrol *control) +{ + int i; + for (i=0; i<31; i++) { + control->control[i] = REG_READ(&priv->regs->routes[i]); } - - return DRVMGR_OK; + for (i=0; i<224; i++) { + control->control_logical[i] = REG_READ(&priv->regs->routes[i+31]); + } + return ROUTER_ERR_OK; } -int router_register_io(rtems_device_major_number *m) +STATIC int router_portmap_set(struct router_priv *priv, + struct router_route_portmap *pmap) { - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &router_driver, m)) == RTEMS_SUCCESSFUL) { - ROUTER_DBG("ROUTER driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("ROUTER rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - printk("ROUTER rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - printk("ROUTER rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - printk("ROUTER rtems_io_register_driver failed\n"); - return -1; - } + int i; + for (i=0; i<31; i++) { + REG_WRITE(&priv->regs->psetup[i], pmap->pmap[i]); } - return 0; + for (i=0; i<224; i++) { + REG_WRITE(&priv->regs->psetup[i+31], pmap->pmap_logical[i]); + } + return ROUTER_ERR_OK; } -static rtems_device_driver router_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg - ) +STATIC int router_portmap_get(struct router_priv *priv, + struct router_route_portmap *pmap) { - return RTEMS_SUCCESSFUL; + int i; + for (i=0; i<31; i++) { + pmap->pmap[i] = REG_READ(&priv->regs->psetup[i]); + } + for (i=0; i<224; i++) { + pmap->pmap_logical[i] = REG_READ(&priv->regs->psetup[i+31]); + } + return ROUTER_ERR_OK; } -static rtems_device_driver router_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) +STATIC int router_init(struct router_priv *priv) { - struct router_priv *priv; - struct drvmgr_dev *dev; + #ifdef THREAD_SAFE + int i; + + /* Device Semaphore created with count = 1 */ + if (rtems_semaphore_create( + rtems_build_name('S', 'R', 'O', '0' + priv->index), 1, + RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ + RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ + RTEMS_NO_PRIORITY_CEILING, 0, &priv->sem) != RTEMS_SUCCESSFUL) { + return DRVMGR_FAIL; + } + #endif - if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) { - ROUTER_DBG("Wrong minor %d\n", minor); - return RTEMS_INVALID_NAME; + /* Find router info */ + router_hwinfo(priv, &priv->hwinfo); + + priv->open = 0; + /* Number of ports has to consider the configuration port (1 + SPW + AMBA + FIFO) */ + priv->nports = 1 + priv->hwinfo.nports_spw + priv->hwinfo.nports_amba + + priv->hwinfo.nports_fifo; + if ((priv->nports < 2) || (priv->nports > 32)) { + return DRVMGR_EIO; } - priv = (struct router_priv *)dev->priv; - if ( !priv || priv->open ) { - return RTEMS_RESOURCE_IN_USE; + #ifdef THREAD_SAFE + /* Init port spin-lock memory structures */ + for (i=0; inports; i++) { + SPIN_INIT(&priv->plock[i],"portlock"); } + #endif - priv->open = 1; + /* DEBUG print */ + DBG("SPW ROUTER[%d] with following capabilities:\n", priv->index); + router_hwinfo_print(&priv->hwinfo); - return RTEMS_SUCCESSFUL; + return DRVMGR_OK; } -static rtems_device_driver router_close( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) +int router_init2(struct drvmgr_dev *dev) { - struct router_priv *priv; - struct drvmgr_dev *dev; + struct router_priv *priv = dev->priv; + struct amba_dev_info *ambadev; + struct ambapp_core *pnpinfo; + unsigned int tmp; + int i; + int status; + + DBG("SPW ROUTER[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) { - ROUTER_DBG("Wrong minor %d\n", minor); - return RTEMS_INVALID_NAME; + if (router_count >= ROUTER_MAX) { + return DRVMGR_ENORES; } - priv = (struct router_priv *)dev->priv; - priv->open = 0; + if (priv == NULL) { + return DRVMGR_NOMEM; + } + priv->dev = dev; - return RTEMS_SUCCESSFUL; -} + /* Get device information from AMBA PnP information */ + ambadev = (struct amba_dev_info *)priv->dev->businfo; + if (ambadev == NULL) { + return DRVMGR_FAIL; + } + pnpinfo = &ambadev->info; + priv->regs = (struct router_regs *)pnpinfo->ahb_slv->start[0]; + priv->minor = dev->minor_drv; -static void router_hwinfo( - struct router_priv *priv, - struct router_hw_info *hwinfo) -{ - unsigned int tmp; + /* Initilize driver struct */ + status = router_init(priv); + if (status != DRVMGR_OK) { + return status; + } + + /* Startup Action: + * - Clear interrupts + * - Mask interrupts + */ + /* Mask interrupts in ROTUER */ + REG_WRITE(&priv->regs->imask,0); + REG_WRITE(&priv->regs->ipmask,0); + + /* Clear interrupts in ROTUER */ + REG_WRITE(&priv->regs->pip,0xffffffff); + + /* Clear errors in router and ports */ tmp = REG_READ(&priv->regs->cfgsts); - hwinfo->nports_spw = (tmp >> 27) & 0x1f; - hwinfo->nports_amba = (tmp >> 22) & 0x1f; - hwinfo->nports_fifo = (tmp >> 17) & 0x1f; - hwinfo->timers_avail = (tmp >> 1) & 0x1; - hwinfo->pnp_avail = (tmp >> 0) & 0x1; + REG_WRITE(&priv->regs->cfgsts, tmp | RTRCFG_WCLEAR); + tmp = REG_READ(&priv->regs->psts[0]); + REG_WRITE(&priv->regs->psts[0], tmp & PSTSCFG_WCLEAR); + for (i=1; inports; i++) { + tmp = REG_READ(&priv->regs->psts[i]); + REG_WRITE(&priv->regs->psts[i], tmp & PSTS_WCLEAR); + } - tmp = REG_READ(&priv->regs->ver); - hwinfo->ver_major = (tmp >> 24) & 0xff; - hwinfo->ver_minor = (tmp >> 16) & 0xff; - hwinfo->ver_patch = (tmp >> 8) & 0xff; - hwinfo->iid = (tmp >> 0) & 0xff; + /* Register driver internally */ + priv->index = router_count; + priv_tab[priv->index] = priv; + router_count++; + + /* Device name */ + sprintf(priv->devname, "router%d", priv->index); + + return DRVMGR_OK; } -static int router_config_set( - struct router_priv *priv, - struct router_config *cfg) +void *router_open(unsigned int dev_no) { - int i; + struct router_priv *priv, *ret; - if ( (cfg->flags & (ROUTER_FLG_TPRES|ROUTER_FLG_TRLD)) && - !priv->hwinfo.timers_avail ) { - return RTEMS_NOT_IMPLEMENTED; + if (dev_no >= router_count) { + DBG("ROUTER Wrong index %u\n", dev_no); + return NULL; } - /* Write only configuration bits in Config register */ - if ( cfg->flags & ROUTER_FLG_CFG ) { - REG_WRITE(&priv->regs->cfgsts, cfg->config & ~0x4); + priv = priv_tab[dev_no]; + + if (priv == NULL) { + DBG("ROUTER Device not initialized\n"); + return NULL; } - /* Write Instance ID to Version Register */ - if ( cfg->flags & ROUTER_FLG_IID ) { - REG_WRITE(&priv->regs->ver, cfg->iid); + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return NULL; } + #endif - /* Write startup-clock-divisor Register */ - if ( cfg->flags & ROUTER_FLG_IDIV ) { - REG_WRITE(&priv->regs->idiv, cfg->idiv); + if (priv->open) { + DBG("ROUTER Device already opened\n"); + ret = NULL; + } else { + /* Take the device */ + priv->open = 1; + ret = priv; } + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif - /* Write Timer Prescaler Register */ - if ( cfg->flags & ROUTER_FLG_TPRES ) { - REG_WRITE(&priv->regs->tprescaler, cfg->timer_prescaler); + return ret; +} + +int router_close(void *d) +{ + struct router_priv *priv = d; + int ret; + + if (priv == NULL) { + DBG("ROUTER Device not initialized\n"); + return ROUTER_ERR_EINVAL; } - /* Write Timer Reload Register */ - if ( cfg->flags & ROUTER_FLG_TRLD ) { - for (i=0; i<=priv->nports; i++) - REG_WRITE(&priv->regs->treload[i], cfg->timer_reload[i]); + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; } + #endif - return 0; + if (priv->open == 0) { + DBG("ROUTER Device already closed\n"); + ret = ROUTER_ERR_ERROR; + } else { + /* Mark not open */ + priv->open = 0; + ret = ROUTER_ERR_OK; + } + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ret; } -static int router_config_read( - struct router_priv *priv, - struct router_config *cfg) +STATIC int router_check_open(void *d) { - int i; + struct router_priv *priv = d; - cfg->config = REG_READ(&priv->regs->cfgsts) & ~0xffff0007; - cfg->iid = REG_READ(&priv->regs->ver) & 0xff; - cfg->idiv = REG_READ(&priv->regs->idiv) & 0xff; - cfg->timer_prescaler = REG_READ(&priv->regs->tprescaler); - for (i=0; i<=priv->nports; i++) - cfg->timer_reload[i] = REG_READ(&priv->regs->treload[i]); + if (priv == NULL) { + DBG("ROUTER Device not initialized\n"); + return ROUTER_ERR_EINVAL; + } - return 0; -} + if (priv->open == 0) { + DBG("ROUTER Device closed\n"); + return ROUTER_ERR_ERROR; + } -static int router_routes_set( - struct router_priv *priv, - struct router_routes *routes) -{ - int i; - for (i=0; i<224; i++) - REG_WRITE(&priv->regs->routes[i], routes->route[i]); return 0; } -static int router_routes_read( - struct router_priv *priv, - struct router_routes *routes) +STATIC int router_check_port(void *d, int port) { - int i; - for (i=0; i<224; i++) - routes->route[i] = REG_READ(&priv->regs->routes[i]); - return 0; -} + int ret = router_check_open(d); -static int router_ps_set(struct router_priv *priv, struct router_ps *ps) -{ - int i; - unsigned int *p = &ps->ps[0]; - for (i=0; i<255; i++,p++) - REG_WRITE(&priv->regs->psetup[i], *p); - return 0; -} + if (ret == 0) { + struct router_priv *priv = d; + if((port < 0) || (port >= priv->nports)) { + DBG("ROUTER wrong port\n"); + ret = ROUTER_ERR_EINVAL; + } + } -static int router_ps_read(struct router_priv *priv, struct router_ps *ps) -{ - int i; - unsigned int *p = &ps->ps[0]; - for (i=0; i<255; i++,p++) - REG_WRITE(&priv->regs->psetup[i], *p); - return 0; + return ret; } -static int router_we_set(struct router_priv *priv, int we) +STATIC int router_check_distint_support(void *d) { - REG_WRITE(&priv->regs->cfgwe, we & 0x1); - return 0; + int ret = router_check_open(d); + + if (ret == 0) { + struct router_priv *priv = d; + if (priv->hwinfo.dist_int_support == 0) { + DBG("ROUTER Dist interrupts not supported\n"); + ret = ROUTER_ERR_IMPLEMENTED; + } + } + + return ret; } -static int router_port_ctrl(struct router_priv *priv, struct router_port *port) +int router_hwinfo_get(void *d, struct router_hw_info *hwinfo) { - unsigned int ctrl, sts; + struct router_priv *priv = d; + int error = router_check_open(d); - if ( port->port > priv->nports ) - return RTEMS_INVALID_NAME; + if (error) + return error; - ctrl = port->ctrl; - if ( port->flag & ROUTER_PORTFLG_GET_CTRL ) { - ctrl = REG_READ(&priv->regs->pctrl[port->port]); - } - sts = port->sts; - if ( port->flag & ROUTER_PORTFLG_GET_STS ) { - sts = REG_READ(&priv->regs->psts[port->port]); + if (hwinfo == NULL) { + DBG("ROUTER Wrong pointer\n"); + return ROUTER_ERR_EINVAL; } - if ( port->flag & ROUTER_PORTFLG_SET_CTRL ) { - REG_WRITE(&priv->regs->pctrl[port->port], port->ctrl); - } - if ( port->flag & ROUTER_PORTFLG_SET_STS ) { - REG_WRITE(&priv->regs->psts[port->port], port->sts); - } + /* Get hwinfo */ + router_hwinfo(priv, hwinfo); - port->ctrl = ctrl; - port->sts = sts; - return 0; + return ROUTER_ERR_OK; } -static int router_cfgsts_set(struct router_priv *priv, unsigned int cfgsts) +int router_print(void *d) { - REG_WRITE(&priv->regs->cfgsts, cfgsts); - return 0; -} + struct router_priv *priv = d; + int error = router_check_open(d); -static int router_cfgsts_read(struct router_priv *priv, unsigned int *cfgsts) -{ - *cfgsts = REG_READ(&priv->regs->cfgsts); - return 0; -} + if (error) + return error; -static int router_tc_read(struct router_priv *priv, unsigned int *tc) -{ - *tc = REG_READ(&priv->regs->timecode); - return 0; + /* DEBUG print */ + DBG("Number of routers: %d\n", router_count); + DBG("SPW ROUTER[%d] with following capabilities:\n", priv->index); + router_hwinfo_print(&priv->hwinfo); + + return ROUTER_ERR_OK; } -static rtems_device_driver router_control( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) +/* Configure Router. Leave field NULL in order to skip configuration + */ +int router_config_set(void *d, struct router_config *cfg) { - struct router_priv *priv; - struct drvmgr_dev *dev; - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg; - void *argp = (void *)ioarg->buffer; + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; - if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) { - ROUTER_DBG("Wrong minor %d\n", minor); - return RTEMS_INVALID_NAME; + if (cfg == NULL) { + DBG("ROUTER CFG wrong\n"); + return ROUTER_ERR_EINVAL; } - priv = (struct router_priv *)dev->priv; - ioarg->ioctl_return = 0; - switch (ioarg->command) { + if ((cfg->flags & (ROUTER_FLG_TPRES|ROUTER_FLG_TRLD)) && + !priv->hwinfo.timers_avail) { + return ROUTER_ERR_IMPLEMENTED; + } - /* Get Hardware support/information available */ - case GRSPWR_IOCTL_HWINFO: - { - struct router_hw_info *hwinfo = argp; - router_hwinfo(priv, hwinfo); - break; + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; } + #endif - /* Set Router Configuration */ - case GRSPWR_IOCTL_CFG_SET: - { - struct router_config *cfg = argp; - return router_config_set(priv, cfg); + /* Write only configuration bits in Config register */ + if (cfg->flags & ROUTER_FLG_CFG) { + REG_WRITE(&priv->regs->cfgsts, cfg->config & ~(RTRCFG_WCLEAR)); } - /* Read Router Configuration */ - case GRSPWR_IOCTL_CFG_GET: - { - struct router_config *cfg = argp; - router_config_read(priv, cfg); - break; + /* Write Instance ID to Version Register */ + if (cfg->flags & ROUTER_FLG_IID) { + REG_WRITE(&priv->regs->ver, (cfg->iid << VER_ID_BIT) & VER_ID); } - /* Routes */ - case GRSPWR_IOCTL_ROUTES_SET: - { - struct router_routes *routes = argp; - return router_routes_set(priv, routes); + /* Write startup-clock-divisor Register */ + if (cfg->flags & ROUTER_FLG_IDIV) { + REG_WRITE(&priv->regs->idiv, (cfg->idiv << IDIV_ID_BIT) & IDIV_ID); } - case GRSPWR_IOCTL_ROUTES_GET: - { - struct router_routes *routes = argp; - router_routes_read(priv, routes); - break; + /* Write Timer Prescaler Register */ + if (cfg->flags & ROUTER_FLG_TPRES) { + REG_WRITE(&priv->regs->tprescaler, + (cfg->timer_prescaler << PRESCALER_RL_BIT) & PRESCALER_RL); } - /* Port Setup */ - case GRSPWR_IOCTL_PS_SET: - { - struct router_ps *ps = argp; - return router_ps_set(priv, ps); + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_config_get(void *d, struct router_config *cfg) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + if (cfg == NULL) { + DBG("ROUTER CFG wrong\n"); + return ROUTER_ERR_EINVAL; } - case GRSPWR_IOCTL_PS_GET: - { - struct router_ps *ps = argp; - router_ps_read(priv, ps); - break; + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; } + #endif + + cfg->config = REG_READ(&priv->regs->cfgsts) & + ~(RTRCFG_SP|RTRCFG_AP|RTRCFG_FP|RTRCFG_SR|RTRCFG_PE|RTRCFG_ME| + RTRCFG_TA|RTRCFG_PP); + cfg->iid = (REG_READ(&priv->regs->ver) & VER_ID) >> VER_ID_BIT; + cfg->idiv = (REG_READ(&priv->regs->idiv) & IDIV_ID) >> IDIV_ID_BIT; + cfg->timer_prescaler = + (REG_READ(&priv->regs->tprescaler) & PRESCALER_RL) >> PRESCALER_RL_BIT; + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} - /* Set configuration write enable */ - case GRSPWR_IOCTL_WE_SET: - { - return router_we_set(priv, (int)argp); +/* Configure Router routing table. + * Leave field NULL in order to skip configuration + */ +int router_routing_table_set(void *d, struct router_routing_table *cfg) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + if (cfg == NULL) { + DBG("ROUTER CFG wrong\n"); + return ROUTER_ERR_EINVAL; } - /* Set/Get Port Control/Status */ - case GRSPWR_IOCTL_PORT: - { - struct router_port *port = argp; - int result; - if ( (result=router_port_ctrl(priv, port)) ) - return result; - break; + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; } + #endif - /* Set Router Configuration/Status Register */ - case GRSPWR_IOCTL_CFGSTS_SET: - { - return router_cfgsts_set(priv, (int)argp); + /* Write Address control */ + if (cfg->flags & ROUTER_ROUTE_FLG_CTRL) { + router_acontrol_set(priv,&cfg->acontrol); } - /* Get Router Configuration/Status Register */ - case GRSPWR_IOCTL_CFGSTS_GET: - { - unsigned int *cfgsts = argp; - router_cfgsts_read(priv, cfgsts); - break; + /* Write Port map */ + if (cfg->flags & ROUTER_ROUTE_FLG_MAP) { + router_portmap_set(priv,&cfg->portmap); } - /* Get Current Time-Code Register */ - case GRSPWR_IOCTL_TC_GET: - { - unsigned int *tc = argp; - router_tc_read(priv, tc); - break; + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_routing_table_get(void *d, struct router_routing_table *cfg) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + if (cfg == NULL) { + DBG("ROUTER CFG wrong\n"); + return ROUTER_ERR_EINVAL; } - default: return RTEMS_NOT_IMPLEMENTED; + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; } + #endif - return 0; + /* Read Address control */ + router_acontrol_get(priv,&cfg->acontrol); + + /* Read Port map */ + router_portmap_get(priv,&cfg->portmap); + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_route_set(void *d, struct router_route *route) +{ + struct router_priv *priv = d; + int i; + unsigned int mask; + int error = router_check_open(d); + + if (error) + return error; + + if (route == NULL) { + DBG("ROUTER route wrong\n"); + return ROUTER_ERR_EINVAL; + } + + if (route->from_address < 32) { + /* Physical address */ + if ((route->from_address == 0) || + (route->from_address >= priv->nports)) { + DBG("ROUTER wrong physical address\n"); + return ROUTER_ERR_TOOMANY; + } + } + + /* Compute port map */ + mask=0; + for (i=0; i < route->count; i++) { + if ((route->to_port[i] == 0) || (route->to_port[i] >= priv->nports)) { + DBG("ROUTER route wrong destiny port\n"); + return ROUTER_ERR_EINVAL; + } + mask |= (0x1 << route->to_port[i]); + } + if (route->options & ROUTER_ROUTE_PACKETDISTRIBUTION_ENABLE) { + mask |= RTPMAP_PD; + } + + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; + } + #endif + + /* Write port map */ + REG_WRITE(&priv->regs->psetup[route->from_address-1], mask); + + /* Write Address control */ + REG_WRITE(&priv->regs->routes[route->from_address-1], + route->options & (0xf)); + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_route_get(void *d, struct router_route *route) +{ + struct router_priv *priv = d; + int i,count; + unsigned int mask; + int error = router_check_open(d); + + if (error) + return error; + + if (route == NULL) { + DBG("ROUTER route wrong\n"); + return ROUTER_ERR_EINVAL; + } + + if (route->from_address < 32) { + /* Physical address */ + if ((route->from_address == 0) || + (route->from_address >= priv->nports)) { + DBG("ROUTER wrong physical address\n"); + return ROUTER_ERR_TOOMANY; + } + } + + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; + } + #endif + + /* Get Address control */ + route->options = + REG_READ(&priv->regs->routes[route->from_address-1]) & (0xf); + + /* Read port map */ + mask=REG_READ(&priv->regs->psetup[route->from_address-1]); + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + if (mask & RTPMAP_PD) { + route->options |= ROUTER_ROUTE_PACKETDISTRIBUTION_ENABLE; + } + + /*DBG("ROUTE from address 0x%02x read, PMAP: 0x%08x, CTRL: 0x%08x\n", + * (unsigned int) route->from_address, mask, + * (unsigned int) route->options);*/ + + i=0; + count=0; + mask &= (RTPMAP_PE); + while (mask != 0) { + if (mask & 0x1) { + route->to_port[count] = i; + count++; + } + mask >>= 1; + i++; + } + route->count=count; + + return ROUTER_ERR_OK; +} + +int router_write_enable(void *d) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->cfgwe, 0x1); + + return ROUTER_ERR_OK; +} + +int router_write_disable(void *d) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->cfgwe, 0x0); + + return ROUTER_ERR_OK; +} + +int router_port_ioc(void *d, int port, struct router_port *cfg) +{ + struct router_priv *priv = d; + unsigned int ctrl, ctrl2, sts, timer, pktl; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + if (cfg == NULL) { + DBG("ROUTER Wrong cfg\n"); + return ROUTER_ERR_EINVAL; + } + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + ctrl = cfg->ctrl; + if (cfg->flag & ROUTER_PORT_FLG_GET_CTRL) { + ctrl = REG_READ(&priv->regs->pctrl[port]); + } + ctrl2 = cfg->ctrl; + if (cfg->flag & ROUTER_PORT_FLG_GET_CTRL2) { + ctrl2 = REG_READ(&priv->regs->pctrl2[port]); + } + sts = cfg->sts; + if (cfg->flag & ROUTER_PORT_FLG_GET_STS) { + sts = REG_READ(&priv->regs->psts[port]); + } + timer = cfg->timer_reload; + if (cfg->flag & ROUTER_PORT_FLG_GET_TIMER) { + REG_READ(&priv->regs->treload[port]); + } + pktl = cfg->packet_length; + if (cfg->flag & ROUTER_PORT_FLG_GET_PKTLEN) { + REG_READ(&priv->regs->maxplen[port]); + } + + if (cfg->flag & ROUTER_PORT_FLG_SET_CTRL) { + REG_WRITE(&priv->regs->pctrl[port], cfg->ctrl); + } + if (cfg->flag & ROUTER_PORT_FLG_SET_CTRL2) { + REG_WRITE(&priv->regs->pctrl2[port], cfg->ctrl2); + } + if (cfg->flag & ROUTER_PORT_FLG_SET_STS) { + REG_WRITE(&priv->regs->psts[port], cfg->sts); + } + if (cfg->flag & ROUTER_PORT_FLG_SET_TIMER) { + REG_WRITE(&priv->regs->treload[port], cfg->timer_reload & PTIMER_RL); + } + if (cfg->flag & ROUTER_PORT_FLG_SET_PKTLEN) { + REG_WRITE(&priv->regs->maxplen[port], cfg->packet_length & MAXPLEN_ML); + } + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + cfg->ctrl = ctrl; + cfg->ctrl2 = ctrl2; + cfg->sts = sts; + cfg->timer_reload = timer; + cfg->packet_length = pktl; + + return ROUTER_ERR_OK; +} + +/* Read Port Control register */ +int router_port_ctrl_get(void *d, int port, uint32_t *ctrl) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + if (ctrl == NULL) { + DBG("ROUTER Wrong ctrl\n"); + return ROUTER_ERR_EINVAL; + } + + *ctrl = REG_READ(&priv->regs->pctrl[port]); + return ROUTER_ERR_OK; +} + +/* Read Port Status register and clear errors if there are */ +int router_port_status(void *d, int port, uint32_t *sts, uint32_t clrmsk) /* review clrmsks */ +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + if (sts == NULL) { + DBG("ROUTER Wrong sts\n"); + return ROUTER_ERR_EINVAL; + } + *sts = REG_READ(&priv->regs->psts[port]); + if (port == 0) { + REG_WRITE(&priv->regs->psts[port], (*sts) & PSTSCFG_WCLEAR); + }else{ + REG_WRITE(&priv->regs->psts[port], (*sts) & PSTS_WCLEAR); + } + return ROUTER_ERR_OK; +} + +/* Read Port Control2 register */ +int router_port_ctrl2_get(void *d, int port, uint32_t *ctrl2) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + if (ctrl2 == NULL) { + DBG("ROUTER Wrong ctrl2\n"); + return ROUTER_ERR_EINVAL; + } + + *ctrl2 = REG_READ(&priv->regs->pctrl2[port]); + return ROUTER_ERR_OK; +} + +/* Write Port Control Register */ +int router_port_ctrl_set(void *d, int port, uint32_t ctrl) +{ + struct router_priv *priv = d; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + REG_WRITE(&priv->regs->pctrl[port],ctrl); /* this is not SMP safe? */ + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + return ROUTER_ERR_OK; +} + +/* Write Port Control2 Register */ +int router_port_ctrl2_set(void *d, int port, uint32_t ctrl2) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + REG_WRITE(&priv->regs->pctrl2[port],ctrl2); + + return ROUTER_ERR_OK; +} + +int router_port_treload_set(void *d, int port, uint32_t reload) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + REG_WRITE(&priv->regs->treload[port], reload & PTIMER_RL); + + return ROUTER_ERR_OK; +} + +int router_port_treload_get(void *d, int port, uint32_t *reload) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + if (reload == NULL) { + DBG("ROUTER Wrong reload pointer\n"); + return ROUTER_ERR_EINVAL; + } + + *reload = REG_READ(&priv->regs->treload[port]) & PTIMER_RL; + + return ROUTER_ERR_OK; +} + +int router_port_maxplen_set(void *d, int port, uint32_t length) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + REG_WRITE(&priv->regs->maxplen[port], length & MAXPLEN_ML); + + return ROUTER_ERR_OK; +} + +int router_port_maxplen_get(void *d, int port, uint32_t *length) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + if (length == NULL) { + DBG("ROUTER Wrong length pointer\n"); + return ROUTER_ERR_EINVAL; + } + + *length = REG_READ(&priv->regs->maxplen[port]); + + return ROUTER_ERR_OK; +} + +/* Get Port Link Status */ +int router_port_link_status(void *d, int port) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + return ((REG_READ(&priv->regs->psts[port]) & PSTS_LS) >> PSTS_LS_BIT); +} + +int router_port_disable(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int ctrl; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + ctrl = REG_READ(&priv->regs->pctrl[port]); + REG_WRITE(&priv->regs->pctrl[port], (ctrl | PCTRL_DI)); + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + return ROUTER_ERR_OK; +} + +int router_port_enable(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int ctrl; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + ctrl = REG_READ(&priv->regs->pctrl[port]); + REG_WRITE(&priv->regs->pctrl[port], (ctrl & ~(PCTRL_DI))); + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + return ROUTER_ERR_OK; +} + +int router_port_link_stop(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int ctrl; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + ctrl = REG_READ(&priv->regs->pctrl[port]); + REG_WRITE(&priv->regs->pctrl[port], ((ctrl & ~(PCTRL_LS) )| (PCTRL_LD))); + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + return ROUTER_ERR_OK; +} + +int router_port_link_start(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int ctrl; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + ctrl = REG_READ(&priv->regs->pctrl[port]); + REG_WRITE(&priv->regs->pctrl[port], ((ctrl & ~(PCTRL_LD) )| (PCTRL_LS))); + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + return ROUTER_ERR_OK; +} + +int router_port_link_receive_spill(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int ctrl; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + ctrl = REG_READ(&priv->regs->pctrl[port]); + REG_WRITE(&priv->regs->pctrl[port], (ctrl| (PCTRL_RS))); + + /* Wait until the spill is done */ + while(REG_READ(&priv->regs->pctrl[port]) & PCTRL_RS) {}; + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + return ROUTER_ERR_OK; +} + +int router_port_link_transmit_reset(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int ctrl; + SPIN_IRQFLAGS(irqflags); + int error = router_check_port(d, port); + + if (error) + return error; + + SPIN_LOCK_IRQ(&priv->plock[port], irqflags); + + ctrl = REG_READ(&priv->regs->pctrl[port]); + REG_WRITE(&priv->regs->pctrl[port], (ctrl| (PCTRL_TF))); + + /* Wait until the spill is done */ + while(REG_READ(&priv->regs->pctrl[port]) & PCTRL_TF) {}; + + SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); + + return ROUTER_ERR_OK; +} + +int router_port_cred_get(void *d, int port, uint32_t *cred) +{ + struct router_priv *priv = d; + int error = router_check_port(d, port); + + if (error) + return error; + + if (cred == NULL) { + DBG("ROUTER Wrong cred pointer\n"); + return ROUTER_ERR_EINVAL; + } + + *cred = REG_READ(&priv->regs->credcnt[port]); + return ROUTER_ERR_OK; +} + +int router_instance_set(void *d, uint8_t instance) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->ver, (instance << VER_ID_BIT) & VER_ID); + return ROUTER_ERR_OK; +} + +int router_idiv_set(void *d, uint8_t idiv) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->idiv, (idiv << IDIV_ID_BIT) & IDIV_ID); + return ROUTER_ERR_OK; +} + +int router_tpresc_set(void *d, uint32_t prescaler) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->tprescaler, + (prescaler << PRESCALER_RL_BIT) & PRESCALER_RL); + return ROUTER_ERR_OK; +} + +int router_instance_get(void *d, uint8_t *instance) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + if (instance == NULL) { + DBG("ROUTER Wrong instance pointer\n"); + return ROUTER_ERR_EINVAL; + } + + *instance = REG_READ(&priv->regs->ver); + + return ROUTER_ERR_OK; +} + +int router_idiv_get(void *d, uint8_t *idiv) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + if (idiv == NULL) { + DBG("ROUTER Wrong idiv pointer\n"); + return ROUTER_ERR_EINVAL; + } + + *idiv = REG_READ(&priv->regs->idiv); + + return ROUTER_ERR_OK; +} + +int router_tpresc_get(void *d, uint32_t *prescaler) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + if (prescaler == NULL) { + DBG("ROUTER Wrong prescaler pointer\n"); + return ROUTER_ERR_EINVAL; + } + + *prescaler = REG_READ(&priv->regs->tprescaler); + + return ROUTER_ERR_OK; +} + +int router_cfgsts_set(void *d, uint32_t cfgsts) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->cfgsts, cfgsts); + + return ROUTER_ERR_OK; +} + +int router_cfgsts_get(void *d, uint32_t *cfgsts) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + if (cfgsts == NULL) { + DBG("ROUTER Wrong cfgsts pointer\n"); + return ROUTER_ERR_EINVAL; + } + + *cfgsts = REG_READ(&priv->regs->cfgsts); + + return ROUTER_ERR_OK; +} + +int router_tc_enable(void *d) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->timecode, TC_EN); + + return ROUTER_ERR_OK; +} + +int router_tc_disable(void *d) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->timecode, 0); + + return ROUTER_ERR_OK; +} + +int router_tc_reset(void *d) +{ + struct router_priv *priv = d; + unsigned int tc; + int error = router_check_open(d); + + if (error) + return error; + + tc = REG_READ(&priv->regs->timecode); + REG_WRITE(&priv->regs->timecode, tc | TC_RE); + + return ROUTER_ERR_OK; +} + +int router_tc_get(void *d) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + return (REG_READ(&priv->regs->timecode) & (TC_CF | TC_TC)) >> TC_TC_BIT; +} + +int router_interrupt_unmask(void *d, int options) +{ + struct router_priv *priv = d; + unsigned int mask; + int error = router_check_open(d); + + if (error) + return error; + + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; + } + #endif + + /* Unmask interrupts in ROTUER */ + /* Get previous mask */ + mask = REG_READ(&priv->regs->imask); + + /* Clear previous interrupts*/ + REG_WRITE(&priv->regs->pip, 0xffffffff); + + /* Set new mask */ + REG_WRITE(&priv->regs->imask, mask | options); + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_interrupt_mask(void *d, int options) +{ + struct router_priv *priv = d; + unsigned int mask; + int error = router_check_open(d); + + if (error) + return error; + + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; + } + #endif + + /* Mask interrupts in ROTUER */ + /* Get previous mask */ + mask = REG_READ(&priv->regs->imask); + + /* Clear previous interrupts*/ + REG_WRITE(&priv->regs->pip, 0xffffffff); + + /* Set new mask */ + REG_WRITE(&priv->regs->imask, mask & ~(options)); + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_port_interrupt_unmask(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int mask; + int error = router_check_port(d, port); + + if (error) + return error; + + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; + } + #endif + + /* Unmask interrupts in ROTUER */ + /* Get previous mask */ + mask = REG_READ(&priv->regs->ipmask); + + /* Clear previous interrupts*/ + REG_WRITE(&priv->regs->pip, (0x1 << port)); + + /* Set new mask */ + REG_WRITE(&priv->regs->ipmask, mask | (0x1 << port)); + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_port_interrupt_mask(void *d, int port) +{ + struct router_priv *priv = d; + unsigned int mask; + int error = router_check_port(d, port); + + if (error) + return error; + + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; + } + #endif + + /* Mask interrupts in ROTUER */ + /* Get previous mask */ + mask = REG_READ(&priv->regs->ipmask); + + /* Clear previous interrupts*/ + REG_WRITE(&priv->regs->pip, (0x1 << port)); + + /* Set new mask */ + REG_WRITE(&priv->regs->ipmask, mask & ~(0x1 << port)); + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_reset(void *d) +{ + struct router_priv *priv = d; + int error = router_check_open(d); + + if (error) + return error; + + /* Reset router */ + REG_WRITE(&priv->regs->cfgsts, RTRCFG_RE); + + return ROUTER_ERR_OK; +} + +int router_icodegen_enable(void *d, uint8_t intn, uint32_t aitimer, + int options) +{ + struct router_priv *priv = d; + int error = router_check_distint_support(d); + + if (error) + return error; + + #ifdef THREAD_SAFE + /* Take device lock - Wait until we get semaphore */ + if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) + != RTEMS_SUCCESSFUL) { + DBG("ROUTER Sempahore failed\n"); + return ROUTER_ERR_ERROR; + } + #endif + + REG_WRITE(&priv->regs->icodegen, (options & ~(ICODEGEN_IN)) | + ICODEGEN_EN | (intn & ICODEGEN_IN)); + + if (options & ICODEGEN_TE) { + REG_WRITE(&priv->regs->aitimer, (aitimer & AITIMER_RL)); + } + + #ifdef THREAD_SAFE + /* Unlock dev */ + rtems_semaphore_release(priv->sem); + #endif + + return ROUTER_ERR_OK; +} + +int router_icodegen_disable(void *d) +{ + struct router_priv *priv = d; + int error = router_check_distint_support(d); + + if (error) + return error; + + REG_WRITE(&priv->regs->icodegen, ICODEGEN_TE); + + return ROUTER_ERR_OK; +} + +int router_isrctimer_set(void *d, uint32_t reloadvalue) +{ + struct router_priv *priv = d; + int error = router_check_distint_support(d); + + if (error) + return error; + + /* Set ISRC TIMER */ + REG_WRITE(&priv->regs->isrctimer, (reloadvalue & (ISRCTIMER_RL))); + + return ROUTER_ERR_OK; +} + +int router_isrtimer_set(void *d, uint32_t reloadvalue) +{ + struct router_priv *priv = d; + int error = router_check_distint_support(d); + + if (error) + return error; + + /* Set ISR TIMER */ + REG_WRITE(&priv->regs->isrtimer, (reloadvalue & (ISRTIMER_RL))); + + return ROUTER_ERR_OK; +} + +int router_isrctimer_get(void *d, uint32_t *reloadvalue) +{ + struct router_priv *priv = d; + int error = router_check_distint_support(d); + + if (error) + return error; + + if (reloadvalue == NULL) { + DBG("ROUTER Wrong reloadvalue pointer\n"); + return ROUTER_ERR_EINVAL; + } + + /* Set ISRC TIMER */ + *reloadvalue = REG_READ(&priv->regs->isrctimer) & (ISRCTIMER_RL); + + return ROUTER_ERR_OK; +} + +int router_isrtimer_get(void *d, uint32_t *reloadvalue) +{ + struct router_priv *priv = d; + int error = router_check_distint_support(d); + + if (error) + return error; + + if (reloadvalue == NULL) { + DBG("ROUTER Wrong reloadvalue pointer\n"); + return ROUTER_ERR_EINVAL; + } + + /* Set ISR TIMER */ + *reloadvalue = REG_READ(&priv->regs->isrtimer) & (ISRTIMER_RL); + + return ROUTER_ERR_OK; } -- cgit v1.2.3