^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * General Purpose functions for the global management of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * 8260 Communication Processor Module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 1999-2001 Dan Malek <dan@embeddedalley.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * 2.3.99 Updates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * 2006 (c) MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Vitaly Bordug <vbordug@ru.mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * Merged to arch/powerpc from arch/ppc/syslib/cpm2_common.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This file is licensed under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * version 2. This program is licensed "as is" without any warranty of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * In addition to the individual control of the communication
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * channels, there are a few functions that globally affect the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * communication processor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * Buffer descriptors must be allocated from the dual ported memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * space. The allocator for that is here. When the communication
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * process is reset, we reclaim the memory available. There is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * currently no deallocator for this memory.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #include <linux/param.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #include <linux/mm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #include <asm/mpc8260.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #include <asm/page.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #include <asm/cpm2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #include <asm/rheap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #include <asm/fs_pd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #include <sysdev/fsl_soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) /* We allocate this here because it is used almost exclusively for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * the communication processor devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) cpm2_map_t __iomem *cpm2_immr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) EXPORT_SYMBOL(cpm2_immr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define CPM_MAP_SIZE (0x40000) /* 256k - the PQ3 reserve this amount
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) of space for CPM as it is larger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) than on PQ2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) void __init cpm2_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #ifdef CONFIG_PPC_85xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) cpm2_immr = ioremap(get_immrbase() + 0x80000, CPM_MAP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) cpm2_immr = ioremap(get_immrbase(), CPM_MAP_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) /* Tell everyone where the comm processor resides.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) cpmp = &cpm2_immr->im_cpm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #ifndef CONFIG_PPC_EARLY_DEBUG_CPM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) /* Reset the CPM.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) cpm_command(CPM_CR_RST, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static DEFINE_SPINLOCK(cmd_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) #define MAX_CR_CMD_LOOPS 10000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) int cpm_command(u32 command, u8 opcode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) spin_lock_irqsave(&cmd_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) out_be32(&cpmp->cp_cpcr, command | opcode | CPM_CR_FLG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) ret = -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) spin_unlock_irqrestore(&cmd_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) EXPORT_SYMBOL(cpm_command);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) /* Set a baud rate generator. This needs lots of work. There are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * eight BRGs, which can be connected to the CPM channels or output
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * as clocks. The BRGs are in two different block of internal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * memory mapped space.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * The baud rate clock is the system clock divided by something.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * It was set up long ago during the initial boot phase and is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * is given to us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * Baud rate clocks are zero-based in the driver code (as that maps
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * to port numbers). Documentation uses 1-based numbering.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) u32 __iomem *bp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) u32 val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* This is good enough to get SMCs running.....
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (brg < 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) bp = cpm2_map_size(im_brgc1, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) bp = cpm2_map_size(im_brgc5, 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) brg -= 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bp += brg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* Round the clock divider to the nearest integer. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) val = (((clk * 2 / rate) - 1) & ~1) | CPM_BRG_EN | src;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (div16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) val |= CPM_BRG_DIV16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) out_be32(bp, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) cpm2_unmap(bp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) EXPORT_SYMBOL(__cpm2_setbrg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) int i, bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) cpmux_t __iomem *im_cpmux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) u32 __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) u32 mask = 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) u8 clk_map[][3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) {CPM_CLK_FCC1, CPM_BRG5, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) {CPM_CLK_FCC1, CPM_BRG6, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {CPM_CLK_FCC1, CPM_BRG7, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {CPM_CLK_FCC1, CPM_BRG8, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) {CPM_CLK_FCC1, CPM_CLK9, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {CPM_CLK_FCC1, CPM_CLK10, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {CPM_CLK_FCC1, CPM_CLK11, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) {CPM_CLK_FCC1, CPM_CLK12, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {CPM_CLK_FCC2, CPM_BRG5, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) {CPM_CLK_FCC2, CPM_BRG6, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) {CPM_CLK_FCC2, CPM_BRG7, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) {CPM_CLK_FCC2, CPM_BRG8, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {CPM_CLK_FCC2, CPM_CLK13, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) {CPM_CLK_FCC2, CPM_CLK14, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) {CPM_CLK_FCC2, CPM_CLK15, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) {CPM_CLK_FCC2, CPM_CLK16, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {CPM_CLK_FCC3, CPM_BRG5, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) {CPM_CLK_FCC3, CPM_BRG6, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) {CPM_CLK_FCC3, CPM_BRG7, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) {CPM_CLK_FCC3, CPM_BRG8, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) {CPM_CLK_FCC3, CPM_CLK13, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) {CPM_CLK_FCC3, CPM_CLK14, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {CPM_CLK_FCC3, CPM_CLK15, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) {CPM_CLK_FCC3, CPM_CLK16, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) {CPM_CLK_SCC1, CPM_BRG1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) {CPM_CLK_SCC1, CPM_BRG2, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {CPM_CLK_SCC1, CPM_BRG3, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {CPM_CLK_SCC1, CPM_BRG4, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {CPM_CLK_SCC1, CPM_CLK11, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {CPM_CLK_SCC1, CPM_CLK12, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) {CPM_CLK_SCC1, CPM_CLK3, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {CPM_CLK_SCC1, CPM_CLK4, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {CPM_CLK_SCC2, CPM_BRG1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) {CPM_CLK_SCC2, CPM_BRG2, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {CPM_CLK_SCC2, CPM_BRG3, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) {CPM_CLK_SCC2, CPM_BRG4, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {CPM_CLK_SCC2, CPM_CLK11, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {CPM_CLK_SCC2, CPM_CLK12, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {CPM_CLK_SCC2, CPM_CLK3, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) {CPM_CLK_SCC2, CPM_CLK4, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {CPM_CLK_SCC3, CPM_BRG1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {CPM_CLK_SCC3, CPM_BRG2, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) {CPM_CLK_SCC3, CPM_BRG3, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {CPM_CLK_SCC3, CPM_BRG4, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {CPM_CLK_SCC3, CPM_CLK5, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) {CPM_CLK_SCC3, CPM_CLK6, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {CPM_CLK_SCC3, CPM_CLK7, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) {CPM_CLK_SCC3, CPM_CLK8, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) {CPM_CLK_SCC4, CPM_BRG1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {CPM_CLK_SCC4, CPM_BRG2, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) {CPM_CLK_SCC4, CPM_BRG3, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {CPM_CLK_SCC4, CPM_BRG4, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) {CPM_CLK_SCC4, CPM_CLK5, 4},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {CPM_CLK_SCC4, CPM_CLK6, 5},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) {CPM_CLK_SCC4, CPM_CLK7, 6},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {CPM_CLK_SCC4, CPM_CLK8, 7},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) im_cpmux = cpm2_map(im_cpmux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) switch (target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) case CPM_CLK_SCC1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) reg = &im_cpmux->cmx_scr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) shift = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) case CPM_CLK_SCC2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) reg = &im_cpmux->cmx_scr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) shift = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case CPM_CLK_SCC3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) reg = &im_cpmux->cmx_scr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) shift = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) case CPM_CLK_SCC4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) reg = &im_cpmux->cmx_scr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case CPM_CLK_FCC1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) reg = &im_cpmux->cmx_fcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) shift = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) case CPM_CLK_FCC2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) reg = &im_cpmux->cmx_fcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) shift = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) case CPM_CLK_FCC3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) reg = &im_cpmux->cmx_fcr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) shift = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (clk_map[i][0] == target && clk_map[i][1] == clock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) bits = clk_map[i][2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (i == ARRAY_SIZE(clk_map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) bits <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) mask <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) if (mode == CPM_CLK_RTX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) bits |= bits << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mask |= mask << 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) } else if (mode == CPM_CLK_RX) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) bits <<= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) mask <<= 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) out_be32(reg, (in_be32(reg) & ~mask) | bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) cpm2_unmap(im_cpmux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) int shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) int i, bits = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) cpmux_t __iomem *im_cpmux;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) u8 __iomem *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) u8 mask = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) u8 clk_map[][3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) {CPM_CLK_SMC1, CPM_BRG1, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) {CPM_CLK_SMC1, CPM_BRG7, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) {CPM_CLK_SMC1, CPM_CLK7, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {CPM_CLK_SMC1, CPM_CLK9, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {CPM_CLK_SMC2, CPM_BRG2, 0},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) {CPM_CLK_SMC2, CPM_BRG8, 1},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {CPM_CLK_SMC2, CPM_CLK4, 2},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) {CPM_CLK_SMC2, CPM_CLK15, 3},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) im_cpmux = cpm2_map(im_cpmux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) switch (target) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) case CPM_CLK_SMC1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) reg = &im_cpmux->cmx_smr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) mask = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) shift = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case CPM_CLK_SMC2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) reg = &im_cpmux->cmx_smr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) mask = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) shift = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) if (clk_map[i][0] == target && clk_map[i][1] == clock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) bits = clk_map[i][2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (i == ARRAY_SIZE(clk_map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) bits <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) mask <<= shift;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) out_8(reg, (in_8(reg) & ~mask) | bits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) cpm2_unmap(im_cpmux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct cpm2_ioports {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) u32 dir, par, sor, odr, dat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) u32 res[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) void cpm2_set_pin(int port, int pin, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) struct cpm2_ioports __iomem *iop =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) (struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) pin = 1 << (31 - pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) if (flags & CPM_PIN_OUTPUT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) setbits32(&iop[port].dir, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) clrbits32(&iop[port].dir, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (!(flags & CPM_PIN_GPIO))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) setbits32(&iop[port].par, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) clrbits32(&iop[port].par, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (flags & CPM_PIN_SECONDARY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) setbits32(&iop[port].sor, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) clrbits32(&iop[port].sor, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (flags & CPM_PIN_OPENDRAIN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) setbits32(&iop[port].odr, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) clrbits32(&iop[port].odr, pin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }