linux/arch/powerpc/sysdev/cpm2.c
<<
>>
Prefs
   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
  49cpm_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 */
  54cpm2_map_t __iomem *cpm2_immr;
  55EXPORT_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
  61void __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        /* Reclaim the DP memory for our use.
  70         */
  71        cpm_muram_init();
  72
  73        /* Tell everyone where the comm processor resides.
  74         */
  75        cpmp = &cpm2_immr->im_cpm;
  76
  77#ifndef CONFIG_PPC_EARLY_DEBUG_CPM
  78        /* Reset the CPM.
  79         */
  80        cpm_command(CPM_CR_RST, 0);
  81#endif
  82}
  83
  84static DEFINE_SPINLOCK(cmd_lock);
  85
  86#define MAX_CR_CMD_LOOPS        10000
  87
  88int cpm_command(u32 command, u8 opcode)
  89{
  90        int i, ret;
  91        unsigned long flags;
  92
  93        spin_lock_irqsave(&cmd_lock, flags);
  94
  95        ret = 0;
  96        out_be32(&cpmp->cp_cpcr, command | opcode | CPM_CR_FLG);
  97        for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
  98                if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
  99                        goto out;
 100
 101        printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
 102        ret = -EIO;
 103out:
 104        spin_unlock_irqrestore(&cmd_lock, flags);
 105        return ret;
 106}
 107EXPORT_SYMBOL(cpm_command);
 108
 109/* Set a baud rate generator.  This needs lots of work.  There are
 110 * eight BRGs, which can be connected to the CPM channels or output
 111 * as clocks.  The BRGs are in two different block of internal
 112 * memory mapped space.
 113 * The baud rate clock is the system clock divided by something.
 114 * It was set up long ago during the initial boot phase and is
 115 * is given to us.
 116 * Baud rate clocks are zero-based in the driver code (as that maps
 117 * to port numbers).  Documentation uses 1-based numbering.
 118 */
 119void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src)
 120{
 121        u32 __iomem *bp;
 122        u32 val;
 123
 124        /* This is good enough to get SMCs running.....
 125        */
 126        if (brg < 4) {
 127                bp = cpm2_map_size(im_brgc1, 16);
 128        } else {
 129                bp = cpm2_map_size(im_brgc5, 16);
 130                brg -= 4;
 131        }
 132        bp += brg;
 133        /* Round the clock divider to the nearest integer. */
 134        val = (((clk * 2 / rate) - 1) & ~1) | CPM_BRG_EN | src;
 135        if (div16)
 136                val |= CPM_BRG_DIV16;
 137
 138        out_be32(bp, val);
 139        cpm2_unmap(bp);
 140}
 141EXPORT_SYMBOL(__cpm2_setbrg);
 142
 143int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
 144{
 145        int ret = 0;
 146        int shift;
 147        int i, bits = 0;
 148        cpmux_t __iomem *im_cpmux;
 149        u32 __iomem *reg;
 150        u32 mask = 7;
 151
 152        u8 clk_map[][3] = {
 153                {CPM_CLK_FCC1, CPM_BRG5, 0},
 154                {CPM_CLK_FCC1, CPM_BRG6, 1},
 155                {CPM_CLK_FCC1, CPM_BRG7, 2},
 156                {CPM_CLK_FCC1, CPM_BRG8, 3},
 157                {CPM_CLK_FCC1, CPM_CLK9, 4},
 158                {CPM_CLK_FCC1, CPM_CLK10, 5},
 159                {CPM_CLK_FCC1, CPM_CLK11, 6},
 160                {CPM_CLK_FCC1, CPM_CLK12, 7},
 161                {CPM_CLK_FCC2, CPM_BRG5, 0},
 162                {CPM_CLK_FCC2, CPM_BRG6, 1},
 163                {CPM_CLK_FCC2, CPM_BRG7, 2},
 164                {CPM_CLK_FCC2, CPM_BRG8, 3},
 165                {CPM_CLK_FCC2, CPM_CLK13, 4},
 166                {CPM_CLK_FCC2, CPM_CLK14, 5},
 167                {CPM_CLK_FCC2, CPM_CLK15, 6},
 168                {CPM_CLK_FCC2, CPM_CLK16, 7},
 169                {CPM_CLK_FCC3, CPM_BRG5, 0},
 170                {CPM_CLK_FCC3, CPM_BRG6, 1},
 171                {CPM_CLK_FCC3, CPM_BRG7, 2},
 172                {CPM_CLK_FCC3, CPM_BRG8, 3},
 173                {CPM_CLK_FCC3, CPM_CLK13, 4},
 174                {CPM_CLK_FCC3, CPM_CLK14, 5},
 175                {CPM_CLK_FCC3, CPM_CLK15, 6},
 176                {CPM_CLK_FCC3, CPM_CLK16, 7},
 177                {CPM_CLK_SCC1, CPM_BRG1, 0},
 178                {CPM_CLK_SCC1, CPM_BRG2, 1},
 179                {CPM_CLK_SCC1, CPM_BRG3, 2},
 180                {CPM_CLK_SCC1, CPM_BRG4, 3},
 181                {CPM_CLK_SCC1, CPM_CLK11, 4},
 182                {CPM_CLK_SCC1, CPM_CLK12, 5},
 183                {CPM_CLK_SCC1, CPM_CLK3, 6},
 184                {CPM_CLK_SCC1, CPM_CLK4, 7},
 185                {CPM_CLK_SCC2, CPM_BRG1, 0},
 186                {CPM_CLK_SCC2, CPM_BRG2, 1},
 187                {CPM_CLK_SCC2, CPM_BRG3, 2},
 188                {CPM_CLK_SCC2, CPM_BRG4, 3},
 189                {CPM_CLK_SCC2, CPM_CLK11, 4},
 190                {CPM_CLK_SCC2, CPM_CLK12, 5},
 191                {CPM_CLK_SCC2, CPM_CLK3, 6},
 192                {CPM_CLK_SCC2, CPM_CLK4, 7},
 193                {CPM_CLK_SCC3, CPM_BRG1, 0},
 194                {CPM_CLK_SCC3, CPM_BRG2, 1},
 195                {CPM_CLK_SCC3, CPM_BRG3, 2},
 196                {CPM_CLK_SCC3, CPM_BRG4, 3},
 197                {CPM_CLK_SCC3, CPM_CLK5, 4},
 198                {CPM_CLK_SCC3, CPM_CLK6, 5},
 199                {CPM_CLK_SCC3, CPM_CLK7, 6},
 200                {CPM_CLK_SCC3, CPM_CLK8, 7},
 201                {CPM_CLK_SCC4, CPM_BRG1, 0},
 202                {CPM_CLK_SCC4, CPM_BRG2, 1},
 203                {CPM_CLK_SCC4, CPM_BRG3, 2},
 204                {CPM_CLK_SCC4, CPM_BRG4, 3},
 205                {CPM_CLK_SCC4, CPM_CLK5, 4},
 206                {CPM_CLK_SCC4, CPM_CLK6, 5},
 207                {CPM_CLK_SCC4, CPM_CLK7, 6},
 208                {CPM_CLK_SCC4, CPM_CLK8, 7},
 209        };
 210
 211        im_cpmux = cpm2_map(im_cpmux);
 212
 213        switch (target) {
 214        case CPM_CLK_SCC1:
 215                reg = &im_cpmux->cmx_scr;
 216                shift = 24;
 217                break;
 218        case CPM_CLK_SCC2:
 219                reg = &im_cpmux->cmx_scr;
 220                shift = 16;
 221                break;
 222        case CPM_CLK_SCC3:
 223                reg = &im_cpmux->cmx_scr;
 224                shift = 8;
 225                break;
 226        case CPM_CLK_SCC4:
 227                reg = &im_cpmux->cmx_scr;
 228                shift = 0;
 229                break;
 230        case CPM_CLK_FCC1:
 231                reg = &im_cpmux->cmx_fcr;
 232                shift = 24;
 233                break;
 234        case CPM_CLK_FCC2:
 235                reg = &im_cpmux->cmx_fcr;
 236                shift = 16;
 237                break;
 238        case CPM_CLK_FCC3:
 239                reg = &im_cpmux->cmx_fcr;
 240                shift = 8;
 241                break;
 242        default:
 243                printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
 244                return -EINVAL;
 245        }
 246
 247        for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
 248                if (clk_map[i][0] == target && clk_map[i][1] == clock) {
 249                        bits = clk_map[i][2];
 250                        break;
 251                }
 252        }
 253        if (i == ARRAY_SIZE(clk_map))
 254            ret = -EINVAL;
 255
 256        bits <<= shift;
 257        mask <<= shift;
 258
 259        if (mode == CPM_CLK_RTX) {
 260                bits |= bits << 3;
 261                mask |= mask << 3;
 262        } else if (mode == CPM_CLK_RX) {
 263                bits <<= 3;
 264                mask <<= 3;
 265        }
 266
 267        out_be32(reg, (in_be32(reg) & ~mask) | bits);
 268
 269        cpm2_unmap(im_cpmux);
 270        return ret;
 271}
 272
 273int cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
 274{
 275        int ret = 0;
 276        int shift;
 277        int i, bits = 0;
 278        cpmux_t __iomem *im_cpmux;
 279        u8 __iomem *reg;
 280        u8 mask = 3;
 281
 282        u8 clk_map[][3] = {
 283                {CPM_CLK_SMC1, CPM_BRG1, 0},
 284                {CPM_CLK_SMC1, CPM_BRG7, 1},
 285                {CPM_CLK_SMC1, CPM_CLK7, 2},
 286                {CPM_CLK_SMC1, CPM_CLK9, 3},
 287                {CPM_CLK_SMC2, CPM_BRG2, 0},
 288                {CPM_CLK_SMC2, CPM_BRG8, 1},
 289                {CPM_CLK_SMC2, CPM_CLK4, 2},
 290                {CPM_CLK_SMC2, CPM_CLK15, 3},
 291        };
 292
 293        im_cpmux = cpm2_map(im_cpmux);
 294
 295        switch (target) {
 296        case CPM_CLK_SMC1:
 297                reg = &im_cpmux->cmx_smr;
 298                mask = 3;
 299                shift = 4;
 300                break;
 301        case CPM_CLK_SMC2:
 302                reg = &im_cpmux->cmx_smr;
 303                mask = 3;
 304                shift = 0;
 305                break;
 306        default:
 307                printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n");
 308                return -EINVAL;
 309        }
 310
 311        for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
 312                if (clk_map[i][0] == target && clk_map[i][1] == clock) {
 313                        bits = clk_map[i][2];
 314                        break;
 315                }
 316        }
 317        if (i == ARRAY_SIZE(clk_map))
 318            ret = -EINVAL;
 319
 320        bits <<= shift;
 321        mask <<= shift;
 322
 323        out_8(reg, (in_8(reg) & ~mask) | bits);
 324
 325        cpm2_unmap(im_cpmux);
 326        return ret;
 327}
 328
 329struct cpm2_ioports {
 330        u32 dir, par, sor, odr, dat;
 331        u32 res[3];
 332};
 333
 334void cpm2_set_pin(int port, int pin, int flags)
 335{
 336        struct cpm2_ioports __iomem *iop =
 337                (struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport;
 338
 339        pin = 1 << (31 - pin);
 340
 341        if (flags & CPM_PIN_OUTPUT)
 342                setbits32(&iop[port].dir, pin);
 343        else
 344                clrbits32(&iop[port].dir, pin);
 345
 346        if (!(flags & CPM_PIN_GPIO))
 347                setbits32(&iop[port].par, pin);
 348        else
 349                clrbits32(&iop[port].par, pin);
 350
 351        if (flags & CPM_PIN_SECONDARY)
 352                setbits32(&iop[port].sor, pin);
 353        else
 354                clrbits32(&iop[port].sor, pin);
 355
 356        if (flags & CPM_PIN_OPENDRAIN)
 357                setbits32(&iop[port].odr, pin);
 358        else
 359                clrbits32(&iop[port].odr, pin);
 360}
 361
 362static int cpm_init_par_io(void)
 363{
 364        struct device_node *np;
 365
 366        for_each_compatible_node(np, NULL, "fsl,cpm2-pario-bank")
 367                cpm2_gpiochip_add32(np);
 368        return 0;
 369}
 370arch_initcall(cpm_init_par_io);
 371
 372