mpc85xx.c revision 257178
193787Sdes/*-
294691Sdes * Copyright (C) 2008 Semihalf, Rafal Jaworowski
393787Sdes * All rights reserved.
493787Sdes *
593787Sdes * Redistribution and use in source and binary forms, with or without
693787Sdes * modification, are permitted provided that the following conditions
793787Sdes * are met:
893787Sdes * 1. Redistributions of source code must retain the above copyright
993787Sdes *    notice, this list of conditions and the following disclaimer.
1093787Sdes * 2. Redistributions in binary form must reproduce the above copyright
1193787Sdes *    notice, this list of conditions and the following disclaimer in the
1293787Sdes *    documentation and/or other materials provided with the distribution.
1393787Sdes *
1493787Sdes * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1593787Sdes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1693787Sdes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1793787Sdes * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
1893787Sdes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1993787Sdes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2093787Sdes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2193787Sdes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2293787Sdes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2393787Sdes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2493787Sdes * SUCH DAMAGE.
2593787Sdes */
2693787Sdes
2793787Sdes#include <sys/cdefs.h>
2893787Sdes__FBSDID("$FreeBSD: head/sys/powerpc/mpc85xx/mpc85xx.c 257178 2013-10-26 18:18:14Z nwhitehorn $");
2993787Sdes
3093787Sdes#include <sys/param.h>
3193787Sdes#include <sys/systm.h>
3293787Sdes#include <sys/lock.h>
3393787Sdes#include <sys/mutex.h>
3493787Sdes#include <sys/rman.h>
3593787Sdes
3693787Sdes#include <vm/vm.h>
3793787Sdes#include <vm/vm_param.h>
3893787Sdes
3993787Sdes#include <machine/cpu.h>
4093787Sdes#include <machine/cpufunc.h>
4193787Sdes#include <machine/pio.h>
4293787Sdes#include <machine/spr.h>
4393787Sdes
4493787Sdes#include <dev/fdt/fdt_common.h>
4593787Sdes
4693787Sdes#include <powerpc/mpc85xx/mpc85xx.h>
4793787Sdes
4893787Sdes/*
4993787Sdes * MPC85xx system specific routines
5093787Sdes */
5193787Sdes
5293787Sdesuint32_t
5393787Sdesccsr_read4(uintptr_t addr)
5493787Sdes{
5593787Sdes	volatile uint32_t *ptr = (void *)addr;
5693787Sdes
5793787Sdes	return (*ptr);
5893787Sdes}
5993787Sdes
6093787Sdesvoid
6193787Sdesccsr_write4(uintptr_t addr, uint32_t val)
6293787Sdes{
6394691Sdes	volatile uint32_t *ptr = (void *)addr;
6493787Sdes
6593787Sdes	*ptr = val;
6693787Sdes	powerpc_iomb();
6793787Sdes}
6893787Sdes
6993787Sdesint
7093787Sdeslaw_getmax(void)
7193787Sdes{
7293787Sdes	uint32_t ver;
7393787Sdes
7493787Sdes	ver = SVR_VER(mfspr(SPR_SVR));
7593787Sdes	if (ver == SVR_MPC8555E || ver == SVR_MPC8555)
7693787Sdes		return (8);
7793787Sdes	if (ver == SVR_MPC8548E || ver == SVR_MPC8548 ||
7893787Sdes	    ver == SVR_MPC8533E || ver == SVR_MPC8533)
7993787Sdes		return (10);
8093787Sdes
8193787Sdes	return (12);
8293787Sdes}
8393787Sdes
8493787Sdes#define	_LAW_SR(trgt,size)	(0x80000000 | (trgt << 20) | (ffsl(size) - 2))
8593787Sdes#define	_LAW_BAR(addr)		(addr >> 12)
8693787Sdes
8793787Sdesint
8893787Sdeslaw_enable(int trgt, u_long addr, u_long size)
8993787Sdes{
9093787Sdes	uint32_t bar, sr;
9193787Sdes	int i, law_max;
9293787Sdes
9393787Sdes	if (size == 0)
9493787Sdes		return (0);
9593787Sdes
9693787Sdes	law_max = law_getmax();
9793787Sdes	bar = _LAW_BAR(addr);
9893787Sdes	sr = _LAW_SR(trgt, size);
9993787Sdes
10093787Sdes	/* Bail if already programmed. */
10193787Sdes	for (i = 0; i < law_max; i++)
10293787Sdes		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
10393787Sdes		    bar == ccsr_read4(OCP85XX_LAWBAR(i)))
10493787Sdes			return (0);
10593787Sdes
10693787Sdes	/* Find an unused access window. */
10793787Sdes	for (i = 0; i < law_max; i++)
10893787Sdes		if ((ccsr_read4(OCP85XX_LAWSR(i)) & 0x80000000) == 0)
10993787Sdes			break;
11093787Sdes
11193787Sdes	if (i == law_max)
11293787Sdes		return (ENOSPC);
11393787Sdes
11493787Sdes	ccsr_write4(OCP85XX_LAWBAR(i), bar);
11593787Sdes	ccsr_write4(OCP85XX_LAWSR(i), sr);
11693787Sdes	return (0);
11793787Sdes}
11893787Sdes
11993787Sdesint
12093787Sdeslaw_disable(int trgt, u_long addr, u_long size)
12193787Sdes{
12293787Sdes	uint32_t bar, sr;
12393787Sdes	int i, law_max;
12493787Sdes
12593787Sdes	law_max = law_getmax();
12693787Sdes	bar = _LAW_BAR(addr);
12793787Sdes	sr = _LAW_SR(trgt, size);
12893787Sdes
12993787Sdes	/* Find and disable requested LAW. */
13093787Sdes	for (i = 0; i < law_max; i++)
13193787Sdes		if (sr == ccsr_read4(OCP85XX_LAWSR(i)) &&
13293787Sdes		    bar == ccsr_read4(OCP85XX_LAWBAR(i))) {
13393787Sdes			ccsr_write4(OCP85XX_LAWBAR(i), 0);
13493787Sdes			ccsr_write4(OCP85XX_LAWSR(i), 0);
13593787Sdes			return (0);
13693787Sdes		}
13793787Sdes
13893787Sdes	return (ENOENT);
13993787Sdes}
14093787Sdes
14193787Sdesint
14293787Sdeslaw_pci_target(struct resource *res, int *trgt_mem, int *trgt_io)
14394691Sdes{
14493787Sdes	u_long start;
14594691Sdes	uint32_t ver;
14694691Sdes	int trgt, rv;
14793787Sdes
14893787Sdes	ver = SVR_VER(mfspr(SPR_SVR));
14993787Sdes
15093787Sdes	start = rman_get_start(res) & 0xf000;
15193787Sdes
15293787Sdes	rv = 0;
15393787Sdes	trgt = -1;
15493787Sdes	switch (start) {
15593787Sdes	case 0x8000:
15693787Sdes		trgt = 0;
15793787Sdes		break;
15893787Sdes	case 0x9000:
15993787Sdes		trgt = 1;
16093787Sdes		break;
16193787Sdes	case 0xa000:
16293787Sdes		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
16393787Sdes			trgt = 3;
16493787Sdes		else
16594691Sdes			trgt = 2;
16693787Sdes		break;
16794691Sdes	case 0xb000:
16894691Sdes		if (ver == SVR_MPC8548E || ver == SVR_MPC8548)
16993787Sdes			rv = EINVAL;
17093787Sdes		else
17193787Sdes			trgt = 3;
17293787Sdes		break;
17393787Sdes	default:
17493787Sdes		rv = ENXIO;
17593787Sdes	}
17693787Sdes	if (rv == 0) {
17793787Sdes		*trgt_mem = trgt;
17893787Sdes		*trgt_io = trgt;
17993787Sdes	}
18093787Sdes	return (rv);
18193787Sdes}
18293787Sdes
18393787Sdes