160812Sps/*
260786Sps * arch/arm/mach-kirkwood/mpp.c
360786Sps *
460786Sps * MPP functions for Marvell Kirkwood SoCs
560786Sps * Referenced from Linux kernel source
660786Sps *
760786Sps * This file is licensed under the terms of the GNU General Public
860786Sps * License version 2.  This program is licensed "as is" without any
960786Sps * warranty of any kind, whether express or implied.
1060786Sps */
1160786Sps
1260786Sps#include <common.h>
1360786Sps#include <log.h>
1460786Sps#include <asm/io.h>
1560786Sps#include <asm/arch/cpu.h>
1660786Sps#include <asm/arch/soc.h>
1760786Sps#include <asm/arch/mpp.h>
1889022Sps
1989022Spsstatic u32 kirkwood_variant(void)
2089022Sps{
2160786Sps	switch (readl(KW_REG_DEVICE_ID) & 0x03) {
2260786Sps	case 1:
2360786Sps		return MPP_F6192_MASK;
2460786Sps	case 2:
2560786Sps		return MPP_F6281_MASK;
2660786Sps	default:
2760786Sps		debug("MPP setup: unknown kirkwood variant\n");
2860786Sps		return 0;
2960786Sps	}
3060786Sps}
3160786Sps
3260786Sps#define MPP_CTRL(i)	(KW_MPP_BASE + (i* 4))
3360786Sps#define MPP_NR_REGS	(1 + MPP_MAX/8)
3460786Sps
3560786Spsvoid kirkwood_mpp_conf(const u32 *mpp_list, u32 *mpp_save)
3660786Sps{
3760786Sps	u32 mpp_ctrl[MPP_NR_REGS];
3860786Sps	unsigned int variant_mask;
3960786Sps	int i;
4060786Sps
4160786Sps	variant_mask = kirkwood_variant();
4260812Sps	if (!variant_mask)
4360786Sps		return;
4460786Sps
4560786Sps	debug( "initial MPP regs:");
4660786Sps	for (i = 0; i < MPP_NR_REGS; i++) {
4760786Sps		mpp_ctrl[i] = readl(MPP_CTRL(i));
4860786Sps		debug(" %08x", mpp_ctrl[i]);
4960786Sps	}
5060786Sps	debug("\n");
5160786Sps
5260786Sps
5360786Sps	while (*mpp_list) {
5460786Sps		unsigned int num = MPP_NUM(*mpp_list);
5560786Sps		unsigned int sel = MPP_SEL(*mpp_list);
5660786Sps		unsigned int sel_save;
5760786Sps		int shift;
5863131Sps
5960786Sps		if (num > MPP_MAX) {
6060786Sps			debug("kirkwood_mpp_conf: invalid MPP "
6160786Sps					"number (%u)\n", num);
6260786Sps			continue;
6360786Sps		}
6460786Sps		if (!(*mpp_list & variant_mask)) {
6560786Sps			debug("kirkwood_mpp_conf: requested MPP%u config "
6660786Sps				"unavailable on this hardware\n", num);
6760786Sps			continue;
6860786Sps		}
6960786Sps
7060786Sps		shift = (num & 7) << 2;
7160786Sps
7260786Sps		if (mpp_save) {
7360786Sps			sel_save = (mpp_ctrl[num / 8] >> shift) & 0xf;
7460786Sps			*mpp_save = num | (sel_save << 8) | variant_mask;
7560786Sps			mpp_save++;
7660786Sps		}
7760786Sps
7860786Sps		mpp_ctrl[num / 8] &= ~(0xf << shift);
7960786Sps		mpp_ctrl[num / 8] |= sel << shift;
8060786Sps
8160786Sps		mpp_list++;
8260786Sps	}
8360786Sps
8460786Sps	debug("  final MPP regs:");
8560786Sps	for (i = 0; i < MPP_NR_REGS; i++) {
8660786Sps		writel(mpp_ctrl[i], MPP_CTRL(i));
8760786Sps		debug(" %08x", mpp_ctrl[i]);
8860786Sps	}
8960786Sps	debug("\n");
9060786Sps
9160786Sps}
9260786Sps