root/arch/powerpc/sysdev/cpm2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cpm2_reset
  2. cpm_command
  3. __cpm2_setbrg
  4. cpm2_clk_setup
  5. cpm2_smc_clk_setup
  6. cpm2_set_pin

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

/* [<][>][^][v][top][bottom][index][help] */