/drivers/staging/westbridge/astoria/api/src/cyasintr.c
C | 143 lines | 80 code | 30 blank | 33 comment | 18 complexity | a42b3ec087b7fae7871c4c38e027f651 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* Cypress West Bridge API source file (cyasintr.c)
2## ===========================
3## Copyright (C) 2010 Cypress Semiconductor
4##
5## This program is free software; you can redistribute it and/or
6## modify it under the terms of the GNU General Public License
7## as published by the Free Software Foundation; either version 2
8## of the License, or (at your option) any later version.
9##
10## This program is distributed in the hope that it will be useful,
11## but WITHOUT ANY WARRANTY; without even the implied warranty of
12## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13## GNU General Public License for more details.
14##
15## You should have received a copy of the GNU General Public License
16## along with this program; if not, write to the Free Software
17## Foundation, Inc., 51 Franklin Street, Fifth Floor
18## Boston, MA 02110-1301, USA.
19## ===========================
20*/
21
22#include "../../include/linux/westbridge/cyashal.h"
23#include "../../include/linux/westbridge/cyasdevice.h"
24#include "../../include/linux/westbridge/cyasregs.h"
25#include "../../include/linux/westbridge/cyaserr.h"
26
27extern void cy_as_mail_box_interrupt_handler(cy_as_device *);
28
29void
30cy_as_mcu_interrupt_handler(cy_as_device *dev_p)
31{
32 /* Read and clear the interrupt. */
33 uint16_t v;
34
35 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_MCU_STAT);
36 v = v;
37}
38
39void
40cy_as_power_management_interrupt_handler(cy_as_device *dev_p)
41{
42 uint16_t v;
43
44 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PWR_MAGT_STAT);
45 v = v;
46}
47
48void
49cy_as_pll_lock_loss_interrupt_handler(cy_as_device *dev_p)
50{
51 uint16_t v;
52
53 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_PLL_LOCK_LOSS_STAT);
54 v = v;
55}
56
57uint32_t cy_as_intr_start(cy_as_device *dev_p, cy_bool dmaintr)
58{
59 uint16_t v;
60
61 cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
62
63 if (cy_as_device_is_intr_running(dev_p) != 0)
64 return CY_AS_ERROR_ALREADY_RUNNING;
65
66 v = CY_AS_MEM_P0_INT_MASK_REG_MMCUINT |
67 CY_AS_MEM_P0_INT_MASK_REG_MMBINT |
68 CY_AS_MEM_P0_INT_MASK_REG_MPMINT;
69
70 if (dmaintr)
71 v |= CY_AS_MEM_P0_INT_MASK_REG_MDRQINT;
72
73 /* Enable the interrupts of interest */
74 cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, v);
75
76 /* Mark the interrupt module as initialized */
77 cy_as_device_set_intr_running(dev_p);
78
79 return CY_AS_ERROR_SUCCESS;
80}
81
82uint32_t cy_as_intr_stop(cy_as_device *dev_p)
83{
84 cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
85
86 if (cy_as_device_is_intr_running(dev_p) == 0)
87 return CY_AS_ERROR_NOT_RUNNING;
88
89 cy_as_hal_write_register(dev_p->tag, CY_AS_MEM_P0_INT_MASK_REG, 0);
90 cy_as_device_set_intr_stopped(dev_p);
91
92 return CY_AS_ERROR_SUCCESS;
93}
94
95void cy_as_intr_service_interrupt(cy_as_hal_device_tag tag)
96{
97 uint16_t v;
98 cy_as_device *dev_p;
99
100 dev_p = cy_as_device_find_from_tag(tag);
101
102 /*
103 * only power management interrupts can occur before the
104 * antioch API setup is complete. if this is a PM interrupt
105 * handle it here; otherwise output a warning message.
106 */
107 if (dev_p == 0) {
108 v = cy_as_hal_read_register(tag, CY_AS_MEM_P0_INTR_REG);
109 if (v == CY_AS_MEM_P0_INTR_REG_PMINT) {
110 /* Read the PWR_MAGT_STAT register
111 * to clear this interrupt. */
112 v = cy_as_hal_read_register(tag,
113 CY_AS_MEM_PWR_MAGT_STAT);
114 } else
115 cy_as_hal_print_message("stray antioch "
116 "interrupt detected"
117 ", tag not associated "
118 "with any created device.");
119 return;
120 }
121
122 /* Make sure we got a valid object from CyAsDeviceFindFromTag */
123 cy_as_hal_assert(dev_p->sig == CY_AS_DEVICE_HANDLE_SIGNATURE);
124
125 v = cy_as_hal_read_register(dev_p->tag, CY_AS_MEM_P0_INTR_REG);
126
127 if (v & CY_AS_MEM_P0_INTR_REG_MCUINT)
128 cy_as_mcu_interrupt_handler(dev_p);
129
130 if (v & CY_AS_MEM_P0_INTR_REG_PMINT)
131 cy_as_power_management_interrupt_handler(dev_p);
132
133 if (v & CY_AS_MEM_P0_INTR_REG_PLLLOCKINT)
134 cy_as_pll_lock_loss_interrupt_handler(dev_p);
135
136 /* If the interrupt module is not running, no mailbox
137 * interrupts are expected from the west bridge. */
138 if (cy_as_device_is_intr_running(dev_p) == 0)
139 return;
140
141 if (v & CY_AS_MEM_P0_INTR_REG_MBINT)
142 cy_as_mail_box_interrupt_handler(dev_p);
143}