blob: 1de747501dc0e8a0534ab55b79601fcde6552a62 [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 0 = 8 Mbyte register space
42 bar 2 = 16 Mbyte DDR space
43 bar 4 = 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 for MPC8308 */
69#define DRV_PCIE_INT_IRQ_BASE 96
70#define PCIE_DEV0_IV_0 (DRV_PCIE_INT_IRQ_BASE + 24)
71#define PCIE_DEV0_IV_1 (DRV_PCIE_INT_IRQ_BASE + 25)
72#define PCIE_DEV1_IV_0 (DRV_PCIE_INT_IRQ_BASE + 0)
73#define PCIE_DEV1_IV_1 (DRV_PCIE_INT_IRQ_BASE + 1)
74
75/* Maple device object struct */
76typedef struct
77{
78 uint32_t llpcie_irq;
79 uint32_t llpcie_status_irq;
80} maple_llpcie_device_irqs;
81
82maple_llpcie_device_irqs llpcie_device_irqs[BCMOLT_MAX_MAPLE_DEVICES] =
83{
84 {PCIE_DEV0_IV_0,PCIE_DEV0_IV_1},
85 {PCIE_DEV1_IV_0,PCIE_DEV1_IV_1}
86};
87
88
89#ifdef LLPCIE_SET_BASE_ADDRESSES_MANUALLY
90
91typedef struct
92{
93 unsigned long soc_regs_base; /**< Device registers base in host address space */
94 unsigned long soc_sram_base; /**< Device SRAM base in host address space */
95 unsigned long soc_ddr_base; /**< Device DDR base in host address space */
96
97} maple_llpcie_base_addresses;
98
99maple_llpcie_base_addresses llpcie_base_addresses[BCMOLT_MAX_MAPLE_DEVICES] =
100{
101 {.soc_regs_base = 0xe0000000, .soc_sram_base = 0xe2000000, .soc_ddr_base = 0xe1000000},
102 /* in this example there is only one device*/
103 {.soc_regs_base = 0x00000000, .soc_sram_base = 0x00000000, .soc_ddr_base = 0x00000000}
104};
105#endif
106
107/* Maple device object struct */
108typedef struct
109{
110 bcm_ll_dev_info device;
111 bcmos_fastlock lock;
112 int err_status;
113 int phylink;
114 int prev_datalink;
115 int datalink;
116 uint32_t deviceid; // start from 0
117 unsigned int *traceaddr;
118 void *pdev;
119 int pciBusNo; /* PCI bus number */
120 int pciDevNo; /* PCI device number */
121 int pciFuncNo; /* PCI function number */
122 uint32_t dev_status_irq;
123} maple_device_info;
124
125/* Maple device objects */
126maple_device_info g_maple_devs_info[BCMOLT_MAX_MAPLE_DEVICES];
127
128int g_maple_dev_num = 0;
129
130/* Device PCIE interface status change callback */
131bcm_ll_pcie_status_change g_dev_status_change_cb;
132
133/** Device status change ISR
134 * \irq IRQ number
135 * \dev_instance device object
136 */
137int dev_status_interrupt (int irq, void *dev_instance)
138{
139 uint32_t reg_value = 0;
140 maple_device_info *device_info = NULL;
141 long flags = 0;
142 int handled = 0;
143 uint32_t dev_id = 0;
144
145 device_info = (maple_device_info *)dev_instance;
146 dev_id = device_info->deviceid;
147
148 flags = bcmos_fastlock_lock(&device_info->lock);
149
150 reg_value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
151 {
152 if (device_info->datalink != device_info->prev_datalink)
153 {
154 if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
155 printf("Device=%d : Link is up !!!\n", dev_id);
156 else
157 {
158 printf("Device=%d : Link is down !!!\n", dev_id);
159 printf("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
160 }
161 device_info->prev_datalink = device_info->datalink;
162 if (g_dev_status_change_cb)
163 {
164 g_dev_status_change_cb(dev_id, device_info->datalink);
165 }
166 }
167 reg_value = bcm_pci_read32(
168 (uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
169 {
170 handled = 1;
171 }
172 }
173
174 bcmos_fastlock_unlock(&device_info->lock, flags);
175
176 return handled;
177}
178
179/** Maple device detection and initialization
180 */
181bcmos_errno bcm_ll_pcie_interface_init()
182{
183 STATUS ret_status;
184 maple_device_info *dev_info = NULL;
185 uint32_t readval = 0;
186 uint8_t readvalb = 0;
187 uint32_t pci_dev_idx = 0;
188
189 printf("%s()\r\n", __FUNCTION__);
190
191 // check maple device number
192 if (g_maple_dev_num >= BCMOLT_MAX_MAPLE_DEVICES)
193 {
194 printf("Maximum Maple devices already defined (%d)\n", BCMOLT_MAX_MAPLE_DEVICES);
195 return BCM_ERR_ALREADY;
196 }
197
198 // Support multiple Maple devices
199 for (pci_dev_idx = 0; pci_dev_idx < BCMOLT_MAX_MAPLE_DEVICES; pci_dev_idx++)
200 {
201 uint16_t device_id;
202
203 // Init device object struct
204 dev_info = &g_maple_devs_info[pci_dev_idx];
205 memset(dev_info, 0, sizeof(maple_device_info));
206
207 // Try to find maple device
208 ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
209 PCIE_MAPLE_DEVICE_ID,
210 pci_dev_idx,
211 &dev_info->pciBusNo,
212 &dev_info->pciDevNo,
213 &dev_info->pciFuncNo);
214
215 if (ret_status == OK)
216 {
217 device_id = PCIE_MAPLE_DEVICE_ID;
218 goto found_device_id;
219 }
220
221 ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
222 PCIE_MAPLE_6863_SKU_DEVICE_ID,
223 pci_dev_idx,
224 &dev_info->pciBusNo,
225 &dev_info->pciDevNo,
226 &dev_info->pciFuncNo);
227
228 if (ret_status == OK)
229 {
230 device_id = PCIE_MAPLE_6863_SKU_DEVICE_ID;
231 goto found_device_id;
232 }
233
234 ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
235 PCIE_MAPLE_EPON_DEVICE_ID,
236 pci_dev_idx,
237 &dev_info->pciBusNo,
238 &dev_info->pciDevNo,
239 &dev_info->pciFuncNo);
240
241 if (ret_status == OK)
242 {
243 device_id = PCIE_MAPLE_EPON_DEVICE_ID;
244 goto found_device_id;
245 }
246
247 printf("No more devices, Found %d maple device(s)\n", g_maple_dev_num);
248 break;
249
250found_device_id:
251 // Found new Maple device
252 printf("Found maple device[%x - %x][%d] @ Bus %d, Dev %d, Func %d\n",
253 PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_DEVICE_ID, pci_dev_idx,
254 dev_info->pciBusNo, dev_info->pciDevNo, dev_info->pciFuncNo);
255 g_maple_dev_num += 1;
256
257 // init
258 dev_info->deviceid = pci_dev_idx;
259 dev_info->pdev = NULL;
260
261
262 // Enable PCI address map
263 pciConfigInByte(dev_info->pciBusNo,
264 dev_info->pciDevNo,
265 dev_info->pciFuncNo,
266 PCI_CFG_COMMAND,
267 (UINT8 *)&readvalb);
268 printf("CMD reg = 0x%x\n", readvalb);
269
270 readvalb |= 0x6;
271 pciConfigOutByte(dev_info->pciBusNo,
272 dev_info->pciDevNo,
273 dev_info->pciFuncNo,
274 PCI_CFG_COMMAND,
275 (UINT8)readvalb);
276
277 pciConfigInByte(dev_info->pciBusNo,
278 dev_info->pciDevNo,
279 dev_info->pciFuncNo,
280 PCI_CFG_COMMAND,
281 (UINT8 *)&readvalb);
282 printf("Adjusted CMD reg = 0x%x\n", readvalb);
283
284 // Init base addresses
285
286#ifdef LLPCIE_SET_BASE_ADDRESSES_MANUALLY
287 dev_info->device.soc_regs_base = llpcie_base_addresses.soc_regs_base;
288 dev_info->device.soc_sram_base = llpcie_base_addresses.soc_sram_base;
289 dev_info->device.soc_ddr_base = llpcie_base_addresses.soc_ddr_base;
290 dev_info->device.soc_ddr_length = MAPLE_DDR_LENGTH; // 16M */
291#else
292 pciConfigInLong(dev_info->pciBusNo,
293 dev_info->pciDevNo,
294 dev_info->pciFuncNo,
295 PCI_CFG_BASE_ADDRESS_0,
296 (UINT32 *)&readval);
297 printf("BAR0 = 0x%x\n", readval);
298 dev_info->device.soc_regs_base = (readval & PCI_MEMBASE_MASK);
299
300 pciConfigInLong(dev_info->pciBusNo,
301 dev_info->pciDevNo,
302 dev_info->pciFuncNo,
303 PCI_CFG_BASE_ADDRESS_2,
304 (UINT32 *)&readval);
305 printf("BAR2 = 0x%x\n", readval);
306 dev_info->device.soc_ddr_base = (readval & PCI_MEMBASE_MASK);
307 dev_info->device.soc_ddr_length = MAPLE_DDR_LENGTH; // 16M
308
309 pciConfigInLong(dev_info->pciBusNo,
310 dev_info->pciDevNo,
311 dev_info->pciFuncNo,
312 PCI_CFG_BASE_ADDRESS_4,
313 (UINT32 *)&readval);
314 printf("BAR4 = 0x%x\n", readval);
315 dev_info->device.soc_sram_base = (readval & PCI_MEMBASE_MASK);
316#endif
317
318 printf("Regs Base = 0x%lx, DDR Base = 0x%lx, DDR Length = 0x%x, SRAM Base = 0x%lx\n",
319 dev_info->device.soc_regs_base,
320 dev_info->device.soc_ddr_base,
321 dev_info->device.soc_ddr_length,
322 dev_info->device.soc_sram_base);
323
324 // init interrupt
325 dev_info->device.irq = llpcie_device_irqs[pci_dev_idx].llpcie_irq;
326 dev_info->dev_status_irq = llpcie_device_irqs[pci_dev_idx].llpcie_status_irq;
327 printf("DMA IRQ = %d, Device status IRQ = %d\n",
328 dev_info->device.irq, dev_info->dev_status_irq);
329
330 // read revision register
331 readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
332 printf("readval = 0x%x\n", readval);
333 printf("Card %d version major=%02x minor=%02x\n",
334 dev_info->deviceid,
335 ((readval & 0x0000ff00) >> 8),
336 (readval & 0x000000ff));
337
338 // read status register
339 readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
340 printf("readval = 0x%x\n", readval);
341 dev_info->err_status = (readval & 0x0000000f);
342 dev_info->phylink = ((readval >> 4) & 0x1);
343 dev_info->datalink = ((readval >> 5) & 0x1);
344 dev_info->prev_datalink = dev_info->datalink;
345
346 // connect INT for device status
347 bcmos_fastlock_init(&dev_info->lock, 0);
348 bcmos_int_connect((int)dev_info->dev_status_irq,
349 0,
350 BCMOS_IRQ_SHARED,
351 dev_status_interrupt,
352 "status_isr",
353 dev_info);
354 }
355
356 // Return status
357 if (0 >=g_maple_dev_num)
358 {
359 return BCM_ERR_NODEV;
360 }
361 else
362 {
363 return BCM_ERR_OK;
364 }
365}
366
367/** Get Maple device object struct
368 * \crt devie index,start from 0
369 */
370static maple_device_info *get_maple_pci_info(int crt)
371{
372 bcmos_errno err = BCM_ERR_OK;
373 uint32_t readval = 0;
374 maple_device_info *device_info = NULL;
375
376 /* check input parameter */
377 /* don't access invalid device regs base address */
378 if (crt >= g_maple_dev_num)
379 {
380 return NULL;
381 }
382 device_info = &g_maple_devs_info[crt];
383
384 /* read status register */
385 readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
386 device_info->err_status = (readval & 0x0000000f);
387 device_info->phylink = ((readval >> 4) & 0x1);
388 device_info->datalink = ((readval >> 5) & 0x1);
389
390 /* return device */
391 return device_info;
392}
393
394/** Register status change notification callback
395 * \param[in] cb Status change notification callback
396 * \return 0=OK or error <0
397 */
398bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
399{
400 int i;
401 maple_device_info *dev_info;
402
403 g_dev_status_change_cb = cb;
404 for (i = 0; i < g_maple_dev_num; i++)
405 {
406 dev_info = get_maple_pci_info(i);
407 g_dev_status_change_cb(i, dev_info->datalink);
408 }
409
410 return BCM_ERR_OK;
411}
412
413/** Unregister status change notification callback
414 * \return 0=OK or error <0
415 */
416bcmos_errno bcm_ll_pcie_status_change_unregister(void)
417{
418 g_dev_status_change_cb = NULL;
419
420 return BCM_ERR_OK;
421}
422
423/** Query PCIe device
424 * \param[in] dev_id Device id
425 * \param[out] info Device info
426 * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
427 */
428bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
429{
430 maple_device_info *dev_info = NULL;
431
432 /* check input parameter */
433 if (NULL == info)
434 {
435 return BCM_ERR_PARM;
436 }
437
438 /* don't access invalid device regs base address */
439 if (dev_id < g_maple_dev_num)
440 {
441 dev_info = get_maple_pci_info(dev_id);
442 if (NULL == dev_info)
443 {
444 return BCM_ERR_NOENT;
445 }
446 if (dev_info->datalink == BCM_LL_PCIE_LINK_DOWN)
447 {
448 return BCM_ERR_IO;
449 }
450
451 *info = dev_info->device;
452 return BCM_ERR_OK;
453 }
454
455 return BCM_ERR_RANGE;
456}
457
458/** Get low-level device handle
459 * \param[in] dev_id Device id
460 * \param[out] lldev Low-level device handle
461 * \return device handle or NULL if link is down
462 */
463bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
464{
465 maple_device_info *dev_info = NULL;
466
467 /* check input parameter */
468 /* don't access invalid device regs base address */
469 if (dev_id < g_maple_dev_num)
470 {
471 dev_info = get_maple_pci_info(dev_id);
472 if (NULL == dev_info)
473 {
474 return NULL;
475 }
476 else
477 {
478 return dev_info->pdev;
479 }
480 }
481
482 return NULL;
483}
484
485/** Host reset enable
486 * \enabled
487 */
488bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
489{
490 uint32_t val;
491
492 /* check input parameter */
493 /* don't access invalid device regs base address */
494 if (dev_id >= g_maple_dev_num)
495 {
496 return BCM_ERR_OVERFLOW;
497 }
498
499 val = enabled ? 0 : 1;
500 bcm_pci_write32((uint32_t *)(g_maple_devs_info[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET),
501 val);
502
503 return BCM_ERR_OK;
504}
505