193a686eeSJean-Christophe PLAGNIOL-VILLARD /*
293a686eeSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2004 Tundra Semiconductor Corp.
393a686eeSJean-Christophe PLAGNIOL-VILLARD * Alex Bounine <alexandreb@tundra.com>
493a686eeSJean-Christophe PLAGNIOL-VILLARD *
5*1a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
693a686eeSJean-Christophe PLAGNIOL-VILLARD */
793a686eeSJean-Christophe PLAGNIOL-VILLARD
893a686eeSJean-Christophe PLAGNIOL-VILLARD /*
993a686eeSJean-Christophe PLAGNIOL-VILLARD * PCI initialisation for the Tsi108 EMU board.
1093a686eeSJean-Christophe PLAGNIOL-VILLARD */
1193a686eeSJean-Christophe PLAGNIOL-VILLARD
1293a686eeSJean-Christophe PLAGNIOL-VILLARD #include <config.h>
1393a686eeSJean-Christophe PLAGNIOL-VILLARD
1493a686eeSJean-Christophe PLAGNIOL-VILLARD #include <common.h>
1593a686eeSJean-Christophe PLAGNIOL-VILLARD #include <pci.h>
1693a686eeSJean-Christophe PLAGNIOL-VILLARD #include <asm/io.h>
1793a686eeSJean-Christophe PLAGNIOL-VILLARD #include <tsi108.h>
18589c0427SGerald Van Baren #if defined(CONFIG_OF_LIBFDT)
19589c0427SGerald Van Baren #include <libfdt.h>
20589c0427SGerald Van Baren #include <fdt_support.h>
2193a686eeSJean-Christophe PLAGNIOL-VILLARD #endif
2293a686eeSJean-Christophe PLAGNIOL-VILLARD
2393a686eeSJean-Christophe PLAGNIOL-VILLARD struct pci_controller local_hose;
2493a686eeSJean-Christophe PLAGNIOL-VILLARD
tsi108_clear_pci_error(void)2593a686eeSJean-Christophe PLAGNIOL-VILLARD void tsi108_clear_pci_error (void)
2693a686eeSJean-Christophe PLAGNIOL-VILLARD {
2793a686eeSJean-Christophe PLAGNIOL-VILLARD u32 err_stat, err_addr, pci_stat;
2893a686eeSJean-Christophe PLAGNIOL-VILLARD
2993a686eeSJean-Christophe PLAGNIOL-VILLARD /*
3093a686eeSJean-Christophe PLAGNIOL-VILLARD * Quietly clear errors signalled as result of PCI/X configuration read
3193a686eeSJean-Christophe PLAGNIOL-VILLARD * requests.
3293a686eeSJean-Christophe PLAGNIOL-VILLARD */
3393a686eeSJean-Christophe PLAGNIOL-VILLARD /* Read PB Error Log Registers */
346d0f6bcfSJean-Christophe PLAGNIOL-VILLARD err_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
3593a686eeSJean-Christophe PLAGNIOL-VILLARD TSI108_PB_REG_OFFSET + PB_ERRCS);
366d0f6bcfSJean-Christophe PLAGNIOL-VILLARD err_addr = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
3793a686eeSJean-Christophe PLAGNIOL-VILLARD TSI108_PB_REG_OFFSET + PB_AERR);
3893a686eeSJean-Christophe PLAGNIOL-VILLARD if (err_stat & PB_ERRCS_ES) {
3993a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear PCI/X bus errors if applicable */
406d0f6bcfSJean-Christophe PLAGNIOL-VILLARD if ((err_addr & 0xFF000000) == CONFIG_SYS_PCI_CFG_BASE) {
4193a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear error flag */
426d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
4393a686eeSJean-Christophe PLAGNIOL-VILLARD TSI108_PB_REG_OFFSET + PB_ERRCS) =
4493a686eeSJean-Christophe PLAGNIOL-VILLARD PB_ERRCS_ES;
4593a686eeSJean-Christophe PLAGNIOL-VILLARD
4693a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear read error reported in PB_ISR */
476d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE +
4893a686eeSJean-Christophe PLAGNIOL-VILLARD TSI108_PB_REG_OFFSET + PB_ISR) =
4993a686eeSJean-Christophe PLAGNIOL-VILLARD PB_ISR_PBS_RD_ERR;
5093a686eeSJean-Christophe PLAGNIOL-VILLARD
5193a686eeSJean-Christophe PLAGNIOL-VILLARD /* Clear errors reported by PCI CSR (Normally Master Abort) */
526d0f6bcfSJean-Christophe PLAGNIOL-VILLARD pci_stat = *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
5393a686eeSJean-Christophe PLAGNIOL-VILLARD TSI108_PCI_REG_OFFSET +
5493a686eeSJean-Christophe PLAGNIOL-VILLARD PCI_CSR);
556d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
5693a686eeSJean-Christophe PLAGNIOL-VILLARD TSI108_PCI_REG_OFFSET + PCI_CSR) =
5793a686eeSJean-Christophe PLAGNIOL-VILLARD pci_stat;
5893a686eeSJean-Christophe PLAGNIOL-VILLARD
596d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(volatile u32 *)(CONFIG_SYS_TSI108_CSR_BASE +
6093a686eeSJean-Christophe PLAGNIOL-VILLARD TSI108_PCI_REG_OFFSET +
6193a686eeSJean-Christophe PLAGNIOL-VILLARD PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR;
6293a686eeSJean-Christophe PLAGNIOL-VILLARD }
6393a686eeSJean-Christophe PLAGNIOL-VILLARD }
6493a686eeSJean-Christophe PLAGNIOL-VILLARD
6593a686eeSJean-Christophe PLAGNIOL-VILLARD return;
6693a686eeSJean-Christophe PLAGNIOL-VILLARD }
6793a686eeSJean-Christophe PLAGNIOL-VILLARD
__get_pci_config_dword(u32 addr)6893a686eeSJean-Christophe PLAGNIOL-VILLARD unsigned int __get_pci_config_dword (u32 addr)
6993a686eeSJean-Christophe PLAGNIOL-VILLARD {
7093a686eeSJean-Christophe PLAGNIOL-VILLARD unsigned int retval;
7193a686eeSJean-Christophe PLAGNIOL-VILLARD
7293a686eeSJean-Christophe PLAGNIOL-VILLARD __asm__ __volatile__ (" lwbrx %0,0,%1\n"
7393a686eeSJean-Christophe PLAGNIOL-VILLARD "1: eieio\n"
7493a686eeSJean-Christophe PLAGNIOL-VILLARD "2:\n"
7593a686eeSJean-Christophe PLAGNIOL-VILLARD ".section .fixup,\"ax\"\n"
7693a686eeSJean-Christophe PLAGNIOL-VILLARD "3: li %0,-1\n"
7793a686eeSJean-Christophe PLAGNIOL-VILLARD " b 2b\n"
7893a686eeSJean-Christophe PLAGNIOL-VILLARD ".section __ex_table,\"a\"\n"
7993a686eeSJean-Christophe PLAGNIOL-VILLARD " .align 2\n"
8093a686eeSJean-Christophe PLAGNIOL-VILLARD " .long 1b,3b\n"
81e2c2a95eSWolfgang Denk ".section .text.__get_pci_config_dword"
82e2c2a95eSWolfgang Denk : "=r"(retval) : "r"(addr));
8393a686eeSJean-Christophe PLAGNIOL-VILLARD
8493a686eeSJean-Christophe PLAGNIOL-VILLARD return (retval);
8593a686eeSJean-Christophe PLAGNIOL-VILLARD }
8693a686eeSJean-Christophe PLAGNIOL-VILLARD
tsi108_read_config_dword(struct pci_controller * hose,pci_dev_t dev,int offset,u32 * value)8793a686eeSJean-Christophe PLAGNIOL-VILLARD static int tsi108_read_config_dword (struct pci_controller *hose,
8893a686eeSJean-Christophe PLAGNIOL-VILLARD pci_dev_t dev, int offset, u32 * value)
8993a686eeSJean-Christophe PLAGNIOL-VILLARD {
906d0f6bcfSJean-Christophe PLAGNIOL-VILLARD dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
916d0f6bcfSJean-Christophe PLAGNIOL-VILLARD dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
9293a686eeSJean-Christophe PLAGNIOL-VILLARD *value = __get_pci_config_dword(dev);
9393a686eeSJean-Christophe PLAGNIOL-VILLARD if (0xFFFFFFFF == *value)
9493a686eeSJean-Christophe PLAGNIOL-VILLARD tsi108_clear_pci_error ();
9593a686eeSJean-Christophe PLAGNIOL-VILLARD return 0;
9693a686eeSJean-Christophe PLAGNIOL-VILLARD }
9793a686eeSJean-Christophe PLAGNIOL-VILLARD
tsi108_write_config_dword(struct pci_controller * hose,pci_dev_t dev,int offset,u32 value)9893a686eeSJean-Christophe PLAGNIOL-VILLARD static int tsi108_write_config_dword (struct pci_controller *hose,
9993a686eeSJean-Christophe PLAGNIOL-VILLARD pci_dev_t dev, int offset, u32 value)
10093a686eeSJean-Christophe PLAGNIOL-VILLARD {
1016d0f6bcfSJean-Christophe PLAGNIOL-VILLARD dev &= (CONFIG_SYS_PCI_CFG_SIZE - 1);
1026d0f6bcfSJean-Christophe PLAGNIOL-VILLARD dev |= (CONFIG_SYS_PCI_CFG_BASE | (offset & 0xfc));
10393a686eeSJean-Christophe PLAGNIOL-VILLARD
10493a686eeSJean-Christophe PLAGNIOL-VILLARD out_le32 ((volatile unsigned *)dev, value);
10593a686eeSJean-Christophe PLAGNIOL-VILLARD
10693a686eeSJean-Christophe PLAGNIOL-VILLARD return 0;
10793a686eeSJean-Christophe PLAGNIOL-VILLARD }
10893a686eeSJean-Christophe PLAGNIOL-VILLARD
pci_init_board(void)10993a686eeSJean-Christophe PLAGNIOL-VILLARD void pci_init_board (void)
11093a686eeSJean-Christophe PLAGNIOL-VILLARD {
11193a686eeSJean-Christophe PLAGNIOL-VILLARD struct pci_controller *hose = (struct pci_controller *)&local_hose;
11293a686eeSJean-Christophe PLAGNIOL-VILLARD
11393a686eeSJean-Christophe PLAGNIOL-VILLARD hose->first_busno = 0;
11493a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = 0xff;
11593a686eeSJean-Christophe PLAGNIOL-VILLARD
11693a686eeSJean-Christophe PLAGNIOL-VILLARD pci_set_region (hose->regions + 0,
1176d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_PCI_MEMORY_BUS,
1186d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_PCI_MEMORY_PHYS,
119ff4e66e9SKumar Gala CONFIG_SYS_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
12093a686eeSJean-Christophe PLAGNIOL-VILLARD
12193a686eeSJean-Christophe PLAGNIOL-VILLARD /* PCI memory space */
12293a686eeSJean-Christophe PLAGNIOL-VILLARD pci_set_region (hose->regions + 1,
1236d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_PCI_MEM_BUS,
1246d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_PCI_MEM_PHYS, CONFIG_SYS_PCI_MEM_SIZE, PCI_REGION_MEM);
12593a686eeSJean-Christophe PLAGNIOL-VILLARD
12693a686eeSJean-Christophe PLAGNIOL-VILLARD /* PCI I/O space */
12793a686eeSJean-Christophe PLAGNIOL-VILLARD pci_set_region (hose->regions + 2,
1286d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_PCI_IO_BUS,
1296d0f6bcfSJean-Christophe PLAGNIOL-VILLARD CONFIG_SYS_PCI_IO_PHYS, CONFIG_SYS_PCI_IO_SIZE, PCI_REGION_IO);
13093a686eeSJean-Christophe PLAGNIOL-VILLARD
13193a686eeSJean-Christophe PLAGNIOL-VILLARD hose->region_count = 3;
13293a686eeSJean-Christophe PLAGNIOL-VILLARD
13393a686eeSJean-Christophe PLAGNIOL-VILLARD pci_set_ops (hose,
13493a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_byte_via_dword,
13593a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_read_config_word_via_dword,
13693a686eeSJean-Christophe PLAGNIOL-VILLARD tsi108_read_config_dword,
13793a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_byte_via_dword,
13893a686eeSJean-Christophe PLAGNIOL-VILLARD pci_hose_write_config_word_via_dword,
13993a686eeSJean-Christophe PLAGNIOL-VILLARD tsi108_write_config_dword);
14093a686eeSJean-Christophe PLAGNIOL-VILLARD
14193a686eeSJean-Christophe PLAGNIOL-VILLARD pci_register_hose (hose);
14293a686eeSJean-Christophe PLAGNIOL-VILLARD
14393a686eeSJean-Christophe PLAGNIOL-VILLARD hose->last_busno = pci_hose_scan (hose);
14493a686eeSJean-Christophe PLAGNIOL-VILLARD
14593a686eeSJean-Christophe PLAGNIOL-VILLARD debug ("Done PCI initialization\n");
14693a686eeSJean-Christophe PLAGNIOL-VILLARD return;
14793a686eeSJean-Christophe PLAGNIOL-VILLARD }
14893a686eeSJean-Christophe PLAGNIOL-VILLARD
149589c0427SGerald Van Baren #if defined(CONFIG_OF_LIBFDT)
ft_pci_setup(void * blob,bd_t * bd)150589c0427SGerald Van Baren void ft_pci_setup(void *blob, bd_t *bd)
15193a686eeSJean-Christophe PLAGNIOL-VILLARD {
152589c0427SGerald Van Baren int nodeoffset;
153589c0427SGerald Van Baren int tmp[2];
154589c0427SGerald Van Baren const char *path;
15593a686eeSJean-Christophe PLAGNIOL-VILLARD
156589c0427SGerald Van Baren nodeoffset = fdt_path_offset(blob, "/aliases");
157589c0427SGerald Van Baren if (nodeoffset >= 0) {
158589c0427SGerald Van Baren path = fdt_getprop(blob, nodeoffset, "pci", NULL);
159589c0427SGerald Van Baren if (path) {
160589c0427SGerald Van Baren tmp[0] = cpu_to_be32(local_hose.first_busno);
161589c0427SGerald Van Baren tmp[1] = cpu_to_be32(local_hose.last_busno);
162589c0427SGerald Van Baren do_fixup_by_path(blob, path, "bus-range",
163589c0427SGerald Van Baren &tmp, sizeof(tmp), 1);
16493a686eeSJean-Christophe PLAGNIOL-VILLARD }
16593a686eeSJean-Christophe PLAGNIOL-VILLARD }
166589c0427SGerald Van Baren }
167589c0427SGerald Van Baren #endif /* CONFIG_OF_LIBFDT */
168