root/usr/src/uts/sun4u/sys/mc-us3i.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_MC_US3I_H
#define _SYS_MC_US3I_H

#pragma ident   "%Z%%M% %I%     %E% SMI"

#ifdef  __cplusplus
extern "C" {
#endif

#if defined(_KERNEL)

#define NDGRPS_PER_MC           2               /* max dimm groups per mctrl */
#define NDIMMS_PER_DGRP         2               /* max dimms in a group/pair */
#define NLOGBANKS_PER_DGRP      2               /* max logical banks per grp */
#define NLOGBANKS_PER_MC        16              /* max logical banks per mc */
#define NLOGBANKS_PER_SEG       16              /* max logical banks per seg */
#define MAX_DEVLEN              8
#define TRANSFER_SIZE           64

#define MC_SELECT_MASK          0x3000000000LL  /* upto 4 MCs at 64GB boundry */
#define MC_SELECT_SHIFT         36
#define DIMM_PAIR_SELECT_MASK   0x200000000LL   /* at 8GB boundry */
#define DIMM_PAIR_SELECT_SHIFT  33
#define LOG_BANK_SELECT_MASK    0x100000000LL   /* at 4GB boundry */
#define LOG_BANK_SELECT_SHIFT   32
#define XOR_DEVICE_SELECT_MASK  0x200000LL      /* at 2MB boundry */
#define XOR_DEVICE_SELECT_SHIFT 21
#define XOR_BANK_SELECT_MASK    0x100000LL      /* at 1MB boundry */
#define XOR_BANK_SELECT_SHIFT   20

#define MC_SIZE_MAX             0x1000000000LL  /* 64GB */
#define DGRP_SIZE_MAX           0x200000000LL   /*  8GB */
#define BANK_SIZE_MAX           0x100000000LL   /*  4GB */

#define MC_BASE(id)             (id * MC_SIZE_MAX)
#define DGRP_BASE(id)           ((id & (NDGRPS_PER_MC - 1)) * DGRP_SIZE_MAX)
#define LOGBANK_BASE(id)        ((id & (NLOGBANKS_PER_SEG - 1)) * BANK_SIZE_MAX)

#define ADDR_GEN_128Mb_X8_ROW_0 14
#define ADDR_GEN_512Mb_X8_ROW_0 15

#ifndef _ASM

struct mc_soft_state {
        dev_info_t      *dip;   /* dev info of myself */
        int             portid;
        int             mcr_read_ok;
        uint64_t        mcreg1;
        int             reglen;
        void            *reg;
        int             memlayoutlen;
        void            *memlayoutp;
};

struct memory_reg_info {
        uint64_t base;
        uint64_t size;
};

struct dimm_info {
        char    label[NDGRPS_PER_MC * NDIMMS_PER_DGRP][MAX_DEVLEN];
        char    table_width;    /* 1: symmetric 0: asymmetric */
        char    data[1];
};

struct pin_info {
        uchar_t dimmtable[18];
        uchar_t pintable[144];
};

/* This struct is included at the following structs to set up list */
typedef struct mc_dlist {
        struct mc_dlist *next;
        struct mc_dlist *prev;
        int id;
} mc_dlist_t;

/* unique segment id */
struct seg_info {
        mc_dlist_t seg_node;
        int nbanks;             /* The number of banks at this segment */
        uint32_t ifactor;       /* Max interleave factor at this segment */
        uint64_t base;
        uint64_t size;          /* memory size per segment */
        struct bank_info *head; /* first bank at this segment */
        struct bank_info *tail; /* last bank at this segment */
};

/* id = mc_id * nbanks + bank_no */
struct bank_info {
        mc_dlist_t bank_node;
        int local_id;           /* unique local bank id per segment */
        int seg_id;             /* unique segment id */
        int devgrp_id;          /* unique device group id */
        uint64_t mask;          /* If (Physical Address & MASK) == MATCH */
        uint64_t match;         /* Physic Address is located at this bank. */
        uint64_t base;          /* base address of the logical bank */
        uint64_t size;          /* memory size per logical bank */
        struct bank_info *next; /* next bank at the same segment */
};

/* id = id of dgrp_info * ndevices + device_no */
struct device_info {
        mc_dlist_t dev_node;
        char label[MAX_DEVLEN];
        uint64_t size;          /* memory size per physical dimm */
};

/* id = mc_id * ndevgrps + devgrp_no */
struct dgrp_info {
        mc_dlist_t dgrp_node;
        int ndevices;           /* number of physical dimms - always a pair */
        int nlogbanks;          /* number of logical banks - single or dual */
        int base_device;        /* base density - 128Mb, 256Mb, 512Mb or 1Gb */
        int part_type;          /* part type - x4, x8 */
        uint64_t base;          /* physical memory base of the dev group */
        uint64_t size;          /* total memory size of the dev group */
        int deviceids[NDIMMS_PER_DGRP]; /* 2 dimms per group on Jalapeno */
};

/* id = portid */
struct mctrl_info {
        mc_dlist_t mctrl_node;
        int ndevgrps;           /* The number of dimm groups */
        int devgrpids[NDGRPS_PER_MC];
        struct dimm_info *dimminfop;
};

extern int (*p2get_mem_unum)(int, uint64_t, char *, int, int *);
extern int (*p2get_mem_info)(int, uint64_t, uint64_t *, uint64_t *,
    uint64_t *, int *, int *, int *);
extern void plat_add_mem_unum_label(char *, int, int, int);

uint64_t get_mcr(int);

/* #ifdef       DEBUG */

#include <sys/promif.h>

/* useful debugging level of DPRINTF */
#define MC_ATTACH_DEBUG 0x00000001
#define MC_DETACH_DEBUG 0x00000002
#define MC_CMD_DEBUG    0x00000004
#define MC_REG_DEBUG    0x00000008
#define MC_GUNUM_DEBUG  0x00000010
#define MC_CNSTRC_DEBUG 0x00000020
#define MC_DESTRC_DEBUG 0x00000040
#define MC_LIST_DEBUG   0x00000080


#define _PRINTF printf
#define DPRINTF(flag, args)     if (mc_debug & flag) _PRINTF args;
#else
#define DPRINTF(flag, args)

/* #endif  DEBUG */

#endif  /* !_ASM */

/* Memory Control Registers */
#define ASI_MCU_CTRL            0x72
#define MCREG1OFFSET            0x00

/* Mask and shift constants for Memory Control Register I */
#define MCREG1_DIMM2_BANK3      0x8000000000000000ULL   /* bit 63 */
#define MCREG1_DIMM1_BANK1      0x4000000000000000ULL   /* bit 62 */
#define MCREG1_DIMM2_BANK2      0x2000000000000000ULL   /* bit 61 */
#define MCREG1_DIMM1_BANK0      0x1000000000000000ULL   /* bit 60 */

#define MCREG1_XOR_ENABLE       0x10000000000LL         /* bit 40 */
#define MCREG1_ADDRGEN2_MASK    0xE000000000LL          /* bits 39:37 */
#define MCREG1_ADDRGEN2_SHIFT   37
#define MCREG1_ADDRGEN1_MASK    0x1C00000000LL          /* bits 36:34 */
#define MCREG1_ADDRGEN1_SHIFT   34
#define BASE_DEVICE_128Mb       0
#define BASE_DEVICE_256Mb       1
#define BASE_DEVICE_512Mb       2
#define BASE_DEVICE_1Gb         3

#define MCREG1_INTERLEAVE_MASK                  0x1800000LL     /* bits 24:23 */
#define MCREG1_INTERLEAVE_SHIFT                 23
#define INTERLEAVE_DISABLE                      0
#define INTERLEAVE_INTEXT_SAME_DIMM_PAIR        1
#define INTERLEAVE_INTERNAL                     2
#define INTERLEAVE_INTEXT_BOTH_DIMM_PAIR        3

#define MCREG1_X4DIMM2_MASK     0x200000LL              /* bit 21 */
#define MCREG1_X4DIMM2_SHIFT    21
#define MCREG1_X4DIMM1_MASK     0x100000LL              /* bit 20 */
#define MCREG1_X4DIMM1_SHIFT    20
#define PART_TYPE_X4            1
#define PART_TYPE_X8            0

#endif  /* _KERNEL */

#ifdef  __cplusplus
}
#endif

#endif  /* _SYS_MC_US3I_H */