aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/platform/x86/Kconfig8
-rw-r--r--drivers/platform/x86/Makefile1
-rw-r--r--drivers/platform/x86/intel_baytrail.c224
-rw-r--r--drivers/platform/x86/intel_baytrail.h90
4 files changed, 323 insertions, 0 deletions
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index d9dcd37b5a52..a698b928327d 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -808,4 +808,12 @@ config PVPANIC
808 a paravirtualized device provided by QEMU; it lets a virtual machine 808 a paravirtualized device provided by QEMU; it lets a virtual machine
809 (guest) communicate panic events to the host. 809 (guest) communicate panic events to the host.
810 810
811config INTEL_BAYTRAIL_MBI
812 tristate
813 depends on PCI
814 ---help---
815 Needed on Baytrail platforms for access to the IOSF Sideband Mailbox
816 Interface. This is a requirement for systems that need to configure
817 the PUNIT for power management features such as RAPL.
818
811endif # X86_PLATFORM_DEVICES 819endif # X86_PLATFORM_DEVICES
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index f0e6aa407ffb..79bd3c49be3d 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -54,3 +54,4 @@ obj-$(CONFIG_INTEL_RST) += intel-rst.o
54obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o 54obj-$(CONFIG_INTEL_SMARTCONNECT) += intel-smartconnect.o
55 55
56obj-$(CONFIG_PVPANIC) += pvpanic.o 56obj-$(CONFIG_PVPANIC) += pvpanic.o
57obj-$(CONFIG_INTEL_BAYTRAIL_MBI) += intel_baytrail.o
diff --git a/drivers/platform/x86/intel_baytrail.c b/drivers/platform/x86/intel_baytrail.c
new file mode 100644
index 000000000000..f96626b17260
--- /dev/null
+++ b/drivers/platform/x86/intel_baytrail.c
@@ -0,0 +1,224 @@
1/*
2 * Baytrail 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 BayTrail-specific access to this interface.
18 */
19
20#include <linux/module.h>
21#include <linux/init.h>
22#include <linux/spinlock.h>
23#include <linux/pci.h>
24
25#include "intel_baytrail.h"
26
27static DEFINE_SPINLOCK(iosf_mbi_lock);
28
29static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset)
30{
31 return (op << 24) | (port << 16) | (offset << 8) | BT_MBI_ENABLE;
32}
33
34static struct pci_dev *mbi_pdev; /* one mbi device */
35
36/* Hold lock before calling */
37static int iosf_mbi_pci_read_mdr(u32 mcrx, u32 mcr, u32 *mdr)
38{
39 int result;
40
41 if (!mbi_pdev)
42 return -ENODEV;
43
44 if (mcrx) {
45 result = pci_write_config_dword(mbi_pdev,
46 BT_MBI_MCRX_OFFSET, mcrx);
47 if (result < 0)
48 goto iosf_mbi_read_err;
49 }
50
51 result = pci_write_config_dword(mbi_pdev,
52 BT_MBI_MCR_OFFSET, mcr);
53 if (result < 0)
54 goto iosf_mbi_read_err;
55
56 result = pci_read_config_dword(mbi_pdev,
57 BT_MBI_MDR_OFFSET, mdr);
58 if (result < 0)
59 goto iosf_mbi_read_err;
60
61 return 0;
62
63iosf_mbi_read_err:
64 dev_err(&mbi_pdev->dev, "error: PCI config operation returned %d\n",
65 result);
66 return result;
67}
68
69/* Hold lock before calling */
70static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
71{
72 int result;
73
74 if (!mbi_pdev)
75 return -ENODEV;
76
77 result = pci_write_config_dword(mbi_pdev,
78 BT_MBI_MDR_OFFSET, mdr);
79 if (result < 0)
80 goto iosf_mbi_write_err;
81
82 if (mcrx) {
83 result = pci_write_config_dword(mbi_pdev,
84 BT_MBI_MCRX_OFFSET, mcrx);
85 if (result < 0)
86 goto iosf_mbi_write_err;
87 }
88
89 result = pci_write_config_dword(mbi_pdev,
90 BT_MBI_MCR_OFFSET, mcr);
91 if (result < 0)
92 goto iosf_mbi_write_err;
93
94 return 0;
95
96iosf_mbi_write_err:
97 dev_err(&mbi_pdev->dev, "error: PCI config operation returned %d\n",
98 result);
99 return result;
100}
101
102int bt_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
103{
104 u32 mcr, mcrx;
105 unsigned long flags;
106 int ret;
107
108 /*Access to the GFX unit is handled by GPU code */
109 BUG_ON(port == BT_MBI_UNIT_GFX);
110
111 mcr = iosf_mbi_form_mcr(opcode, port, offset & BT_MBI_MASK_LO);
112 mcrx = offset & BT_MBI_MASK_HI;
113
114 spin_lock_irqsave(&iosf_mbi_lock, flags);
115 ret = iosf_mbi_pci_read_mdr(mcrx, mcr, mdr);
116 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
117
118 return ret;
119}
120EXPORT_SYMBOL(bt_mbi_read);
121
122int bt_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr)
123{
124 u32 mcr, mcrx;
125 unsigned long flags;
126 int ret;
127
128 /*Access to the GFX unit is handled by GPU code */
129 BUG_ON(port == BT_MBI_UNIT_GFX);
130
131 mcr = iosf_mbi_form_mcr(opcode, port, offset & BT_MBI_MASK_LO);
132 mcrx = offset & BT_MBI_MASK_HI;
133
134 spin_lock_irqsave(&iosf_mbi_lock, flags);
135 ret = iosf_mbi_pci_write_mdr(mcrx, mcr, mdr);
136 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
137
138 return ret;
139}
140EXPORT_SYMBOL(bt_mbi_write);
141
142int bt_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
143{
144 u32 mcr, mcrx;
145 u32 value;
146 unsigned long flags;
147 int ret;
148
149 /*Access to the GFX unit is handled by GPU code */
150 BUG_ON(port == BT_MBI_UNIT_GFX);
151
152 mcr = iosf_mbi_form_mcr(opcode, port, offset & BT_MBI_MASK_LO);
153 mcrx = offset & BT_MBI_MASK_HI;
154
155 spin_lock_irqsave(&iosf_mbi_lock, flags);
156
157 /* Read current mdr value */
158 ret = iosf_mbi_pci_read_mdr(mcrx, mcr & BT_MBI_RD_MASK, &value);
159 if (ret < 0) {
160 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
161 return ret;
162 }
163
164 /* Apply mask */
165 value &= ~mask;
166 mdr &= mask;
167 value |= mdr;
168
169 /* Write back */
170 ret = iosf_mbi_pci_write_mdr(mcrx, mcr | BT_MBI_WR_MASK, value);
171
172 spin_unlock_irqrestore(&iosf_mbi_lock, flags);
173
174 return ret;
175}
176EXPORT_SYMBOL(bt_mbi_modify);
177
178static int iosf_mbi_probe(struct pci_dev *pdev,
179 const struct pci_device_id *unused)
180{
181 int ret;
182
183 ret = pci_enable_device(pdev);
184 if (ret < 0) {
185 dev_err(&pdev->dev, "error: could not enable device\n");
186 return ret;
187 }
188
189 mbi_pdev = pci_dev_get(pdev);
190 return 0;
191}
192
193static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = {
194 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) },
195 { 0, },
196};
197MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids);
198
199static struct pci_driver iosf_mbi_pci_driver = {
200 .name = "iosf_mbi_pci",
201 .probe = iosf_mbi_probe,
202 .id_table = iosf_mbi_pci_ids,
203};
204
205static int __init bt_mbi_init(void)
206{
207 return pci_register_driver(&iosf_mbi_pci_driver);
208}
209
210static void __exit bt_mbi_exit(void)
211{
212 pci_unregister_driver(&iosf_mbi_pci_driver);
213 if (mbi_pdev) {
214 pci_dev_put(mbi_pdev);
215 mbi_pdev = NULL;
216 }
217}
218
219module_init(bt_mbi_init);
220module_exit(bt_mbi_exit);
221
222MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
223MODULE_DESCRIPTION("BayTrail Mailbox Interface accessor");
224MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/intel_baytrail.h b/drivers/platform/x86/intel_baytrail.h
new file mode 100644
index 000000000000..8bcc311262e9
--- /dev/null
+++ b/drivers/platform/x86/intel_baytrail.h
@@ -0,0 +1,90 @@
1/*
2 * intel_baytrail.h: MailBox access support for Intel BayTrail platforms
3 */
4
5#ifndef INTEL_BAYTRAIL_MBI_SYMS_H
6#define INTEL_BAYTRAIL_MBI_SYMS_H
7
8#define BT_MBI_MCR_OFFSET 0xD0
9#define BT_MBI_MDR_OFFSET 0xD4
10#define BT_MBI_MCRX_OFFSET 0xD8
11
12#define BT_MBI_RD_MASK 0xFEFFFFFF
13#define BT_MBI_WR_MASK 0X01000000
14
15#define BT_MBI_MASK_HI 0xFFFFFF00
16#define BT_MBI_MASK_LO 0x000000FF
17#define BT_MBI_ENABLE 0xF0
18
19/* BT-SB unit access methods */
20#define BT_MBI_UNIT_AUNIT 0x00
21#define BT_MBI_UNIT_SMC 0x01
22#define BT_MBI_UNIT_CPU 0x02
23#define BT_MBI_UNIT_BUNIT 0x03
24#define BT_MBI_UNIT_PMC 0x04
25#define BT_MBI_UNIT_GFX 0x06
26#define BT_MBI_UNIT_SMI 0x0C
27#define BT_MBI_UNIT_USB 0x43
28#define BT_MBI_UNIT_SATA 0xA3
29#define BT_MBI_UNIT_PCIE 0xA6
30
31/* Read/write opcodes */
32#define BT_MBI_AUNIT_READ 0x10
33#define BT_MBI_AUNIT_WRITE 0x11
34#define BT_MBI_SMC_READ 0x10
35#define BT_MBI_SMC_WRITE 0x11
36#define BT_MBI_CPU_READ 0x10
37#define BT_MBI_CPU_WRITE 0x11
38#define BT_MBI_BUNIT_READ 0x10
39#define BT_MBI_BUNIT_WRITE 0x11
40#define BT_MBI_PMC_READ 0x06
41#define BT_MBI_PMC_WRITE 0x07
42#define BT_MBI_GFX_READ 0x00
43#define BT_MBI_GFX_WRITE 0x01
44#define BT_MBI_SMIO_READ 0x06
45#define BT_MBI_SMIO_WRITE 0x07
46#define BT_MBI_USB_READ 0x06
47#define BT_MBI_USB_WRITE 0x07
48#define BT_MBI_SATA_READ 0x00
49#define BT_MBI_SATA_WRITE 0x01
50#define BT_MBI_PCIE_READ 0x00
51#define BT_MBI_PCIE_WRITE 0x01
52
53/**
54 * bt_mbi_read() - MailBox Interface read command
55 * @port: port indicating subunit being accessed
56 * @opcode: port specific read or write opcode
57 * @offset: register address offset
58 * @mdr: register data to be read
59 *
60 * Locking is handled by spinlock - cannot sleep.
61 * Return: Nonzero on error
62 */
63int bt_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr);
64
65/**
66 * bt_mbi_write() - MailBox unmasked write command
67 * @port: port indicating subunit being accessed
68 * @opcode: port specific read or write opcode
69 * @offset: register address offset
70 * @mdr: register data to be written
71 *
72 * Locking is handled by spinlock - cannot sleep.
73 * Return: Nonzero on error
74 */
75int bt_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr);
76
77/**
78 * bt_mbi_modify() - MailBox masked write command
79 * @port: port indicating subunit being accessed
80 * @opcode: port specific read or write opcode
81 * @offset: register address offset
82 * @mdr: register data being modified
83 * @mask: mask indicating bits in mdr to be modified
84 *
85 * Locking is handled by spinlock - cannot sleep.
86 * Return: Nonzero on error
87 */
88int bt_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask);
89
90#endif /* INTEL_BAYTRAIL_MBI_SYMS_H */