diff options
Diffstat (limited to 'drivers/staging/westbridge/astoria/api/src/cyasintr.c')
-rw-r--r-- | drivers/staging/westbridge/astoria/api/src/cyasintr.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/drivers/staging/westbridge/astoria/api/src/cyasintr.c b/drivers/staging/westbridge/astoria/api/src/cyasintr.c new file mode 100644 index 00000000000..aea6c3ebf06 --- /dev/null +++ b/drivers/staging/westbridge/astoria/api/src/cyasintr.c @@ -0,0 +1,143 @@ +/* Cypress West Bridge API source file (cyasintr.c) +## =========================== +## Copyright (C) 2010 Cypress Semiconductor +## +## This program is free software; you can redistribute it and/or +## modify it under the terms of the GNU General Public License +## as published by the Free Software Foundation; either version 2 +## of the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Fifth Floor +## Boston, MA 02110-1301, USA. +## =========================== +*/ + +#include "../../include/linux/westbridge/cyashal.h" +#include "../../include/linux/westbridge/cyasdevice.h" +#include "../../include/linux/westbridge/cyasregs.h" +#include "../../include/linux/westbridge/cyaserr.h" + +extern void cy_as_mail_box_interrupt_handler(cy_as_device *) ; + +void +cy_as_mcu_interrupt_handler(cy_as_device *dev_p) +{ + /* Read and clear the interrupt. */ + uint16_t v ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_MCU_STAT) ; + v = v ; +} + +void +cy_as_power_management_interrupt_handler(cy_as_device *dev_p) +{ + uint16_t v ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PWR_MAGT_STAT) ; + v = v ; +} + +void +cy_as_pll_lock_loss_interrupt_handler(cy_as_device *dev_p) +{ + uint16_t v ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PLL_LOCK_LOSS_STAT) ; + v = v ; +} + +uint32_t cy_as_intr_start(cy_as_device *dev_p, cy_bool dmaintr) +{ + uint16_t v ; + + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + if (cy_as_device_is_intr_running(dev_p) != 0) + return CY_AS_ERROR_ALREADY_RUNNING ; + + v = CY_AS_MEM_P0_INT_MASK_REG_MMCUINT | + CY_AS_MEM_P0_INT_MASK_REG_MMBINT | + CY_AS_MEM_P0_INT_MASK_REG_MPMINT ; + + if (dmaintr) + v |= CY_AS_MEM_P0_INT_MASK_REG_MDRQINT ; + + /* Enable the interrupts of interest */ + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, v) ; + + /* Mark the interrupt module as initialized */ + cy_as_device_set_intr_running(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +uint32_t cy_as_intr_stop(cy_as_device *dev_p) +{ + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + if (cy_as_device_is_intr_running(dev_p) == 0) + return CY_AS_ERROR_NOT_RUNNING ; + + cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, 0) ; + cy_as_device_set_intr_stopped(dev_p) ; + + return CY_AS_ERROR_SUCCESS ; +} + +void cy_as_intr_service_interrupt(cy_as_hal_device_tag tag) +{ + uint16_t v ; + cy_as_device *dev_p ; + + dev_p = cy_as_device_find_from_tag(tag) ; + + /* + * only power management interrupts can occur before the + * antioch API setup is complete. if this is a PM interrupt + * handle it here; otherwise output a warning message. + */ + if (dev_p == 0) { + v = cy_as_hal_read_register(tag, CY_AS_MEM_P0_INTR_REG) ; + if (v == CY_AS_MEM_P0_INTR_REG_PMINT) { + /* Read the PWR_MAGT_STAT register + * to clear this interrupt. */ + v = cy_as_hal_read_register(tag, + CY_AS_MEM_PWR_MAGT_STAT) ; + } else + cy_as_hal_print_message("stray antioch " + "interrupt detected" + ", tag not associated " + "with any created device.") ; + return ; + } + + /* Make sure we got a valid object from CyAsDeviceFindFromTag */ + cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE) ; + + v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_INTR_REG) ; + + if (v & CY_AS_MEM_P0_INTR_REG_MCUINT) + cy_as_mcu_interrupt_handler(dev_p) ; + + if (v & CY_AS_MEM_P0_INTR_REG_PMINT) + cy_as_power_management_interrupt_handler(dev_p) ; + + if (v & CY_AS_MEM_P0_INTR_REG_PLLLOCKINT) + cy_as_pll_lock_loss_interrupt_handler(dev_p) ; + + /* If the interrupt module is not running, no mailbox + * interrupts are expected from the west bridge. */ + if (cy_as_device_is_intr_running(dev_p) == 0) + return ; + + if (v & CY_AS_MEM_P0_INTR_REG_MBINT) + cy_as_mail_box_interrupt_handler(dev_p) ; +} |