]> git.sur5r.net Git - u-boot/blob - board/funkwerk/vovpn-gw/vovpn-gw.c
powerpc/83xx/km: make local functions and structs static
[u-boot] / board / funkwerk / vovpn-gw / vovpn-gw.c
1 /*
2  * (C) Copyright 2004
3  * Elmeg Communications Systems GmbH, Juergen Selent (j.selent@elmeg.de)
4  *
5  * Support for the Elmeg VoVPN Gateway Module
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20  * MA 02111-1307 USA
21  */
22
23 #include <common.h>
24 #include <ioports.h>
25 #include <mpc8260.h>
26 #include <asm/m8260_pci.h>
27 #include <miiphy.h>
28 #include <linux/compiler.h>
29
30 #include "m88e6060.h"
31
32 /*
33  * I/O Port configuration table
34  *
35  * if conf is 1, then that port pin will be configured at boot time
36  * according to the five values podr/pdir/ppar/psor/pdat for that entry
37  */
38
39 const iop_conf_t iop_conf_tab[4][32] = {
40     /* Port A configuration */
41     {   /*           conf ppar psor pdir podr pdat */
42         /* PA31 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1252           */
43         /* PA30 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    BP_RES           */
44         /* PA29 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1253           */
45         /* PA28 */ { 1,   1,   1,   1,   0,   0 }, /* FCC1   RMII TX_EN       */
46         /* PA27 */ { 1,   1,   1,   0,   0,   0 }, /* FCC1   RMII CRS_DV      */
47         /* PA26 */ { 1,   1,   1,   0,   0,   0 }, /* FCC1   RMII RX_ERR      */
48         /* PA25 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    HWID             */
49         /* PA24 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    HWID             */
50         /* PA23 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    HWID             */
51         /* PA22 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    HWID             */
52         /* PA21 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    HWID             */
53         /* PA20 */ { 1,   0,   0,   1,   0,   1 }, /* GPO    LED STATUS       */
54         /* PA19 */ { 1,   1,   0,   1,   0,   0 }, /* FCC1   RMII TxD[1]      */
55         /* PA18 */ { 1,   1,   0,   1,   0,   0 }, /* FCC1   RMII TxD[0]      */
56         /* PA17 */ { 1,   1,   0,   0,   0,   0 }, /* FCC1   RMII RxD[0]      */
57         /* PA16 */ { 1,   1,   0,   0,   0,   0 }, /* FCC1   RMII RxD[1]      */
58         /* PA15 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1255           */
59         /* PA14 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP????           */
60         /* PA13 */ { 1,   0,   0,   1,   0,   1 }, /* GPO    EN_BCTL1 XXX jse */
61         /* PA12 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    SWITCH RESET     */
62         /* PA11 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    DSP SL1 RESET    */
63         /* PA10 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    DSP SL2 RESET    */
64         /* PA9  */ { 1,   1,   0,   1,   0,   0 }, /* SMC2   TXD              */
65         /* PA8  */ { 1,   1,   0,   0,   0,   0 }, /* SMC2   RXD              */
66         /* PA7  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exit       */
67         /* PA6  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exit       */
68         /* PA5  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exit       */
69         /* PA4  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exit       */
70         /* PA3  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exit       */
71         /* PA2  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exit       */
72         /* PA1  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exit       */
73         /* PA0  */ { 0,   0,   0,   0,   0,   0 }  /* pin does not exit       */
74     },
75
76     /* Port B configuration */
77     {   /*           conf ppar psor pdir podr pdat */
78         /* PB31 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1257           */
79         /* PB30 */ { 1,   1,   0,   0,   0,   0 }, /* FCC2   RMII CRS_DV      */
80         /* PB29 */ { 1,   1,   1,   1,   0,   0 }, /* FCC2   RMII TX_EN       */
81         /* PB28 */ { 1,   1,   0,   0,   0,   0 }, /* FCC2   RMII RX_ERR      */
82         /* PB27 */ { 1,   1,   1,   0,   1,   0 }, /* TDM_B2 L1TXD XXX val=0  */
83         /* PB26 */ { 1,   1,   1,   0,   1,   0 }, /* TDM_B2 L1RXD XXX val,dr */
84         /* PB25 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1259           */
85         /* PB24 */ { 1,   1,   1,   0,   0,   0 }, /* TDM_B2 L1RSYNC          */
86         /* PB23 */ { 1,   1,   0,   1,   0,   0 }, /* FCC2   RMII TxD[1]      */
87         /* PB22 */ { 1,   1,   0,   1,   0,   0 }, /* FCC2   RMII TxD[0]      */
88         /* PB21 */ { 1,   1,   0,   0,   0,   0 }, /* FCC2   RMII RxD[0]      */
89         /* PB20 */ { 1,   1,   0,   0,   0,   0 }, /* FCC2   RMII RxD[1]      */
90         /* PB19 */ { 1,   0,   0,   1,   0,   1 }, /* GPO    PHY MDC          */
91         /* PB18 */ { 1,   0,   0,   0,   0,   0 }, /* GPIO   PHY MDIO         */
92         /* PB17 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
93         /* PB16 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
94         /* PB15 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
95         /* PB14 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
96         /* PB13 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
97         /* PB12 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
98         /* PB11 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
99         /* PB10 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
100         /* PB9  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
101         /* PB8  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
102         /* PB7  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
103         /* PB6  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
104         /* PB5  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
105         /* PB4  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
106         /* PB3  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
107         /* PB2  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
108         /* PB1  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
109         /* PB0  */ { 0,   0,   0,   0,   0,   0 }  /* pin does not exist      */
110     },
111
112     /* Port C */
113     {   /*           conf ppar psor pdir podr pdat */
114         /* PC31 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
115         /* PC30 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
116         /* PC29 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1183           */
117         /* PC28 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1184           */
118         /* PC27 */ { 1,   1,   0,   0,   0,   0 }, /* CLK5   TDM_A1 RX        */
119         /* PC26 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1185           */
120         /* PC25 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1178           */
121         /* PC24 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1186           */
122         /* PC23 */ { 1,   1,   0,   0,   0,   0 }, /* CLK9   TDM_B2 RX        */
123         /* PC22 */ { 1,   1,   0,   0,   0,   0 }, /* CLK10  FCC1 RMII REFCLK */
124         /* PC21 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1187           */
125         /* PC20 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1182           */
126         /* PC19 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1188           */
127         /* PC18 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    HW RESET         */
128         /* PC17 */ { 1,   1,   0,   1,   0,   0 }, /* BRG8   SWITCH CLKIN     */
129         /* PC16 */ { 1,   1,   0,   0,   0,   0 }, /* CLK16  FCC2 RMII REFCLK */
130         /* PC15 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL1_MTYPE_3      */
131         /* PC14 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL1_MTYPE_2      */
132         /* PC13 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL1_MTYPE_1      */
133         /* PC12 */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL1_MTYPE_0      */
134         /* PC11 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1176           */
135         /* PC10 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1177           */
136         /* PC9  */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL2_MTYPE_3      */
137         /* PC8  */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL2_MTYPE_2      */
138         /* PC7  */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL2_MTYPE_1      */
139         /* PC6  */ { 1,   0,   0,   0,   0,   0 }, /* GPI    SL2_MTYPE_0      */
140         /* PC5  */ { 1,   1,   0,   1,   0,   0 }, /* SMC1   TXD              */
141         /* PC4  */ { 1,   1,   0,   0,   0,   0 }, /* SMC1   RXD              */
142         /* PC3  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
143         /* PC2  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
144         /* PC1  */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1192           */
145         /* PC0  */ { 1,   0,   0,   0,   0,   0 }, /* GPI    RACK             */
146     },
147
148     /* Port D */
149     {   /*           conf ppar psor pdir podr pdat */
150         /* PD31 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1193           */
151         /* PD30 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1194           */
152         /* PD29 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1195           */
153         /* PD28 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
154         /* PD27 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
155         /* PD26 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
156         /* PD25 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1179           */
157         /* PD24 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1180           */
158         /* PD23 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1181           */
159         /* PD22 */ { 1,   1,   1,   0,   1,   0 }, /* TDM_A2 L1TXD            */
160         /* PD21 */ { 1,   1,   1,   0,   1,   0 }, /* TDM_A2 L1RXD            */
161         /* PD20 */ { 1,   1,   1,   0,   0,   0 }, /* TDM_A2 L1RSYNC          */
162         /* PD19 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1196           */
163         /* PD18 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1197           */
164         /* PD17 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1198           */
165         /* PD16 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1199           */
166         /* PD15 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1250           */
167         /* PD14 */ { 1,   0,   0,   1,   0,   0 }, /* GPO    TP1251           */
168         /* PD13 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
169         /* PD12 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
170         /* PD11 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
171         /* PD10 */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
172         /* PD9  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
173         /* PD8  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
174         /* PD7  */ { 0,   0,   0,   1,   0,   0 }, /* GPO    FL_BYTE          */
175         /* PD6  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
176         /* PD5  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
177         /* PD4  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
178         /* PD3  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
179         /* PD2  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
180         /* PD1  */ { 0,   0,   0,   0,   0,   0 }, /* pin does not exist      */
181         /* PD0  */ { 0,   0,   0,   0,   0,   0 }  /* pin does not exist      */
182     }
183 };
184
185 void reset_phy (void)
186 {
187         volatile ioport_t *iop;
188 #if defined(CONFIG_CMD_NET)
189         int i;
190         unsigned short val;
191 #endif
192
193         iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 0);
194
195         /* Reset the PHY */
196         iop->pdat &= 0xfff7ffff;        /* PA12 = |SWITCH_RESET */
197 #if defined(CONFIG_CMD_NET)
198         udelay(20000);
199         iop->pdat |= 0x00080000;
200         for (i=0; i<100; i++) {
201                 udelay(20000);
202                 if (bb_miiphy_read("FCC1", CONFIG_SYS_PHY_ADDR,2,&val ) == 0) {
203                         break;
204                 }
205         }
206         /* initialize switch */
207         m88e6060_initialize( CONFIG_SYS_PHY_ADDR );
208 #endif
209 }
210
211 static unsigned long UPMATable[] = {
212         0x8fffec00,  0x0ffcfc00,  0x0ffcfc00,  0x0ffcfc00, /* Words 0 to 3      */
213         0x0ffcfc04,  0x3ffdfc00,  0xfffffc01,  0xfffffc01, /* Words 4 to 7      */
214         0xfffffc00,  0xfffffc04,  0xfffffc01,  0xfffffc00, /* Words 8 to 11     */
215         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, /* Words 12 to 15    */
216         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, /* Words 16 to 19    */
217         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc01, /* Words 20 to 23    */
218         0x8fffec00,  0x00fffc00,  0x00fffc00,  0x00fffc00, /* Words 24 to 27    */
219         0x0ffffc04,  0xfffffc01,  0xfffffc01,  0xfffffc01, /* Words 28 to 31    */
220         0xfffffc00,  0xfffffc01,  0xfffffc01,  0xfffffc00, /* Words 32 to 35    */
221         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, /* Words 36 to 39    */
222         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, /* Words 40 to 43    */
223         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc01, /* Words 44 to 47    */
224         0xfffffc00,  0xfffffc04,  0xfffffc01,  0xfffffc00, /* Words 48 to 51    */
225         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc00, /* Words 52 to 55    */
226         0xfffffc00,  0xfffffc00,  0xfffffc00,  0xfffffc01, /* Words 56 to 59    */
227         0xffffec00,  0xffffec04,  0xffffec00,  0xfffffc01  /* Words 60 to 63    */
228 };
229
230 int board_early_init_f (void)
231 {
232         volatile immap_t *immap;
233         volatile memctl8260_t *memctl;
234         volatile unsigned char *dummy;
235         int i;
236
237         immap = (immap_t *) CONFIG_SYS_IMMR;
238         memctl = &immap->im_memctl;
239
240 #if 0
241         /* CS2-5 - DSP via UPMA */
242         dummy = (volatile unsigned char *) (memctl->memc_br2 & BRx_BA_MSK);
243         memctl->memc_mar = 0;
244         memctl->memc_mamr = MxMR_OP_WARR;
245         for (i = 0; i < 64; i++) {
246                 memctl->memc_mdr = UPMATable[i];
247                 *dummy = 0;
248         }
249         memctl->memc_mamr = 0x00044440;
250 #else
251         /* CS7 - DPRAM via UPMA */
252         dummy = (volatile unsigned char *) (memctl->memc_br7 & BRx_BA_MSK);
253         memctl->memc_mar = 0;
254         memctl->memc_mamr = MxMR_OP_WARR;
255         for (i = 0; i < 64; i++) {
256                 memctl->memc_mdr = UPMATable[i];
257                 *dummy = 0;
258         }
259         memctl->memc_mamr = 0x00044440;
260 #endif
261         return 0;
262 }
263
264 int misc_init_r (void)
265 {
266         volatile ioport_t *iop;
267         __maybe_unused unsigned char temp;
268 #if 0
269         /* DUMP UPMA RAM */
270         volatile immap_t *immap;
271         volatile memctl8260_t *memctl;
272         volatile unsigned char *dummy;
273         unsigned char c;
274         int i;
275
276         immap = (immap_t *) CONFIG_SYS_IMMR;
277         memctl = &immap->im_memctl;
278
279
280         dummy = (volatile unsigned char *) (memctl->memc_br7 & BRx_BA_MSK);
281         memctl->memc_mar = 0;
282         memctl->memc_mamr = MxMR_OP_RARR;
283         for (i = 0; i < 64; i++) {
284                 c = *dummy;
285                 printf( "UPMA[%02d]: 0x%08lx,0x%08lx: 0x%08lx\n",i,
286                         memctl->memc_mamr,
287                         memctl->memc_mar,
288                         memctl->memc_mdr );
289         }
290         memctl->memc_mamr = 0x00044440;
291 #endif
292         /* enable buffers (DSP, DPRAM) */
293         iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 0);
294         iop->pdat &= 0xfffbffff;        /* PA13 = |EN_M_BCTL1 */
295
296         /* destroy DPRAM magic */
297         *(volatile unsigned char *)0xf0500000 = 0x00;
298
299         /* clear any pending DPRAM irq */
300         temp = *(volatile unsigned char *)0xf05003ff;
301
302         /* write module-id into DPRAM */
303         *(volatile unsigned char *)0xf0500201 = 0x50;
304
305         return 0;
306 }
307
308 #if defined(CONFIG_HAVE_OWN_RESET)
309 int
310 do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
311 {
312         volatile ioport_t *iop;
313
314         iop = ioport_addr((immap_t *)CONFIG_SYS_IMMR, 2);
315         iop->pdat |= 0x00002000;        /* PC18 = HW_RESET */
316         return 1;
317 }
318 #endif  /* CONFIG_HAVE_OWN_RESET */
319
320 #define ns2clk(ns) (ns / (1000000000 / CONFIG_8260_CLKIN) + 1)
321
322 phys_size_t initdram (int board_type)
323 {
324 #ifndef CONFIG_SYS_RAMBOOT
325         volatile immap_t *immap;
326         volatile memctl8260_t *memctl;
327         volatile uchar *ramaddr;
328         int i;
329         uchar c;
330
331         immap = (immap_t *) CONFIG_SYS_IMMR;
332         memctl = &immap->im_memctl;
333         ramaddr = (uchar *) CONFIG_SYS_SDRAM_BASE;
334         c = 0xff;
335
336         immap->im_siu_conf.sc_ppc_acr  = 0x02;
337         immap->im_siu_conf.sc_ppc_alrh = 0x01267893;
338         immap->im_siu_conf.sc_ppc_alrl = 0x89abcdef;
339         immap->im_siu_conf.sc_tescr1   = 0x00000000;
340         immap->im_siu_conf.sc_tescr2   = 0x00000000;
341
342         memctl->memc_mptpr = CONFIG_SYS_MPTPR;
343         memctl->memc_psrt = CONFIG_SYS_PSRT;
344         memctl->memc_or1 = CONFIG_SYS_OR1_PRELIM;
345         memctl->memc_br1 = CONFIG_SYS_SDRAM_BASE | CONFIG_SYS_BR1_PRELIM;
346
347         /* Precharge all banks */
348         memctl->memc_psdmr = CONFIG_SYS_PSDMR | 0x28000000;
349         *ramaddr = c;
350
351         /* CBR refresh */
352         memctl->memc_psdmr = CONFIG_SYS_PSDMR | 0x08000000;
353         for (i = 0; i < 8; i++)
354                 *ramaddr = c;
355
356         /* Mode Register write */
357         memctl->memc_psdmr = CONFIG_SYS_PSDMR | 0x18000000;
358         *ramaddr = c;
359
360         /* Refresh enable */
361         memctl->memc_psdmr = CONFIG_SYS_PSDMR | 0x40000000;
362         *ramaddr = c;
363 #endif /* CONFIG_SYS_RAMBOOT */
364
365         return (CONFIG_SYS_SDRAM_SIZE);
366 }
367
368 int checkboard (void)
369 {
370 #ifdef CONFIG_CLKIN_66MHz
371         puts ("Board: Elmeg VoVPN Gateway Module (66MHz)\n");
372 #else
373         puts ("Board: Elmeg VoVPN Gateway Module (100MHz)\n");
374 #endif
375         return 0;
376 }