1294838Szbb/*-
2294838Szbb*******************************************************************************
3294838SzbbCopyright (C) 2015 Annapurna Labs Ltd.
4294838Szbb
5294838SzbbThis file may be licensed under the terms of the Annapurna Labs Commercial
6294838SzbbLicense Agreement.
7294838Szbb
8294838SzbbAlternatively, this file can be distributed under the terms of the GNU General
9294838SzbbPublic License V2 as published by the Free Software Foundation and can be
10294838Szbbfound at http://www.gnu.org/licenses/gpl-2.0.html
11294838Szbb
12294838SzbbAlternatively, redistribution and use in source and binary forms, with or
13294838Szbbwithout modification, are permitted provided that the following conditions are
14294838Szbbmet:
15294838Szbb
16294838Szbb    *     Redistributions of source code must retain the above copyright notice,
17294838Szbbthis list of conditions and the following disclaimer.
18294838Szbb
19294838Szbb    *     Redistributions in binary form must reproduce the above copyright
20294838Szbbnotice, this list of conditions and the following disclaimer in
21294838Szbbthe documentation and/or other materials provided with the
22294838Szbbdistribution.
23294838Szbb
24294838SzbbTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25294838SzbbANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26294838SzbbWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27294838SzbbDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28294838SzbbANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29294838Szbb(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30294838SzbbLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31294838SzbbANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32294838Szbb(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33294838SzbbSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34294838Szbb
35294838Szbb*******************************************************************************/
36294838Szbb
37294838Szbb/**
38294838Szbb *  @{
39294838Szbb * @file   al_hal_udma_iofic.c
40294838Szbb *
41294838Szbb * @brief  unit interrupts configurations
42294838Szbb *
43294838Szbb */
44294838Szbb
45294838Szbb#include "al_hal_udma_iofic.h"
46294838Szbb#include "al_hal_udma_regs.h"
47294838Szbb
48294838Szbb/*
49294838Szbb * configure the interrupt registers, interrupts will are kept masked
50294838Szbb */
51294838Szbbstatic int al_udma_main_iofic_config(struct al_iofic_regs __iomem *base,
52294838Szbb				    enum al_iofic_mode mode)
53294838Szbb{
54294838Szbb	switch (mode) {
55294838Szbb	case AL_IOFIC_MODE_LEGACY:
56294838Szbb		al_iofic_config(base, AL_INT_GROUP_A,
57294838Szbb				INT_CONTROL_GRP_SET_ON_POSEDGE |
58294838Szbb				INT_CONTROL_GRP_MASK_MSI_X |
59294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ);
60294838Szbb		al_iofic_config(base, AL_INT_GROUP_B,
61294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ |
62294838Szbb				INT_CONTROL_GRP_MASK_MSI_X);
63294838Szbb		al_iofic_config(base, AL_INT_GROUP_C,
64294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ |
65294838Szbb				INT_CONTROL_GRP_MASK_MSI_X);
66294838Szbb		al_iofic_config(base, AL_INT_GROUP_D,
67294838Szbb				INT_CONTROL_GRP_SET_ON_POSEDGE |
68294838Szbb				INT_CONTROL_GRP_MASK_MSI_X |
69294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ);
70294838Szbb		break;
71294838Szbb	case AL_IOFIC_MODE_MSIX_PER_Q:
72294838Szbb		al_iofic_config(base, AL_INT_GROUP_A,
73294838Szbb				INT_CONTROL_GRP_SET_ON_POSEDGE |
74294838Szbb				INT_CONTROL_GRP_AUTO_MASK |
75294838Szbb				INT_CONTROL_GRP_AUTO_CLEAR);
76294838Szbb		al_iofic_config(base, AL_INT_GROUP_B,
77294838Szbb				INT_CONTROL_GRP_AUTO_CLEAR |
78294838Szbb				INT_CONTROL_GRP_AUTO_MASK |
79294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ);
80294838Szbb		al_iofic_config(base, AL_INT_GROUP_C,
81294838Szbb				INT_CONTROL_GRP_AUTO_CLEAR |
82294838Szbb				INT_CONTROL_GRP_AUTO_MASK |
83294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ);
84294838Szbb		al_iofic_config(base, AL_INT_GROUP_D,
85294838Szbb				INT_CONTROL_GRP_SET_ON_POSEDGE |
86294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ |
87294838Szbb				INT_CONTROL_GRP_MASK_MSI_X);
88294838Szbb		break;
89294838Szbb	case AL_IOFIC_MODE_MSIX_PER_GROUP:
90294838Szbb		al_iofic_config(base, AL_INT_GROUP_A,
91294838Szbb				INT_CONTROL_GRP_SET_ON_POSEDGE |
92294838Szbb				INT_CONTROL_GRP_AUTO_CLEAR |
93294838Szbb				INT_CONTROL_GRP_AUTO_MASK);
94294838Szbb		al_iofic_config(base, AL_INT_GROUP_B,
95294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ |
96294838Szbb				INT_CONTROL_GRP_MASK_MSI_X);
97294838Szbb		al_iofic_config(base, AL_INT_GROUP_C,
98294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ |
99294838Szbb				INT_CONTROL_GRP_MASK_MSI_X);
100294838Szbb		al_iofic_config(base, AL_INT_GROUP_D,
101294838Szbb				INT_CONTROL_GRP_SET_ON_POSEDGE |
102294838Szbb				INT_CONTROL_GRP_CLEAR_ON_READ |
103294838Szbb				INT_CONTROL_GRP_MASK_MSI_X);
104294838Szbb		break;
105294838Szbb	default:
106294838Szbb		al_err("%s: invalid mode (%d)\n", __func__, mode);
107294838Szbb		return -EINVAL;
108294838Szbb	}
109294838Szbb
110294838Szbb	al_dbg("%s: base.%p mode %d\n", __func__, base, mode);
111294838Szbb	return 0;
112294838Szbb}
113294838Szbb
114294838Szbb/*
115294838Szbb * configure the UDMA interrupt registers, interrupts are kept masked
116294838Szbb */
117294838Szbbint al_udma_iofic_config(struct unit_regs __iomem *regs, enum al_iofic_mode mode,
118294838Szbb			uint32_t	m2s_errors_disable,
119294838Szbb			uint32_t	m2s_aborts_disable,
120294838Szbb			uint32_t	s2m_errors_disable,
121294838Szbb			uint32_t	s2m_aborts_disable)
122294838Szbb{
123294838Szbb	int rc;
124294838Szbb
125294838Szbb	rc = al_udma_main_iofic_config(&regs->gen.interrupt_regs.main_iofic, mode);
126294838Szbb	if (rc != 0)
127294838Szbb		return rc;
128294838Szbb
129294838Szbb	al_iofic_unmask(&regs->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_A, ~m2s_errors_disable);
130294838Szbb	al_iofic_abort_mask(&regs->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_A, m2s_aborts_disable);
131294838Szbb
132294838Szbb	al_iofic_unmask(&regs->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_B, ~s2m_errors_disable);
133294838Szbb	al_iofic_abort_mask(&regs->gen.interrupt_regs.secondary_iofic_ctrl, AL_INT_GROUP_B, s2m_aborts_disable);
134294838Szbb
135294838Szbb	al_dbg("%s base.%p mode %d\n", __func__, regs, mode);
136294838Szbb	return 0;
137294838Szbb}
138294838Szbb
139294838Szbb/*
140294838Szbb * return the offset of the unmask register for a given group
141294838Szbb */
142294838Szbbuint32_t __iomem * al_udma_iofic_unmask_offset_get(
143294838Szbb	struct unit_regs __iomem	*regs,
144294838Szbb	enum al_udma_iofic_level	level,
145294838Szbb	int				group)
146294838Szbb{
147294838Szbb	al_assert(al_udma_iofic_level_and_group_valid(level, group));
148294838Szbb	return al_iofic_unmask_offset_get(al_udma_iofic_reg_base_get(regs, level), group);
149294838Szbb}
150294838Szbb
151294838Szbb/** @} end of UDMA group */
152