1*4882a593Smuzhiyun /* 2*4882a593Smuzhiyun * arch/arm/mach-kirkwood/mpp.c 3*4882a593Smuzhiyun * 4*4882a593Smuzhiyun * MPP functions for Marvell Kirkwood SoCs 5*4882a593Smuzhiyun * Referenced from Linux kernel source 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * This file is licensed under the terms of the GNU General Public 8*4882a593Smuzhiyun * License version 2. This program is licensed "as is" without any 9*4882a593Smuzhiyun * warranty of any kind, whether express or implied. 10*4882a593Smuzhiyun */ 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun #include <common.h> 13*4882a593Smuzhiyun #include <asm/io.h> 14*4882a593Smuzhiyun #include <asm/arch/cpu.h> 15*4882a593Smuzhiyun #include <asm/arch/soc.h> 16*4882a593Smuzhiyun #include <asm/arch/mpp.h> 17*4882a593Smuzhiyun kirkwood_variant(void)18*4882a593Smuzhiyunstatic u32 kirkwood_variant(void) 19*4882a593Smuzhiyun { 20*4882a593Smuzhiyun switch (readl(KW_REG_DEVICE_ID) & 0x03) { 21*4882a593Smuzhiyun case 1: 22*4882a593Smuzhiyun return MPP_F6192_MASK; 23*4882a593Smuzhiyun case 2: 24*4882a593Smuzhiyun return MPP_F6281_MASK; 25*4882a593Smuzhiyun default: 26*4882a593Smuzhiyun debug("MPP setup: unknown kirkwood variant\n"); 27*4882a593Smuzhiyun return 0; 28*4882a593Smuzhiyun } 29*4882a593Smuzhiyun } 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun #define MPP_CTRL(i) (KW_MPP_BASE + (i* 4)) 32*4882a593Smuzhiyun #define MPP_NR_REGS (1 + MPP_MAX/8) 33*4882a593Smuzhiyun kirkwood_mpp_conf(const u32 * mpp_list,u32 * mpp_save)34*4882a593Smuzhiyunvoid kirkwood_mpp_conf(const u32 *mpp_list, u32 *mpp_save) 35*4882a593Smuzhiyun { 36*4882a593Smuzhiyun u32 mpp_ctrl[MPP_NR_REGS]; 37*4882a593Smuzhiyun unsigned int variant_mask; 38*4882a593Smuzhiyun int i; 39*4882a593Smuzhiyun 40*4882a593Smuzhiyun variant_mask = kirkwood_variant(); 41*4882a593Smuzhiyun if (!variant_mask) 42*4882a593Smuzhiyun return; 43*4882a593Smuzhiyun 44*4882a593Smuzhiyun debug( "initial MPP regs:"); 45*4882a593Smuzhiyun for (i = 0; i < MPP_NR_REGS; i++) { 46*4882a593Smuzhiyun mpp_ctrl[i] = readl(MPP_CTRL(i)); 47*4882a593Smuzhiyun debug(" %08x", mpp_ctrl[i]); 48*4882a593Smuzhiyun } 49*4882a593Smuzhiyun debug("\n"); 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun while (*mpp_list) { 53*4882a593Smuzhiyun unsigned int num = MPP_NUM(*mpp_list); 54*4882a593Smuzhiyun unsigned int sel = MPP_SEL(*mpp_list); 55*4882a593Smuzhiyun unsigned int sel_save; 56*4882a593Smuzhiyun int shift; 57*4882a593Smuzhiyun 58*4882a593Smuzhiyun if (num > MPP_MAX) { 59*4882a593Smuzhiyun debug("kirkwood_mpp_conf: invalid MPP " 60*4882a593Smuzhiyun "number (%u)\n", num); 61*4882a593Smuzhiyun continue; 62*4882a593Smuzhiyun } 63*4882a593Smuzhiyun if (!(*mpp_list & variant_mask)) { 64*4882a593Smuzhiyun debug("kirkwood_mpp_conf: requested MPP%u config " 65*4882a593Smuzhiyun "unavailable on this hardware\n", num); 66*4882a593Smuzhiyun continue; 67*4882a593Smuzhiyun } 68*4882a593Smuzhiyun 69*4882a593Smuzhiyun shift = (num & 7) << 2; 70*4882a593Smuzhiyun 71*4882a593Smuzhiyun if (mpp_save) { 72*4882a593Smuzhiyun sel_save = (mpp_ctrl[num / 8] >> shift) & 0xf; 73*4882a593Smuzhiyun *mpp_save = num | (sel_save << 8) | variant_mask; 74*4882a593Smuzhiyun mpp_save++; 75*4882a593Smuzhiyun } 76*4882a593Smuzhiyun 77*4882a593Smuzhiyun mpp_ctrl[num / 8] &= ~(0xf << shift); 78*4882a593Smuzhiyun mpp_ctrl[num / 8] |= sel << shift; 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun mpp_list++; 81*4882a593Smuzhiyun } 82*4882a593Smuzhiyun 83*4882a593Smuzhiyun debug(" final MPP regs:"); 84*4882a593Smuzhiyun for (i = 0; i < MPP_NR_REGS; i++) { 85*4882a593Smuzhiyun writel(mpp_ctrl[i], MPP_CTRL(i)); 86*4882a593Smuzhiyun debug(" %08x", mpp_ctrl[i]); 87*4882a593Smuzhiyun } 88*4882a593Smuzhiyun debug("\n"); 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun } 91