1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) NEC Electronics Corporation 2004-2006
5 * This file is based on the arch/mips/pci/ops-vr41xx.c
7 * Copyright 2001 MontaVista Software Inc.
10 #include <linux/pci.h>
11 #include <linux/kernel.h>
12 #include <linux/types.h>
14 #include <asm/addrspace.h>
16 #include <asm/emma/emma2rh.h>
18 #define RTABORT (0x1<<9)
19 #define RMABORT (0x1<<10)
20 #define EMMA2RH_PCI_SLOT_NUM 9 /* 0000:09.0 is final PCI device */
26 static int check_args(struct pci_bus
*bus
, u32 devfn
, u32
* bus_num
)
28 /* check if the bus is top-level */
29 if (bus
->parent
!= NULL
)
30 *bus_num
= bus
->number
;
36 if (PCI_SLOT(devfn
) >= 10)
37 return PCIBIOS_DEVICE_NOT_FOUND
;
40 if ((*bus_num
>= 64) || (PCI_SLOT(devfn
) >= 16))
41 return PCIBIOS_DEVICE_NOT_FOUND
;
46 static inline int set_pci_configuration_address(unsigned char bus_num
,
47 unsigned int devfn
, int where
)
51 emma2rh_out32(EMMA2RH_PCI_INT
, ~RMABORT
);
54 * Type 0 configuration
56 config_win0
= (1 << (22 + PCI_SLOT(devfn
))) | (5 << 9);
59 * Type 1 configuration
61 config_win0
= (bus_num
<< 26) | (PCI_SLOT(devfn
) << 22) |
64 emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR
, config_win0
);
69 static int pci_config_read(struct pci_bus
*bus
, unsigned int devfn
, int where
,
70 int size
, uint32_t * val
)
73 u32 base
= KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE
);
79 if (check_args(bus
, devfn
, &bus_num
) == PCIBIOS_DEVICE_NOT_FOUND
)
80 return PCIBIOS_DEVICE_NOT_FOUND
;
82 backup_win0
= emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR
);
84 if (set_pci_configuration_address(bus_num
, devfn
, where
) < 0)
85 return PCIBIOS_DEVICE_NOT_FOUND
;
88 *(volatile u32
*)(base
+ (PCI_FUNC(devfn
) << 8) +
89 (where
& 0xfffffffc));
93 *val
= (data
>> ((where
& 3) << 3)) & 0xffU
;
96 *val
= (data
>> ((where
& 2) << 3)) & 0xffffU
;
102 emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR
, backup_win0
);
103 return PCIBIOS_FUNC_NOT_SUPPORTED
;
106 emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR
, backup_win0
);
108 if (emma2rh_in32(EMMA2RH_PCI_INT
) & RMABORT
)
109 return PCIBIOS_DEVICE_NOT_FOUND
;
111 return PCIBIOS_SUCCESSFUL
;
114 static int pci_config_write(struct pci_bus
*bus
, unsigned int devfn
, int where
,
118 u32 base
= KSEG1ADDR(EMMA2RH_PCI_CONFIG_BASE
);
123 if (check_args(bus
, devfn
, &bus_num
) == PCIBIOS_DEVICE_NOT_FOUND
)
124 return PCIBIOS_DEVICE_NOT_FOUND
;
126 backup_win0
= emma2rh_in32(EMMA2RH_PCI_IWIN0_CTR
);
128 if (set_pci_configuration_address(bus_num
, devfn
, where
) < 0)
129 return PCIBIOS_DEVICE_NOT_FOUND
;
131 /* read modify write */
133 *(volatile u32
*)(base
+ (PCI_FUNC(devfn
) << 8) +
134 (where
& 0xfffffffc));
138 shift
= (where
& 3) << 3;
139 data
&= ~(0xffU
<< shift
);
140 data
|= ((val
& 0xffU
) << shift
);
143 shift
= (where
& 2) << 3;
144 data
&= ~(0xffffU
<< shift
);
145 data
|= ((val
& 0xffffU
) << shift
);
151 emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR
, backup_win0
);
152 return PCIBIOS_FUNC_NOT_SUPPORTED
;
154 *(volatile u32
*)(base
+ (PCI_FUNC(devfn
) << 8) +
155 (where
& 0xfffffffc)) = data
;
157 emma2rh_out32(EMMA2RH_PCI_IWIN0_CTR
, backup_win0
);
158 if (emma2rh_in32(EMMA2RH_PCI_INT
) & RMABORT
)
159 return PCIBIOS_DEVICE_NOT_FOUND
;
161 return PCIBIOS_SUCCESSFUL
;
164 struct pci_ops emma2rh_pci_ops
= {
165 .read
= pci_config_read
,
166 .write
= pci_config_write
,