xref: /linux/arch/sh/drivers/pci/ops-sh4.c (revision 597473720f4dc69749542bfcfed4a927a43d935e)
1*ff4a7481SKuninori Morimoto // SPDX-License-Identifier: GPL-2.0
2959f85f8SPaul Mundt /*
3959f85f8SPaul Mundt  * Generic SH-4 / SH-4A PCIC operations (SH7751, SH7780).
4959f85f8SPaul Mundt  *
57e4ba0d7SPaul Mundt  * Copyright (C) 2002 - 2009  Paul Mundt
6959f85f8SPaul Mundt  */
7959f85f8SPaul Mundt #include <linux/pci.h>
87e4ba0d7SPaul Mundt #include <linux/io.h>
939a90865SPaul Mundt #include <linux/spinlock.h>
10959f85f8SPaul Mundt #include <asm/addrspace.h>
11959f85f8SPaul Mundt #include "pci-sh4.h"
12959f85f8SPaul Mundt 
13959f85f8SPaul Mundt /*
14959f85f8SPaul Mundt  * Direct access to PCI hardware...
15959f85f8SPaul Mundt  */
16959f85f8SPaul Mundt #define CONFIG_CMD(bus, devfn, where) \
17ef407beeSPaul Mundt 	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
18959f85f8SPaul Mundt 
19959f85f8SPaul Mundt /*
20959f85f8SPaul Mundt  * Functions for accessing PCI configuration space with type 1 accesses
21959f85f8SPaul Mundt  */
sh4_pci_read(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 * val)22959f85f8SPaul Mundt static int sh4_pci_read(struct pci_bus *bus, unsigned int devfn,
23959f85f8SPaul Mundt 			   int where, int size, u32 *val)
24959f85f8SPaul Mundt {
25b6706ef1SMagnus Damm 	struct pci_channel *chan = bus->sysdata;
26959f85f8SPaul Mundt 	unsigned long flags;
27959f85f8SPaul Mundt 	u32 data;
28959f85f8SPaul Mundt 
29959f85f8SPaul Mundt 	/*
30959f85f8SPaul Mundt 	 * PCIPDR may only be accessed as 32 bit words,
31959f85f8SPaul Mundt 	 * so we must do byte alignment by hand
32959f85f8SPaul Mundt 	 */
3339a90865SPaul Mundt 	raw_spin_lock_irqsave(&pci_config_lock, flags);
34b6706ef1SMagnus Damm 	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
35b6706ef1SMagnus Damm 	data = pci_read_reg(chan, SH4_PCIPDR);
3639a90865SPaul Mundt 	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
37959f85f8SPaul Mundt 
38959f85f8SPaul Mundt 	switch (size) {
39959f85f8SPaul Mundt 	case 1:
40959f85f8SPaul Mundt 		*val = (data >> ((where & 3) << 3)) & 0xff;
41959f85f8SPaul Mundt 		break;
42959f85f8SPaul Mundt 	case 2:
43959f85f8SPaul Mundt 		*val = (data >> ((where & 2) << 3)) & 0xffff;
44959f85f8SPaul Mundt 		break;
45959f85f8SPaul Mundt 	case 4:
46959f85f8SPaul Mundt 		*val = data;
47959f85f8SPaul Mundt 		break;
48959f85f8SPaul Mundt 	default:
49959f85f8SPaul Mundt 		return PCIBIOS_FUNC_NOT_SUPPORTED;
50959f85f8SPaul Mundt 	}
51959f85f8SPaul Mundt 
52959f85f8SPaul Mundt 	return PCIBIOS_SUCCESSFUL;
53959f85f8SPaul Mundt }
54959f85f8SPaul Mundt 
55959f85f8SPaul Mundt /*
56959f85f8SPaul Mundt  * Since SH4 only does 32bit access we'll have to do a read,
57959f85f8SPaul Mundt  * mask,write operation.
58959f85f8SPaul Mundt  * We'll allow an odd byte offset, though it should be illegal.
59959f85f8SPaul Mundt  */
sh4_pci_write(struct pci_bus * bus,unsigned int devfn,int where,int size,u32 val)60959f85f8SPaul Mundt static int sh4_pci_write(struct pci_bus *bus, unsigned int devfn,
61959f85f8SPaul Mundt 			 int where, int size, u32 val)
62959f85f8SPaul Mundt {
63b6706ef1SMagnus Damm 	struct pci_channel *chan = bus->sysdata;
64959f85f8SPaul Mundt 	unsigned long flags;
65959f85f8SPaul Mundt 	int shift;
66959f85f8SPaul Mundt 	u32 data;
67959f85f8SPaul Mundt 
6839a90865SPaul Mundt 	raw_spin_lock_irqsave(&pci_config_lock, flags);
69b6706ef1SMagnus Damm 	pci_write_reg(chan, CONFIG_CMD(bus, devfn, where), SH4_PCIPAR);
70b6706ef1SMagnus Damm 	data = pci_read_reg(chan, SH4_PCIPDR);
7139a90865SPaul Mundt 	raw_spin_unlock_irqrestore(&pci_config_lock, flags);
72959f85f8SPaul Mundt 
73959f85f8SPaul Mundt 	switch (size) {
74959f85f8SPaul Mundt 	case 1:
75959f85f8SPaul Mundt 		shift = (where & 3) << 3;
76959f85f8SPaul Mundt 		data &= ~(0xff << shift);
77959f85f8SPaul Mundt 		data |= ((val & 0xff) << shift);
78959f85f8SPaul Mundt 		break;
79959f85f8SPaul Mundt 	case 2:
80959f85f8SPaul Mundt 		shift = (where & 2) << 3;
81959f85f8SPaul Mundt 		data &= ~(0xffff << shift);
82959f85f8SPaul Mundt 		data |= ((val & 0xffff) << shift);
83959f85f8SPaul Mundt 		break;
84959f85f8SPaul Mundt 	case 4:
85959f85f8SPaul Mundt 		data = val;
86959f85f8SPaul Mundt 		break;
87959f85f8SPaul Mundt 	default:
88959f85f8SPaul Mundt 		return PCIBIOS_FUNC_NOT_SUPPORTED;
89959f85f8SPaul Mundt 	}
90959f85f8SPaul Mundt 
91b6706ef1SMagnus Damm 	pci_write_reg(chan, data, SH4_PCIPDR);
92959f85f8SPaul Mundt 
93959f85f8SPaul Mundt 	return PCIBIOS_SUCCESSFUL;
94959f85f8SPaul Mundt }
95959f85f8SPaul Mundt 
96959f85f8SPaul Mundt struct pci_ops sh4_pci_ops = {
97959f85f8SPaul Mundt 	.read		= sh4_pci_read,
98959f85f8SPaul Mundt 	.write		= sh4_pci_write,
99959f85f8SPaul Mundt };
100959f85f8SPaul Mundt 
pci_fixup_pcic(struct pci_channel * chan)101b8b47bfbSMagnus Damm int __attribute__((weak)) pci_fixup_pcic(struct pci_channel *chan)
102cd6c7ea2SPaul Mundt {
103cd6c7ea2SPaul Mundt 	/* Nothing to do. */
104cd6c7ea2SPaul Mundt 	return 0;
105cd6c7ea2SPaul Mundt }
106