Coding style cleanup
[platform/kernel/u-boot.git] / cpu / mpc86xx / pcie_indirect.c
1 /*
2  * Support for indirect PCI bridges.
3  *
4  * Copyright (c) Freescale Semiconductor, Inc.
5  * 2006. All rights reserved.
6  *
7  * Jason Jin <Jason.jin@freescale.com>
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version
12  * 2 of the License, or (at your option) any later version.
13  *
14  * partly derived from
15  * arch/powerpc/platforms/86xx/mpc86xx_pcie.c
16  */
17
18 #include <common.h>
19
20 #ifdef CONFIG_PCI
21
22 #include <asm/processor.h>
23 #include <asm/io.h>
24 #include <pci.h>
25
26 #define PCI_CFG_OUT     out_be32
27 #define PEX_FIX         out_be32(hose->cfg_addr+0x4, 0x0400ffff)
28
29 static int
30 indirect_read_config_pcie(struct pci_controller *hose,
31                           pci_dev_t dev,
32                           int offset,
33                           int len,
34                           u32 *val)
35 {
36         int bus = PCI_BUS(dev);
37
38         volatile unsigned char *cfg_data;
39         u32 temp;
40
41         PEX_FIX;
42         if (bus == 0xff) {
43                 PCI_CFG_OUT(hose->cfg_addr,
44                             dev | (offset & 0xfc) | 0x80000001);
45         } else {
46                 PCI_CFG_OUT(hose->cfg_addr,
47                             dev | (offset & 0xfc) | 0x80000000);
48         }
49         /*
50          * Note: the caller has already checked that offset is
51          * suitably aligned and that len is 1, 2 or 4.
52          */
53         /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
54         cfg_data = hose->cfg_data;
55         PEX_FIX;
56         temp = in_le32((u32 *) cfg_data);
57         switch (len) {
58         case 1:
59                 *val = (temp >> (((offset & 3)) * 8)) & 0xff;
60                 break;
61         case 2:
62                 *val = (temp >> (((offset & 3)) * 8)) & 0xffff;
63                 break;
64         default:
65                 *val = temp;
66                 break;
67         }
68
69         return 0;
70 }
71
72 static int
73 indirect_write_config_pcie(struct pci_controller *hose,
74                            pci_dev_t dev,
75                            int offset,
76                            int len,
77                            u32 val)
78 {
79         int bus = PCI_BUS(dev);
80         volatile unsigned char *cfg_data;
81         u32 temp;
82
83         PEX_FIX;
84         if (bus == 0xff) {
85                 PCI_CFG_OUT(hose->cfg_addr,
86                             dev | (offset & 0xfc) | 0x80000001);
87         } else {
88                 PCI_CFG_OUT(hose->cfg_addr,
89                             dev | (offset & 0xfc) | 0x80000000);
90         }
91
92         /*
93          * Note: the caller has already checked that offset is
94          * suitably aligned and that len is 1, 2 or 4.
95          */
96         /* ERRATA PCI-Ex 12 - Configuration Address/Data Alignment */
97         cfg_data = hose->cfg_data;
98         switch (len) {
99         case 1:
100                 PEX_FIX;
101                 temp = in_le32((u32 *) cfg_data);
102                 temp = (temp & ~(0xff << ((offset & 3) * 8))) |
103                     (val << ((offset & 3) * 8));
104                 PEX_FIX;
105                 out_le32((u32 *) cfg_data, temp);
106                 break;
107         case 2:
108                 PEX_FIX;
109                 temp = in_le32((u32 *) cfg_data);
110                 temp = (temp & ~(0xffff << ((offset & 3) * 8)));
111                 temp |= (val << ((offset & 3) * 8));
112                 PEX_FIX;
113                 out_le32((u32 *) cfg_data, temp);
114                 break;
115         default:
116                 PEX_FIX;
117                 out_le32((u32 *) cfg_data, val);
118                 break;
119         }
120         PEX_FIX;
121         return 0;
122 }
123
124 static int
125 indirect_read_config_byte_pcie(struct pci_controller *hose,
126                                pci_dev_t dev,
127                                int offset,
128                                u8 *val)
129 {
130         u32 val32;
131         indirect_read_config_pcie(hose, dev, offset, 1, &val32);
132         *val = (u8) val32;
133         return 0;
134 }
135
136 static int
137 indirect_read_config_word_pcie(struct pci_controller *hose,
138                                pci_dev_t dev,
139                                int offset,
140                                u16 *val)
141 {
142         u32 val32;
143         indirect_read_config_pcie(hose, dev, offset, 2, &val32);
144         *val = (u16) val32;
145         return 0;
146 }
147
148 static int
149 indirect_read_config_dword_pcie(struct pci_controller *hose,
150                                 pci_dev_t dev,
151                                 int offset,
152                                 u32 *val)
153 {
154         return indirect_read_config_pcie(hose, dev, offset, 4, val);
155 }
156
157 static int
158 indirect_write_config_byte_pcie(struct pci_controller *hose,
159                                 pci_dev_t dev,
160                                 int offset,
161                                 u8 val)
162 {
163         return indirect_write_config_pcie(hose, dev, offset, 1, (u32) val);
164 }
165
166 static int
167 indirect_write_config_word_pcie(struct pci_controller *hose,
168                                 pci_dev_t dev,
169                                 int offset,
170                                 unsigned short val)
171 {
172         return indirect_write_config_pcie(hose, dev, offset, 2, (u32) val);
173 }
174
175 static int
176 indirect_write_config_dword_pcie(struct pci_controller *hose,
177                                  pci_dev_t dev,
178                                  int offset,
179                                  u32 val)
180 {
181         return indirect_write_config_pcie(hose, dev, offset, 4, val);
182 }
183
184 void
185 pcie_setup_indirect(struct pci_controller *hose, u32 cfg_addr, u32 cfg_data)
186 {
187         pci_set_ops(hose,
188                     indirect_read_config_byte_pcie,
189                     indirect_read_config_word_pcie,
190                     indirect_read_config_dword_pcie,
191                     indirect_write_config_byte_pcie,
192                     indirect_write_config_word_pcie,
193                     indirect_write_config_dword_pcie);
194
195         hose->cfg_addr = (unsigned int *)cfg_addr;
196         hose->cfg_data = (unsigned char *)cfg_data;
197 }
198
199 #endif                          /* CONFIG_PCI */