xref: /openbmc/linux/drivers/xen/xen-pciback/conf_space_header.c (revision fd5b221b348adf63d413de9adad030e4f13664b7)
130edc14bSKonrad Rzeszutek Wilk /*
230edc14bSKonrad Rzeszutek Wilk  * PCI Backend - Handles the virtual fields in the configuration space headers.
330edc14bSKonrad Rzeszutek Wilk  *
430edc14bSKonrad Rzeszutek Wilk  * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
530edc14bSKonrad Rzeszutek Wilk  */
630edc14bSKonrad Rzeszutek Wilk 
730edc14bSKonrad Rzeszutek Wilk #include <linux/kernel.h>
830edc14bSKonrad Rzeszutek Wilk #include <linux/pci.h>
930edc14bSKonrad Rzeszutek Wilk #include "pciback.h"
1030edc14bSKonrad Rzeszutek Wilk #include "conf_space.h"
1130edc14bSKonrad Rzeszutek Wilk 
1230edc14bSKonrad Rzeszutek Wilk struct pci_bar_info {
1330edc14bSKonrad Rzeszutek Wilk 	u32 val;
1430edc14bSKonrad Rzeszutek Wilk 	u32 len_val;
1530edc14bSKonrad Rzeszutek Wilk 	int which;
1630edc14bSKonrad Rzeszutek Wilk };
1730edc14bSKonrad Rzeszutek Wilk 
1830edc14bSKonrad Rzeszutek Wilk #define is_enable_cmd(value) ((value)&(PCI_COMMAND_MEMORY|PCI_COMMAND_IO))
1930edc14bSKonrad Rzeszutek Wilk #define is_master_cmd(value) ((value)&PCI_COMMAND_MASTER)
2030edc14bSKonrad Rzeszutek Wilk 
21*fd5b221bSZhao, Yu static int command_read(struct pci_dev *dev, int offset, u16 *value, void *data)
22*fd5b221bSZhao, Yu {
23*fd5b221bSZhao, Yu 	int i;
24*fd5b221bSZhao, Yu 	int ret;
25*fd5b221bSZhao, Yu 
26*fd5b221bSZhao, Yu 	ret = pciback_read_config_word(dev, offset, value, data);
27*fd5b221bSZhao, Yu 	if (!atomic_read(&dev->enable_cnt))
28*fd5b221bSZhao, Yu 		return ret;
29*fd5b221bSZhao, Yu 
30*fd5b221bSZhao, Yu 	for (i = 0; i < PCI_ROM_RESOURCE; i++) {
31*fd5b221bSZhao, Yu 		if (dev->resource[i].flags & IORESOURCE_IO)
32*fd5b221bSZhao, Yu 			*value |= PCI_COMMAND_IO;
33*fd5b221bSZhao, Yu 		if (dev->resource[i].flags & IORESOURCE_MEM)
34*fd5b221bSZhao, Yu 			*value |= PCI_COMMAND_MEMORY;
35*fd5b221bSZhao, Yu 	}
36*fd5b221bSZhao, Yu 
37*fd5b221bSZhao, Yu 	return ret;
38*fd5b221bSZhao, Yu }
39*fd5b221bSZhao, Yu 
4030edc14bSKonrad Rzeszutek Wilk static int command_write(struct pci_dev *dev, int offset, u16 value, void *data)
4130edc14bSKonrad Rzeszutek Wilk {
4230edc14bSKonrad Rzeszutek Wilk 	int err;
4330edc14bSKonrad Rzeszutek Wilk 
4430edc14bSKonrad Rzeszutek Wilk 	if (!pci_is_enabled(dev) && is_enable_cmd(value)) {
4530edc14bSKonrad Rzeszutek Wilk 		if (unlikely(verbose_request))
4630edc14bSKonrad Rzeszutek Wilk 			printk(KERN_DEBUG "pciback: %s: enable\n",
4730edc14bSKonrad Rzeszutek Wilk 			       pci_name(dev));
4830edc14bSKonrad Rzeszutek Wilk 		err = pci_enable_device(dev);
4930edc14bSKonrad Rzeszutek Wilk 		if (err)
5030edc14bSKonrad Rzeszutek Wilk 			return err;
5130edc14bSKonrad Rzeszutek Wilk 	} else if (pci_is_enabled(dev) && !is_enable_cmd(value)) {
5230edc14bSKonrad Rzeszutek Wilk 		if (unlikely(verbose_request))
5330edc14bSKonrad Rzeszutek Wilk 			printk(KERN_DEBUG "pciback: %s: disable\n",
5430edc14bSKonrad Rzeszutek Wilk 			       pci_name(dev));
5530edc14bSKonrad Rzeszutek Wilk 		pci_disable_device(dev);
5630edc14bSKonrad Rzeszutek Wilk 	}
5730edc14bSKonrad Rzeszutek Wilk 
5830edc14bSKonrad Rzeszutek Wilk 	if (!dev->is_busmaster && is_master_cmd(value)) {
5930edc14bSKonrad Rzeszutek Wilk 		if (unlikely(verbose_request))
6030edc14bSKonrad Rzeszutek Wilk 			printk(KERN_DEBUG "pciback: %s: set bus master\n",
6130edc14bSKonrad Rzeszutek Wilk 			       pci_name(dev));
6230edc14bSKonrad Rzeszutek Wilk 		pci_set_master(dev);
6330edc14bSKonrad Rzeszutek Wilk 	}
6430edc14bSKonrad Rzeszutek Wilk 
6530edc14bSKonrad Rzeszutek Wilk 	if (value & PCI_COMMAND_INVALIDATE) {
6630edc14bSKonrad Rzeszutek Wilk 		if (unlikely(verbose_request))
6730edc14bSKonrad Rzeszutek Wilk 			printk(KERN_DEBUG
6830edc14bSKonrad Rzeszutek Wilk 			       "pciback: %s: enable memory-write-invalidate\n",
6930edc14bSKonrad Rzeszutek Wilk 			       pci_name(dev));
7030edc14bSKonrad Rzeszutek Wilk 		err = pci_set_mwi(dev);
7130edc14bSKonrad Rzeszutek Wilk 		if (err) {
7230edc14bSKonrad Rzeszutek Wilk 			printk(KERN_WARNING
7330edc14bSKonrad Rzeszutek Wilk 			       "pciback: %s: cannot enable "
7430edc14bSKonrad Rzeszutek Wilk 			       "memory-write-invalidate (%d)\n",
7530edc14bSKonrad Rzeszutek Wilk 			       pci_name(dev), err);
7630edc14bSKonrad Rzeszutek Wilk 			value &= ~PCI_COMMAND_INVALIDATE;
7730edc14bSKonrad Rzeszutek Wilk 		}
7830edc14bSKonrad Rzeszutek Wilk 	}
7930edc14bSKonrad Rzeszutek Wilk 
8030edc14bSKonrad Rzeszutek Wilk 	return pci_write_config_word(dev, offset, value);
8130edc14bSKonrad Rzeszutek Wilk }
8230edc14bSKonrad Rzeszutek Wilk 
8330edc14bSKonrad Rzeszutek Wilk static int rom_write(struct pci_dev *dev, int offset, u32 value, void *data)
8430edc14bSKonrad Rzeszutek Wilk {
8530edc14bSKonrad Rzeszutek Wilk 	struct pci_bar_info *bar = data;
8630edc14bSKonrad Rzeszutek Wilk 
8730edc14bSKonrad Rzeszutek Wilk 	if (unlikely(!bar)) {
8830edc14bSKonrad Rzeszutek Wilk 		printk(KERN_WARNING "pciback: driver data not found for %s\n",
8930edc14bSKonrad Rzeszutek Wilk 		       pci_name(dev));
9030edc14bSKonrad Rzeszutek Wilk 		return XEN_PCI_ERR_op_failed;
9130edc14bSKonrad Rzeszutek Wilk 	}
9230edc14bSKonrad Rzeszutek Wilk 
9330edc14bSKonrad Rzeszutek Wilk 	/* A write to obtain the length must happen as a 32-bit write.
9430edc14bSKonrad Rzeszutek Wilk 	 * This does not (yet) support writing individual bytes
9530edc14bSKonrad Rzeszutek Wilk 	 */
9630edc14bSKonrad Rzeszutek Wilk 	if (value == ~PCI_ROM_ADDRESS_ENABLE)
9730edc14bSKonrad Rzeszutek Wilk 		bar->which = 1;
9830edc14bSKonrad Rzeszutek Wilk 	else {
9930edc14bSKonrad Rzeszutek Wilk 		u32 tmpval;
10030edc14bSKonrad Rzeszutek Wilk 		pci_read_config_dword(dev, offset, &tmpval);
10130edc14bSKonrad Rzeszutek Wilk 		if (tmpval != bar->val && value == bar->val) {
10230edc14bSKonrad Rzeszutek Wilk 			/* Allow restoration of bar value. */
10330edc14bSKonrad Rzeszutek Wilk 			pci_write_config_dword(dev, offset, bar->val);
10430edc14bSKonrad Rzeszutek Wilk 		}
10530edc14bSKonrad Rzeszutek Wilk 		bar->which = 0;
10630edc14bSKonrad Rzeszutek Wilk 	}
10730edc14bSKonrad Rzeszutek Wilk 
10830edc14bSKonrad Rzeszutek Wilk 	/* Do we need to support enabling/disabling the rom address here? */
10930edc14bSKonrad Rzeszutek Wilk 
11030edc14bSKonrad Rzeszutek Wilk 	return 0;
11130edc14bSKonrad Rzeszutek Wilk }
11230edc14bSKonrad Rzeszutek Wilk 
11330edc14bSKonrad Rzeszutek Wilk /* For the BARs, only allow writes which write ~0 or
11430edc14bSKonrad Rzeszutek Wilk  * the correct resource information
11530edc14bSKonrad Rzeszutek Wilk  * (Needed for when the driver probes the resource usage)
11630edc14bSKonrad Rzeszutek Wilk  */
11730edc14bSKonrad Rzeszutek Wilk static int bar_write(struct pci_dev *dev, int offset, u32 value, void *data)
11830edc14bSKonrad Rzeszutek Wilk {
11930edc14bSKonrad Rzeszutek Wilk 	struct pci_bar_info *bar = data;
12030edc14bSKonrad Rzeszutek Wilk 
12130edc14bSKonrad Rzeszutek Wilk 	if (unlikely(!bar)) {
12230edc14bSKonrad Rzeszutek Wilk 		printk(KERN_WARNING "pciback: driver data not found for %s\n",
12330edc14bSKonrad Rzeszutek Wilk 		       pci_name(dev));
12430edc14bSKonrad Rzeszutek Wilk 		return XEN_PCI_ERR_op_failed;
12530edc14bSKonrad Rzeszutek Wilk 	}
12630edc14bSKonrad Rzeszutek Wilk 
12730edc14bSKonrad Rzeszutek Wilk 	/* A write to obtain the length must happen as a 32-bit write.
12830edc14bSKonrad Rzeszutek Wilk 	 * This does not (yet) support writing individual bytes
12930edc14bSKonrad Rzeszutek Wilk 	 */
13030edc14bSKonrad Rzeszutek Wilk 	if (value == ~0)
13130edc14bSKonrad Rzeszutek Wilk 		bar->which = 1;
13230edc14bSKonrad Rzeszutek Wilk 	else {
13330edc14bSKonrad Rzeszutek Wilk 		u32 tmpval;
13430edc14bSKonrad Rzeszutek Wilk 		pci_read_config_dword(dev, offset, &tmpval);
13530edc14bSKonrad Rzeszutek Wilk 		if (tmpval != bar->val && value == bar->val) {
13630edc14bSKonrad Rzeszutek Wilk 			/* Allow restoration of bar value. */
13730edc14bSKonrad Rzeszutek Wilk 			pci_write_config_dword(dev, offset, bar->val);
13830edc14bSKonrad Rzeszutek Wilk 		}
13930edc14bSKonrad Rzeszutek Wilk 		bar->which = 0;
14030edc14bSKonrad Rzeszutek Wilk 	}
14130edc14bSKonrad Rzeszutek Wilk 
14230edc14bSKonrad Rzeszutek Wilk 	return 0;
14330edc14bSKonrad Rzeszutek Wilk }
14430edc14bSKonrad Rzeszutek Wilk 
14530edc14bSKonrad Rzeszutek Wilk static int bar_read(struct pci_dev *dev, int offset, u32 * value, void *data)
14630edc14bSKonrad Rzeszutek Wilk {
14730edc14bSKonrad Rzeszutek Wilk 	struct pci_bar_info *bar = data;
14830edc14bSKonrad Rzeszutek Wilk 
14930edc14bSKonrad Rzeszutek Wilk 	if (unlikely(!bar)) {
15030edc14bSKonrad Rzeszutek Wilk 		printk(KERN_WARNING "pciback: driver data not found for %s\n",
15130edc14bSKonrad Rzeszutek Wilk 		       pci_name(dev));
15230edc14bSKonrad Rzeszutek Wilk 		return XEN_PCI_ERR_op_failed;
15330edc14bSKonrad Rzeszutek Wilk 	}
15430edc14bSKonrad Rzeszutek Wilk 
15530edc14bSKonrad Rzeszutek Wilk 	*value = bar->which ? bar->len_val : bar->val;
15630edc14bSKonrad Rzeszutek Wilk 
15730edc14bSKonrad Rzeszutek Wilk 	return 0;
15830edc14bSKonrad Rzeszutek Wilk }
15930edc14bSKonrad Rzeszutek Wilk 
16030edc14bSKonrad Rzeszutek Wilk static inline void read_dev_bar(struct pci_dev *dev,
16130edc14bSKonrad Rzeszutek Wilk 				struct pci_bar_info *bar_info, int offset,
16230edc14bSKonrad Rzeszutek Wilk 				u32 len_mask)
16330edc14bSKonrad Rzeszutek Wilk {
164*fd5b221bSZhao, Yu 	int	pos;
165*fd5b221bSZhao, Yu 	struct resource	*res = dev->resource;
166*fd5b221bSZhao, Yu 
167*fd5b221bSZhao, Yu 	if (offset == PCI_ROM_ADDRESS || offset == PCI_ROM_ADDRESS1)
168*fd5b221bSZhao, Yu 		pos = PCI_ROM_RESOURCE;
169*fd5b221bSZhao, Yu 	else {
170*fd5b221bSZhao, Yu 		pos = (offset - PCI_BASE_ADDRESS_0) / 4;
171*fd5b221bSZhao, Yu 		if (pos && ((res[pos - 1].flags & (PCI_BASE_ADDRESS_SPACE |
172*fd5b221bSZhao, Yu 				PCI_BASE_ADDRESS_MEM_TYPE_MASK)) ==
173*fd5b221bSZhao, Yu 			   (PCI_BASE_ADDRESS_SPACE_MEMORY |
174*fd5b221bSZhao, Yu 				PCI_BASE_ADDRESS_MEM_TYPE_64))) {
175*fd5b221bSZhao, Yu 			bar_info->val = res[pos - 1].start >> 32;
176*fd5b221bSZhao, Yu 			bar_info->len_val = res[pos - 1].end >> 32;
177*fd5b221bSZhao, Yu 			return;
178*fd5b221bSZhao, Yu 		}
179*fd5b221bSZhao, Yu 	}
180*fd5b221bSZhao, Yu 
181*fd5b221bSZhao, Yu 	bar_info->val = res[pos].start |
182*fd5b221bSZhao, Yu 			(res[pos].flags & PCI_REGION_FLAG_MASK);
183*fd5b221bSZhao, Yu 	bar_info->len_val = res[pos].end - res[pos].start + 1;
18430edc14bSKonrad Rzeszutek Wilk }
18530edc14bSKonrad Rzeszutek Wilk 
18630edc14bSKonrad Rzeszutek Wilk static void *bar_init(struct pci_dev *dev, int offset)
18730edc14bSKonrad Rzeszutek Wilk {
18830edc14bSKonrad Rzeszutek Wilk 	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
18930edc14bSKonrad Rzeszutek Wilk 
19030edc14bSKonrad Rzeszutek Wilk 	if (!bar)
19130edc14bSKonrad Rzeszutek Wilk 		return ERR_PTR(-ENOMEM);
19230edc14bSKonrad Rzeszutek Wilk 
19330edc14bSKonrad Rzeszutek Wilk 	read_dev_bar(dev, bar, offset, ~0);
19430edc14bSKonrad Rzeszutek Wilk 	bar->which = 0;
19530edc14bSKonrad Rzeszutek Wilk 
19630edc14bSKonrad Rzeszutek Wilk 	return bar;
19730edc14bSKonrad Rzeszutek Wilk }
19830edc14bSKonrad Rzeszutek Wilk 
19930edc14bSKonrad Rzeszutek Wilk static void *rom_init(struct pci_dev *dev, int offset)
20030edc14bSKonrad Rzeszutek Wilk {
20130edc14bSKonrad Rzeszutek Wilk 	struct pci_bar_info *bar = kmalloc(sizeof(*bar), GFP_KERNEL);
20230edc14bSKonrad Rzeszutek Wilk 
20330edc14bSKonrad Rzeszutek Wilk 	if (!bar)
20430edc14bSKonrad Rzeszutek Wilk 		return ERR_PTR(-ENOMEM);
20530edc14bSKonrad Rzeszutek Wilk 
20630edc14bSKonrad Rzeszutek Wilk 	read_dev_bar(dev, bar, offset, ~PCI_ROM_ADDRESS_ENABLE);
20730edc14bSKonrad Rzeszutek Wilk 	bar->which = 0;
20830edc14bSKonrad Rzeszutek Wilk 
20930edc14bSKonrad Rzeszutek Wilk 	return bar;
21030edc14bSKonrad Rzeszutek Wilk }
21130edc14bSKonrad Rzeszutek Wilk 
21230edc14bSKonrad Rzeszutek Wilk static void bar_reset(struct pci_dev *dev, int offset, void *data)
21330edc14bSKonrad Rzeszutek Wilk {
21430edc14bSKonrad Rzeszutek Wilk 	struct pci_bar_info *bar = data;
21530edc14bSKonrad Rzeszutek Wilk 
21630edc14bSKonrad Rzeszutek Wilk 	bar->which = 0;
21730edc14bSKonrad Rzeszutek Wilk }
21830edc14bSKonrad Rzeszutek Wilk 
21930edc14bSKonrad Rzeszutek Wilk static void bar_release(struct pci_dev *dev, int offset, void *data)
22030edc14bSKonrad Rzeszutek Wilk {
22130edc14bSKonrad Rzeszutek Wilk 	kfree(data);
22230edc14bSKonrad Rzeszutek Wilk }
22330edc14bSKonrad Rzeszutek Wilk 
224*fd5b221bSZhao, Yu static int pciback_read_vendor(struct pci_dev *dev, int offset,
225*fd5b221bSZhao, Yu 			       u16 *value, void *data)
226*fd5b221bSZhao, Yu {
227*fd5b221bSZhao, Yu 	*value = dev->vendor;
228*fd5b221bSZhao, Yu 
229*fd5b221bSZhao, Yu 	return 0;
230*fd5b221bSZhao, Yu }
231*fd5b221bSZhao, Yu 
232*fd5b221bSZhao, Yu static int pciback_read_device(struct pci_dev *dev, int offset,
233*fd5b221bSZhao, Yu 			       u16 *value, void *data)
234*fd5b221bSZhao, Yu {
235*fd5b221bSZhao, Yu 	*value = dev->device;
236*fd5b221bSZhao, Yu 
237*fd5b221bSZhao, Yu 	return 0;
238*fd5b221bSZhao, Yu }
239*fd5b221bSZhao, Yu 
24030edc14bSKonrad Rzeszutek Wilk static int interrupt_read(struct pci_dev *dev, int offset, u8 * value,
24130edc14bSKonrad Rzeszutek Wilk 			  void *data)
24230edc14bSKonrad Rzeszutek Wilk {
24330edc14bSKonrad Rzeszutek Wilk 	*value = (u8) dev->irq;
24430edc14bSKonrad Rzeszutek Wilk 
24530edc14bSKonrad Rzeszutek Wilk 	return 0;
24630edc14bSKonrad Rzeszutek Wilk }
24730edc14bSKonrad Rzeszutek Wilk 
24830edc14bSKonrad Rzeszutek Wilk static int bist_write(struct pci_dev *dev, int offset, u8 value, void *data)
24930edc14bSKonrad Rzeszutek Wilk {
25030edc14bSKonrad Rzeszutek Wilk 	u8 cur_value;
25130edc14bSKonrad Rzeszutek Wilk 	int err;
25230edc14bSKonrad Rzeszutek Wilk 
25330edc14bSKonrad Rzeszutek Wilk 	err = pci_read_config_byte(dev, offset, &cur_value);
25430edc14bSKonrad Rzeszutek Wilk 	if (err)
25530edc14bSKonrad Rzeszutek Wilk 		goto out;
25630edc14bSKonrad Rzeszutek Wilk 
25730edc14bSKonrad Rzeszutek Wilk 	if ((cur_value & ~PCI_BIST_START) == (value & ~PCI_BIST_START)
25830edc14bSKonrad Rzeszutek Wilk 	    || value == PCI_BIST_START)
25930edc14bSKonrad Rzeszutek Wilk 		err = pci_write_config_byte(dev, offset, value);
26030edc14bSKonrad Rzeszutek Wilk 
26130edc14bSKonrad Rzeszutek Wilk out:
26230edc14bSKonrad Rzeszutek Wilk 	return err;
26330edc14bSKonrad Rzeszutek Wilk }
26430edc14bSKonrad Rzeszutek Wilk 
26530edc14bSKonrad Rzeszutek Wilk static const struct config_field header_common[] = {
26630edc14bSKonrad Rzeszutek Wilk 	{
267*fd5b221bSZhao, Yu 	 .offset    = PCI_VENDOR_ID,
268*fd5b221bSZhao, Yu 	 .size      = 2,
269*fd5b221bSZhao, Yu 	 .u.w.read  = pciback_read_vendor,
270*fd5b221bSZhao, Yu 	},
271*fd5b221bSZhao, Yu 	{
272*fd5b221bSZhao, Yu 	 .offset    = PCI_DEVICE_ID,
273*fd5b221bSZhao, Yu 	 .size      = 2,
274*fd5b221bSZhao, Yu 	 .u.w.read  = pciback_read_device,
275*fd5b221bSZhao, Yu 	},
276*fd5b221bSZhao, Yu 	{
27730edc14bSKonrad Rzeszutek Wilk 	 .offset    = PCI_COMMAND,
27830edc14bSKonrad Rzeszutek Wilk 	 .size      = 2,
279*fd5b221bSZhao, Yu 	 .u.w.read  = command_read,
28030edc14bSKonrad Rzeszutek Wilk 	 .u.w.write = command_write,
28130edc14bSKonrad Rzeszutek Wilk 	},
28230edc14bSKonrad Rzeszutek Wilk 	{
28330edc14bSKonrad Rzeszutek Wilk 	 .offset    = PCI_INTERRUPT_LINE,
28430edc14bSKonrad Rzeszutek Wilk 	 .size      = 1,
28530edc14bSKonrad Rzeszutek Wilk 	 .u.b.read  = interrupt_read,
28630edc14bSKonrad Rzeszutek Wilk 	},
28730edc14bSKonrad Rzeszutek Wilk 	{
28830edc14bSKonrad Rzeszutek Wilk 	 .offset    = PCI_INTERRUPT_PIN,
28930edc14bSKonrad Rzeszutek Wilk 	 .size      = 1,
29030edc14bSKonrad Rzeszutek Wilk 	 .u.b.read  = pciback_read_config_byte,
29130edc14bSKonrad Rzeszutek Wilk 	},
29230edc14bSKonrad Rzeszutek Wilk 	{
29330edc14bSKonrad Rzeszutek Wilk 	 /* Any side effects of letting driver domain control cache line? */
29430edc14bSKonrad Rzeszutek Wilk 	 .offset    = PCI_CACHE_LINE_SIZE,
29530edc14bSKonrad Rzeszutek Wilk 	 .size      = 1,
29630edc14bSKonrad Rzeszutek Wilk 	 .u.b.read  = pciback_read_config_byte,
29730edc14bSKonrad Rzeszutek Wilk 	 .u.b.write = pciback_write_config_byte,
29830edc14bSKonrad Rzeszutek Wilk 	},
29930edc14bSKonrad Rzeszutek Wilk 	{
30030edc14bSKonrad Rzeszutek Wilk 	 .offset    = PCI_LATENCY_TIMER,
30130edc14bSKonrad Rzeszutek Wilk 	 .size      = 1,
30230edc14bSKonrad Rzeszutek Wilk 	 .u.b.read  = pciback_read_config_byte,
30330edc14bSKonrad Rzeszutek Wilk 	},
30430edc14bSKonrad Rzeszutek Wilk 	{
30530edc14bSKonrad Rzeszutek Wilk 	 .offset    = PCI_BIST,
30630edc14bSKonrad Rzeszutek Wilk 	 .size      = 1,
30730edc14bSKonrad Rzeszutek Wilk 	 .u.b.read  = pciback_read_config_byte,
30830edc14bSKonrad Rzeszutek Wilk 	 .u.b.write = bist_write,
30930edc14bSKonrad Rzeszutek Wilk 	},
31030edc14bSKonrad Rzeszutek Wilk 	{}
31130edc14bSKonrad Rzeszutek Wilk };
31230edc14bSKonrad Rzeszutek Wilk 
31330edc14bSKonrad Rzeszutek Wilk #define CFG_FIELD_BAR(reg_offset)			\
31430edc14bSKonrad Rzeszutek Wilk 	{						\
31530edc14bSKonrad Rzeszutek Wilk 	.offset     = reg_offset,			\
31630edc14bSKonrad Rzeszutek Wilk 	.size       = 4,				\
31730edc14bSKonrad Rzeszutek Wilk 	.init       = bar_init,				\
31830edc14bSKonrad Rzeszutek Wilk 	.reset      = bar_reset,			\
31930edc14bSKonrad Rzeszutek Wilk 	.release    = bar_release,			\
32030edc14bSKonrad Rzeszutek Wilk 	.u.dw.read  = bar_read,				\
32130edc14bSKonrad Rzeszutek Wilk 	.u.dw.write = bar_write,			\
32230edc14bSKonrad Rzeszutek Wilk 	}
32330edc14bSKonrad Rzeszutek Wilk 
32430edc14bSKonrad Rzeszutek Wilk #define CFG_FIELD_ROM(reg_offset)			\
32530edc14bSKonrad Rzeszutek Wilk 	{						\
32630edc14bSKonrad Rzeszutek Wilk 	.offset     = reg_offset,			\
32730edc14bSKonrad Rzeszutek Wilk 	.size       = 4,				\
32830edc14bSKonrad Rzeszutek Wilk 	.init       = rom_init,				\
32930edc14bSKonrad Rzeszutek Wilk 	.reset      = bar_reset,			\
33030edc14bSKonrad Rzeszutek Wilk 	.release    = bar_release,			\
33130edc14bSKonrad Rzeszutek Wilk 	.u.dw.read  = bar_read,				\
33230edc14bSKonrad Rzeszutek Wilk 	.u.dw.write = rom_write,			\
33330edc14bSKonrad Rzeszutek Wilk 	}
33430edc14bSKonrad Rzeszutek Wilk 
33530edc14bSKonrad Rzeszutek Wilk static const struct config_field header_0[] = {
33630edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
33730edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
33830edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_2),
33930edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_3),
34030edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_4),
34130edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_5),
34230edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_ROM(PCI_ROM_ADDRESS),
34330edc14bSKonrad Rzeszutek Wilk 	{}
34430edc14bSKonrad Rzeszutek Wilk };
34530edc14bSKonrad Rzeszutek Wilk 
34630edc14bSKonrad Rzeszutek Wilk static const struct config_field header_1[] = {
34730edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_0),
34830edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_BAR(PCI_BASE_ADDRESS_1),
34930edc14bSKonrad Rzeszutek Wilk 	CFG_FIELD_ROM(PCI_ROM_ADDRESS1),
35030edc14bSKonrad Rzeszutek Wilk 	{}
35130edc14bSKonrad Rzeszutek Wilk };
35230edc14bSKonrad Rzeszutek Wilk 
35330edc14bSKonrad Rzeszutek Wilk int pciback_config_header_add_fields(struct pci_dev *dev)
35430edc14bSKonrad Rzeszutek Wilk {
35530edc14bSKonrad Rzeszutek Wilk 	int err;
35630edc14bSKonrad Rzeszutek Wilk 
35730edc14bSKonrad Rzeszutek Wilk 	err = pciback_config_add_fields(dev, header_common);
35830edc14bSKonrad Rzeszutek Wilk 	if (err)
35930edc14bSKonrad Rzeszutek Wilk 		goto out;
36030edc14bSKonrad Rzeszutek Wilk 
36130edc14bSKonrad Rzeszutek Wilk 	switch (dev->hdr_type) {
36230edc14bSKonrad Rzeszutek Wilk 	case PCI_HEADER_TYPE_NORMAL:
36330edc14bSKonrad Rzeszutek Wilk 		err = pciback_config_add_fields(dev, header_0);
36430edc14bSKonrad Rzeszutek Wilk 		break;
36530edc14bSKonrad Rzeszutek Wilk 
36630edc14bSKonrad Rzeszutek Wilk 	case PCI_HEADER_TYPE_BRIDGE:
36730edc14bSKonrad Rzeszutek Wilk 		err = pciback_config_add_fields(dev, header_1);
36830edc14bSKonrad Rzeszutek Wilk 		break;
36930edc14bSKonrad Rzeszutek Wilk 
37030edc14bSKonrad Rzeszutek Wilk 	default:
37130edc14bSKonrad Rzeszutek Wilk 		err = -EINVAL;
37230edc14bSKonrad Rzeszutek Wilk 		printk(KERN_ERR "pciback: %s: Unsupported header type %d!\n",
37330edc14bSKonrad Rzeszutek Wilk 		       pci_name(dev), dev->hdr_type);
37430edc14bSKonrad Rzeszutek Wilk 		break;
37530edc14bSKonrad Rzeszutek Wilk 	}
37630edc14bSKonrad Rzeszutek Wilk 
37730edc14bSKonrad Rzeszutek Wilk out:
37830edc14bSKonrad Rzeszutek Wilk 	return err;
37930edc14bSKonrad Rzeszutek Wilk }
380