Skip to content

Commit 74e8ee8

Browse files
committed
Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull Intel SoC changes from Ingo Molnar: "Improved Intel SoC platform support" * 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, tsc, apic: Unbreak static (MSR) calibration when CONFIG_X86_LOCAL_APIC=n x86, tsc: Add static (MSR) TSC calibration on Intel Atom SoCs arch: x86: New MailBox support driver for Intel SOC's
2 parents 8bd6964 + ca1e631 commit 74e8ee8

File tree

7 files changed

+466
-1
lines changed

7 files changed

+466
-1
lines changed

arch/x86/Kconfig

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2358,6 +2358,14 @@ config X86_DMA_REMAP
23582358
bool
23592359
depends on STA2X11
23602360

2361+
config IOSF_MBI
2362+
bool
2363+
depends on PCI
2364+
---help---
2365+
To be selected by modules requiring access to the Intel OnChip System
2366+
Fabric (IOSF) Sideband MailBox Interface (MBI). For MBI platforms
2367+
enumerable by PCI.
2368+
23612369
source "net/Kconfig"
23622370

23632371
source "drivers/Kconfig"

arch/x86/include/asm/iosf_mbi.h

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
/*
2+
* iosf_mbi.h: Intel OnChip System Fabric MailBox access support
3+
*/
4+
5+
#ifndef IOSF_MBI_SYMS_H
6+
#define IOSF_MBI_SYMS_H
7+
8+
#define MBI_MCR_OFFSET 0xD0
9+
#define MBI_MDR_OFFSET 0xD4
10+
#define MBI_MCRX_OFFSET 0xD8
11+
12+
#define MBI_RD_MASK 0xFEFFFFFF
13+
#define MBI_WR_MASK 0X01000000
14+
15+
#define MBI_MASK_HI 0xFFFFFF00
16+
#define MBI_MASK_LO 0x000000FF
17+
#define MBI_ENABLE 0xF0
18+
19+
/* Baytrail available units */
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+
/* Baytrail 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+
* iosf_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+
*/
63+
int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr);
64+
65+
/**
66+
* iosf_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+
*/
75+
int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr);
76+
77+
/**
78+
* iosf_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+
*/
88+
int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask);
89+
90+
#endif /* IOSF_MBI_SYMS_H */

arch/x86/include/asm/tsc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,7 @@ extern int notsc_setup(char *);
6565
extern void tsc_save_sched_clock_state(void);
6666
extern void tsc_restore_sched_clock_state(void);
6767

68+
/* MSR based TSC calibration for Intel Atom SoC platforms */
69+
int try_msr_calibrate_tsc(unsigned long *fast_calibrate);
70+
6871
#endif /* _ASM_X86_TSC_H */

arch/x86/kernel/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ obj-$(CONFIG_SYSFS) += ksysfs.o
3333
obj-y += bootflag.o e820.o
3434
obj-y += pci-dma.o quirks.o topology.o kdebugfs.o
3535
obj-y += alternative.o i8253.o pci-nommu.o hw_breakpoint.o
36-
obj-y += tsc.o io_delay.o rtc.o
36+
obj-y += tsc.o tsc_msr.o io_delay.o rtc.o
3737
obj-y += pci-iommu_table.o
3838
obj-y += resource.o
3939

@@ -103,6 +103,7 @@ obj-$(CONFIG_EFI) += sysfb_efi.o
103103

104104
obj-$(CONFIG_PERF_EVENTS) += perf_regs.o
105105
obj-$(CONFIG_TRACING) += tracepoint.o
106+
obj-$(CONFIG_IOSF_MBI) += iosf_mbi.o
106107

107108
###
108109
# 64 bit specific files

