OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [sysdev/] [commproc.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * General Purpose functions for the global management of the
3
 * Communication Processor Module.
4
 * Copyright (c) 1997 Dan error_act (dmalek@jlc.net)
5
 *
6
 * In addition to the individual control of the communication
7
 * channels, there are a few functions that globally affect the
8
 * communication processor.
9
 *
10
 * Buffer descriptors must be allocated from the dual ported memory
11
 * space.  The allocator for that is here.  When the communication
12
 * process is reset, we reclaim the memory available.  There is
13
 * currently no deallocator for this memory.
14
 * The amount of space available is platform dependent.  On the
15
 * MBX, the EPPC software loads additional microcode into the
16
 * communication processor, and uses some of the DP ram for this
17
 * purpose.  Current, the first 512 bytes and the last 256 bytes of
18
 * memory are used.  Right now I am conservative and only use the
19
 * memory that can never be used for microcode.  If there are
20
 * applications that require more DP ram, we can expand the boundaries
21
 * but then we have to be careful of any downloaded microcode.
22
 */
23
#include <linux/errno.h>
24
#include <linux/sched.h>
25
#include <linux/kernel.h>
26
#include <linux/dma-mapping.h>
27
#include <linux/param.h>
28
#include <linux/string.h>
29
#include <linux/mm.h>
30
#include <linux/interrupt.h>
31
#include <linux/irq.h>
32
#include <linux/module.h>
33
#include <asm/mpc8xx.h>
34
#include <asm/page.h>
35
#include <asm/pgtable.h>
36
#include <asm/8xx_immap.h>
37
#include <asm/commproc.h>
38
#include <asm/io.h>
39
#include <asm/tlbflush.h>
40
#include <asm/rheap.h>
41
#include <asm/prom.h>
42
#include <asm/cpm.h>
43
 
44
#include <asm/fs_pd.h>
45
 
46
#define CPM_MAP_SIZE    (0x4000)
47
 
48
#ifndef CONFIG_PPC_CPM_NEW_BINDING
49
static void m8xx_cpm_dpinit(void);
50
#endif
51
static uint host_buffer; /* One page of host buffer */
52
static uint host_end;    /* end + 1 */
53
cpm8xx_t __iomem *cpmp;  /* Pointer to comm processor space */
54
immap_t __iomem *mpc8xx_immr;
55
static cpic8xx_t __iomem *cpic_reg;
56
 
57
static struct irq_host *cpm_pic_host;
58
 
59
static void cpm_mask_irq(unsigned int irq)
60
{
61
        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
62
 
63
        clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
64
}
65
 
66
static void cpm_unmask_irq(unsigned int irq)
67
{
68
        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
69
 
70
        setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
71
}
72
 
73
static void cpm_end_irq(unsigned int irq)
74
{
75
        unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
76
 
77
        out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
78
}
79
 
80
static struct irq_chip cpm_pic = {
81
        .typename = " CPM PIC ",
82
        .mask = cpm_mask_irq,
83
        .unmask = cpm_unmask_irq,
84
        .eoi = cpm_end_irq,
85
};
86
 
87
int cpm_get_irq(void)
88
{
89
        int cpm_vec;
90
 
91
        /* Get the vector by setting the ACK bit and then reading
92
         * the register.
93
         */
94
        out_be16(&cpic_reg->cpic_civr, 1);
95
        cpm_vec = in_be16(&cpic_reg->cpic_civr);
96
        cpm_vec >>= 11;
97
 
98
        return irq_linear_revmap(cpm_pic_host, cpm_vec);
99
}
100
 
101
static int cpm_pic_host_map(struct irq_host *h, unsigned int virq,
102
                          irq_hw_number_t hw)
103
{
104
        pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
105
 
106
        get_irq_desc(virq)->status |= IRQ_LEVEL;
107
        set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
108
        return 0;
109
}
110
 
111
/* The CPM can generate the error interrupt when there is a race condition
112
 * between generating and masking interrupts.  All we have to do is ACK it
113
 * and return.  This is a no-op function so we don't need any special
114
 * tests in the interrupt handler.
115
 */
116
static irqreturn_t cpm_error_interrupt(int irq, void *dev)
117
{
118
        return IRQ_HANDLED;
119
}
120
 
121
static struct irqaction cpm_error_irqaction = {
122
        .handler = cpm_error_interrupt,
123
        .mask = CPU_MASK_NONE,
124
        .name = "error",
125
};
126
 
127
static struct irq_host_ops cpm_pic_host_ops = {
128
        .map = cpm_pic_host_map,
129
};
130
 
131
unsigned int cpm_pic_init(void)
132
{
133
        struct device_node *np = NULL;
134
        struct resource res;
135
        unsigned int sirq = NO_IRQ, hwirq, eirq;
136
        int ret;
137
 
138
        pr_debug("cpm_pic_init\n");
139
 
140
        np = of_find_compatible_node(NULL, NULL, "fsl,cpm1-pic");
141
        if (np == NULL)
142
                np = of_find_compatible_node(NULL, "cpm-pic", "CPM");
143
        if (np == NULL) {
144
                printk(KERN_ERR "CPM PIC init: can not find cpm-pic node\n");
145
                return sirq;
146
        }
147
 
148
        ret = of_address_to_resource(np, 0, &res);
149
        if (ret)
150
                goto end;
151
 
152
        cpic_reg = ioremap(res.start, res.end - res.start + 1);
153
        if (cpic_reg == NULL)
154
                goto end;
155
 
156
        sirq = irq_of_parse_and_map(np, 0);
157
        if (sirq == NO_IRQ)
158
                goto end;
159
 
160
        /* Initialize the CPM interrupt controller. */
161
        hwirq = (unsigned int)irq_map[sirq].hwirq;
162
        out_be32(&cpic_reg->cpic_cicr,
163
            (CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
164
                ((hwirq/2) << 13) | CICR_HP_MASK);
165
 
166
        out_be32(&cpic_reg->cpic_cimr, 0);
167
 
168
        cpm_pic_host = irq_alloc_host(of_node_get(np), IRQ_HOST_MAP_LINEAR,
169
                                      64, &cpm_pic_host_ops, 64);
170
        if (cpm_pic_host == NULL) {
171
                printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
172
                sirq = NO_IRQ;
173
                goto end;
174
        }
175
 
176
        /* Install our own error handler. */
177
        np = of_find_compatible_node(NULL, NULL, "fsl,cpm1");
178
        if (np == NULL)
179
                np = of_find_node_by_type(NULL, "cpm");
180
        if (np == NULL) {
181
                printk(KERN_ERR "CPM PIC init: can not find cpm node\n");
182
                goto end;
183
        }
184
 
185
        eirq = irq_of_parse_and_map(np, 0);
186
        if (eirq == NO_IRQ)
187
                goto end;
188
 
189
        if (setup_irq(eirq, &cpm_error_irqaction))
190
                printk(KERN_ERR "Could not allocate CPM error IRQ!");
191
 
192
        setbits32(&cpic_reg->cpic_cicr, CICR_IEN);
193
 
194
end:
195
        of_node_put(np);
196
        return sirq;
197
}
198
 
199
void __init cpm_reset(void)
200
{
201
        sysconf8xx_t __iomem *siu_conf;
202
 
203
        mpc8xx_immr = ioremap(get_immrbase(), 0x4000);
204
        if (!mpc8xx_immr) {
205
                printk(KERN_CRIT "Could not map IMMR\n");
206
                return;
207
        }
208
 
209
        cpmp = &mpc8xx_immr->im_cpm;
210
 
211
#ifndef CONFIG_PPC_EARLY_DEBUG_CPM
212
        /* Perform a reset.
213
        */
214
        out_be16(&cpmp->cp_cpcr, CPM_CR_RST | CPM_CR_FLG);
215
 
216
        /* Wait for it.
217
        */
218
        while (in_be16(&cpmp->cp_cpcr) & CPM_CR_FLG);
219
#endif
220
 
221
#ifdef CONFIG_UCODE_PATCH
222
        cpm_load_patch(cpmp);
223
#endif
224
 
225
        /* Set SDMA Bus Request priority 5.
226
         * On 860T, this also enables FEC priority 6.  I am not sure
227
         * this is what we realy want for some applications, but the
228
         * manual recommends it.
229
         * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
230
         */
231
        siu_conf = immr_map(im_siu_conf);
232
        out_be32(&siu_conf->sc_sdcr, 1);
233
        immr_unmap(siu_conf);
234
 
235
#ifdef CONFIG_PPC_CPM_NEW_BINDING
236
        cpm_muram_init();
237
#else
238
        /* Reclaim the DP memory for our use. */
239
        m8xx_cpm_dpinit();
240
#endif
241
}
242
 
243
/* We used to do this earlier, but have to postpone as long as possible
244
 * to ensure the kernel VM is now running.
245
 */
246
static void
247
alloc_host_memory(void)
248
{
249
        dma_addr_t      physaddr;
250
 
251
        /* Set the host page for allocation.
252
        */
253
        host_buffer = (uint)dma_alloc_coherent(NULL, PAGE_SIZE, &physaddr,
254
                        GFP_KERNEL);
255
        host_end = host_buffer + PAGE_SIZE;
256
}
257
 
258
/* We also own one page of host buffer space for the allocation of
259
 * UART "fifos" and the like.
260
 */
261
uint
262
m8xx_cpm_hostalloc(uint size)
263
{
264
        uint    retloc;
265
 
266
        if (host_buffer == 0)
267
                alloc_host_memory();
268
 
269
        if ((host_buffer + size) >= host_end)
270
                return(0);
271
 
272
        retloc = host_buffer;
273
        host_buffer += size;
274
 
275
        return(retloc);
276
}
277
 
278
/* Set a baud rate generator.  This needs lots of work.  There are
279
 * four BRGs, any of which can be wired to any channel.
280
 * The internal baud rate clock is the system clock divided by 16.
281
 * This assumes the baudrate is 16x oversampled by the uart.
282
 */
283
#define BRG_INT_CLK             (get_brgfreq())
284
#define BRG_UART_CLK            (BRG_INT_CLK/16)
285
#define BRG_UART_CLK_DIV16      (BRG_UART_CLK/16)
286
 
287
void
288
cpm_setbrg(uint brg, uint rate)
289
{
290
        u32 __iomem *bp;
291
 
292
        /* This is good enough to get SMCs running.....
293
        */
294
        bp = &cpmp->cp_brgc1;
295
        bp += brg;
296
        /* The BRG has a 12-bit counter.  For really slow baud rates (or
297
         * really fast processors), we may have to further divide by 16.
298
         */
299
        if (((BRG_UART_CLK / rate) - 1) < 4096)
300
                out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN);
301
        else
302
                out_be32(bp, (((BRG_UART_CLK_DIV16 / rate) - 1) << 1) |
303
                             CPM_BRG_EN | CPM_BRG_DIV16);
304
}
305
 
306
#ifndef CONFIG_PPC_CPM_NEW_BINDING
307
/*
308
 * dpalloc / dpfree bits.
309
 */
310
static spinlock_t cpm_dpmem_lock;
311
/*
312
 * 16 blocks should be enough to satisfy all requests
313
 * until the memory subsystem goes up...
314
 */
315
static rh_block_t cpm_boot_dpmem_rh_block[16];
316
static rh_info_t cpm_dpmem_info;
317
 
318
#define CPM_DPMEM_ALIGNMENT     8
319
static u8 __iomem *dpram_vbase;
320
static phys_addr_t dpram_pbase;
321
 
322
static void m8xx_cpm_dpinit(void)
323
{
324
        spin_lock_init(&cpm_dpmem_lock);
325
 
326
        dpram_vbase = cpmp->cp_dpmem;
327
        dpram_pbase = get_immrbase() + offsetof(immap_t, im_cpm.cp_dpmem);
328
 
329
        /* Initialize the info header */
330
        rh_init(&cpm_dpmem_info, CPM_DPMEM_ALIGNMENT,
331
                        sizeof(cpm_boot_dpmem_rh_block) /
332
                        sizeof(cpm_boot_dpmem_rh_block[0]),
333
                        cpm_boot_dpmem_rh_block);
334
 
335
        /*
336
         * Attach the usable dpmem area.
337
         * XXX: This is actually crap.  CPM_DATAONLY_BASE and
338
         * CPM_DATAONLY_SIZE are a subset of the available dparm.  It varies
339
         * with the processor and the microcode patches applied / activated.
340
         * But the following should be at least safe.
341
         */
342
        rh_attach_region(&cpm_dpmem_info, CPM_DATAONLY_BASE, CPM_DATAONLY_SIZE);
343
}
344
 
345
/*
346
 * Allocate the requested size worth of DP memory.
347
 * This function returns an offset into the DPRAM area.
348
 * Use cpm_dpram_addr() to get the virtual address of the area.
349
 */
350
unsigned long cpm_dpalloc(uint size, uint align)
351
{
352
        unsigned long start;
353
        unsigned long flags;
354
 
355
        spin_lock_irqsave(&cpm_dpmem_lock, flags);
356
        cpm_dpmem_info.alignment = align;
357
        start = rh_alloc(&cpm_dpmem_info, size, "commproc");
358
        spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
359
 
360
        return (uint)start;
361
}
362
EXPORT_SYMBOL(cpm_dpalloc);
363
 
364
int cpm_dpfree(unsigned long offset)
365
{
366
        int ret;
367
        unsigned long flags;
368
 
369
        spin_lock_irqsave(&cpm_dpmem_lock, flags);
370
        ret = rh_free(&cpm_dpmem_info, offset);
371
        spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
372
 
373
        return ret;
374
}
375
EXPORT_SYMBOL(cpm_dpfree);
376
 
377
unsigned long cpm_dpalloc_fixed(unsigned long offset, uint size, uint align)
378
{
379
        unsigned long start;
380
        unsigned long flags;
381
 
382
        spin_lock_irqsave(&cpm_dpmem_lock, flags);
383
        cpm_dpmem_info.alignment = align;
384
        start = rh_alloc_fixed(&cpm_dpmem_info, offset, size, "commproc");
385
        spin_unlock_irqrestore(&cpm_dpmem_lock, flags);
386
 
387
        return start;
388
}
389
EXPORT_SYMBOL(cpm_dpalloc_fixed);
390
 
391
void cpm_dpdump(void)
392
{
393
        rh_dump(&cpm_dpmem_info);
394
}
395
EXPORT_SYMBOL(cpm_dpdump);
396
 
397
void *cpm_dpram_addr(unsigned long offset)
398
{
399
        return (void *)(dpram_vbase + offset);
400
}
401
EXPORT_SYMBOL(cpm_dpram_addr);
402
 
403
uint cpm_dpram_phys(u8 *addr)
404
{
405
        return (dpram_pbase + (uint)(addr - dpram_vbase));
406
}
407
EXPORT_SYMBOL(cpm_dpram_phys);
408
#endif /* !CONFIG_PPC_CPM_NEW_BINDING */
409
 
410
struct cpm_ioport16 {
411
        __be16 dir, par, sor, dat, intr;
412
        __be16 res[3];
413
};
414
 
415
struct cpm_ioport32 {
416
        __be32 dir, par, sor;
417
};
418
 
419
static void cpm1_set_pin32(int port, int pin, int flags)
420
{
421
        struct cpm_ioport32 __iomem *iop;
422
        pin = 1 << (31 - pin);
423
 
424
        if (port == CPM_PORTB)
425
                iop = (struct cpm_ioport32 __iomem *)
426
                      &mpc8xx_immr->im_cpm.cp_pbdir;
427
        else
428
                iop = (struct cpm_ioport32 __iomem *)
429
                      &mpc8xx_immr->im_cpm.cp_pedir;
430
 
431
        if (flags & CPM_PIN_OUTPUT)
432
                setbits32(&iop->dir, pin);
433
        else
434
                clrbits32(&iop->dir, pin);
435
 
436
        if (!(flags & CPM_PIN_GPIO))
437
                setbits32(&iop->par, pin);
438
        else
439
                clrbits32(&iop->par, pin);
440
 
441
        if (port == CPM_PORTE) {
442
                if (flags & CPM_PIN_SECONDARY)
443
                        setbits32(&iop->sor, pin);
444
                else
445
                        clrbits32(&iop->sor, pin);
446
 
447
                if (flags & CPM_PIN_OPENDRAIN)
448
                        setbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin);
449
                else
450
                        clrbits32(&mpc8xx_immr->im_cpm.cp_peodr, pin);
451
        }
452
}
453
 
