blob: df6d3c0283f4067b9f466f637d378d5411604c1c [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/*
2<:copyright-BRCM:2016:DUAL/GPL:standard
3
4 Broadcom Proprietary and Confidential.(c) 2016 Broadcom
5 All Rights Reserved
6
7Unless you and Broadcom execute a separate written software license
8agreement governing use of this software, this software is licensed
9to you under the terms of the GNU General Public License version 2
10(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
11with the following added to such license:
12
13 As a special exception, the copyright holders of this software give
14 you permission to link this software with independent modules, and
15 to copy and distribute the resulting executable under terms of your
16 choice, provided that you also meet, for each linked independent
17 module, the terms and conditions of the license of that module.
18 An independent module is a module which is not derived from this
19 software. The special exception does not apply to any modifications
20 of the software.
21
22Not withstanding the above, under no circumstances may you combine
23this software in any way with any other Broadcom software provided
24under a license other than the GPL, without Broadcom's express prior
25written consent.
26
27:>
28*/
29
30#include <vxWorks.h>
31#include <drv/pci/pciConfigLib.h>
32#include "bcmolt_llpcie.h"
33
34/* Define PCIE device BAR registers */
35#define BAR_REGS 0
36#define BAR_DDR 2
37#define BAR_SRAM 4
38
39/*
40Define PCIE device BAR space length:
41 bar 1 = 8 Mbyte register space
42 bar 2 = 16 Mbyte DDR space
43 bar 3 = 64 Kbyte SRAM space
44*/
45#define MAPLE_REGS_LENGTH 0x00800000
46#define MAPLE_DDR_LENGTH 0x01000000
47#define MAPLE_SRAM_LENGTH 0x00010000
48
49/* Define special registers address */
50#ifdef TX_ENABLE_EVENT_TRACE
51#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO 0x064014U
52#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI 0x064018U
53#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT 0x064074U
54#endif
55#define PCIE_REVISION_REGISTER_OFFSET 0x6406C /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_REVISION */
56#define PCIE_STATUS_REGISTER_OFFSET 0x64068 /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
57#define PCIE_HARD_DEBUG_REGISTER_OFFSET 0x64204U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_HARD_DEBUG */
58#define PCIE_INT_STATUS_REGISTER_OFFSET 0x69400 /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_STATUS */
59#define PCIE_INT_CLEAR_MASK_OFFSET 0x6940C /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_MASK_CLEAR */
60#define PCIE_INTR1_STATUS_REGISTER_OFFSET 0x69300 /* Interrupt Status Register */
61
62/* Maple device ID */
63#define PCIE_MAPLE_VENDOR_ID 0x14E4 /* PCIE_CFG_TYPE0_EP_SUBSYSTEM_ID_VENDOR_ID */
64#define PCIE_MAPLE_DEVICE_ID 0x6862
65#define PCIE_MAPLE_6863_SKU_DEVICE_ID 0x6863
66#define PCIE_MAPLE_EPON_DEVICE_ID 0x5554
67
68/* Define interrupt vector number according BCM53003 BSP */
69#define PCIE1_IV_0 86
70#define PCIE1_IV_1 87
71#define PCIE1_INT_LINE 4
72
73/* Maple device object struct */
74typedef struct
75{
76 bcm_ll_dev_info device;
77 bcmos_fastlock lock;
78 int err_status;
79 int phylink;
80 int prev_datalink;
81 int datalink;
82 uint32_t deviceid; // start from 0
83 unsigned int *traceaddr;
84 void *pdev;
85 int pciBusNo; /* PCI bus number */
86 int pciDevNo; /* PCI device number */
87 int pciFuncNo; /* PCI function number */
88 uint32_t dev_status_irq;
89} maple_device_info;
90
91/* Maple device objects */
92static maple_device_info devices[MAPLE_MAX_DEVICES];
93int crt_device = 0;
94
95/* Device PCIE interface status change callback */
96static bcm_ll_pcie_status_change callback;
97
98/** Device status change ISR
99 * \irq IRQ number
100 * \dev_instance device object
101 */
102int dev_status_interrupt (int irq, void *dev_instance)
103{
104 bcmos_errno err = BCM_ERR_OK;
105 uint32_t reg_value = 0;
106 maple_device_info *device_info = NULL;
107 long flags = 0;
108 int handled = 0;
109 uint32_t dev_id = 0;
110
111 device_info = (maple_device_info *)dev_instance;
112 dev_id = device_info->deviceid;
113
114 flags = bcmos_fastlock_lock(&device_info->lock);
115
116 reg_value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
117 {
118 if (device_info->datalink != device_info->prev_datalink)
119 {
120 if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
121 printf("Device=%d : Link is up !!!\n", dev_id);
122 else
123 {
124 printf("Device=%d : Link is down !!!\n", dev_id);
125 printf("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
126 }
127 device_info->prev_datalink = device_info->datalink;
128 if (callback)
129 {
130 callback(dev_id, device_info->datalink);
131 }
132 }
133 reg_value = bcm_pci_read32(
134 (uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
135 {
136 handled = 1;
137 }
138 }
139
140 bcmos_fastlock_unlock(&device_info->lock, flags);
141
142 return handled;
143}
144
145/** Maple device detection and initialization
146 */
147bcmos_errno bcm_ll_pcie_interface_init()
148{
149 STATUS ret_status;
150 maple_device_info *dev_info = NULL;
151 uint32_t readval = 0;
152 uint8_t readvalb = 0;
153 bcmos_errno err = BCM_ERR_OK;
154 uint8_t irq = 0;
155 uint16_t device_id;
156
157 printf("%s()\r\n", __FUNCTION__);
158
159 // check maple device number
160 if (crt_device == MAPLE_MAX_DEVICES)
161 {
162 printf(" Maximum Maple devices already defined (%d)\n", MAPLE_MAX_DEVICES);
163 return BCM_ERR_ALREADY;
164 }
165 // Init device object struct
166 dev_info = &devices[crt_device++];
167 memset(dev_info, 0, sizeof(maple_device_info));
168
169 // find maple 6862 device
170 ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
171 PCIE_MAPLE_DEVICE_ID,
172 0,
173 &dev_info->pciBusNo,
174 &dev_info->pciDevNo,
175 &dev_info->pciFuncNo);
176
177 if (OK == ret_status)
178 {
179 device_id = PCIE_MAPLE_DEVICE_ID;
180 goto found_device_id;
181 }
182
183 // find maple 6863 device
184 ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
185 PCIE_MAPLE_6863_SKU_DEVICE_ID,
186 0,
187 &dev_info->pciBusNo,
188 &dev_info->pciDevNo,
189 &dev_info->pciFuncNo);
190
191 if (OK == ret_status)
192 {
193 device_id = PCIE_MAPLE_6863_SKU_DEVICE_ID;
194 goto found_device_id;
195 }
196
197 // find maple epon device
198 ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
199 PCIE_MAPLE_EPON_DEVICE_ID,
200 0,
201 &dev_info->pciBusNo,
202 &dev_info->pciDevNo,
203 &dev_info->pciFuncNo);
204
205 if (OK == ret_status)
206 {
207 device_id = PCIE_MAPLE_EPON_DEVICE_ID;
208 goto found_device_id;
209 }
210
211 printf("Can't find any device[%d]\n", PCIE_MAPLE_VENDOR_ID);
212 return BCM_ERR_NODEV;
213
214found_device_id:
215 printf("Found maple device[%x - %x]\n", PCIE_MAPLE_VENDOR_ID, device_id);
216
217 // init
218 dev_info->deviceid = (crt_device - 1);
219 dev_info->pdev = NULL;
220
221
222 // Enable PCI address map
223 pciConfigInByte(dev_info->pciBusNo,
224 dev_info->pciDevNo,
225 dev_info->pciFuncNo,
226 PCI_CFG_COMMAND,
227 (UINT8 *)&readvalb);
228 printf("CMD reg = 0x%x\n", readvalb);
229
230 readvalb |= 0x6;
231 pciConfigOutByte(dev_info->pciBusNo,
232 dev_info->pciDevNo,
233 dev_info->pciFuncNo,
234 PCI_CFG_COMMAND,
235 (UINT8)readvalb);
236
237 pciConfigInByte(dev_info->pciBusNo,
238 dev_info->pciDevNo,
239 dev_info->pciFuncNo,
240 PCI_CFG_COMMAND,
241 (UINT8 *)&readvalb);
242 printf("Adjusted CMD reg = 0x%x\n", readvalb);
243
244 // Init base addresses
245 dev_info->device.soc_regs_base = 0xe0000000;
246 dev_info->device.soc_sram_base = 0xe2000000;
247 dev_info->device.soc_ddr_base = 0xe1000000;
248 dev_info->device.soc_ddr_length = 0x1000000; // 16M
249
250 // init interrupt line
251 readvalb = PCIE1_INT_LINE;
252 pciConfigOutByte(dev_info->pciBusNo,
253 dev_info->pciDevNo,
254 dev_info->pciFuncNo,
255 PCI_CFG_DEV_INT_LINE,
256 (UINT8)readvalb);
257 pciConfigInByte(dev_info->pciBusNo,
258 dev_info->pciDevNo,
259 dev_info->pciFuncNo,
260 PCI_CFG_DEV_INT_LINE,
261 (UINT8 *)&readvalb);
262 printf("Adjusted INT Line reg = 0x%x\n", readvalb);
263
264 // init interrupt
265 dev_info->device.irq = PCIE1_IV_0;
266 dev_info->dev_status_irq = PCIE1_IV_1;
267
268 // read revision register
269 readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
270 printf("readval = 0x%x\n", readval);
271 printf("Card %d version major=%02x minor=%02x\n",
272 dev_info->deviceid,
273 ((readval & 0x0000ff00) >> 8),
274 (readval & 0x000000ff));
275
276 // read status register
277 readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
278 printf("readval = 0x%x\n", readval);
279 dev_info->err_status = (readval & 0x0000000f);
280 dev_info->phylink = ((readval >> 4) & 0x1);
281 dev_info->datalink = ((readval >> 5) & 0x1);
282 dev_info->prev_datalink = dev_info->datalink;
283
284 // connect INT for device status
285 bcmos_fastlock_init(&dev_info->lock, 0);
286 bcmos_int_connect((int)dev_info->dev_status_irq,
287 0,
288 BCMOS_IRQ_SHARED,
289 dev_status_interrupt,
290 "status_isr",
291 dev_info);
292
293 return BCM_ERR_OK;
294}
295
296/** Get Maple device object struct
297 * \crt devie index,start from 0
298 */
299static maple_device_info *get_maple_pci_info(int crt)
300{
301 bcmos_errno err = BCM_ERR_OK;
302 uint32_t readval = 0;
303 maple_device_info *device_info = NULL;
304
305 /* check input parameter */
306 if (MAPLE_MAX_DEVICES <= crt)
307 {
308 return NULL;
309 }
310 device_info = &devices[crt];
311
312 /* read status register */
313 readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
314 device_info->err_status = (readval & 0x0000000f);
315 device_info->phylink = ((readval >> 4) & 0x1);
316 device_info->datalink = ((readval >> 5) & 0x1);
317
318 /* return device */
319 return device_info;
320}
321
322/** Register status change notification callback
323 * \param[in] cb Status change notification callback
324 * \return 0=OK or error <0
325 */
326bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
327{
328 int i;
329 maple_device_info *dev_info;
330
331 callback = cb;
332 for (i = 0; i < crt_device; i++)
333 {
334 dev_info = get_maple_pci_info(i);
335 callback(i, dev_info->datalink);
336 }
337
338 return BCM_ERR_OK;
339}
340
341/** Unregister status change notification callback
342 * \return 0=OK or error <0
343 */
344bcmos_errno bcm_ll_pcie_status_change_unregister(void)
345{
346 callback = NULL;
347
348 return BCM_ERR_OK;
349}
350
351/** Query PCIe device
352 * \param[in] dev_id Device id
353 * \param[out] info Device info
354 * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
355 */
356bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
357{
358 maple_device_info *dev_info;
359
360 if (NULL == info)
361 {
362 return BCM_ERR_PARM;
363 }
364
365 if (dev_id < crt_device)
366 {
367 dev_info = get_maple_pci_info(dev_id);
368 if (dev_info->datalink == BCM_LL_PCIE_LINK_DOWN)
369 {
370 return BCM_ERR_IO;
371 }
372
373 *info = dev_info->device;
374 return BCM_ERR_OK;
375 }
376
377 return BCM_ERR_RANGE;
378}
379
380/** Get low-level device handle
381 * \param[in] dev_id Device id
382 * \param[out] lldev Low-level device handle
383 * \return device handle or NULL if link is down
384 */
385bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
386{
387 maple_device_info *dev_info;
388
389 if (dev_id < MAPLE_MAX_DEVICES)
390 {
391 dev_info = get_maple_pci_info(dev_id);
392 return dev_info->pdev;
393 }
394
395 return NULL;
396}
397
398/** Host reset enable
399 * \enabled
400 */
401bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
402{
403 uint32_t val;
404
405 val = enabled ? 0 : 1;
406 bcm_pci_write32((uint32_t *)(devices[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET) , val);
407
408 return BCM_ERR_OK;
409}
410