arch/x86/kernel/iosf_mbi.c

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
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+
static DEFINE_SPINLOCK(iosf_mbi_lock);
29+
30+
static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset)
31+
{
32+
return (op << 24) | (port << 16) | (offset << 8) | MBI_ENABLE;
33+
}
34+
35+
static struct pci_dev *mbi_pdev; /* one mbi device */
36+
37+
static 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, MBI_MCRX_OFFSET,
46+
mcrx);
47+
if (result < 0)
48+
goto fail_read;
49+
}
50+
51+
result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr);
52+
if (result < 0)
53+
goto fail_read;
54+
55+
result = pci_read_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr);
56+
if (result < 0)
57+
goto fail_read;
58+
59+
return 0;
60+
61+
fail_read:
62+
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
63+
return result;
64+
}
65+
66+
static int iosf_mbi_pci_write_mdr(u32 mcrx, u32 mcr, u32 mdr)
67+
{
68+
int result;
69+
70+
if (!mbi_pdev)
71+
return -ENODEV;
72+
73+
result = pci_write_config_dword(mbi_pdev, MBI_MDR_OFFSET, mdr);
74+
if (result < 0)
75+
goto fail_write;
76+
77+
if (mcrx) {
78+
result = pci_write_config_dword(mbi_pdev, MBI_MCRX_OFFSET,
79+
mcrx);
80+
if (result < 0)
81+
goto fail_write;
82+
}
83+
84+
result = pci_write_config_dword(mbi_pdev, MBI_MCR_OFFSET, mcr);
85+
if (result < 0)
86+
goto fail_write;
87+
88+
return 0;
89+
90+
fail_write:
91+
dev_err(&mbi_pdev->dev, "PCI config access failed with %d\n", result);
92+
return result;
93+
}
94+
95+
int iosf_mbi_read(u8 port, u8 opcode, u32 offset, u32 *mdr)
96+
{
97+
u32 mcr, mcrx;
98+
unsigned long flags;
99+
int ret;
100+
101+
/*Access to the GFX unit is handled by GPU code */
102+
if (port == BT_MBI_UNIT_GFX) {
103+
WARN_ON(1);
104+
return -EPERM;
105+
}
106+
107+
mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
108+
mcrx = offset & MBI_MASK_HI;
109+
110+
spin_lock_irqsave(&iosf_mbi_lock, flags);
111+
ret = iosf_mbi_pci_read_mdr(mcrx, mcr, mdr);
112+
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
113+
114+
return ret;
115+
}
116+
EXPORT_SYMBOL(iosf_mbi_read);
117+
118+
int iosf_mbi_write(u8 port, u8 opcode, u32 offset, u32 mdr)
119+
{
120+
u32 mcr, mcrx;
121+
unsigned long flags;
122+
int ret;
123+
124+
/*Access to the GFX unit is handled by GPU code */
125+
if (port == BT_MBI_UNIT_GFX) {
126+
WARN_ON(1);
127+
return -EPERM;
128+
}
129+
130+
mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
131+
mcrx = offset & MBI_MASK_HI;
132+
133+
spin_lock_irqsave(&iosf_mbi_lock, flags);
134+
ret = iosf_mbi_pci_write_mdr(mcrx, mcr, mdr);
135+
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
136+
137+
return ret;
138+
}
139+
EXPORT_SYMBOL(iosf_mbi_write);
140+
141+
int iosf_mbi_modify(u8 port, u8 opcode, u32 offset, u32 mdr, u32 mask)
142+
{
143+
u32 mcr, mcrx;
144+
u32 value;
145+
unsigned long flags;
146+
int ret;
147+
148+
/*Access to the GFX unit is handled by GPU code */
149+
if (port == BT_MBI_UNIT_GFX) {
150+
WARN_ON(1);
151+
return -EPERM;
152+
}
153+
154+
mcr = iosf_mbi_form_mcr(opcode, port, offset & MBI_MASK_LO);
155+
mcrx = offset & MBI_MASK_HI;
156+
157+
spin_lock_irqsave(&iosf_mbi_lock, flags);
158+
159+
/* Read current mdr value */
160+
ret = iosf_mbi_pci_read_mdr(mcrx, mcr & MBI_RD_MASK, &value);
161+
if (ret < 0) {
162+
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
163+
return ret;
164+
}
165+
166+
/* Apply mask */
167+
value &= ~mask;
168+
mdr &= mask;
169+
value |= mdr;
170+
171+
/* Write back */
172+
ret = iosf_mbi_pci_write_mdr(mcrx, mcr | MBI_WR_MASK, value);
173+
174+
spin_unlock_irqrestore(&iosf_mbi_lock, flags);
175+
176+
return ret;
177+
}
178+
EXPORT_SYMBOL(iosf_mbi_modify);
179+
180+
static int iosf_mbi_probe(struct pci_dev *pdev,
181+
const struct pci_device_id *unused)
182+
{
183+
int ret;
184+
185+
ret = pci_enable_device(pdev);
186+
if (ret < 0) {
187+
dev_err(&pdev->dev, "error: could not enable device\n");
188+
return ret;
189+
}
190+
191+
mbi_pdev = pci_dev_get(pdev);
192+
return 0;
193+
}
194+
195+
static DEFINE_PCI_DEVICE_TABLE(iosf_mbi_pci_ids) = {
196+
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0F00) },
197+
{ 0, },
198+
};
199+
MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids);
200+
201+
static struct pci_driver iosf_mbi_pci_driver = {
202+
.name = "iosf_mbi_pci",
203+
.probe = iosf_mbi_probe,
204+
.id_table = iosf_mbi_pci_ids,
205+
};
206+
207+
static int __init iosf_mbi_init(void)
208+
{
209+
return pci_register_driver(&iosf_mbi_pci_driver);
210+
}
211+
212+
static void __exit iosf_mbi_exit(void)
213+
{
214+
pci_unregister_driver(&iosf_mbi_pci_driver);
215+
if (mbi_pdev) {
216+
pci_dev_put(mbi_pdev);
217+
mbi_pdev = NULL;
218+
}
219+
}
220+
221+
module_init(iosf_mbi_init);
222+
module_exit(iosf_mbi_exit);
223+
224+
MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
225+
MODULE_DESCRIPTION("IOSF Mailbox Interface accessor");
226+
MODULE_LICENSE("GPL v2");

arch/x86/kernel/tsc.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,16 @@ unsigned long native_calibrate_tsc(void)
651651
unsigned long flags, latch, ms, fast_calibrate;
652652
int hpet = is_hpet_enabled(), i, loopmin;
653653

654+
/* Calibrate TSC using MSR for Intel Atom SoCs */
655+
local_irq_save(flags);
656+
i = try_msr_calibrate_tsc(&fast_calibrate);
657+
local_irq_restore(flags);
658+
if (i >= 0) {
659+
if (i == 0)
660+
pr_warn("Fast TSC calibration using MSR failed\n");
661+
return fast_calibrate;
662+
}
663+
654664
local_irq_save(flags);
655665
fast_calibrate = quick_pit_calibrate();
656666
local_irq_restore(flags);

0 commit comments

Comments
 (0)