~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/mips/pci/ops-rc32434.c

Version: ~ [ linux-4.18 ] ~ [ linux-4.17.14 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.62 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.119 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.147 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.118 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.57 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.27.62 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~ [ linux-next-20180810 ] ~ [ linux-next-20180813 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  BRIEF MODULE DESCRIPTION
  3  *     pci_ops for IDT EB434 board
  4  *
  5  *  Copyright 2004 IDT Inc. (rischelp@idt.com)
  6  *  Copyright 2006 Felix Fietkau <nbd@openwrt.org>
  7  *
  8  *  This program is free software; you can redistribute  it and/or modify it
  9  *  under  the terms of  the GNU General  Public License as published by the
 10  *  Free Software Foundation;  either version 2 of the  License, or (at your
 11  *  option) any later version.
 12  *
 13  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
 14  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
 15  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
 16  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
 17  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 18  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
 19  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 20  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
 21  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 22  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 23  *
 24  *  You should have received a copy of the  GNU General Public License along
 25  *  with this program; if not, write  to the Free Software Foundation, Inc.,
 26  *  675 Mass Ave, Cambridge, MA 02139, USA.
 27  */
 28 #include <linux/delay.h>
 29 #include <linux/io.h>
 30 #include <linux/pci.h>
 31 #include <linux/types.h>
 32 
 33 #include <asm/cpu.h>
 34 #include <asm/mach-rc32434/rc32434.h>
 35 #include <asm/mach-rc32434/pci.h>
 36 
 37 #define PCI_ACCESS_READ  0
 38 #define PCI_ACCESS_WRITE 1
 39 
 40 
 41 #define PCI_CFG_SET(bus, slot, func, off) \
 42         (rc32434_pci->pcicfga = (0x80000000 | \
 43                                 ((bus) << 16) | ((slot)<<11) | \
 44                                 ((func)<<8) | (off)))
 45 
 46 static inline int config_access(unsigned char access_type,
 47                                 struct pci_bus *bus, unsigned int devfn,
 48                                 unsigned char where, u32 *data)
 49 {
 50         unsigned int slot = PCI_SLOT(devfn);
 51         u8 func = PCI_FUNC(devfn);
 52 
 53         /* Setup address */
 54         PCI_CFG_SET(bus->number, slot, func, where);
 55         rc32434_sync();
 56 
 57         if (access_type == PCI_ACCESS_WRITE)
 58                 rc32434_pci->pcicfgd = *data;
 59         else
 60                 *data = rc32434_pci->pcicfgd;
 61 
 62         rc32434_sync();
 63 
 64         return 0;
 65 }
 66 
 67 
 68 /*
 69  * We can't address 8 and 16 bit words directly.  Instead we have to
 70  * read/write a 32bit word and mask/modify the data we actually want.
 71  */
 72 static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
 73                             int where, u8 *val)
 74 {
 75         u32 data;
 76         int ret;
 77 
 78         ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
 79         *val = (data >> ((where & 3) << 3)) & 0xff;
 80         return ret;
 81 }
 82 
 83 static int read_config_word(struct pci_bus *bus, unsigned int devfn,
 84                             int where, u16 *val)
 85 {
 86         u32 data;
 87         int ret;
 88 
 89         ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
 90         *val = (data >> ((where & 3) << 3)) & 0xffff;
 91         return ret;
 92 }
 93 
 94 static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
 95                              int where, u32 *val)
 96 {
 97         int ret;
 98         int delay = 1;
 99 
100         /*
101          * Don't scan too far, else there will be errors with plugged in
102          * daughterboard (rb564).
103          */
104         if (bus->number == 0 && PCI_SLOT(devfn) > 21)
105                 return 0;
106 
107 retry:
108         ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
109 
110         /*
111          * Certain devices react delayed at device scan time, this
112          * gives them time to settle
113          */
114         if (where == PCI_VENDOR_ID) {
115                 if (ret == 0xffffffff || ret == 0x00000000 ||
116                     ret == 0x0000ffff || ret == 0xffff0000) {
117                         if (delay > 4)
118                                 return 0;
119                         delay *= 2;
120                         msleep(delay);
121                         goto retry;
122                 }
123         }
124 
125         return ret;
126 }
127 
128 static int
129 write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
130                   u8 val)
131 {
132         u32 data = 0;
133 
134         if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
135                 return -1;
136 
137         data = (data & ~(0xff << ((where & 3) << 3))) |
138             (val << ((where & 3) << 3));
139 
140         if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
141                 return -1;
142 
143         return PCIBIOS_SUCCESSFUL;
144 }
145 
146 
147 static int
148 write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
149                   u16 val)
150 {
151         u32 data = 0;
152 
153         if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
154                 return -1;
155 
156         data = (data & ~(0xffff << ((where & 3) << 3))) |
157             (val << ((where & 3) << 3));
158 
159         if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
160                 return -1;
161 
162 
163         return PCIBIOS_SUCCESSFUL;
164 }
165 
166 
167 static int
168 write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
169                    u32 val)
170 {
171         if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
172                 return -1;
173 
174         return PCIBIOS_SUCCESSFUL;
175 }
176 
177 static int pci_config_read(struct pci_bus *bus, unsigned int devfn,
178                            int where, int size, u32 *val)
179 {
180         switch (size) {
181         case 1:
182                 return read_config_byte(bus, devfn, where, (u8 *) val);
183         case 2:
184                 return read_config_word(bus, devfn, where, (u16 *) val);
185         default:
186                 return read_config_dword(bus, devfn, where, val);
187         }
188 }
189 
190 static int pci_config_write(struct pci_bus *bus, unsigned int devfn,
191                             int where, int size, u32 val)
192 {
193         switch (size) {
194         case 1:
195                 return write_config_byte(bus, devfn, where, (u8) val);
196         case 2:
197                 return write_config_word(bus, devfn, where, (u16) val);
198         default:
199                 return write_config_dword(bus, devfn, where, val);
200         }
201 }
202 
203 struct pci_ops rc32434_pci_ops = {
204         .read = pci_config_read,
205         .write = pci_config_write,
206 };
207 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp