]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - arch/x86/kernel/iosf_mbi.c
PCI: Remove DEFINE_PCI_DEVICE_TABLE macro use
[mirror_ubuntu-bionic-kernel.git] / arch / x86 / kernel / iosf_mbi.c
1 /*
2 * IOSF-SB MailBox Interface Driver
3 * Copyright (c) 2013, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *
15 * The IOSF-SB is a fabric bus available on Atom based SOC's that uses a
16 * mailbox interface (MBI) to communicate with mutiple devices. This
17 * driver implements access to this interface for those platforms that can
18 * enumerate the device using PCI.
19 */
20
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/spinlock.h>
24 #include <linux/pci.h>
25
26 #include <asm/iosf_mbi.h>
27
28 #define PCI_DEVICE_ID_BAYTRAIL 0x0F00
29 #define PCI_DEVICE_ID_QUARK_X1000 0x0958
30
31 static DEFINE_SPINLOCK(iosf_mbi_lock);
32
33 static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset)
34 {
35 return (op << 24) | (port << 16) | (offset << 8) | MBI_ENABLE;
36 }
37
38 static struct pci_dev *mbi_pdev; /* one mbi device */
39
40 static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr)
41 {
42 int result;
43
44 if (!mbi_pdev)
45 return -ENODEV;
46
47 if (mcrx) {
48 result = pci_write_config_dword(mbi_pdev, MBI_MCRX_OFFSET,
49 mcrx);
50 if (result < 0)
51 goto fail_read;
52 }
53
54 result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr);
55 if (result < 0)
56 goto fail_read;
57
58 result = pci_read_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr);
59 if (result < 0)
60 goto fail_read;
61
62 return 0;
63
64 fail_read:
65 dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
66 return result;
67 }
68
69 static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
70 {
71 int result;
72
73 if (!mbi_pdev)
74 return -ENODEV;
75
76 result = pci_write_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr);
77 if (result < 0)
78 goto fail_write;
79
80 if (mcrx) {
81 result = pci_write_config_dword(mbi_pdev, MBI_MCRX_OFFSET,
82 mcrx);
83 if (result < 0)
84 goto fail_write;
85 }
86
87 result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr);
88 if (result < 0)
89 goto fail_write;
90
91 return 0;
92
93 fail_write:
94 dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
95 return result;
96 }
97
98 int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
99 {
100 u32 mcr, mcrx;
101 unsigned long flags;
102 int ret;
103
104 /*Access to the GFX unit is handled by GPU code */
105 if (port == BT_MBI_UNIT_GFX) {
106 WARN_ON(1);
107 return -EPERM;
108 }
109
110 mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
111 mcrx = offset & MBI_MASK_HI;
112
113 spin_lock_irqsave(&iosf_mbi_lock, flags);
114 ret = iosf_mbi_pci_read_mdr(mcrx, mcr, mdr);
115 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
116
117 return ret;
118 }
119 EXPORT_SYMBOL(iosf_mbi_read);
120
121 int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr)
122 {
123 u32 mcr, mcrx;
124 unsigned long flags;
125 int ret;
126
127 /*Access to the GFX unit is handled by GPU code */
128 if (port == BT_MBI_UNIT_GFX) {
129 WARN_ON(1);
130 return -EPERM;
131 }
132
133 mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
134 mcrx = offset & MBI_MASK_HI;
135
136 spin_lock_irqsave(&iosf_mbi_lock, flags);
137 ret = iosf_mbi_pci_write_mdr(mcrx, mcr, mdr);
138 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
139
140 return ret;
141 }
142 EXPORT_SYMBOL(iosf_mbi_write);
143
144 int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
145 {
146 u32 mcr, mcrx;
147 u32 value;
148 unsigned long flags;
149 int ret;
150
151 /*Access to the GFX unit is handled by GPU code */
152 if (port == BT_MBI_UNIT_GFX) {
153 WARN_ON(1);
154 return -EPERM;
155 }
156
157 mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
158 mcrx = offset & MBI_MASK_HI;
159
160 spin_lock_irqsave(&iosf_mbi_lock, flags);
161
162 /* Read current mdr value */
163 ret = iosf_mbi_pci_read_mdr(mcrx, mcr & MBI_RD_MASK, &value);
164 if (ret < 0) {
165 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
166 return ret;
167 }
168
169 /* Apply mask */
170 value &= ~mask;
171 mdr &= mask;
172 value |= mdr;
173
174 /* Write back */
175 ret = iosf_mbi_pci_write_mdr(mcrx, mcr | MBI_WR_MASK, value);
176
177 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
178
179 return ret;
180 }
181 EXPORT_SYMBOL(iosf_mbi_modify);
182
183 bool iosf_mbi_available(void)
184 {
185 /* Mbi isn't hot-pluggable. No remove routine is provided */
186 return mbi_pdev;
187 }
188 EXPORT_SYMBOL(iosf_mbi_available);
189
190 static int iosf_mbi_probe(struct pci_dev *pdev,
191 const struct pci_device_id *unused)
192 {
193 int ret;
194
195 ret = pci_enable_device(pdev);
196 if (ret < 0) {
197 dev_err(&pdev->dev, "error: could not enable device\n");
198 return ret;
199 }
200
201 mbi_pdev = pci_dev_get(pdev);
202 return 0;
203 }
204
205 static const struct pci_device_id iosf_mbi_pci_ids[] = {
206 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) },
207 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) },
208 { 0, },
209 };
210 MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids);
211
212 static struct pci_driver iosf_mbi_pci_driver = {
213 .name = "iosf_mbi_pci",
214 .probe = iosf_mbi_probe,
215 .id_table = iosf_mbi_pci_ids,
216 };
217
218 static int __init iosf_mbi_init(void)
219 {
220 return pci_register_driver(&iosf_mbi_pci_driver);
221 }
222
223 static void __exit iosf_mbi_exit(void)
224 {
225 pci_unregister_driver(&iosf_mbi_pci_driver);
226 if (mbi_pdev) {
227 pci_dev_put(mbi_pdev);
228 mbi_pdev = NULL;
229 }
230 }
231
232 module_init(iosf_mbi_init);
233 module_exit(iosf_mbi_exit);
234
235 MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
236 MODULE_DESCRIPTION("IOSF Mailbox Interface accessor");
237 MODULE_LICENSE("GPL v2");