Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  *  BRIEF MODULE DESCRIPTION
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *     pci_ops for IDT EB434 board
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright 2004 IDT Inc. (rischelp@idt.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *  Copyright 2006 Felix Fietkau <nbd@openwrt.org>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  This program is free software; you can redistribute  it and/or modify it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *  under  the terms of  the GNU General  Public License as published by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *  Free Software Foundation;  either version 2 of the  License, or (at your
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *  option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  *  You should have received a copy of the  GNU General Public License along
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  *  with this program; if not, write  to the Free Software Foundation, Inc.,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  *  675 Mass Ave, Cambridge, MA 02139, USA.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include <asm/mach-rc32434/rc32434.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <asm/mach-rc32434/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #define PCI_ACCESS_READ	 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define PCI_ACCESS_WRITE 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) #define PCI_CFG_SET(bus, slot, func, off) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	(rc32434_pci->pcicfga = (0x80000000 | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 				((bus) << 16) | ((slot)<<11) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 				((func)<<8) | (off)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) static inline int config_access(unsigned char access_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 				struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 				unsigned char where, u32 *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	unsigned int slot = PCI_SLOT(devfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 	u8 func = PCI_FUNC(devfn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	/* Setup address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	PCI_CFG_SET(bus->number, slot, func, where);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	rc32434_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	if (access_type == PCI_ACCESS_WRITE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 		rc32434_pci->pcicfgd = *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		*data = rc32434_pci->pcicfgd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	rc32434_sync();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69)  * We can't address 8 and 16 bit words directly.  Instead we have to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)  * read/write a 32bit word and mask/modify the data we actually want.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) static int read_config_byte(struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 			    int where, u8 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	*val = (data >> ((where & 3) << 3)) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) static int read_config_word(struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 			    int where, u16 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	u32 data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	*val = (data >> ((where & 3) << 3)) & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) static int read_config_dword(struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 			     int where, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	int delay = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	 * Don't scan too far, else there will be errors with plugged in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	 * daughterboard (rb564).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	if (bus->number == 0 && PCI_SLOT(devfn) > 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	ret = config_access(PCI_ACCESS_READ, bus, devfn, where, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	 * Certain devices react delayed at device scan time, this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	 * gives them time to settle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	if (where == PCI_VENDOR_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		if (ret == 0xffffffff || ret == 0x00000000 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		    ret == 0x0000ffff || ret == 0xffff0000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 			if (delay > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 				return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			delay *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 			msleep(delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			goto retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) write_config_byte(struct pci_bus *bus, unsigned int devfn, int where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		  u8 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	u32 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	data = (data & ~(0xff << ((where & 3) << 3))) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	    (val << ((where & 3) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) write_config_word(struct pci_bus *bus, unsigned int devfn, int where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		  u16 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	u32 data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if (config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	data = (data & ~(0xffff << ((where & 3) << 3))) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	    (val << ((where & 3) << 3));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) write_config_dword(struct pci_bus *bus, unsigned int devfn, int where,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		   u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	if (config_access(PCI_ACCESS_WRITE, bus, devfn, where, &val))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	return PCIBIOS_SUCCESSFUL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) static int pci_config_read(struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 			   int where, int size, u32 *val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 	switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		return read_config_byte(bus, devfn, where, (u8 *) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		return read_config_word(bus, devfn, where, (u16 *) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		return read_config_dword(bus, devfn, where, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static int pci_config_write(struct pci_bus *bus, unsigned int devfn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			    int where, int size, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	switch (size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 		return write_config_byte(bus, devfn, where, (u8) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 		return write_config_word(bus, devfn, where, (u16) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		return write_config_dword(bus, devfn, where, val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) struct pci_ops rc32434_pci_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	.read = pci_config_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 	.write = pci_config_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) };