~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to arch/mips/pci/ops-msc.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 1999, 2000, 2004, 2005  MIPS Technologies, Inc.
 
3
 *    All rights reserved.
 
4
 *    Authors: Carsten Langgaard <carstenl@mips.com>
 
5
 *             Maciej W. Rozycki <macro@mips.com>
 
6
 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
 
7
 *
 
8
 *  This program is free software; you can distribute it and/or modify it
 
9
 *  under the terms of the GNU General Public License (Version 2) as
 
10
 *  published by the Free Software Foundation.
 
11
 *
 
12
 *  This program is distributed in the hope it will be useful, but WITHOUT
 
13
 *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
14
 *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 
15
 *  for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License along
 
18
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 
19
 *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 
20
 *
 
21
 * MIPS boards specific PCI support.
 
22
 *
 
23
 */
 
24
#include <linux/types.h>
 
25
#include <linux/pci.h>
 
26
#include <linux/kernel.h>
 
27
#include <linux/init.h>
 
28
 
 
29
#include <asm/mips-boards/msc01_pci.h>
 
30
 
 
31
#define PCI_ACCESS_READ  0
 
32
#define PCI_ACCESS_WRITE 1
 
33
 
 
34
/*
 
35
 *  PCI configuration cycle AD bus definition
 
36
 */
 
37
/* Type 0 */
 
38
#define PCI_CFG_TYPE0_REG_SHF           0
 
39
#define PCI_CFG_TYPE0_FUNC_SHF          8
 
40
 
 
41
/* Type 1 */
 
42
#define PCI_CFG_TYPE1_REG_SHF           0
 
43
#define PCI_CFG_TYPE1_FUNC_SHF          8
 
44
#define PCI_CFG_TYPE1_DEV_SHF           11
 
45
#define PCI_CFG_TYPE1_BUS_SHF           16
 
46
 
 
47
static int msc_pcibios_config_access(unsigned char access_type,
 
48
        struct pci_bus *bus, unsigned int devfn, int where, u32 * data)
 
49
{
 
50
        unsigned char busnum = bus->number;
 
51
        u32 intr;
 
52
 
 
53
        /* Clear status register bits. */
 
54
        MSC_WRITE(MSC01_PCI_INTSTAT,
 
55
                  (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
 
56
 
 
57
        MSC_WRITE(MSC01_PCI_CFGADDR,
 
58
                  ((busnum << MSC01_PCI_CFGADDR_BNUM_SHF) |
 
59
                   (PCI_SLOT(devfn) << MSC01_PCI_CFGADDR_DNUM_SHF) |
 
60
                   (PCI_FUNC(devfn) << MSC01_PCI_CFGADDR_FNUM_SHF) |
 
61
                   ((where / 4) << MSC01_PCI_CFGADDR_RNUM_SHF)));
 
62
 
 
63
        /* Perform access */
 
64
        if (access_type == PCI_ACCESS_WRITE)
 
65
                MSC_WRITE(MSC01_PCI_CFGDATA, *data);
 
66
        else
 
67
                MSC_READ(MSC01_PCI_CFGDATA, *data);
 
68
 
 
69
        /* Detect Master/Target abort */
 
70
        MSC_READ(MSC01_PCI_INTSTAT, intr);
 
71
        if (intr & (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT)) {
 
72
                /* Error occurred */
 
73
 
 
74
                /* Clear bits */
 
75
                MSC_WRITE(MSC01_PCI_INTSTAT,
 
76
                          (MSC01_PCI_INTCFG_MA_BIT | MSC01_PCI_INTCFG_TA_BIT));
 
77
 
 
78
                return -1;
 
79
        }
 
80
 
 
81
        return 0;
 
82
}
 
83
 
 
84
 
 
85
/*
 
86
 * We can't address 8 and 16 bit words directly.  Instead we have to
 
87
 * read/write a 32bit word and mask/modify the data we actually want.
 
88
 */
 
89
static int msc_pcibios_read(struct pci_bus *bus, unsigned int devfn,
 
90
                             int where, int size, u32 * val)
 
91
{
 
92
        u32 data = 0;
 
93
 
 
94
        if ((size == 2) && (where & 1))
 
95
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
96
        else if ((size == 4) && (where & 3))
 
97
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
98
 
 
99
        if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn, where,
 
100
                                      &data))
 
101
                return -1;
 
102
 
 
103
        if (size == 1)
 
104
                *val = (data >> ((where & 3) << 3)) & 0xff;
 
105
        else if (size == 2)
 
106
                *val = (data >> ((where & 3) << 3)) & 0xffff;
 
107
        else
 
108
                *val = data;
 
109
 
 
110
        return PCIBIOS_SUCCESSFUL;
 
111
}
 
112
 
 
113
static int msc_pcibios_write(struct pci_bus *bus, unsigned int devfn,
 
114
                              int where, int size, u32 val)
 
115
{
 
116
        u32 data = 0;
 
117
 
 
118
        if ((size == 2) && (where & 1))
 
119
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
120
        else if ((size == 4) && (where & 3))
 
121
                return PCIBIOS_BAD_REGISTER_NUMBER;
 
122
 
 
123
        if (size == 4)
 
124
                data = val;
 
125
        else {
 
126
                if (msc_pcibios_config_access(PCI_ACCESS_READ, bus, devfn,
 
127
                                              where, &data))
 
128
                        return -1;
 
129
 
 
130
                if (size == 1)
 
131
                        data = (data & ~(0xff << ((where & 3) << 3))) |
 
132
                                (val << ((where & 3) << 3));
 
133
                else if (size == 2)
 
134
                        data = (data & ~(0xffff << ((where & 3) << 3))) |
 
135
                                (val << ((where & 3) << 3));
 
136
        }
 
137
 
 
138
        if (msc_pcibios_config_access(PCI_ACCESS_WRITE, bus, devfn, where,
 
139
                                       &data))
 
140
                return -1;
 
141
 
 
142
        return PCIBIOS_SUCCESSFUL;
 
143
}
 
144
 
 
145
struct pci_ops msc_pci_ops = {
 
146
        .read = msc_pcibios_read,
 
147
        .write = msc_pcibios_write
 
148
};