454
static void cpm1_set_pin16(int port, int pin, int flags)
455
{
456
        struct cpm_ioport16 __iomem *iop =
457
                (struct cpm_ioport16 __iomem *)&mpc8xx_immr->im_ioport;
458
 
459
        pin = 1 << (15 - pin);
460
 
461
        if (port != 0)
462
                iop += port - 1;
463
 
464
        if (flags & CPM_PIN_OUTPUT)
465
                setbits16(&iop->dir, pin);
466
        else
467
                clrbits16(&iop->dir, pin);
468
 
469
        if (!(flags & CPM_PIN_GPIO))
470
                setbits16(&iop->par, pin);
471
        else
472
                clrbits16(&iop->par, pin);
473
 
474
        if (port == CPM_PORTC) {
475
                if (flags & CPM_PIN_SECONDARY)
476
                        setbits16(&iop->sor, pin);
477
                else
478
                        clrbits16(&iop->sor, pin);
479
        }
480
}
481
 
482
void cpm1_set_pin(enum cpm_port port, int pin, int flags)
483
{
484
        if (port == CPM_PORTB || port == CPM_PORTE)
485
                cpm1_set_pin32(port, pin, flags);
486
        else
487
                cpm1_set_pin16(port, pin, flags);
488
}
489
 
490
int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode)
491
{
492
        int shift;
493
        int i, bits = 0;
494
        u32 __iomem *reg;
495
        u32 mask = 7;
496
 
497
        u8 clk_map[][3] = {
498
                {CPM_CLK_SCC1, CPM_BRG1, 0},
499
                {CPM_CLK_SCC1, CPM_BRG2, 1},
500
                {CPM_CLK_SCC1, CPM_BRG3, 2},
501
                {CPM_CLK_SCC1, CPM_BRG4, 3},
502
                {CPM_CLK_SCC1, CPM_CLK1, 4},
503
                {CPM_CLK_SCC1, CPM_CLK2, 5},
504
                {CPM_CLK_SCC1, CPM_CLK3, 6},
505
                {CPM_CLK_SCC1, CPM_CLK4, 7},
506
 
507
                {CPM_CLK_SCC2, CPM_BRG1, 0},
508
                {CPM_CLK_SCC2, CPM_BRG2, 1},
509
                {CPM_CLK_SCC2, CPM_BRG3, 2},
510
                {CPM_CLK_SCC2, CPM_BRG4, 3},
511
                {CPM_CLK_SCC2, CPM_CLK1, 4},
512
                {CPM_CLK_SCC2, CPM_CLK2, 5},
513
                {CPM_CLK_SCC2, CPM_CLK3, 6},
514
                {CPM_CLK_SCC2, CPM_CLK4, 7},
515
 
516
                {CPM_CLK_SCC3, CPM_BRG1, 0},
517
                {CPM_CLK_SCC3, CPM_BRG2, 1},
518
                {CPM_CLK_SCC3, CPM_BRG3, 2},
519
                {CPM_CLK_SCC3, CPM_BRG4, 3},
520
                {CPM_CLK_SCC3, CPM_CLK5, 4},
521
                {CPM_CLK_SCC3, CPM_CLK6, 5},
522
                {CPM_CLK_SCC3, CPM_CLK7, 6},
523
                {CPM_CLK_SCC3, CPM_CLK8, 7},
524
 
525
                {CPM_CLK_SCC4, CPM_BRG1, 0},
526
                {CPM_CLK_SCC4, CPM_BRG2, 1},
527
                {CPM_CLK_SCC4, CPM_BRG3, 2},
528
                {CPM_CLK_SCC4, CPM_BRG4, 3},
529
                {CPM_CLK_SCC4, CPM_CLK5, 4},
530
                {CPM_CLK_SCC4, CPM_CLK6, 5},
531
                {CPM_CLK_SCC4, CPM_CLK7, 6},
532
                {CPM_CLK_SCC4, CPM_CLK8, 7},
533
 
534
                {CPM_CLK_SMC1, CPM_BRG1, 0},
535
                {CPM_CLK_SMC1, CPM_BRG2, 1},
536
                {CPM_CLK_SMC1, CPM_BRG3, 2},
537
                {CPM_CLK_SMC1, CPM_BRG4, 3},
538
                {CPM_CLK_SMC1, CPM_CLK1, 4},
539
                {CPM_CLK_SMC1, CPM_CLK2, 5},
540
                {CPM_CLK_SMC1, CPM_CLK3, 6},
541
                {CPM_CLK_SMC1, CPM_CLK4, 7},
542
 
543
                {CPM_CLK_SMC2, CPM_BRG1, 0},
544
                {CPM_CLK_SMC2, CPM_BRG2, 1},
545
                {CPM_CLK_SMC2, CPM_BRG3, 2},
546
                {CPM_CLK_SMC2, CPM_BRG4, 3},
547
                {CPM_CLK_SMC2, CPM_CLK5, 4},
548
                {CPM_CLK_SMC2, CPM_CLK6, 5},
549
                {CPM_CLK_SMC2, CPM_CLK7, 6},
550
                {CPM_CLK_SMC2, CPM_CLK8, 7},
551
        };
552
 
553
        switch (target) {
554
        case CPM_CLK_SCC1:
555
                reg = &mpc8xx_immr->im_cpm.cp_sicr;
556
                shift = 0;
557
                break;
558
 
559
        case CPM_CLK_SCC2:
560
                reg = &mpc8xx_immr->im_cpm.cp_sicr;
561
                shift = 8;
562
                break;
563
 
564
        case CPM_CLK_SCC3:
565
                reg = &mpc8xx_immr->im_cpm.cp_sicr;
566
                shift = 16;
567
                break;
568
 
569
        case CPM_CLK_SCC4:
570
                reg = &mpc8xx_immr->im_cpm.cp_sicr;
571
                shift = 24;
572
                break;
573
 
574
        case CPM_CLK_SMC1:
575
                reg = &mpc8xx_immr->im_cpm.cp_simode;
576
                shift = 12;
577
                break;
578
 
579
        case CPM_CLK_SMC2:
580
                reg = &mpc8xx_immr->im_cpm.cp_simode;
581
                shift = 28;
582
                break;
583
 
584
        default:
585
                printk(KERN_ERR "cpm1_clock_setup: invalid clock target\n");
586
                return -EINVAL;
587
        }
588
 
589
        if (reg == &mpc8xx_immr->im_cpm.cp_sicr && mode == CPM_CLK_RX)
590
                shift += 3;
591
 
592
        for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
593
                if (clk_map[i][0] == target && clk_map[i][1] == clock) {
594
                        bits = clk_map[i][2];
595
                        break;
596
                }
597
        }
598
 
599
        if (i == ARRAY_SIZE(clk_map)) {
600
                printk(KERN_ERR "cpm1_clock_setup: invalid clock combination\n");
601
                return -EINVAL;
602
        }
603
 
604
        bits <<= shift;
605
        mask <<= shift;
606
        out_be32(reg, (in_be32(reg) & ~mask) | bits);
607
 
608
        return 0;
609
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.