1a47a12beSStefan Roese /* 2a47a12beSStefan Roese * Copyright 2004 Freescale Semiconductor. 3a47a12beSStefan Roese * Copyright (C) 2003 Motorola Inc. 4a47a12beSStefan Roese * Xianghua Xiao (x.xiao@motorola.com) 5a47a12beSStefan Roese * 61a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+ 7a47a12beSStefan Roese */ 8a47a12beSStefan Roese 9a47a12beSStefan Roese /* 10a47a12beSStefan Roese * PCI Configuration space access support for MPC85xx PCI Bridge 11a47a12beSStefan Roese */ 12a47a12beSStefan Roese #include <common.h> 13a47a12beSStefan Roese #include <asm/cpm_85xx.h> 14a47a12beSStefan Roese #include <pci.h> 15a47a12beSStefan Roese 16a47a12beSStefan Roese #if !defined(CONFIG_FSL_PCI_INIT) 17a47a12beSStefan Roese 18a47a12beSStefan Roese #ifndef CONFIG_SYS_PCI1_MEM_BUS 19a47a12beSStefan Roese #define CONFIG_SYS_PCI1_MEM_BUS CONFIG_SYS_PCI1_MEM_BASE 20a47a12beSStefan Roese #endif 21a47a12beSStefan Roese 22a47a12beSStefan Roese #ifndef CONFIG_SYS_PCI1_IO_BUS 23a47a12beSStefan Roese #define CONFIG_SYS_PCI1_IO_BUS CONFIG_SYS_PCI1_IO_BASE 24a47a12beSStefan Roese #endif 25a47a12beSStefan Roese 26a47a12beSStefan Roese #ifndef CONFIG_SYS_PCI2_MEM_BUS 27a47a12beSStefan Roese #define CONFIG_SYS_PCI2_MEM_BUS CONFIG_SYS_PCI2_MEM_BASE 28a47a12beSStefan Roese #endif 29a47a12beSStefan Roese 30a47a12beSStefan Roese #ifndef CONFIG_SYS_PCI2_IO_BUS 31a47a12beSStefan Roese #define CONFIG_SYS_PCI2_IO_BUS CONFIG_SYS_PCI2_IO_BASE 32a47a12beSStefan Roese #endif 33a47a12beSStefan Roese 34a47a12beSStefan Roese static struct pci_controller *pci_hose; 35a47a12beSStefan Roese 36a47a12beSStefan Roese void 37a47a12beSStefan Roese pci_mpc85xx_init(struct pci_controller *board_hose) 38a47a12beSStefan Roese { 39a47a12beSStefan Roese u16 reg16; 40a47a12beSStefan Roese u32 dev; 41a47a12beSStefan Roese 42a47a12beSStefan Roese volatile ccsr_pcix_t *pcix = (void *)(CONFIG_SYS_MPC85xx_PCIX_ADDR); 43a47a12beSStefan Roese #ifdef CONFIG_MPC85XX_PCI2 44a47a12beSStefan Roese volatile ccsr_pcix_t *pcix2 = (void *)(CONFIG_SYS_MPC85xx_PCIX2_ADDR); 45a47a12beSStefan Roese #endif 46a47a12beSStefan Roese volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); 47a47a12beSStefan Roese struct pci_controller * hose; 48a47a12beSStefan Roese 49a47a12beSStefan Roese pci_hose = board_hose; 50a47a12beSStefan Roese 51a47a12beSStefan Roese hose = &pci_hose[0]; 52a47a12beSStefan Roese 53a47a12beSStefan Roese hose->first_busno = 0; 54a47a12beSStefan Roese hose->last_busno = 0xff; 55a47a12beSStefan Roese 56a47a12beSStefan Roese pci_setup_indirect(hose, 57a47a12beSStefan Roese (CONFIG_SYS_IMMR+0x8000), 58a47a12beSStefan Roese (CONFIG_SYS_IMMR+0x8004)); 59a47a12beSStefan Roese 60a47a12beSStefan Roese /* 61a47a12beSStefan Roese * Hose scan. 62a47a12beSStefan Roese */ 63a47a12beSStefan Roese dev = PCI_BDF(hose->first_busno, 0, 0); 64a47a12beSStefan Roese pci_hose_read_config_word (hose, dev, PCI_COMMAND, ®16); 65a47a12beSStefan Roese reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 66a47a12beSStefan Roese pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); 67a47a12beSStefan Roese 68a47a12beSStefan Roese /* 69a47a12beSStefan Roese * Clear non-reserved bits in status register. 70a47a12beSStefan Roese */ 71a47a12beSStefan Roese pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); 72a47a12beSStefan Roese 73a47a12beSStefan Roese if (!(gur->pordevsr & MPC85xx_PORDEVSR_PCI1)) { 74a47a12beSStefan Roese /* PCI-X init */ 75a47a12beSStefan Roese if (CONFIG_SYS_CLK_FREQ < 66000000) 76a47a12beSStefan Roese printf("PCI-X will only work at 66 MHz\n"); 77a47a12beSStefan Roese 78a47a12beSStefan Roese reg16 = PCI_X_CMD_MAX_SPLIT | PCI_X_CMD_MAX_READ 79a47a12beSStefan Roese | PCI_X_CMD_ERO | PCI_X_CMD_DPERR_E; 80a47a12beSStefan Roese pci_hose_write_config_word(hose, dev, PCIX_COMMAND, reg16); 81a47a12beSStefan Roese } 82a47a12beSStefan Roese 83a47a12beSStefan Roese pcix->potar1 = (CONFIG_SYS_PCI1_MEM_BUS >> 12) & 0x000fffff; 84a47a12beSStefan Roese pcix->potear1 = 0x00000000; 85a47a12beSStefan Roese pcix->powbar1 = (CONFIG_SYS_PCI1_MEM_PHYS >> 12) & 0x000fffff; 86a47a12beSStefan Roese pcix->powbear1 = 0x00000000; 87a47a12beSStefan Roese pcix->powar1 = (POWAR_EN | POWAR_MEM_READ | 88a47a12beSStefan Roese POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI1_MEM_SIZE) - 1)); 89a47a12beSStefan Roese 90a47a12beSStefan Roese pcix->potar2 = (CONFIG_SYS_PCI1_IO_BUS >> 12) & 0x000fffff; 91a47a12beSStefan Roese pcix->potear2 = 0x00000000; 92a47a12beSStefan Roese pcix->powbar2 = (CONFIG_SYS_PCI1_IO_PHYS >> 12) & 0x000fffff; 93a47a12beSStefan Roese pcix->powbear2 = 0x00000000; 94a47a12beSStefan Roese pcix->powar2 = (POWAR_EN | POWAR_IO_READ | 95a47a12beSStefan Roese POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI1_IO_SIZE) - 1)); 96a47a12beSStefan Roese 97a47a12beSStefan Roese pcix->pitar1 = 0x00000000; 98a47a12beSStefan Roese pcix->piwbar1 = 0x00000000; 99a47a12beSStefan Roese pcix->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL | 100a47a12beSStefan Roese PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G); 101a47a12beSStefan Roese 102a47a12beSStefan Roese pcix->powar3 = 0; 103a47a12beSStefan Roese pcix->powar4 = 0; 104a47a12beSStefan Roese pcix->piwar2 = 0; 105a47a12beSStefan Roese pcix->piwar3 = 0; 106a47a12beSStefan Roese 107a47a12beSStefan Roese pci_set_region(hose->regions + 0, 108a47a12beSStefan Roese CONFIG_SYS_PCI1_MEM_BUS, 109a47a12beSStefan Roese CONFIG_SYS_PCI1_MEM_PHYS, 110a47a12beSStefan Roese CONFIG_SYS_PCI1_MEM_SIZE, 111a47a12beSStefan Roese PCI_REGION_MEM); 112a47a12beSStefan Roese 113a47a12beSStefan Roese pci_set_region(hose->regions + 1, 114a47a12beSStefan Roese CONFIG_SYS_PCI1_IO_BUS, 115a47a12beSStefan Roese CONFIG_SYS_PCI1_IO_PHYS, 116a47a12beSStefan Roese CONFIG_SYS_PCI1_IO_SIZE, 117a47a12beSStefan Roese PCI_REGION_IO); 118a47a12beSStefan Roese 119a47a12beSStefan Roese hose->region_count = 2; 120a47a12beSStefan Roese 121a47a12beSStefan Roese pci_register_hose(hose); 122a47a12beSStefan Roese 123*2f2d54b7SYork Sun #if defined(CONFIG_TARGET_MPC8555CDS) || defined(CONFIG_TARGET_MPC8541CDS) 124a47a12beSStefan Roese /* 125a47a12beSStefan Roese * This is a SW workaround for an apparent HW problem 126a47a12beSStefan Roese * in the PCI controller on the MPC85555/41 CDS boards. 127a47a12beSStefan Roese * The first config cycle must be to a valid, known 128a47a12beSStefan Roese * device on the PCI bus in order to trick the PCI 129a47a12beSStefan Roese * controller state machine into a known valid state. 130a47a12beSStefan Roese * Without this, the first config cycle has the chance 131a47a12beSStefan Roese * of hanging the controller permanently, just leaving 132a47a12beSStefan Roese * it in a semi-working state, or leaving it working. 133a47a12beSStefan Roese * 134a47a12beSStefan Roese * Pick on the Tundra, Device 17, to get it right. 135a47a12beSStefan Roese */ 136a47a12beSStefan Roese { 137a47a12beSStefan Roese u8 header_type; 138a47a12beSStefan Roese 139a47a12beSStefan Roese pci_hose_read_config_byte(hose, 140a47a12beSStefan Roese PCI_BDF(0,BRIDGE_ID,0), 141a47a12beSStefan Roese PCI_HEADER_TYPE, 142a47a12beSStefan Roese &header_type); 143a47a12beSStefan Roese } 144a47a12beSStefan Roese #endif 145a47a12beSStefan Roese 146a47a12beSStefan Roese hose->last_busno = pci_hose_scan(hose); 147a47a12beSStefan Roese 148a47a12beSStefan Roese #ifdef CONFIG_MPC85XX_PCI2 149a47a12beSStefan Roese hose = &pci_hose[1]; 150a47a12beSStefan Roese 151a47a12beSStefan Roese hose->first_busno = pci_hose[0].last_busno + 1; 152a47a12beSStefan Roese hose->last_busno = 0xff; 153a47a12beSStefan Roese 154a47a12beSStefan Roese pci_setup_indirect(hose, 155a47a12beSStefan Roese (CONFIG_SYS_IMMR+0x9000), 156a47a12beSStefan Roese (CONFIG_SYS_IMMR+0x9004)); 157a47a12beSStefan Roese 158a47a12beSStefan Roese dev = PCI_BDF(hose->first_busno, 0, 0); 159a47a12beSStefan Roese pci_hose_read_config_word (hose, dev, PCI_COMMAND, ®16); 160a47a12beSStefan Roese reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 161a47a12beSStefan Roese pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); 162a47a12beSStefan Roese 163a47a12beSStefan Roese /* 164a47a12beSStefan Roese * Clear non-reserved bits in status register. 165a47a12beSStefan Roese */ 166a47a12beSStefan Roese pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); 167a47a12beSStefan Roese 168a47a12beSStefan Roese pcix2->potar1 = (CONFIG_SYS_PCI2_MEM_BUS >> 12) & 0x000fffff; 169a47a12beSStefan Roese pcix2->potear1 = 0x00000000; 170a47a12beSStefan Roese pcix2->powbar1 = (CONFIG_SYS_PCI2_MEM_PHYS >> 12) & 0x000fffff; 171a47a12beSStefan Roese pcix2->powbear1 = 0x00000000; 172a47a12beSStefan Roese pcix2->powar1 = (POWAR_EN | POWAR_MEM_READ | 173a47a12beSStefan Roese POWAR_MEM_WRITE | (__ilog2(CONFIG_SYS_PCI2_MEM_SIZE) - 1)); 174a47a12beSStefan Roese 175a47a12beSStefan Roese pcix2->potar2 = (CONFIG_SYS_PCI2_IO_BUS >> 12) & 0x000fffff; 176a47a12beSStefan Roese pcix2->potear2 = 0x00000000; 177a47a12beSStefan Roese pcix2->powbar2 = (CONFIG_SYS_PCI2_IO_PHYS >> 12) & 0x000fffff; 178a47a12beSStefan Roese pcix2->powbear2 = 0x00000000; 179a47a12beSStefan Roese pcix2->powar2 = (POWAR_EN | POWAR_IO_READ | 180a47a12beSStefan Roese POWAR_IO_WRITE | (__ilog2(CONFIG_SYS_PCI2_IO_SIZE) - 1)); 181a47a12beSStefan Roese 182a47a12beSStefan Roese pcix2->pitar1 = 0x00000000; 183a47a12beSStefan Roese pcix2->piwbar1 = 0x00000000; 184a47a12beSStefan Roese pcix2->piwar1 = (PIWAR_EN | PIWAR_PF | PIWAR_LOCAL | 185a47a12beSStefan Roese PIWAR_READ_SNOOP | PIWAR_WRITE_SNOOP | PIWAR_MEM_2G); 186a47a12beSStefan Roese 187a47a12beSStefan Roese pcix2->powar3 = 0; 188a47a12beSStefan Roese pcix2->powar4 = 0; 189a47a12beSStefan Roese pcix2->piwar2 = 0; 190a47a12beSStefan Roese pcix2->piwar3 = 0; 191a47a12beSStefan Roese 192a47a12beSStefan Roese pci_set_region(hose->regions + 0, 193a47a12beSStefan Roese CONFIG_SYS_PCI2_MEM_BUS, 194a47a12beSStefan Roese CONFIG_SYS_PCI2_MEM_PHYS, 195a47a12beSStefan Roese CONFIG_SYS_PCI2_MEM_SIZE, 196a47a12beSStefan Roese PCI_REGION_MEM); 197a47a12beSStefan Roese 198a47a12beSStefan Roese pci_set_region(hose->regions + 1, 199a47a12beSStefan Roese CONFIG_SYS_PCI2_IO_BUS, 200a47a12beSStefan Roese CONFIG_SYS_PCI2_IO_PHYS, 201a47a12beSStefan Roese CONFIG_SYS_PCI2_IO_SIZE, 202a47a12beSStefan Roese PCI_REGION_IO); 203a47a12beSStefan Roese 204a47a12beSStefan Roese hose->region_count = 2; 205a47a12beSStefan Roese 206a47a12beSStefan Roese /* 207a47a12beSStefan Roese * Hose scan. 208a47a12beSStefan Roese */ 209a47a12beSStefan Roese pci_register_hose(hose); 210a47a12beSStefan Roese 211a47a12beSStefan Roese hose->last_busno = pci_hose_scan(hose); 212a47a12beSStefan Roese #endif 213a47a12beSStefan Roese } 214a47a12beSStefan Roese #endif /* !CONFIG_FSL_PCI_INIT */ 215