1/* -*- linux-c -*- */
2/*
3 * Copyright (C) 2001 By Joachim Martillo, Telford Tools, Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 *
10 */
11				/* This file is linked in, but I am
12				   not sure there is ever any
13				   reason directly to read the
14				   serial eprom on the multichannel
15				   server host card. */
16
17/* We handle PCI devices */
18#include <linux/pci.h>
19
20/* We need to use ioremap */
21#include <asm/io.h>
22
23#include <linux/delay.h>
24
25#include "8253xmcs.h"
26#include "8253xctl.h"
27
28/* read a byte out of the serial eeprom/nvram by means of
29 * 16 short commands */
30
31static unsigned int amcc_nvram_breadw(unsigned char *bridge_space,
32				      unsigned short address,
33				      unsigned char *value)
34{
35	unsigned int count;
36	unsigned rhr;
37
38	for(count = 0; count < 20000; ++count)
39	{
40		rhr = readl(bridge_space + AMCC_RCR);
41		if((rhr & AMCC_NVRBUSY) == 0)
42		{
43			break;
44		}
45		udelay(1);
46	}
47	if(count >= 20000)
48	{
49		return FALSE;
50	}
51	rhr = AMCC_NVRWRLA | ((address & 0x00FF) << 16);
52	writel(rhr, bridge_space + AMCC_RCR);
53	rhr = AMCC_NVRWRHA | ((address & 0xFF00) << 8);
54	writel(rhr, bridge_space + AMCC_RCR);
55	writel(AMCC_NVRRDDB, bridge_space + AMCC_RCR);
56	for(count = 0; count < 20000; ++count)
57	{
58		rhr = readl(bridge_space + AMCC_RCR);
59		if((rhr & AMCC_NVRBUSY) == 0)
60		{
61			break;
62		}
63		udelay(1);
64	}
65	if(count >= 20000)
66	{
67		return FALSE;
68	}
69	if(rhr & AMCC_NVRACCFAIL)
70	{
71		return FALSE;
72	}
73	*value = (unsigned char) (rhr >> 16);
74	return TRUE;
75}
76
77/* read the whole serial eeprom from the host card */
78
79unsigned int amcc_read_nvram(unsigned char* buffer, unsigned length, unsigned char *bridge_space)
80{
81	unsigned int count;
82	length <<= 1;			/* covert words to bytes */
83
84	for(count = 0; count < length; ++count)
85	{
86		if(amcc_nvram_breadw(bridge_space, count, &buffer[count]) == FALSE)
87		{
88			return FALSE;
89		}
90	}
91	return TRUE;
92}
93