diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2015-02-02 15:49:29 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2015-02-02 15:49:29 -0500 |
commit | 2cd59deaefbc5fb88e6e232664377a02ca3122ed (patch) | |
tree | df886f88d157af744e9d2781628ad3318a05abcf /arch/arm | |
parent | 341f3a2bcfa25462b55ec72939fd21692fa0d7c9 (diff) | |
parent | 029e2151fc4a5760b4ab963d7613f8603084232a (diff) |
Merge branch 'pci/config' into next
* pci/config:
PCI: xilinx: Convert to use generic config accessors
PCI: xgene: Convert to use generic config accessors
PCI: tegra: Convert to use generic config accessors
PCI: rcar: Convert to use generic config accessors
PCI: generic: Convert to use generic config accessors
powerpc/powermac: Convert PCI to use generic config accessors
powerpc/fsl_pci: Convert PCI to use generic config accessors
ARM: ks8695: Convert PCI to use generic config accessors
ARM: sa1100: Convert PCI to use generic config accessors
ARM: integrator: Convert PCI to use generic config accessors
ARM: cns3xxx: Convert PCI to use generic config accessors
PCI: Add generic config accessors
powerpc/PCI: Add struct pci_ops member names to initialization
mn10300/PCI: Add struct pci_ops member names to initialization
MIPS: PCI: Add struct pci_ops member names to initialization
frv/PCI: Add struct pci_ops member names to initialization
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-cns3xxx/pcie.c | 52 | ||||
-rw-r--r-- | arch/arm/mach-integrator/pci_v3.c | 62 | ||||
-rw-r--r-- | arch/arm/mach-ks8695/pci.c | 77 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/pci-nanoengine.c | 94 |
4 files changed, 29 insertions, 256 deletions
diff --git a/arch/arm/mach-cns3xxx/pcie.c b/arch/arm/mach-cns3xxx/pcie.c index f6bf9f623d70..c622c306c390 100644 --- a/arch/arm/mach-cns3xxx/pcie.c +++ b/arch/arm/mach-cns3xxx/pcie.c | |||
@@ -51,8 +51,8 @@ static struct cns3xxx_pcie *pbus_to_cnspci(struct pci_bus *bus) | |||
51 | return sysdata_to_cnspci(bus->sysdata); | 51 | return sysdata_to_cnspci(bus->sysdata); |
52 | } | 52 | } |
53 | 53 | ||
54 | static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus, | 54 | static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus, |
55 | unsigned int devfn, int where) | 55 | unsigned int devfn, int where) |
56 | { | 56 | { |
57 | struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus); | 57 | struct cns3xxx_pcie *cnspci = pbus_to_cnspci(bus); |
58 | int busno = bus->number; | 58 | int busno = bus->number; |
@@ -88,55 +88,22 @@ static void __iomem *cns3xxx_pci_cfg_base(struct pci_bus *bus, | |||
88 | static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn, | 88 | static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn, |
89 | int where, int size, u32 *val) | 89 | int where, int size, u32 *val) |
90 | { | 90 | { |
91 | u32 v; | 91 | int ret; |
92 | void __iomem *base; | ||
93 | u32 mask = (0x1ull << (size * 8)) - 1; | 92 | u32 mask = (0x1ull << (size * 8)) - 1; |
94 | int shift = (where % 4) * 8; | 93 | int shift = (where % 4) * 8; |
95 | 94 | ||
96 | base = cns3xxx_pci_cfg_base(bus, devfn, where); | 95 | ret = pci_generic_config_read32(bus, devfn, where, size, val); |
97 | if (!base) { | ||
98 | *val = 0xffffffff; | ||
99 | return PCIBIOS_SUCCESSFUL; | ||
100 | } | ||
101 | |||
102 | v = __raw_readl(base); | ||
103 | 96 | ||
104 | if (bus->number == 0 && devfn == 0 && | 97 | if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn && |
105 | (where & 0xffc) == PCI_CLASS_REVISION) { | 98 | (where & 0xffc) == PCI_CLASS_REVISION) |
106 | /* | 99 | /* |
107 | * RC's class is 0xb, but Linux PCI driver needs 0x604 | 100 | * RC's class is 0xb, but Linux PCI driver needs 0x604 |
108 | * for a PCIe bridge. So we must fixup the class code | 101 | * for a PCIe bridge. So we must fixup the class code |
109 | * to 0x604 here. | 102 | * to 0x604 here. |
110 | */ | 103 | */ |
111 | v &= 0xff; | 104 | *val = ((((*val << shift) & 0xff) | (0x604 << 16)) >> shift) & mask; |
112 | v |= 0x604 << 16; | ||
113 | } | ||
114 | |||
115 | *val = (v >> shift) & mask; | ||
116 | |||
117 | return PCIBIOS_SUCCESSFUL; | ||
118 | } | ||
119 | |||
120 | static int cns3xxx_pci_write_config(struct pci_bus *bus, unsigned int devfn, | ||
121 | int where, int size, u32 val) | ||
122 | { | ||
123 | u32 v; | ||
124 | void __iomem *base; | ||
125 | u32 mask = (0x1ull << (size * 8)) - 1; | ||
126 | int shift = (where % 4) * 8; | ||
127 | |||
128 | base = cns3xxx_pci_cfg_base(bus, devfn, where); | ||
129 | if (!base) | ||
130 | return PCIBIOS_SUCCESSFUL; | ||
131 | |||
132 | v = __raw_readl(base); | ||
133 | |||
134 | v &= ~(mask << shift); | ||
135 | v |= (val & mask) << shift; | ||
136 | |||
137 | __raw_writel(v, base); | ||
138 | 105 | ||
139 | return PCIBIOS_SUCCESSFUL; | 106 | return ret; |
140 | } | 107 | } |
141 | 108 | ||
142 | static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys) | 109 | static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys) |
@@ -155,8 +122,9 @@ static int cns3xxx_pci_setup(int nr, struct pci_sys_data *sys) | |||
155 | } | 122 | } |
156 | 123 | ||
157 | static struct pci_ops cns3xxx_pcie_ops = { | 124 | static struct pci_ops cns3xxx_pcie_ops = { |
125 | .map_bus = cns3xxx_pci_map_bus, | ||
158 | .read = cns3xxx_pci_read_config, | 126 | .read = cns3xxx_pci_read_config, |
159 | .write = cns3xxx_pci_write_config, | 127 | .write = pci_generic_config_write, |
160 | }; | 128 | }; |
161 | 129 | ||
162 | static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | 130 | static int cns3xxx_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) |
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c index c186a17c2cff..2565f0e7b5cf 100644 --- a/arch/arm/mach-integrator/pci_v3.c +++ b/arch/arm/mach-integrator/pci_v3.c | |||
@@ -356,7 +356,6 @@ static u64 pre_mem_pci_sz; | |||
356 | * 7:2 register number | 356 | * 7:2 register number |
357 | * | 357 | * |
358 | */ | 358 | */ |
359 | static DEFINE_RAW_SPINLOCK(v3_lock); | ||
360 | 359 | ||
361 | #undef V3_LB_BASE_PREFETCH | 360 | #undef V3_LB_BASE_PREFETCH |
362 | #define V3_LB_BASE_PREFETCH 0 | 361 | #define V3_LB_BASE_PREFETCH 0 |
@@ -457,67 +456,21 @@ static void v3_close_config_window(void) | |||
457 | static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where, | 456 | static int v3_read_config(struct pci_bus *bus, unsigned int devfn, int where, |
458 | int size, u32 *val) | 457 | int size, u32 *val) |
459 | { | 458 | { |
460 | void __iomem *addr; | 459 | int ret = pci_generic_config_read(bus, devfn, where, size, val); |
461 | unsigned long flags; | ||
462 | u32 v; | ||
463 | |||
464 | raw_spin_lock_irqsave(&v3_lock, flags); | ||
465 | addr = v3_open_config_window(bus, devfn, where); | ||
466 | |||
467 | switch (size) { | ||
468 | case 1: | ||
469 | v = __raw_readb(addr); | ||
470 | break; | ||
471 | |||
472 | case 2: | ||
473 | v = __raw_readw(addr); | ||
474 | break; | ||
475 | |||
476 | default: | ||
477 | v = __raw_readl(addr); | ||
478 | break; | ||
479 | } | ||
480 | |||
481 | v3_close_config_window(); | 460 | v3_close_config_window(); |
482 | raw_spin_unlock_irqrestore(&v3_lock, flags); | 461 | return ret; |
483 | |||
484 | *val = v; | ||
485 | return PCIBIOS_SUCCESSFUL; | ||
486 | } | 462 | } |
487 | 463 | ||
488 | static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where, | 464 | static int v3_write_config(struct pci_bus *bus, unsigned int devfn, int where, |
489 | int size, u32 val) | 465 | int size, u32 val) |
490 | { | 466 | { |
491 | void __iomem *addr; | 467 | int ret = pci_generic_config_write(bus, devfn, where, size, val); |
492 | unsigned long flags; | ||
493 | |||
494 | raw_spin_lock_irqsave(&v3_lock, flags); | ||
495 | addr = v3_open_config_window(bus, devfn, where); | ||
496 | |||
497 | switch (size) { | ||
498 | case 1: | ||
499 | __raw_writeb((u8)val, addr); | ||
500 | __raw_readb(addr); | ||
501 | break; | ||
502 | |||
503 | case 2: | ||
504 | __raw_writew((u16)val, addr); | ||
505 | __raw_readw(addr); | ||
506 | break; | ||
507 | |||
508 | case 4: | ||
509 | __raw_writel(val, addr); | ||
510 | __raw_readl(addr); | ||
511 | break; | ||
512 | } | ||
513 | |||
514 | v3_close_config_window(); | 468 | v3_close_config_window(); |
515 | raw_spin_unlock_irqrestore(&v3_lock, flags); | 469 | return ret; |
516 | |||
517 | return PCIBIOS_SUCCESSFUL; | ||
518 | } | 470 | } |
519 | 471 | ||
520 | static struct pci_ops pci_v3_ops = { | 472 | static struct pci_ops pci_v3_ops = { |
473 | .map_bus = v3_open_config_window, | ||
521 | .read = v3_read_config, | 474 | .read = v3_read_config, |
522 | .write = v3_write_config, | 475 | .write = v3_write_config, |
523 | }; | 476 | }; |
@@ -658,7 +611,6 @@ static int __init pci_v3_setup(int nr, struct pci_sys_data *sys) | |||
658 | */ | 611 | */ |
659 | static void __init pci_v3_preinit(void) | 612 | static void __init pci_v3_preinit(void) |
660 | { | 613 | { |
661 | unsigned long flags; | ||
662 | unsigned int temp; | 614 | unsigned int temp; |
663 | phys_addr_t io_address = pci_pio_to_address(io_mem.start); | 615 | phys_addr_t io_address = pci_pio_to_address(io_mem.start); |
664 | 616 | ||
@@ -672,8 +624,6 @@ static void __init pci_v3_preinit(void) | |||
672 | hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); | 624 | hook_fault_code(8, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); |
673 | hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); | 625 | hook_fault_code(10, v3_pci_fault, SIGBUS, 0, "external abort on non-linefetch"); |
674 | 626 | ||
675 | raw_spin_lock_irqsave(&v3_lock, flags); | ||
676 | |||
677 | /* | 627 | /* |
678 | * Unlock V3 registers, but only if they were previously locked. | 628 | * Unlock V3 registers, but only if they were previously locked. |
679 | */ | 629 | */ |
@@ -736,8 +686,6 @@ static void __init pci_v3_preinit(void) | |||
736 | v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10)); | 686 | v3_writew(V3_LB_CFG, v3_readw(V3_LB_CFG) | (1 << 10)); |
737 | v3_writeb(V3_LB_IMASK, 0x28); | 687 | v3_writeb(V3_LB_IMASK, 0x28); |
738 | __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); | 688 | __raw_writel(3, ap_syscon_base + INTEGRATOR_SC_PCIENABLE_OFFSET); |
739 | |||
740 | raw_spin_unlock_irqrestore(&v3_lock, flags); | ||
741 | } | 689 | } |
742 | 690 | ||
743 | static void __init pci_v3_postinit(void) | 691 | static void __init pci_v3_postinit(void) |
diff --git a/arch/arm/mach-ks8695/pci.c b/arch/arm/mach-ks8695/pci.c index bb18193b4bac..c1bc4c3716ed 100644 --- a/arch/arm/mach-ks8695/pci.c +++ b/arch/arm/mach-ks8695/pci.c | |||
@@ -38,8 +38,6 @@ | |||
38 | 38 | ||
39 | 39 | ||
40 | static int pci_dbg; | 40 | static int pci_dbg; |
41 | static int pci_cfg_dbg; | ||
42 | |||
43 | 41 | ||
44 | static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where) | 42 | static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsigned int where) |
45 | { | 43 | { |
@@ -59,75 +57,11 @@ static void ks8695_pci_setupconfig(unsigned int bus_nr, unsigned int devfn, unsi | |||
59 | } | 57 | } |
60 | } | 58 | } |
61 | 59 | ||
62 | 60 | static void __iomem *ks8695_pci_map_bus(struct pci_bus *bus, unsigned int devfn, | |
63 | /* | 61 | int where) |
64 | * The KS8695 datasheet prohibits anything other than 32bit accesses | ||
65 | * to the IO registers, so all our configuration must be done with | ||
66 | * 32bit operations, and the correct bit masking and shifting. | ||
67 | */ | ||
68 | |||
69 | static int ks8695_pci_readconfig(struct pci_bus *bus, | ||
70 | unsigned int devfn, int where, int size, u32 *value) | ||
71 | { | ||
72 | ks8695_pci_setupconfig(bus->number, devfn, where); | ||
73 | |||
74 | *value = __raw_readl(KS8695_PCI_VA + KS8695_PBCD); | ||
75 | |||
76 | switch (size) { | ||
77 | case 4: | ||
78 | break; | ||
79 | case 2: | ||
80 | *value = *value >> ((where & 2) * 8); | ||
81 | *value &= 0xffff; | ||
82 | break; | ||
83 | case 1: | ||
84 | *value = *value >> ((where & 3) * 8); | ||
85 | *value &= 0xff; | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | if (pci_cfg_dbg) { | ||
90 | printk("read: %d,%08x,%02x,%d: %08x (%08x)\n", | ||
91 | bus->number, devfn, where, size, *value, | ||
92 | __raw_readl(KS8695_PCI_VA + KS8695_PBCD)); | ||
93 | } | ||
94 | |||
95 | return PCIBIOS_SUCCESSFUL; | ||
96 | } | ||
97 | |||
98 | static int ks8695_pci_writeconfig(struct pci_bus *bus, | ||
99 | unsigned int devfn, int where, int size, u32 value) | ||
100 | { | 62 | { |
101 | unsigned long tmp; | ||
102 | |||
103 | if (pci_cfg_dbg) { | ||
104 | printk("write: %d,%08x,%02x,%d: %08x\n", | ||
105 | bus->number, devfn, where, size, value); | ||
106 | } | ||
107 | |||
108 | ks8695_pci_setupconfig(bus->number, devfn, where); | 63 | ks8695_pci_setupconfig(bus->number, devfn, where); |
109 | 64 | return KS8695_PCI_VA + KS8695_PBCD; | |
110 | switch (size) { | ||
111 | case 4: | ||
112 | __raw_writel(value, KS8695_PCI_VA + KS8695_PBCD); | ||
113 | break; | ||
114 | case 2: | ||
115 | tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD); | ||
116 | tmp &= ~(0xffff << ((where & 2) * 8)); | ||
117 | tmp |= value << ((where & 2) * 8); | ||
118 | |||
119 | __raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD); | ||
120 | break; | ||
121 | case 1: | ||
122 | tmp = __raw_readl(KS8695_PCI_VA + KS8695_PBCD); | ||
123 | tmp &= ~(0xff << ((where & 3) * 8)); | ||
124 | tmp |= value << ((where & 3) * 8); | ||
125 | |||
126 | __raw_writel(tmp, KS8695_PCI_VA + KS8695_PBCD); | ||
127 | break; | ||
128 | } | ||
129 | |||
130 | return PCIBIOS_SUCCESSFUL; | ||
131 | } | 65 | } |
132 | 66 | ||
133 | static void ks8695_local_writeconfig(int where, u32 value) | 67 | static void ks8695_local_writeconfig(int where, u32 value) |
@@ -137,8 +71,9 @@ static void ks8695_local_writeconfig(int where, u32 value) | |||
137 | } | 71 | } |
138 | 72 | ||
139 | static struct pci_ops ks8695_pci_ops = { | 73 | static struct pci_ops ks8695_pci_ops = { |
140 | .read = ks8695_pci_readconfig, | 74 | .map_bus = ks8695_pci_map_bus, |
141 | .write = ks8695_pci_writeconfig, | 75 | .read = pci_generic_config_read32, |
76 | .write = pci_generic_config_write32, | ||
142 | }; | 77 | }; |
143 | 78 | ||
144 | static struct resource pci_mem = { | 79 | static struct resource pci_mem = { |
diff --git a/arch/arm/mach-sa1100/pci-nanoengine.c b/arch/arm/mach-sa1100/pci-nanoengine.c index b704433c529c..d7ae8d50f6d8 100644 --- a/arch/arm/mach-sa1100/pci-nanoengine.c +++ b/arch/arm/mach-sa1100/pci-nanoengine.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/pci.h> | 24 | #include <linux/pci.h> |
25 | #include <linux/spinlock.h> | ||
26 | 25 | ||
27 | #include <asm/mach/pci.h> | 26 | #include <asm/mach/pci.h> |
28 | #include <asm/mach-types.h> | 27 | #include <asm/mach-types.h> |
@@ -30,97 +29,20 @@ | |||
30 | #include <mach/nanoengine.h> | 29 | #include <mach/nanoengine.h> |
31 | #include <mach/hardware.h> | 30 | #include <mach/hardware.h> |
32 | 31 | ||
33 | static DEFINE_SPINLOCK(nano_lock); | 32 | static void __iomem *nanoengine_pci_map_bus(struct pci_bus *bus, |
34 | 33 | unsigned int devfn, int where) | |
35 | static int nanoengine_get_pci_address(struct pci_bus *bus, | ||
36 | unsigned int devfn, int where, void __iomem **address) | ||
37 | { | 34 | { |
38 | int ret = PCIBIOS_DEVICE_NOT_FOUND; | 35 | if (bus->number != 0 || (devfn >> 3) != 0) |
39 | unsigned int busnr = bus->number; | 36 | return NULL; |
40 | 37 | ||
41 | *address = (void __iomem *)NANO_PCI_CONFIG_SPACE_VIRT + | 38 | return (void __iomem *)NANO_PCI_CONFIG_SPACE_VIRT + |
42 | ((bus->number << 16) | (devfn << 8) | (where & ~3)); | 39 | ((bus->number << 16) | (devfn << 8) | (where & ~3)); |
43 | |||
44 | ret = (busnr > 255 || devfn > 255 || where > 255) ? | ||
45 | PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; | ||
46 | |||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static int nanoengine_read_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
51 | int size, u32 *val) | ||
52 | { | ||
53 | int ret; | ||
54 | void __iomem *address; | ||
55 | unsigned long flags; | ||
56 | u32 v; | ||
57 | |||
58 | /* nanoEngine PCI bridge does not return -1 for a non-existing | ||
59 | * device. We must fake the answer. We know that the only valid | ||
60 | * device is device zero at bus 0, which is the network chip. */ | ||
61 | if (bus->number != 0 || (devfn >> 3) != 0) { | ||
62 | v = -1; | ||
63 | nanoengine_get_pci_address(bus, devfn, where, &address); | ||
64 | goto exit_function; | ||
65 | } | ||
66 | |||
67 | spin_lock_irqsave(&nano_lock, flags); | ||
68 | |||
69 | ret = nanoengine_get_pci_address(bus, devfn, where, &address); | ||
70 | if (ret != PCIBIOS_SUCCESSFUL) | ||
71 | return ret; | ||
72 | v = __raw_readl(address); | ||
73 | |||
74 | spin_unlock_irqrestore(&nano_lock, flags); | ||
75 | |||
76 | v >>= ((where & 3) * 8); | ||
77 | v &= (unsigned long)(-1) >> ((4 - size) * 8); | ||
78 | |||
79 | exit_function: | ||
80 | *val = v; | ||
81 | return PCIBIOS_SUCCESSFUL; | ||
82 | } | ||
83 | |||
84 | static int nanoengine_write_config(struct pci_bus *bus, unsigned int devfn, int where, | ||
85 | int size, u32 val) | ||
86 | { | ||
87 | int ret; | ||
88 | void __iomem *address; | ||
89 | unsigned long flags; | ||
90 | unsigned shift; | ||
91 | u32 v; | ||
92 | |||
93 | shift = (where & 3) * 8; | ||
94 | |||
95 | spin_lock_irqsave(&nano_lock, flags); | ||
96 | |||
97 | ret = nanoengine_get_pci_address(bus, devfn, where, &address); | ||
98 | if (ret != PCIBIOS_SUCCESSFUL) | ||
99 | return ret; | ||
100 | v = __raw_readl(address); | ||
101 | switch (size) { | ||
102 | case 1: | ||
103 | v &= ~(0xFF << shift); | ||
104 | v |= val << shift; | ||
105 | break; | ||
106 | case 2: | ||
107 | v &= ~(0xFFFF << shift); | ||
108 | v |= val << shift; | ||
109 | break; | ||
110 | case 4: | ||
111 | v = val; | ||
112 | break; | ||
113 | } | ||
114 | __raw_writel(v, address); | ||
115 | |||
116 | spin_unlock_irqrestore(&nano_lock, flags); | ||
117 | |||
118 | return PCIBIOS_SUCCESSFUL; | ||
119 | } | 40 | } |
120 | 41 | ||
121 | static struct pci_ops pci_nano_ops = { | 42 | static struct pci_ops pci_nano_ops = { |
122 | .read = nanoengine_read_config, | 43 | .map_bus = nanoengine_pci_map_bus, |
123 | .write = nanoengine_write_config, | 44 | .read = pci_generic_config_read32, |
45 | .write = pci_generic_config_write32, | ||
124 | }; | 46 | }; |
125 | 47 | ||
126 | static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot, | 48 | static int __init pci_nanoengine_map_irq(const struct pci_dev *dev, u8 slot, |