Path: blob/master/arch/m68k/platform/68360/commproc.c
10819 views
/*1* General Purpose functions for the global management of the2* Communication Processor Module.3*4* Copyright (c) 2000 Michael Leslie <[email protected]>5* Copyright (c) 1997 Dan Malek ([email protected])6*7* In addition to the individual control of the communication8* channels, there are a few functions that globally affect the9* communication processor.10*11* Buffer descriptors must be allocated from the dual ported memory12* space. The allocator for that is here. When the communication13* process is reset, we reclaim the memory available. There is14* currently no deallocator for this memory.15* The amount of space available is platform dependent. On the16* MBX, the EPPC software loads additional microcode into the17* communication processor, and uses some of the DP ram for this18* purpose. Current, the first 512 bytes and the last 256 bytes of19* memory are used. Right now I am conservative and only use the20* memory that can never be used for microcode. If there are21* applications that require more DP ram, we can expand the boundaries22* but then we have to be careful of any downloaded microcode.23*24*/2526/*27* Michael Leslie <[email protected]>28* adapted Dan Malek's ppc8xx drivers to M6836029*30*/3132#include <linux/errno.h>33#include <linux/sched.h>34#include <linux/kernel.h>35#include <linux/param.h>36#include <linux/string.h>37#include <linux/mm.h>38#include <linux/interrupt.h>39#include <asm/irq.h>40#include <asm/m68360.h>41#include <asm/commproc.h>4243/* #include <asm/page.h> */44/* #include <asm/pgtable.h> */45extern void *_quicc_base;46extern unsigned int system_clock;474849static uint dp_alloc_base; /* Starting offset in DP ram */50static uint dp_alloc_top; /* Max offset + 1 */5152#if 053static void *host_buffer; /* One page of host buffer */54static void *host_end; /* end + 1 */55#endif5657/* struct cpm360_t *cpmp; */ /* Pointer to comm processor space */5859QUICC *pquicc;60/* QUICC *quicc_dpram; */ /* mleslie - temporary; use extern pquicc elsewhere instead */616263/* CPM interrupt vector functions. */64struct cpm_action {65void (*handler)(void *);66void *dev_id;67};68static struct cpm_action cpm_vecs[CPMVEC_NR];69static void cpm_interrupt(int irq, void * dev, struct pt_regs * regs);70static void cpm_error_interrupt(void *);7172/* prototypes: */73void cpm_install_handler(int vec, void (*handler)(), void *dev_id);74void m360_cpm_reset(void);7576777879void m360_cpm_reset()80{81/* pte_t *pte; */8283pquicc = (struct quicc *)(_quicc_base); /* initialized in crt0_rXm.S */8485/* Perform a CPM reset. */86pquicc->cp_cr = (SOFTWARE_RESET | CMD_FLAG);8788/* Wait for CPM to become ready (should be 2 clocks). */89while (pquicc->cp_cr & CMD_FLAG);9091/* On the recommendation of the 68360 manual, p. 7-6092* - Set sdma interrupt service mask to 793* - Set sdma arbitration ID to 494*/95pquicc->sdma_sdcr = 0x0740;969798/* Claim the DP memory for our use.99*/100dp_alloc_base = CPM_DATAONLY_BASE;101dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;102103104/* Set the host page for allocation.105*/106/* host_buffer = host_page_addr; */107/* host_end = host_page_addr + PAGE_SIZE; */108109/* pte = find_pte(&init_mm, host_page_addr); */110/* pte_val(*pte) |= _PAGE_NO_CACHE; */111/* flush_tlb_page(current->mm->mmap, host_buffer); */112113/* Tell everyone where the comm processor resides.114*/115/* cpmp = (cpm360_t *)commproc; */116}117118119/* This is called during init_IRQ. We used to do it above, but this120* was too early since init_IRQ was not yet called.121*/122void123cpm_interrupt_init(void)124{125/* Initialize the CPM interrupt controller.126* NOTE THAT pquicc had better have been initialized!127* reference: MC68360UM p. 7-377128*/129pquicc->intr_cicr =130(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |131(CPM_INTERRUPT << 13) |132CICR_HP_MASK |133(CPM_VECTOR_BASE << 5) |134CICR_SPS;135136/* mask all CPM interrupts from reaching the cpu32 core: */137pquicc->intr_cimr = 0;138139140/* mles - If I understand correctly, the 360 just pops over to the CPM141* specific vector, obviating the necessity to vector through the IRQ142* whose priority the CPM is set to. This needs a closer look, though.143*/144145/* Set our interrupt handler with the core CPU. */146/* if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) */147/* panic("Could not allocate CPM IRQ!"); */148149/* Install our own error handler.150*/151/* I think we want to hold off on this one for the moment - mles */152/* cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); */153154/* master CPM interrupt enable */155/* pquicc->intr_cicr |= CICR_IEN; */ /* no such animal for 360 */156}157158159160/* CPM interrupt controller interrupt.161*/162static void163cpm_interrupt(int irq, void * dev, struct pt_regs * regs)164{165/* uint vec; */166167/* mles: Note that this stuff is currently being performed by168* M68360_do_irq(int vec, struct pt_regs *fp), in ../ints.c */169170/* figure out the vector */171/* call that vector's handler */172/* clear the irq's bit in the service register */173174#if 0 /* old 860 stuff: */175/* Get the vector by setting the ACK bit and then reading176* the register.177*/178((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;179vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;180vec >>= 11;181182183if (cpm_vecs[vec].handler != 0)184(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);185else186((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);187188/* After servicing the interrupt, we have to remove the status189* indicator.190*/191((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);192#endif193194}195196/* The CPM can generate the error interrupt when there is a race condition197* between generating and masking interrupts. All we have to do is ACK it198* and return. This is a no-op function so we don't need any special199* tests in the interrupt handler.200*/201static void202cpm_error_interrupt(void *dev)203{204}205206/* Install a CPM interrupt handler.207*/208void209cpm_install_handler(int vec, void (*handler)(), void *dev_id)210{211212request_irq(vec, handler, 0, "timer", dev_id);213214/* if (cpm_vecs[vec].handler != 0) */215/* printk(KERN_INFO "CPM interrupt %x replacing %x\n", */216/* (uint)handler, (uint)cpm_vecs[vec].handler); */217/* cpm_vecs[vec].handler = handler; */218/* cpm_vecs[vec].dev_id = dev_id; */219220/* ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); */221/* pquicc->intr_cimr |= (1 << vec); */222223}224225/* Free a CPM interrupt handler.226*/227void228cpm_free_handler(int vec)229{230cpm_vecs[vec].handler = NULL;231cpm_vecs[vec].dev_id = NULL;232/* ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); */233pquicc->intr_cimr &= ~(1 << vec);234}235236237238239/* Allocate some memory from the dual ported ram. We may want to240* enforce alignment restrictions, but right now everyone is a good241* citizen.242*/243uint244m360_cpm_dpalloc(uint size)245{246uint retloc;247248if ((dp_alloc_base + size) >= dp_alloc_top)249return(CPM_DP_NOSPACE);250251retloc = dp_alloc_base;252dp_alloc_base += size;253254return(retloc);255}256257258#if 0 /* mleslie - for now these are simply kmalloc'd */259/* We also own one page of host buffer space for the allocation of260* UART "fifos" and the like.261*/262uint263m360_cpm_hostalloc(uint size)264{265uint retloc;266267if ((host_buffer + size) >= host_end)268return(0);269270retloc = host_buffer;271host_buffer += size;272273return(retloc);274}275#endif276277278/* Set a baud rate generator. This needs lots of work. There are279* 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 (((bd_t *)__res)->bi_intfreq * 1000000) */284#define BRG_INT_CLK system_clock285#define BRG_UART_CLK (BRG_INT_CLK/16)286287void288m360_cpm_setbrg(uint brg, uint rate)289{290volatile uint *bp;291292/* This is good enough to get SMCs running.....293*/294/* bp = (uint *)&cpmp->cp_brgc1; */295bp = (volatile uint *)(&pquicc->brgc[0].l);296bp += brg;297*bp = ((BRG_UART_CLK / rate - 1) << 1) | CPM_BRG_EN;298}299300301/*302* Local variables:303* c-indent-level: 4304* c-basic-offset: 4305* tab-width: 4306* End:307*/308309310