aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 21:12:22 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-11-11 21:12:22 -0500
commitdba538ff5610ee126e33a28fe713b3f108d31f2c (patch)
treee0d8b918f5104e66791206f08e51884bc1b2a6ba /arch/x86
parent2dc1733fd4ebd4a67c9312d85f1dbc2ac2ffeb26 (diff)
parentaeeca404266c8ed2997905afc342ba9561f49ca7 (diff)
Merge branch 'x86-intel-mid-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/intel-mid changes from Ingo Molnar: "Update the 'intel mid' (mobile internet device) platform code as Intel is rolling out more SoC designs. This gets rid of most of the 'MRST' platform code in the process, mostly by renaming and shuffling code around into their respective 'intel-mid' platform drivers" * 'x86-intel-mid-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86, intel-mid: Do not re-introduce usage of obsolete __cpuinit intel_mid: Move platform device setups to their own platform_<device>.* files x86: intel-mid: Add section for sfi device table intel-mid: sfi: Allow struct devs_id.get_platform_data to be NULL intel_mid: Moved SFI related code to sfi.c intel_mid: Added custom handler for ipc devices intel_mid: Added custom device_handler support intel_mid: Refactored sfi_parse_devs() function intel_mid: Renamed *mrst* to *intel_mid* pci: intel_mid: Return true/false in function returning bool intel_mid: Renamed *mrst* to *intel_mid* mrst: Fixed indentation issues mrst: Fixed printk/pr_* related issues
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/include/asm/intel-mid.h113
-rw-r--r--arch/x86/include/asm/intel_mid_vrtc.h (renamed from arch/x86/include/asm/mrst-vrtc.h)4
-rw-r--r--arch/x86/include/asm/mrst.h81
-rw-r--r--arch/x86/include/asm/setup.h4
-rw-r--r--arch/x86/include/uapi/asm/bootparam.h2
-rw-r--r--arch/x86/kernel/apb_timer.c10
-rw-r--r--arch/x86/kernel/early_printk.c2
-rw-r--r--arch/x86/kernel/head32.c4
-rw-r--r--arch/x86/kernel/rtc.c4
-rw-r--r--arch/x86/kernel/vmlinux.lds.S9
-rw-r--r--arch/x86/pci/Makefile2
-rw-r--r--arch/x86/pci/intel_mid_pci.c (renamed from arch/x86/pci/mrst.c)20
-rw-r--r--arch/x86/platform/Makefile2
-rw-r--r--arch/x86/platform/intel-mid/Makefile7
-rw-r--r--arch/x86/platform/intel-mid/device_libs/Makefile22
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_bma023.c20
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_emc1403.c41
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c83
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_ipc.c68
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_ipc.h17
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_lis331.c39
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_max3111.c35
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_max7315.c79
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c36
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic.c87
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic.h19
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c47
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c37
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c48
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c49
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c36
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c37
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c54
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c36
-rw-r--r--arch/x86/platform/intel-mid/device_libs/platform_tca6416.c57
-rw-r--r--arch/x86/platform/intel-mid/early_printk_intel_mid.c (renamed from arch/x86/platform/mrst/early_printk_mrst.c)11
-rw-r--r--arch/x86/platform/intel-mid/intel-mid.c213
-rw-r--r--arch/x86/platform/intel-mid/intel_mid_vrtc.c (renamed from arch/x86/platform/mrst/vrtc.c)19
-rw-r--r--arch/x86/platform/intel-mid/sfi.c488
-rw-r--r--arch/x86/platform/mrst/Makefile3
-rw-r--r--arch/x86/platform/mrst/mrst.c1052
41 files changed, 1819 insertions, 1178 deletions
diff --git a/arch/x86/include/asm/intel-mid.h b/arch/x86/include/asm/intel-mid.h
new file mode 100644
index 000000000000..459769d39263
--- /dev/null
+++ b/arch/x86/include/asm/intel-mid.h
@@ -0,0 +1,113 @@
1/*
2 * intel-mid.h: Intel MID specific setup code
3 *
4 * (C) Copyright 2009 Intel Corporation
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; version 2
9 * of the License.
10 */
11#ifndef _ASM_X86_INTEL_MID_H
12#define _ASM_X86_INTEL_MID_H
13
14#include <linux/sfi.h>
15#include <linux/platform_device.h>
16
17extern int intel_mid_pci_init(void);
18extern int get_gpio_by_name(const char *name);
19extern void intel_scu_device_register(struct platform_device *pdev);
20extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
21extern int __init sfi_parse_mtmr(struct sfi_table_header *table);
22extern int sfi_mrtc_num;
23extern struct sfi_rtc_table_entry sfi_mrtc_array[];
24
25/*
26 * Here defines the array of devices platform data that IAFW would export
27 * through SFI "DEVS" table, we use name and type to match the device and
28 * its platform data.
29 */
30struct devs_id {
31 char name[SFI_NAME_LEN + 1];
32 u8 type;
33 u8 delay;
34 void *(*get_platform_data)(void *info);
35 /* Custom handler for devices */
36 void (*device_handler)(struct sfi_device_table_entry *pentry,
37 struct devs_id *dev);
38};
39
40#define sfi_device(i) \
41 static const struct devs_id *const __intel_mid_sfi_##i##_dev __used \
42 __attribute__((__section__(".x86_intel_mid_dev.init"))) = &i
43
44/*
45 * Medfield is the follow-up of Moorestown, it combines two chip solution into
46 * one. Other than that it also added always-on and constant tsc and lapic
47 * timers. Medfield is the platform name, and the chip name is called Penwell
48 * we treat Medfield/Penwell as a variant of Moorestown. Penwell can be
49 * identified via MSRs.
50 */
51enum intel_mid_cpu_type {
52 /* 1 was Moorestown */
53 INTEL_MID_CPU_CHIP_PENWELL = 2,
54};
55
56extern enum intel_mid_cpu_type __intel_mid_cpu_chip;
57
58#ifdef CONFIG_X86_INTEL_MID
59
60static inline enum intel_mid_cpu_type intel_mid_identify_cpu(void)
61{
62 return __intel_mid_cpu_chip;
63}
64
65static inline bool intel_mid_has_msic(void)
66{
67 return (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL);
68}
69
70#else /* !CONFIG_X86_INTEL_MID */
71
72#define intel_mid_identify_cpu() (0)
73#define intel_mid_has_msic() (0)
74
75#endif /* !CONFIG_X86_INTEL_MID */
76
77enum intel_mid_timer_options {
78 INTEL_MID_TIMER_DEFAULT,
79 INTEL_MID_TIMER_APBT_ONLY,
80 INTEL_MID_TIMER_LAPIC_APBT,
81};
82
83extern enum intel_mid_timer_options intel_mid_timer_options;
84
85/*
86 * Penwell uses spread spectrum clock, so the freq number is not exactly
87 * the same as reported by MSR based on SDM.
88 */
89#define PENWELL_FSB_FREQ_83SKU 83200
90#define PENWELL_FSB_FREQ_100SKU 99840
91
92#define SFI_MTMR_MAX_NUM 8
93#define SFI_MRTC_MAX 8
94
95extern struct console early_mrst_console;
96extern void mrst_early_console_init(void);
97
98extern struct console early_hsu_console;
99extern void hsu_early_console_init(const char *);
100
101extern void intel_scu_devices_create(void);
102extern void intel_scu_devices_destroy(void);
103
104/* VRTC timer */
105#define MRST_VRTC_MAP_SZ (1024)
106/*#define MRST_VRTC_PGOFFSET (0xc00) */
107
108extern void intel_mid_rtc_init(void);
109
110/* the offset for the mapping of global gpio pin to irq */
111#define INTEL_MID_IRQ_OFFSET 0x100
112
113#endif /* _ASM_X86_INTEL_MID_H */
diff --git a/arch/x86/include/asm/mrst-vrtc.h b/arch/x86/include/asm/intel_mid_vrtc.h
index 1e69a75412a4..86ff4685c409 100644
--- a/arch/x86/include/asm/mrst-vrtc.h
+++ b/arch/x86/include/asm/intel_mid_vrtc.h
@@ -1,5 +1,5 @@
1#ifndef _MRST_VRTC_H 1#ifndef _INTEL_MID_VRTC_H
2#define _MRST_VRTC_H 2#define _INTEL_MID_VRTC_H
3 3
4extern unsigned char vrtc_cmos_read(unsigned char reg); 4extern unsigned char vrtc_cmos_read(unsigned char reg);
5extern void vrtc_cmos_write(unsigned char val, unsigned char reg); 5extern void vrtc_cmos_write(unsigned char val, unsigned char reg);
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h
deleted file mode 100644
index fc18bf3ce7c8..000000000000
--- a/arch/x86/include/asm/mrst.h
+++ /dev/null
@@ -1,81 +0,0 @@
1/*
2 * mrst.h: Intel Moorestown platform specific setup code
3 *
4 * (C) Copyright 2009 Intel Corporation
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; version 2
9 * of the License.
10 */
11#ifndef _ASM_X86_MRST_H
12#define _ASM_X86_MRST_H
13
14#include <linux/sfi.h>
15
16extern int pci_mrst_init(void);
17extern int __init sfi_parse_mrtc(struct sfi_table_header *table);
18extern int sfi_mrtc_num;
19extern struct sfi_rtc_table_entry sfi_mrtc_array[];
20
21/*
22 * Medfield is the follow-up of Moorestown, it combines two chip solution into
23 * one. Other than that it also added always-on and constant tsc and lapic
24 * timers. Medfield is the platform name, and the chip name is called Penwell
25 * we treat Medfield/Penwell as a variant of Moorestown. Penwell can be
26 * identified via MSRs.
27 */
28enum mrst_cpu_type {
29 /* 1 was Moorestown */
30 MRST_CPU_CHIP_PENWELL = 2,
31};
32
33extern enum mrst_cpu_type __mrst_cpu_chip;
34
35#ifdef CONFIG_X86_INTEL_MID
36
37static inline enum mrst_cpu_type mrst_identify_cpu(void)
38{
39 return __mrst_cpu_chip;
40}
41
42#else /* !CONFIG_X86_INTEL_MID */
43
44#define mrst_identify_cpu() (0)
45
46#endif /* !CONFIG_X86_INTEL_MID */
47
48enum mrst_timer_options {
49 MRST_TIMER_DEFAULT,
50 MRST_TIMER_APBT_ONLY,
51 MRST_TIMER_LAPIC_APBT,
52};
53
54extern enum mrst_timer_options mrst_timer_options;
55
56/*
57 * Penwell uses spread spectrum clock, so the freq number is not exactly
58 * the same as reported by MSR based on SDM.
59 */
60#define PENWELL_FSB_FREQ_83SKU 83200
61#define PENWELL_FSB_FREQ_100SKU 99840
62
63#define SFI_MTMR_MAX_NUM 8
64#define SFI_MRTC_MAX 8
65
66extern struct console early_mrst_console;
67extern void mrst_early_console_init(void);
68
69extern struct console early_hsu_console;
70extern void hsu_early_console_init(const char *);
71
72extern void intel_scu_devices_create(void);
73extern void intel_scu_devices_destroy(void);
74
75/* VRTC timer */
76#define MRST_VRTC_MAP_SZ (1024)
77/*#define MRST_VRTC_PGOFFSET (0xc00) */
78
79extern void mrst_rtc_init(void);
80
81#endif /* _ASM_X86_MRST_H */
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index 347555492dad..59bcf4e22418 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -51,9 +51,9 @@ extern void i386_reserve_resources(void);
51extern void setup_default_timer_irq(void); 51extern void setup_default_timer_irq(void);
52 52
53#ifdef CONFIG_X86_INTEL_MID 53#ifdef CONFIG_X86_INTEL_MID
54extern void x86_mrst_early_setup(void); 54extern void x86_intel_mid_early_setup(void);
55#else 55#else
56static inline void x86_mrst_early_setup(void) { } 56static inline void x86_intel_mid_early_setup(void) { }
57#endif 57#endif
58 58
59#ifdef CONFIG_X86_INTEL_CE 59#ifdef CONFIG_X86_INTEL_CE
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index c15ddaf90710..9c3733c5f8f7 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -158,7 +158,7 @@ enum {
158 X86_SUBARCH_PC = 0, 158 X86_SUBARCH_PC = 0,
159 X86_SUBARCH_LGUEST, 159 X86_SUBARCH_LGUEST,
160 X86_SUBARCH_XEN, 160 X86_SUBARCH_XEN,
161 X86_SUBARCH_MRST, 161 X86_SUBARCH_INTEL_MID,
162 X86_SUBARCH_CE4100, 162 X86_SUBARCH_CE4100,
163 X86_NR_SUBARCHS, 163 X86_NR_SUBARCHS,
164}; 164};
diff --git a/arch/x86/kernel/apb_timer.c b/arch/x86/kernel/apb_timer.c
index c9876efecafb..af5b08ab3b71 100644
--- a/arch/x86/kernel/apb_timer.c
+++ b/arch/x86/kernel/apb_timer.c
@@ -40,7 +40,7 @@
40 40
41#include <asm/fixmap.h> 41#include <asm/fixmap.h>
42#include <asm/apb_timer.h> 42#include <asm/apb_timer.h>
43#include <asm/mrst.h> 43#include <asm/intel-mid.h>
44#include <asm/time.h> 44#include <asm/time.h>
45 45
46#define APBT_CLOCKEVENT_RATING 110 46#define APBT_CLOCKEVENT_RATING 110
@@ -157,13 +157,13 @@ static int __init apbt_clockevent_register(void)
157 157
158 adev->num = smp_processor_id(); 158 adev->num = smp_processor_id();
159 adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0", 159 adev->timer = dw_apb_clockevent_init(smp_processor_id(), "apbt0",
160 mrst_timer_options == MRST_TIMER_LAPIC_APBT ? 160 intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ?
161 APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING, 161 APBT_CLOCKEVENT_RATING - 100 : APBT_CLOCKEVENT_RATING,
162 adev_virt_addr(adev), 0, apbt_freq); 162 adev_virt_addr(adev), 0, apbt_freq);
163 /* Firmware does EOI handling for us. */ 163 /* Firmware does EOI handling for us. */
164 adev->timer->eoi = NULL; 164 adev->timer->eoi = NULL;
165 165
166 if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { 166 if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) {
167 global_clock_event = &adev->timer->ced; 167 global_clock_event = &adev->timer->ced;
168 printk(KERN_DEBUG "%s clockevent registered as global\n", 168 printk(KERN_DEBUG "%s clockevent registered as global\n",
169 global_clock_event->name); 169 global_clock_event->name);
@@ -253,7 +253,7 @@ static int apbt_cpuhp_notify(struct notifier_block *n,
253 253
254static __init int apbt_late_init(void) 254static __init int apbt_late_init(void)
255{ 255{
256 if (mrst_timer_options == MRST_TIMER_LAPIC_APBT || 256 if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT ||
257 !apb_timer_block_enabled) 257 !apb_timer_block_enabled)
258 return 0; 258 return 0;
259 /* This notifier should be called after workqueue is ready */ 259 /* This notifier should be called after workqueue is ready */
@@ -340,7 +340,7 @@ void __init apbt_time_init(void)
340 } 340 }
341#ifdef CONFIG_SMP 341#ifdef CONFIG_SMP
342 /* kernel cmdline disable apb timer, so we will use lapic timers */ 342 /* kernel cmdline disable apb timer, so we will use lapic timers */
343 if (mrst_timer_options == MRST_TIMER_LAPIC_APBT) { 343 if (intel_mid_timer_options == INTEL_MID_TIMER_LAPIC_APBT) {
344 printk(KERN_INFO "apbt: disabled per cpu timer\n"); 344 printk(KERN_INFO "apbt: disabled per cpu timer\n");
345 return; 345 return;
346 } 346 }
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 6d3d20073615..01d1c187c9f9 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -14,7 +14,7 @@
14#include <xen/hvc-console.h> 14#include <xen/hvc-console.h>
15#include <asm/pci-direct.h> 15#include <asm/pci-direct.h>
16#include <asm/fixmap.h> 16#include <asm/fixmap.h>
17#include <asm/mrst.h> 17#include <asm/intel-mid.h>
18#include <asm/pgtable.h> 18#include <asm/pgtable.h>
19#include <linux/usb/ehci_def.h> 19#include <linux/usb/ehci_def.h>
20#include <linux/efi.h> 20#include <linux/efi.h>
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c
index 06f87bece92a..c61a14a4a310 100644
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -35,8 +35,8 @@ asmlinkage void __init i386_start_kernel(void)
35 35
36 /* Call the subarch specific early setup function */ 36 /* Call the subarch specific early setup function */
37 switch (boot_params.hdr.hardware_subarch) { 37 switch (boot_params.hdr.hardware_subarch) {
38 case X86_SUBARCH_MRST: 38 case X86_SUBARCH_INTEL_MID:
39 x86_mrst_early_setup(); 39 x86_intel_mid_early_setup();
40 break; 40 break;
41 case X86_SUBARCH_CE4100: 41 case X86_SUBARCH_CE4100:
42 x86_ce4100_early_setup(); 42 x86_ce4100_early_setup();
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index 5b9dd445eb89..ca9622a25e95 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -12,7 +12,7 @@
12#include <asm/vsyscall.h> 12#include <asm/vsyscall.h>
13#include <asm/x86_init.h> 13#include <asm/x86_init.h>
14#include <asm/time.h> 14#include <asm/time.h>
15#include <asm/mrst.h> 15#include <asm/intel-mid.h>
16#include <asm/rtc.h> 16#include <asm/rtc.h>
17 17
18#ifdef CONFIG_X86_32 18#ifdef CONFIG_X86_32
@@ -189,7 +189,7 @@ static __init int add_rtc_cmos(void)
189 return 0; 189 return 0;
190 190
191 /* Intel MID platforms don't have ioport rtc */ 191 /* Intel MID platforms don't have ioport rtc */
192 if (mrst_identify_cpu()) 192 if (intel_mid_identify_cpu())
193 return -ENODEV; 193 return -ENODEV;
194 194
195#ifdef CONFIG_ACPI 195#ifdef CONFIG_ACPI
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 10c4f3006afd..da6b35a98260 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -199,6 +199,15 @@ SECTIONS
199 __x86_cpu_dev_end = .; 199 __x86_cpu_dev_end = .;
200 } 200 }
201 201
202#ifdef CONFIG_X86_INTEL_MID
203 .x86_intel_mid_dev.init : AT(ADDR(.x86_intel_mid_dev.init) - \
204 LOAD_OFFSET) {
205 __x86_intel_mid_dev_start = .;
206 *(.x86_intel_mid_dev.init)
207 __x86_intel_mid_dev_end = .;
208 }
209#endif
210
202 /* 211 /*
203 * start address and size of operations which during runtime 212 * start address and size of operations which during runtime
204 * can be patched with virtualization friendly instructions or 213 * can be patched with virtualization friendly instructions or
diff --git a/arch/x86/pci/Makefile b/arch/x86/pci/Makefile
index ee0af58ca5bd..e063eed0f912 100644
--- a/arch/x86/pci/Makefile
+++ b/arch/x86/pci/Makefile
@@ -18,7 +18,7 @@ obj-$(CONFIG_X86_VISWS) += visws.o
18obj-$(CONFIG_X86_NUMAQ) += numaq_32.o 18obj-$(CONFIG_X86_NUMAQ) += numaq_32.o
19obj-$(CONFIG_X86_NUMACHIP) += numachip.o 19obj-$(CONFIG_X86_NUMACHIP) += numachip.o
20 20
21obj-$(CONFIG_X86_INTEL_MID) += mrst.o 21obj-$(CONFIG_X86_INTEL_MID) += intel_mid_pci.o
22 22
23obj-y += common.o early.o 23obj-y += common.o early.o
24obj-y += bus_numa.o 24obj-y += bus_numa.o
diff --git a/arch/x86/pci/mrst.c b/arch/x86/pci/intel_mid_pci.c
index 903fded50786..51384ca727ad 100644
--- a/arch/x86/pci/mrst.c
+++ b/arch/x86/pci/intel_mid_pci.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Moorestown PCI support 2 * Intel MID PCI support
3 * Copyright (c) 2008 Intel Corporation 3 * Copyright (c) 2008 Intel Corporation
4 * Jesse Barnes <jesse.barnes@intel.com> 4 * Jesse Barnes <jesse.barnes@intel.com>
5 * 5 *
@@ -150,12 +150,12 @@ static bool type1_access_ok(unsigned int bus, unsigned int devfn, int reg)
150 * shim. Therefore, use the header type in shim instead. 150 * shim. Therefore, use the header type in shim instead.
151 */ 151 */
152 if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE) 152 if (reg >= 0x100 || reg == PCI_STATUS || reg == PCI_HEADER_TYPE)
153 return 0; 153 return false;
154 if (bus == 0 && (devfn == PCI_DEVFN(2, 0) 154 if (bus == 0 && (devfn == PCI_DEVFN(2, 0)
155 || devfn == PCI_DEVFN(0, 0) 155 || devfn == PCI_DEVFN(0, 0)
156 || devfn == PCI_DEVFN(3, 0))) 156 || devfn == PCI_DEVFN(3, 0)))
157 return 1; 157 return true;
158 return 0; /* Langwell on others */ 158 return false; /* Langwell on others */
159} 159}
160 160
161static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, 161static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
@@ -205,7 +205,7 @@ static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
205 where, size, value); 205 where, size, value);
206} 206}
207 207
208static int mrst_pci_irq_enable(struct pci_dev *dev) 208static int intel_mid_pci_irq_enable(struct pci_dev *dev)
209{ 209{
210 u8 pin; 210 u8 pin;
211 struct io_apic_irq_attr irq_attr; 211 struct io_apic_irq_attr irq_attr;
@@ -225,23 +225,23 @@ static int mrst_pci_irq_enable(struct pci_dev *dev)
225 return 0; 225 return 0;
226} 226}
227 227
228struct pci_ops pci_mrst_ops = { 228struct pci_ops intel_mid_pci_ops = {
229 .read = pci_read, 229 .read = pci_read,
230 .write = pci_write, 230 .write = pci_write,
231}; 231};
232 232
233/** 233/**
234 * pci_mrst_init - installs pci_mrst_ops 234 * intel_mid_pci_init - installs intel_mid_pci_ops
235 * 235 *
236 * Moorestown has an interesting PCI implementation (see above). 236 * Moorestown has an interesting PCI implementation (see above).
237 * Called when the early platform detection installs it. 237 * Called when the early platform detection installs it.
238 */ 238 */
239int __init pci_mrst_init(void) 239int __init intel_mid_pci_init(void)
240{ 240{
241 pr_info("Intel MID platform detected, using MID PCI ops\n"); 241 pr_info("Intel MID platform detected, using MID PCI ops\n");
242 pci_mmcfg_late_init(); 242 pci_mmcfg_late_init();
243 pcibios_enable_irq = mrst_pci_irq_enable; 243 pcibios_enable_irq = intel_mid_pci_irq_enable;
244 pci_root_ops = pci_mrst_ops; 244 pci_root_ops = intel_mid_pci_ops;
245 pci_soc_mode = 1; 245 pci_soc_mode = 1;
246 /* Continue with standard init */ 246 /* Continue with standard init */
247 return 1; 247 return 1;
diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile
index 01e0231a113e..20342d4c82ce 100644
--- a/arch/x86/platform/Makefile
+++ b/arch/x86/platform/Makefile
@@ -4,7 +4,7 @@ obj-y += efi/
4obj-y += geode/ 4obj-y += geode/
5obj-y += goldfish/ 5obj-y += goldfish/
6obj-y += iris/ 6obj-y += iris/
7obj-y += mrst/ 7obj-y += intel-mid/
8obj-y += olpc/ 8obj-y += olpc/
9obj-y += scx200/ 9obj-y += scx200/
10obj-y += sfi/ 10obj-y += sfi/
diff --git a/arch/x86/platform/intel-mid/Makefile b/arch/x86/platform/intel-mid/Makefile
new file mode 100644
index 000000000000..01cc29ea5ff7
--- /dev/null
+++ b/arch/x86/platform/intel-mid/Makefile
@@ -0,0 +1,7 @@
1obj-$(CONFIG_X86_INTEL_MID) += intel-mid.o
2obj-$(CONFIG_X86_INTEL_MID) += intel_mid_vrtc.o
3obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_intel_mid.o
4# SFI specific code
5ifdef CONFIG_X86_INTEL_MID
6obj-$(CONFIG_SFI) += sfi.o device_libs/
7endif
diff --git a/arch/x86/platform/intel-mid/device_libs/Makefile b/arch/x86/platform/intel-mid/device_libs/Makefile
new file mode 100644
index 000000000000..097e7a7940d8
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/Makefile
@@ -0,0 +1,22 @@
1# IPC Devices
2obj-y += platform_ipc.o
3obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic.o
4obj-$(subst m,y,$(CONFIG_SND_MFLD_MACHINE)) += platform_msic_audio.o
5obj-$(subst m,y,$(CONFIG_GPIO_MSIC)) += platform_msic_gpio.o
6obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_ocd.o
7obj-$(subst m,y,$(CONFIG_MFD_INTEL_MSIC)) += platform_msic_battery.o
8obj-$(subst m,y,$(CONFIG_INTEL_MID_POWER_BUTTON)) += platform_msic_power_btn.o
9obj-$(subst m,y,$(CONFIG_GPIO_INTEL_PMIC)) += platform_pmic_gpio.o
10obj-$(subst m,y,$(CONFIG_INTEL_MFLD_THERMAL)) += platform_msic_thermal.o
11# I2C Devices
12obj-$(subst m,y,$(CONFIG_SENSORS_EMC1403)) += platform_emc1403.o
13obj-$(subst m,y,$(CONFIG_SENSORS_LIS3LV02D)) += platform_lis331.o
14obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_max7315.o
15obj-$(subst m,y,$(CONFIG_INPUT_MPU3050)) += platform_mpu3050.o
16obj-$(subst m,y,$(CONFIG_INPUT_BMA150)) += platform_bma023.o
17obj-$(subst m,y,$(CONFIG_GPIO_PCA953X)) += platform_tca6416.o
18obj-$(subst m,y,$(CONFIG_DRM_MEDFIELD)) += platform_tc35876x.o
19# SPI Devices
20obj-$(subst m,y,$(CONFIG_SERIAL_MRST_MAX3110)) += platform_max3111.o
21# MISC Devices
22obj-$(subst m,y,$(CONFIG_KEYBOARD_GPIO)) += platform_gpio_keys.o
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_bma023.c b/arch/x86/platform/intel-mid/device_libs/platform_bma023.c
new file mode 100644
index 000000000000..0ae7f2ae2296
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_bma023.c
@@ -0,0 +1,20 @@
1/*
2 * platform_bma023.c: bma023 platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; version 2
9 * of the License.
10 */
11
12#include <asm/intel-mid.h>
13
14static const struct devs_id bma023_dev_id __initconst = {
15 .name = "bma023",
16 .type = SFI_DEV_TYPE_I2C,
17 .delay = 1,
18};
19
20sfi_device(bma023_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c
new file mode 100644
index 000000000000..0d942c1d26d5
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_emc1403.c
@@ -0,0 +1,41 @@
1/*
2 * platform_emc1403.c: emc1403 platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/init.h>
14#include <linux/gpio.h>
15#include <linux/i2c.h>
16#include <asm/intel-mid.h>
17
18static void __init *emc1403_platform_data(void *info)
19{
20 static short intr2nd_pdata;
21 struct i2c_board_info *i2c_info = info;
22 int intr = get_gpio_by_name("thermal_int");
23 int intr2nd = get_gpio_by_name("thermal_alert");
24
25 if (intr == -1 || intr2nd == -1)
26 return NULL;
27
28 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
29 intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
30
31 return &intr2nd_pdata;
32}
33
34static const struct devs_id emc1403_dev_id __initconst = {
35 .name = "emc1403",
36 .type = SFI_DEV_TYPE_I2C,
37 .delay = 1,
38 .get_platform_data = &emc1403_platform_data,
39};
40
41sfi_device(emc1403_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c
new file mode 100644
index 000000000000..a013a4834bbe
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_gpio_keys.c
@@ -0,0 +1,83 @@
1/*
2 * platform_gpio_keys.c: gpio_keys platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/input.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/gpio.h>
17#include <linux/gpio_keys.h>
18#include <linux/platform_device.h>
19#include <asm/intel-mid.h>
20
21#define DEVICE_NAME "gpio-keys"
22
23/*
24 * we will search these buttons in SFI GPIO table (by name)
25 * and register them dynamically. Please add all possible
26 * buttons here, we will shrink them if no GPIO found.
27 */
28static struct gpio_keys_button gpio_button[] = {
29 {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000},
30 {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20},
31 {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20},
32 {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20},
33 {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20},
34 {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20},
35 {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20},
36 {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20},
37 {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20},
38 {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20},
39};
40
41static struct gpio_keys_platform_data gpio_keys = {
42 .buttons = gpio_button,
43 .rep = 1,
44 .nbuttons = -1, /* will fill it after search */
45};
46
47static struct platform_device pb_device = {
48 .name = DEVICE_NAME,
49 .id = -1,
50 .dev = {
51 .platform_data = &gpio_keys,
52 },
53};
54
55/*
56 * Shrink the non-existent buttons, register the gpio button
57 * device if there is some
58 */
59static int __init pb_keys_init(void)
60{
61 struct gpio_keys_button *gb = gpio_button;
62 int i, num, good = 0;
63
64 num = sizeof(gpio_button) / sizeof(struct gpio_keys_button);
65 for (i = 0; i < num; i++) {
66 gb[i].gpio = get_gpio_by_name(gb[i].desc);
67 pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc,
68 gb[i].gpio);
69 if (gb[i].gpio == -1)
70 continue;
71
72 if (i != good)
73 gb[good] = gb[i];
74 good++;
75 }
76
77 if (good) {
78 gpio_keys.nbuttons = good;
79 return platform_device_register(&pb_device);
80 }
81 return 0;
82}
83late_initcall(pb_keys_init);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_ipc.c b/arch/x86/platform/intel-mid/device_libs/platform_ipc.c
new file mode 100644
index 000000000000..a84b73d6c4a0
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_ipc.c
@@ -0,0 +1,68 @@
1/*
2 * platform_ipc.c: IPC platform library file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/interrupt.h>
16#include <linux/sfi.h>
17#include <linux/gpio.h>
18#include <asm/intel-mid.h>
19#include "platform_ipc.h"
20
21void __init ipc_device_handler(struct sfi_device_table_entry *pentry,
22 struct devs_id *dev)
23{
24 struct platform_device *pdev;
25 void *pdata = NULL;
26 static struct resource res __initdata = {
27 .name = "IRQ",
28 .flags = IORESOURCE_IRQ,
29 };
30
31 pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n",
32 pentry->name, pentry->irq);
33
34 /*
35 * We need to call platform init of IPC devices to fill misc_pdata
36 * structure. It will be used in msic_init for initialization.
37 */
38 if (dev != NULL)
39 pdata = dev->get_platform_data(pentry);
40
41 /*
42 * On Medfield the platform device creation is handled by the MSIC
43 * MFD driver so we don't need to do it here.
44 */
45 if (intel_mid_has_msic())
46 return;
47
48 pdev = platform_device_alloc(pentry->name, 0);
49 if (pdev == NULL) {
50 pr_err("out of memory for SFI platform device '%s'.\n",
51 pentry->name);
52 return;
53 }
54 res.start = pentry->irq;
55 platform_device_add_resources(pdev, &res, 1);
56
57 pdev->dev.platform_data = pdata;
58 intel_scu_device_register(pdev);
59}
60
61static const struct devs_id pmic_audio_dev_id __initconst = {
62 .name = "pmic_audio",
63 .type = SFI_DEV_TYPE_IPC,
64 .delay = 1,
65 .device_handler = &ipc_device_handler,
66};
67
68sfi_device(pmic_audio_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_ipc.h b/arch/x86/platform/intel-mid/device_libs/platform_ipc.h
new file mode 100644
index 000000000000..8f568dd79605
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_ipc.h
@@ -0,0 +1,17 @@
1/*
2 * platform_ipc.h: IPC platform library header file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12#ifndef _PLATFORM_IPC_H_
13#define _PLATFORM_IPC_H_
14
15extern void __init ipc_device_handler(struct sfi_device_table_entry *pentry,
16 struct devs_id *dev) __attribute__((weak));
17#endif
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_lis331.c b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c
new file mode 100644
index 000000000000..15278c11f714
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_lis331.c
@@ -0,0 +1,39 @@
1/*
2 * platform_lis331.c: lis331 platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/i2c.h>
14#include <linux/gpio.h>
15#include <asm/intel-mid.h>
16
17static void __init *lis331dl_platform_data(void *info)
18{
19 static short intr2nd_pdata;
20 struct i2c_board_info *i2c_info = info;
21 int intr = get_gpio_by_name("accel_int");
22 int intr2nd = get_gpio_by_name("accel_2");
23
24 if (intr == -1 || intr2nd == -1)
25 return NULL;
26
27 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
28 intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
29
30 return &intr2nd_pdata;
31}
32
33static const struct devs_id lis331dl_dev_id __initconst = {
34 .name = "i2c_accel",
35 .type = SFI_DEV_TYPE_I2C,
36 .get_platform_data = &lis331dl_platform_data,
37};
38
39sfi_device(lis331dl_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max3111.c b/arch/x86/platform/intel-mid/device_libs/platform_max3111.c
new file mode 100644
index 000000000000..afd1df94e0e5
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_max3111.c
@@ -0,0 +1,35 @@
1/*
2 * platform_max3111.c: max3111 platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/gpio.h>
14#include <linux/spi/spi.h>
15#include <asm/intel-mid.h>
16
17static void __init *max3111_platform_data(void *info)
18{
19 struct spi_board_info *spi_info = info;
20 int intr = get_gpio_by_name("max3111_int");
21
22 spi_info->mode = SPI_MODE_0;
23 if (intr == -1)
24 return NULL;
25 spi_info->irq = intr + INTEL_MID_IRQ_OFFSET;
26 return NULL;
27}
28
29static const struct devs_id max3111_dev_id __initconst = {
30 .name = "spi_max3111",
31 .type = SFI_DEV_TYPE_SPI,
32 .get_platform_data = &max3111_platform_data,
33};
34
35sfi_device(max3111_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_max7315.c b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c
new file mode 100644
index 000000000000..94ade10024ae
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_max7315.c
@@ -0,0 +1,79 @@
1/*
2 * platform_max7315.c: max7315 platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/init.h>
14#include <linux/gpio.h>
15#include <linux/i2c.h>
16#include <linux/platform_data/pca953x.h>
17#include <asm/intel-mid.h>
18
19#define MAX7315_NUM 2
20
21static void __init *max7315_platform_data(void *info)
22{
23 static struct pca953x_platform_data max7315_pdata[MAX7315_NUM];
24 static int nr;
25 struct pca953x_platform_data *max7315 = &max7315_pdata[nr];
26 struct i2c_board_info *i2c_info = info;
27 int gpio_base, intr;
28 char base_pin_name[SFI_NAME_LEN + 1];
29 char intr_pin_name[SFI_NAME_LEN + 1];
30
31 if (nr == MAX7315_NUM) {
32 pr_err("too many max7315s, we only support %d\n",
33 MAX7315_NUM);
34 return NULL;
35 }
36 /* we have several max7315 on the board, we only need load several
37 * instances of the same pca953x driver to cover them
38 */
39 strcpy(i2c_info->type, "max7315");
40 if (nr++) {
41 sprintf(base_pin_name, "max7315_%d_base", nr);
42 sprintf(intr_pin_name, "max7315_%d_int", nr);
43 } else {
44 strcpy(base_pin_name, "max7315_base");
45 strcpy(intr_pin_name, "max7315_int");
46 }
47
48 gpio_base = get_gpio_by_name(base_pin_name);
49 intr = get_gpio_by_name(intr_pin_name);
50
51 if (gpio_base == -1)
52 return NULL;
53 max7315->gpio_base = gpio_base;
54 if (intr != -1) {
55 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
56 max7315->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
57 } else {
58 i2c_info->irq = -1;
59 max7315->irq_base = -1;
60 }
61 return max7315;
62}
63
64static const struct devs_id max7315_dev_id __initconst = {
65 .name = "i2c_max7315",
66 .type = SFI_DEV_TYPE_I2C,
67 .delay = 1,
68 .get_platform_data = &max7315_platform_data,
69};
70
71static const struct devs_id max7315_2_dev_id __initconst = {
72 .name = "i2c_max7315_2",
73 .type = SFI_DEV_TYPE_I2C,
74 .delay = 1,
75 .get_platform_data = &max7315_platform_data,
76};
77
78sfi_device(max7315_dev_id);
79sfi_device(max7315_2_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c
new file mode 100644
index 000000000000..dd28d63c84fb
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_mpu3050.c
@@ -0,0 +1,36 @@
1/*
2 * platform_mpu3050.c: mpu3050 platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/gpio.h>
14#include <linux/i2c.h>
15#include <asm/intel-mid.h>
16
17static void *mpu3050_platform_data(void *info)
18{
19 struct i2c_board_info *i2c_info = info;
20 int intr = get_gpio_by_name("mpu3050_int");
21
22 if (intr == -1)
23 return NULL;
24
25 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
26 return NULL;
27}
28
29static const struct devs_id mpu3050_dev_id __initconst = {
30 .name = "mpu3050",
31 .type = SFI_DEV_TYPE_I2C,
32 .delay = 1,
33 .get_platform_data = &mpu3050_platform_data,
34};
35
36sfi_device(mpu3050_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic.c b/arch/x86/platform/intel-mid/device_libs/platform_msic.c
new file mode 100644
index 000000000000..9f4a775a69d6
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic.c
@@ -0,0 +1,87 @@
1/*
2 * platform_msic.c: MSIC platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/scatterlist.h>
16#include <linux/init.h>
17#include <linux/sfi.h>
18#include <linux/mfd/intel_msic.h>
19#include <asm/intel_scu_ipc.h>
20#include <asm/intel-mid.h>
21#include "platform_msic.h"
22
23struct intel_msic_platform_data msic_pdata;
24
25static struct resource msic_resources[] = {
26 {
27 .start = INTEL_MSIC_IRQ_PHYS_BASE,
28 .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
29 .flags = IORESOURCE_MEM,
30 },
31};
32
33static struct platform_device msic_device = {
34 .name = "intel_msic",
35 .id = -1,
36 .dev = {
37 .platform_data = &msic_pdata,
38 },
39 .num_resources = ARRAY_SIZE(msic_resources),
40 .resource = msic_resources,
41};
42
43static int msic_scu_status_change(struct notifier_block *nb,
44 unsigned long code, void *data)
45{
46 if (code == SCU_DOWN) {
47 platform_device_unregister(&msic_device);
48 return 0;
49 }
50
51 return platform_device_register(&msic_device);
52}
53
54static int __init msic_init(void)
55{
56 static struct notifier_block msic_scu_notifier = {
57 .notifier_call = msic_scu_status_change,
58 };
59
60 /*
61 * We need to be sure that the SCU IPC is ready before MSIC device
62 * can be registered.
63 */
64 if (intel_mid_has_msic())
65 intel_scu_notifier_add(&msic_scu_notifier);
66
67 return 0;
68}
69arch_initcall(msic_init);
70
71/*
72 * msic_generic_platform_data - sets generic platform data for the block
73 * @info: pointer to the SFI device table entry for this block
74 * @block: MSIC block
75 *
76 * Function sets IRQ number from the SFI table entry for given device to
77 * the MSIC platform data.
78 */
79void *msic_generic_platform_data(void *info, enum intel_msic_block block)
80{
81 struct sfi_device_table_entry *entry = info;
82
83 BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
84 msic_pdata.irq[block] = entry->irq;
85
86 return NULL;
87}
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic.h b/arch/x86/platform/intel-mid/device_libs/platform_msic.h
new file mode 100644
index 000000000000..917eb56d77da
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic.h
@@ -0,0 +1,19 @@
1/*
2 * platform_msic.h: MSIC platform data header file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12#ifndef _PLATFORM_MSIC_H_
13#define _PLATFORM_MSIC_H_
14
15extern struct intel_msic_platform_data msic_pdata;
16
17extern void *msic_generic_platform_data(void *info,
18 enum intel_msic_block block) __attribute__((weak));
19#endif
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c
new file mode 100644
index 000000000000..29629397d2b3
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_audio.c
@@ -0,0 +1,47 @@
1/*
2 * platform_msic_audio.c: MSIC audio platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/scatterlist.h>
16#include <linux/init.h>
17#include <linux/sfi.h>
18#include <linux/platform_device.h>
19#include <linux/mfd/intel_msic.h>
20#include <asm/intel-mid.h>
21
22#include "platform_msic.h"
23#include "platform_ipc.h"
24
25static void *msic_audio_platform_data(void *info)
26{
27 struct platform_device *pdev;
28
29 pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
30
31 if (IS_ERR(pdev)) {
32 pr_err("failed to create audio platform device\n");
33 return NULL;
34 }
35
36 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
37}
38
39static const struct devs_id msic_audio_dev_id __initconst = {
40 .name = "msic_audio",
41 .type = SFI_DEV_TYPE_IPC,
42 .delay = 1,
43 .get_platform_data = &msic_audio_platform_data,
44 .device_handler = &ipc_device_handler,
45};
46
47sfi_device(msic_audio_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c
new file mode 100644
index 000000000000..f446c33df1a8
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_battery.c
@@ -0,0 +1,37 @@
1/*
2 * platform_msic_battery.c: MSIC battery platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/scatterlist.h>
16#include <linux/init.h>
17#include <linux/sfi.h>
18#include <linux/mfd/intel_msic.h>
19#include <asm/intel-mid.h>
20
21#include "platform_msic.h"
22#include "platform_ipc.h"
23
24static void __init *msic_battery_platform_data(void *info)
25{
26 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
27}
28
29static const struct devs_id msic_battery_dev_id __initconst = {
30 .name = "msic_battery",
31 .type = SFI_DEV_TYPE_IPC,
32 .delay = 1,
33 .get_platform_data = &msic_battery_platform_data,
34 .device_handler = &ipc_device_handler,
35};
36
37sfi_device(msic_battery_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c
new file mode 100644
index 000000000000..2a4f7b1dd917
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_gpio.c
@@ -0,0 +1,48 @@
1/*
2 * platform_msic_gpio.c: MSIC GPIO platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/scatterlist.h>
16#include <linux/sfi.h>
17#include <linux/init.h>
18#include <linux/gpio.h>
19#include <linux/mfd/intel_msic.h>
20#include <asm/intel-mid.h>
21
22#include "platform_msic.h"
23#include "platform_ipc.h"
24
25static void __init *msic_gpio_platform_data(void *info)
26{
27 static struct intel_msic_gpio_pdata msic_gpio_pdata;
28
29 int gpio = get_gpio_by_name("msic_gpio_base");
30
31 if (gpio < 0)
32 return NULL;
33
34 msic_gpio_pdata.gpio_base = gpio;
35 msic_pdata.gpio = &msic_gpio_pdata;
36
37 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
38}
39
40static const struct devs_id msic_gpio_dev_id __initconst = {
41 .name = "msic_gpio",
42 .type = SFI_DEV_TYPE_IPC,
43 .delay = 1,
44 .get_platform_data = &msic_gpio_platform_data,
45 .device_handler = &ipc_device_handler,
46};
47
48sfi_device(msic_gpio_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c
new file mode 100644
index 000000000000..6497111ddb54
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_ocd.c
@@ -0,0 +1,49 @@
1/*
2 * platform_msic_ocd.c: MSIC OCD platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/scatterlist.h>
16#include <linux/sfi.h>
17#include <linux/init.h>
18#include <linux/gpio.h>
19#include <linux/mfd/intel_msic.h>
20#include <asm/intel-mid.h>
21
22#include "platform_msic.h"
23#include "platform_ipc.h"
24
25static void __init *msic_ocd_platform_data(void *info)
26{
27 static struct intel_msic_ocd_pdata msic_ocd_pdata;
28 int gpio;
29
30 gpio = get_gpio_by_name("ocd_gpio");
31
32 if (gpio < 0)
33 return NULL;
34
35 msic_ocd_pdata.gpio = gpio;
36 msic_pdata.ocd = &msic_ocd_pdata;
37
38 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
39}
40
41static const struct devs_id msic_ocd_dev_id __initconst = {
42 .name = "msic_ocd",
43 .type = SFI_DEV_TYPE_IPC,
44 .delay = 1,
45 .get_platform_data = &msic_ocd_platform_data,
46 .device_handler = &ipc_device_handler,
47};
48
49sfi_device(msic_ocd_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c
new file mode 100644
index 000000000000..83a3459bc337
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_power_btn.c
@@ -0,0 +1,36 @@
1/*
2 * platform_msic_power_btn.c: MSIC power btn platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12#include <linux/kernel.h>
13#include <linux/interrupt.h>
14#include <linux/scatterlist.h>
15#include <linux/sfi.h>
16#include <linux/init.h>
17#include <linux/mfd/intel_msic.h>
18#include <asm/intel-mid.h>
19
20#include "platform_msic.h"
21#include "platform_ipc.h"
22
23static void __init *msic_power_btn_platform_data(void *info)
24{
25 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
26}
27
28static const struct devs_id msic_power_btn_dev_id __initconst = {
29 .name = "msic_power_btn",
30 .type = SFI_DEV_TYPE_IPC,
31 .delay = 1,
32 .get_platform_data = &msic_power_btn_platform_data,
33 .device_handler = &ipc_device_handler,
34};
35
36sfi_device(msic_power_btn_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c b/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c
new file mode 100644
index 000000000000..a351878b96bc
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_msic_thermal.c
@@ -0,0 +1,37 @@
1/*
2 * platform_msic_thermal.c: msic_thermal platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/input.h>
14#include <linux/init.h>
15#include <linux/kernel.h>
16#include <linux/gpio.h>
17#include <linux/platform_device.h>
18#include <linux/mfd/intel_msic.h>
19#include <asm/intel-mid.h>
20
21#include "platform_msic.h"
22#include "platform_ipc.h"
23
24static void __init *msic_thermal_platform_data(void *info)
25{
26 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL);
27}
28
29static const struct devs_id msic_thermal_dev_id __initconst = {
30 .name = "msic_thermal",
31 .type = SFI_DEV_TYPE_IPC,
32 .delay = 1,
33 .get_platform_data = &msic_thermal_platform_data,
34 .device_handler = &ipc_device_handler,
35};
36
37sfi_device(msic_thermal_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c
new file mode 100644
index 000000000000..d87182a09263
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_pmic_gpio.c
@@ -0,0 +1,54 @@
1/*
2 * platform_pmic_gpio.c: PMIC GPIO platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/scatterlist.h>
16#include <linux/gpio.h>
17#include <linux/init.h>
18#include <linux/sfi.h>
19#include <linux/intel_pmic_gpio.h>
20#include <asm/intel-mid.h>
21
22#include "platform_ipc.h"
23
24static void __init *pmic_gpio_platform_data(void *info)
25{
26 static struct intel_pmic_gpio_platform_data pmic_gpio_pdata;
27 int gpio_base = get_gpio_by_name("pmic_gpio_base");
28
29 if (gpio_base == -1)
30 gpio_base = 64;
31 pmic_gpio_pdata.gpio_base = gpio_base;
32 pmic_gpio_pdata.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
33 pmic_gpio_pdata.gpiointr = 0xffffeff8;
34
35 return &pmic_gpio_pdata;
36}
37
38static const struct devs_id pmic_gpio_spi_dev_id __initconst = {
39 .name = "pmic_gpio",
40 .type = SFI_DEV_TYPE_SPI,
41 .delay = 1,
42 .get_platform_data = &pmic_gpio_platform_data,
43};
44
45static const struct devs_id pmic_gpio_ipc_dev_id __initconst = {
46 .name = "pmic_gpio",
47 .type = SFI_DEV_TYPE_IPC,
48 .delay = 1,
49 .get_platform_data = &pmic_gpio_platform_data,
50 .device_handler = &ipc_device_handler
51};
52
53sfi_device(pmic_gpio_spi_dev_id);
54sfi_device(pmic_gpio_ipc_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c
new file mode 100644
index 000000000000..740fc757050c
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_tc35876x.c
@@ -0,0 +1,36 @@
1/*
2 * platform_tc35876x.c: tc35876x platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/gpio.h>
14#include <linux/i2c/tc35876x.h>
15#include <asm/intel-mid.h>
16
17/*tc35876x DSI_LVDS bridge chip and panel platform data*/
18static void *tc35876x_platform_data(void *data)
19{
20 static struct tc35876x_platform_data pdata;
21
22 /* gpio pins set to -1 will not be used by the driver */
23 pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
24 pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
25 pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
26
27 return &pdata;
28}
29
30static const struct devs_id tc35876x_dev_id __initconst = {
31 .name = "i2c_disp_brig",
32 .type = SFI_DEV_TYPE_I2C,
33 .get_platform_data = &tc35876x_platform_data,
34};
35
36sfi_device(tc35876x_dev_id);
diff --git a/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c
new file mode 100644
index 000000000000..22881c9a6737
--- /dev/null
+++ b/arch/x86/platform/intel-mid/device_libs/platform_tca6416.c
@@ -0,0 +1,57 @@
1/*
2 * platform_tca6416.c: tca6416 platform data initilization file
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/platform_data/pca953x.h>
14#include <linux/i2c.h>
15#include <linux/gpio.h>
16#include <asm/intel-mid.h>
17
18#define TCA6416_NAME "tca6416"
19#define TCA6416_BASE "tca6416_base"
20#define TCA6416_INTR "tca6416_int"
21
22static void *tca6416_platform_data(void *info)
23{
24 static struct pca953x_platform_data tca6416;
25 struct i2c_board_info *i2c_info = info;
26 int gpio_base, intr;
27 char base_pin_name[SFI_NAME_LEN + 1];
28 char intr_pin_name[SFI_NAME_LEN + 1];
29
30 strcpy(i2c_info->type, TCA6416_NAME);
31 strcpy(base_pin_name, TCA6416_BASE);
32 strcpy(intr_pin_name, TCA6416_INTR);
33
34 gpio_base = get_gpio_by_name(base_pin_name);
35 intr = get_gpio_by_name(intr_pin_name);
36
37 if (gpio_base == -1)
38 return NULL;
39 tca6416.gpio_base = gpio_base;
40 if (intr != -1) {
41 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
42 tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
43 } else {
44 i2c_info->irq = -1;
45 tca6416.irq_base = -1;
46 }
47 return &tca6416;
48}
49
50static const struct devs_id tca6416_dev_id __initconst = {
51 .name = "tca6416",
52 .type = SFI_DEV_TYPE_I2C,
53 .delay = 1,
54 .get_platform_data = &tca6416_platform_data,
55};
56
57sfi_device(tca6416_dev_id);
diff --git a/arch/x86/platform/mrst/early_printk_mrst.c b/arch/x86/platform/intel-mid/early_printk_intel_mid.c
index 028454f0c3a5..4f702f554f6e 100644
--- a/arch/x86/platform/mrst/early_printk_mrst.c
+++ b/arch/x86/platform/intel-mid/early_printk_intel_mid.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * early_printk_mrst.c - early consoles for Intel MID platforms 2 * early_printk_intel_mid.c - early consoles for Intel MID platforms
3 * 3 *
4 * Copyright (c) 2008-2010, Intel Corporation 4 * Copyright (c) 2008-2010, Intel Corporation
5 * 5 *
@@ -27,7 +27,7 @@
27 27
28#include <asm/fixmap.h> 28#include <asm/fixmap.h>
29#include <asm/pgtable.h> 29#include <asm/pgtable.h>
30#include <asm/mrst.h> 30#include <asm/intel-mid.h>
31 31
32#define MRST_SPI_TIMEOUT 0x200000 32#define MRST_SPI_TIMEOUT 0x200000
33#define MRST_REGBASE_SPI0 0xff128000 33#define MRST_REGBASE_SPI0 0xff128000
@@ -152,7 +152,7 @@ void mrst_early_console_init(void)
152 spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9; 152 spi0_cdiv = ((*pclk_spi0) & 0xe00) >> 9;
153 freq = 100000000 / (spi0_cdiv + 1); 153 freq = 100000000 / (spi0_cdiv + 1);
154 154
155 if (mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL) 155 if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL)
156 mrst_spi_paddr = MRST_REGBASE_SPI1; 156 mrst_spi_paddr = MRST_REGBASE_SPI1;
157 157
158 pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE, 158 pspi = (void *)set_fixmap_offset_nocache(FIX_EARLYCON_MEM_BASE,
@@ -213,13 +213,14 @@ static void early_mrst_spi_putc(char c)
213 } 213 }
214 214
215 if (!timeout) 215 if (!timeout)
216 pr_warning("MRST earlycon: timed out\n"); 216 pr_warn("MRST earlycon: timed out\n");
217 else 217 else
218 max3110_write_data(c); 218 max3110_write_data(c);
219} 219}
220 220
221/* Early SPI only uses polling mode */ 221/* Early SPI only uses polling mode */
222static void early_mrst_spi_write(struct console *con, const char *str, unsigned n) 222static void early_mrst_spi_write(struct console *con, const char *str,
223 unsigned n)
223{ 224{
224 int i; 225 int i;
225 226
diff --git a/arch/x86/platform/intel-mid/intel-mid.c b/arch/x86/platform/intel-mid/intel-mid.c
new file mode 100644
index 000000000000..f90e290f689f
--- /dev/null
+++ b/arch/x86/platform/intel-mid/intel-mid.c
@@ -0,0 +1,213 @@
1/*
2 * intel-mid.c: Intel MID platform setup code
3 *
4 * (C) Copyright 2008, 2012 Intel Corporation
5 * Author: Jacob Pan (jacob.jun.pan@intel.com)
6 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; version 2
11 * of the License.
12 */
13
14#define pr_fmt(fmt) "intel_mid: " fmt
15
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/interrupt.h>
19#include <linux/scatterlist.h>
20#include <linux/sfi.h>
21#include <linux/irq.h>
22#include <linux/module.h>
23#include <linux/notifier.h>
24
25#include <asm/setup.h>
26#include <asm/mpspec_def.h>
27#include <asm/hw_irq.h>
28#include <asm/apic.h>
29#include <asm/io_apic.h>
30#include <asm/intel-mid.h>
31#include <asm/intel_mid_vrtc.h>
32#include <asm/io.h>
33#include <asm/i8259.h>
34#include <asm/intel_scu_ipc.h>
35#include <asm/apb_timer.h>
36#include <asm/reboot.h>
37
38/*
39 * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
40 * cmdline option x86_intel_mid_timer can be used to override the configuration
41 * to prefer one or the other.
42 * at runtime, there are basically three timer configurations:
43 * 1. per cpu apbt clock only
44 * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
45 * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
46 *
47 * by default (without cmdline option), platform code first detects cpu type
48 * to see if we are on lincroft or penwell, then set up both lapic or apbt
49 * clocks accordingly.
50 * i.e. by default, medfield uses configuration #2, moorestown uses #1.
51 * config #3 is supported but not recommended on medfield.
52 *
53 * rating and feature summary:
54 * lapic (with C3STOP) --------- 100
55 * apbt (always-on) ------------ 110
56 * lapic (always-on,ARAT) ------ 150
57 */
58
59enum intel_mid_timer_options intel_mid_timer_options;
60
61enum intel_mid_cpu_type __intel_mid_cpu_chip;
62EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);
63
64static void intel_mid_power_off(void)
65{
66}
67
68static void intel_mid_reboot(void)
69{
70 intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
71}
72
73static unsigned long __init intel_mid_calibrate_tsc(void)
74{
75 unsigned long fast_calibrate;
76 u32 lo, hi, ratio, fsb;
77
78 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
79 pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
80 ratio = (hi >> 8) & 0x1f;
81 pr_debug("ratio is %d\n", ratio);
82 if (!ratio) {
83 pr_err("read a zero ratio, should be incorrect!\n");
84 pr_err("force tsc ratio to 16 ...\n");
85 ratio = 16;
86 }
87 rdmsr(MSR_FSB_FREQ, lo, hi);
88 if ((lo & 0x7) == 0x7)
89 fsb = PENWELL_FSB_FREQ_83SKU;
90 else
91 fsb = PENWELL_FSB_FREQ_100SKU;
92 fast_calibrate = ratio * fsb;
93 pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
94 lapic_timer_frequency = fsb * 1000 / HZ;
95 /* mark tsc clocksource as reliable */
96 set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
97
98 if (fast_calibrate)
99 return fast_calibrate;
100
101 return 0;
102}
103
104static void __init intel_mid_time_init(void)
105{
106 sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
107 switch (intel_mid_timer_options) {
108 case INTEL_MID_TIMER_APBT_ONLY:
109 break;
110 case INTEL_MID_TIMER_LAPIC_APBT:
111 x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
112 x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
113 break;
114 default:
115 if (!boot_cpu_has(X86_FEATURE_ARAT))
116 break;
117 x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
118 x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
119 return;
120 }
121 /* we need at least one APB timer */
122 pre_init_apic_IRQ0();
123 apbt_time_init();
124}
125
126static void intel_mid_arch_setup(void)
127{
128 if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
129 __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
130 else {
131 pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
132 boot_cpu_data.x86, boot_cpu_data.x86_model);
133 __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
134 }
135}
136
137/* MID systems don't have i8042 controller */
138static int intel_mid_i8042_detect(void)
139{
140 return 0;
141}
142
143/*
144 * Moorestown does not have external NMI source nor port 0x61 to report
145 * NMI status. The possible NMI sources are from pmu as a result of NMI
146 * watchdog or lock debug. Reading io port 0x61 results in 0xff which
147 * misled NMI handler.
148 */
149static unsigned char intel_mid_get_nmi_reason(void)
150{
151 return 0;
152}
153
154/*
155 * Moorestown specific x86_init function overrides and early setup
156 * calls.
157 */
158void __init x86_intel_mid_early_setup(void)
159{
160 x86_init.resources.probe_roms = x86_init_noop;
161 x86_init.resources.reserve_resources = x86_init_noop;
162
163 x86_init.timers.timer_init = intel_mid_time_init;
164 x86_init.timers.setup_percpu_clockev = x86_init_noop;
165
166 x86_init.irqs.pre_vector_init = x86_init_noop;
167
168 x86_init.oem.arch_setup = intel_mid_arch_setup;
169
170 x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock;
171
172 x86_platform.calibrate_tsc = intel_mid_calibrate_tsc;
173 x86_platform.i8042_detect = intel_mid_i8042_detect;
174 x86_init.timers.wallclock_init = intel_mid_rtc_init;
175 x86_platform.get_nmi_reason = intel_mid_get_nmi_reason;
176
177 x86_init.pci.init = intel_mid_pci_init;
178 x86_init.pci.fixup_irqs = x86_init_noop;
179
180 legacy_pic = &null_legacy_pic;
181
182 pm_power_off = intel_mid_power_off;
183 machine_ops.emergency_restart = intel_mid_reboot;
184
185 /* Avoid searching for BIOS MP tables */
186 x86_init.mpparse.find_smp_config = x86_init_noop;
187 x86_init.mpparse.get_smp_config = x86_init_uint_noop;
188 set_bit(MP_BUS_ISA, mp_bus_not_pci);
189}
190
191/*
192 * if user does not want to use per CPU apb timer, just give it a lower rating
193 * than local apic timer and skip the late per cpu timer init.
194 */
195static inline int __init setup_x86_intel_mid_timer(char *arg)
196{
197 if (!arg)
198 return -EINVAL;
199
200 if (strcmp("apbt_only", arg) == 0)
201 intel_mid_timer_options = INTEL_MID_TIMER_APBT_ONLY;
202 else if (strcmp("lapic_and_apbt", arg) == 0)
203 intel_mid_timer_options = INTEL_MID_TIMER_LAPIC_APBT;
204 else {
205 pr_warn("X86 INTEL_MID timer option %s not recognised"
206 " use x86_intel_mid_timer=apbt_only or lapic_and_apbt\n",
207 arg);
208 return -EINVAL;
209 }
210 return 0;
211}
212__setup("x86_intel_mid_timer=", setup_x86_intel_mid_timer);
213
diff --git a/arch/x86/platform/mrst/vrtc.c b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
index 5e355b134ba4..4762cff7facd 100644
--- a/arch/x86/platform/mrst/vrtc.c
+++ b/arch/x86/platform/intel-mid/intel_mid_vrtc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * vrtc.c: Driver for virtual RTC device on Intel MID platform 2 * intel_mid_vrtc.c: Driver for virtual RTC device on Intel MID platform
3 * 3 *
4 * (C) Copyright 2009 Intel Corporation 4 * (C) Copyright 2009 Intel Corporation
5 * 5 *
@@ -23,8 +23,8 @@
23#include <linux/sfi.h> 23#include <linux/sfi.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25 25
26#include <asm/mrst.h> 26#include <asm/intel-mid.h>
27#include <asm/mrst-vrtc.h> 27#include <asm/intel_mid_vrtc.h>
28#include <asm/time.h> 28#include <asm/time.h>
29#include <asm/fixmap.h> 29#include <asm/fixmap.h>
30 30
@@ -79,7 +79,7 @@ void vrtc_get_time(struct timespec *now)
79 /* vRTC YEAR reg contains the offset to 1972 */ 79 /* vRTC YEAR reg contains the offset to 1972 */
80 year += 1972; 80 year += 1972;
81 81
82 printk(KERN_INFO "vRTC: sec: %d min: %d hour: %d day: %d " 82 pr_info("vRTC: sec: %d min: %d hour: %d day: %d "
83 "mon: %d year: %d\n", sec, min, hour, mday, mon, year); 83 "mon: %d year: %d\n", sec, min, hour, mday, mon, year);
84 84
85 now->tv_sec = mktime(year, mon, mday, hour, min, sec); 85 now->tv_sec = mktime(year, mon, mday, hour, min, sec);
@@ -109,15 +109,14 @@ int vrtc_set_mmss(const struct timespec *now)
109 vrtc_cmos_write(tm.tm_sec, RTC_SECONDS); 109 vrtc_cmos_write(tm.tm_sec, RTC_SECONDS);
110 spin_unlock_irqrestore(&rtc_lock, flags); 110 spin_unlock_irqrestore(&rtc_lock, flags);
111 } else { 111 } else {
112 printk(KERN_ERR 112 pr_err("%s: Invalid vRTC value: write of %lx to vRTC failed\n",
113 "%s: Invalid vRTC value: write of %lx to vRTC failed\n",
114 __FUNCTION__, now->tv_sec); 113 __FUNCTION__, now->tv_sec);
115 retval = -EINVAL; 114 retval = -EINVAL;
116 } 115 }
117 return retval; 116 return retval;
118} 117}
119 118
120void __init mrst_rtc_init(void) 119void __init intel_mid_rtc_init(void)
121{ 120{
122 unsigned long vrtc_paddr; 121 unsigned long vrtc_paddr;
123 122
@@ -155,10 +154,10 @@ static struct platform_device vrtc_device = {
155}; 154};
156 155
157/* Register the RTC device if appropriate */ 156/* Register the RTC device if appropriate */
158static int __init mrst_device_create(void) 157static int __init intel_mid_device_create(void)
159{ 158{
160 /* No Moorestown, no device */ 159 /* No Moorestown, no device */
161 if (!mrst_identify_cpu()) 160 if (!intel_mid_identify_cpu())
162 return -ENODEV; 161 return -ENODEV;
163 /* No timer, no device */ 162 /* No timer, no device */
164 if (!sfi_mrtc_num) 163 if (!sfi_mrtc_num)
@@ -175,4 +174,4 @@ static int __init mrst_device_create(void)
175 return platform_device_register(&vrtc_device); 174 return platform_device_register(&vrtc_device);
176} 175}
177 176
178module_init(mrst_device_create); 177module_init(intel_mid_device_create);
diff --git a/arch/x86/platform/intel-mid/sfi.c b/arch/x86/platform/intel-mid/sfi.c
new file mode 100644
index 000000000000..c84c1ca396bf
--- /dev/null
+++ b/arch/x86/platform/intel-mid/sfi.c
@@ -0,0 +1,488 @@
1/*
2 * intel_mid_sfi.c: Intel MID SFI initialization code
3 *
4 * (C) Copyright 2013 Intel Corporation
5 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/interrupt.h>
16#include <linux/scatterlist.h>
17#include <linux/sfi.h>
18#include <linux/intel_pmic_gpio.h>
19#include <linux/spi/spi.h>
20#include <linux/i2c.h>
21#include <linux/skbuff.h>
22#include <linux/gpio.h>
23#include <linux/gpio_keys.h>
24#include <linux/input.h>
25#include <linux/platform_device.h>
26#include <linux/irq.h>
27#include <linux/module.h>
28#include <linux/notifier.h>
29#include <linux/mmc/core.h>
30#include <linux/mmc/card.h>
31#include <linux/blkdev.h>
32
33#include <asm/setup.h>
34#include <asm/mpspec_def.h>
35#include <asm/hw_irq.h>
36#include <asm/apic.h>
37#include <asm/io_apic.h>
38#include <asm/intel-mid.h>
39#include <asm/intel_mid_vrtc.h>
40#include <asm/io.h>
41#include <asm/i8259.h>
42#include <asm/intel_scu_ipc.h>
43#include <asm/apb_timer.h>
44#include <asm/reboot.h>
45
46#define SFI_SIG_OEM0 "OEM0"
47#define MAX_IPCDEVS 24
48#define MAX_SCU_SPI 24
49#define MAX_SCU_I2C 24
50
51static struct platform_device *ipc_devs[MAX_IPCDEVS];
52static struct spi_board_info *spi_devs[MAX_SCU_SPI];
53static struct i2c_board_info *i2c_devs[MAX_SCU_I2C];
54static struct sfi_gpio_table_entry *gpio_table;
55static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
56static int ipc_next_dev;
57static int spi_next_dev;
58static int i2c_next_dev;
59static int i2c_bus[MAX_SCU_I2C];
60static int gpio_num_entry;
61static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
62int sfi_mrtc_num;
63int sfi_mtimer_num;
64
65struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
66EXPORT_SYMBOL_GPL(sfi_mrtc_array);
67
68struct blocking_notifier_head intel_scu_notifier =
69 BLOCKING_NOTIFIER_INIT(intel_scu_notifier);
70EXPORT_SYMBOL_GPL(intel_scu_notifier);
71
72#define intel_mid_sfi_get_pdata(dev, priv) \
73 ((dev)->get_platform_data ? (dev)->get_platform_data(priv) : NULL)
74
75/* parse all the mtimer info to a static mtimer array */
76int __init sfi_parse_mtmr(struct sfi_table_header *table)
77{
78 struct sfi_table_simple *sb;
79 struct sfi_timer_table_entry *pentry;
80 struct mpc_intsrc mp_irq;
81 int totallen;
82
83 sb = (struct sfi_table_simple *)table;
84 if (!sfi_mtimer_num) {
85 sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb,
86 struct sfi_timer_table_entry);
87 pentry = (struct sfi_timer_table_entry *) sb->pentry;
88 totallen = sfi_mtimer_num * sizeof(*pentry);
89 memcpy(sfi_mtimer_array, pentry, totallen);
90 }
91
92 pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num);
93 pentry = sfi_mtimer_array;
94 for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) {
95 pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz, irq = %d\n",
96 totallen, (u32)pentry->phys_addr,
97 pentry->freq_hz, pentry->irq);
98 if (!pentry->irq)
99 continue;
100 mp_irq.type = MP_INTSRC;
101 mp_irq.irqtype = mp_INT;
102/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
103 mp_irq.irqflag = 5;
104 mp_irq.srcbus = MP_BUS_ISA;
105 mp_irq.srcbusirq = pentry->irq; /* IRQ */
106 mp_irq.dstapic = MP_APIC_ALL;
107 mp_irq.dstirq = pentry->irq;
108 mp_save_irq(&mp_irq);
109 }
110
111 return 0;
112}
113
114struct sfi_timer_table_entry *sfi_get_mtmr(int hint)
115{
116 int i;
117 if (hint < sfi_mtimer_num) {
118 if (!sfi_mtimer_usage[hint]) {
119 pr_debug("hint taken for timer %d irq %d\n",
120 hint, sfi_mtimer_array[hint].irq);
121 sfi_mtimer_usage[hint] = 1;
122 return &sfi_mtimer_array[hint];
123 }
124 }
125 /* take the first timer available */
126 for (i = 0; i < sfi_mtimer_num;) {
127 if (!sfi_mtimer_usage[i]) {
128 sfi_mtimer_usage[i] = 1;
129 return &sfi_mtimer_array[i];
130 }
131 i++;
132 }
133 return NULL;
134}
135
136void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
137{
138 int i;
139 for (i = 0; i < sfi_mtimer_num;) {
140 if (mtmr->irq == sfi_mtimer_array[i].irq) {
141 sfi_mtimer_usage[i] = 0;
142 return;
143 }
144 i++;
145 }
146}
147
148/* parse all the mrtc info to a global mrtc array */
149int __init sfi_parse_mrtc(struct sfi_table_header *table)
150{
151 struct sfi_table_simple *sb;
152 struct sfi_rtc_table_entry *pentry;
153 struct mpc_intsrc mp_irq;
154
155 int totallen;
156
157 sb = (struct sfi_table_simple *)table;
158 if (!sfi_mrtc_num) {
159 sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
160 struct sfi_rtc_table_entry);
161 pentry = (struct sfi_rtc_table_entry *)sb->pentry;
162 totallen = sfi_mrtc_num * sizeof(*pentry);
163 memcpy(sfi_mrtc_array, pentry, totallen);
164 }
165
166 pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num);
167 pentry = sfi_mrtc_array;
168 for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
169 pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
170 totallen, (u32)pentry->phys_addr, pentry->irq);
171 mp_irq.type = MP_INTSRC;
172 mp_irq.irqtype = mp_INT;
173 mp_irq.irqflag = 0xf; /* level trigger and active low */
174 mp_irq.srcbus = MP_BUS_ISA;
175 mp_irq.srcbusirq = pentry->irq; /* IRQ */
176 mp_irq.dstapic = MP_APIC_ALL;
177 mp_irq.dstirq = pentry->irq;
178 mp_save_irq(&mp_irq);
179 }
180 return 0;
181}
182
183
184/*
185 * Parsing GPIO table first, since the DEVS table will need this table
186 * to map the pin name to the actual pin.
187 */
188static int __init sfi_parse_gpio(struct sfi_table_header *table)
189{
190 struct sfi_table_simple *sb;
191 struct sfi_gpio_table_entry *pentry;
192 int num, i;
193
194 if (gpio_table)
195 return 0;
196 sb = (struct sfi_table_simple *)table;
197 num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
198 pentry = (struct sfi_gpio_table_entry *)sb->pentry;
199
200 gpio_table = kmalloc(num * sizeof(*pentry), GFP_KERNEL);
201 if (!gpio_table)
202 return -1;
203 memcpy(gpio_table, pentry, num * sizeof(*pentry));
204 gpio_num_entry = num;
205
206 pr_debug("GPIO pin info:\n");
207 for (i = 0; i < num; i++, pentry++)
208 pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s,"
209 " pin = %d\n", i,
210 pentry->controller_name,
211 pentry->pin_name,
212 pentry->pin_no);
213 return 0;
214}
215
216int get_gpio_by_name(const char *name)
217{
218 struct sfi_gpio_table_entry *pentry = gpio_table;
219 int i;
220
221 if (!pentry)
222 return -1;
223 for (i = 0; i < gpio_num_entry; i++, pentry++) {
224 if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN))
225 return pentry->pin_no;
226 }
227 return -1;
228}
229
230void __init intel_scu_device_register(struct platform_device *pdev)
231{
232 if (ipc_next_dev == MAX_IPCDEVS)
233 pr_err("too many SCU IPC devices");
234 else
235 ipc_devs[ipc_next_dev++] = pdev;
236}
237
238static void __init intel_scu_spi_device_register(struct spi_board_info *sdev)
239{
240 struct spi_board_info *new_dev;
241
242 if (spi_next_dev == MAX_SCU_SPI) {
243 pr_err("too many SCU SPI devices");
244 return;
245 }
246
247 new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL);
248 if (!new_dev) {
249 pr_err("failed to alloc mem for delayed spi dev %s\n",
250 sdev->modalias);
251 return;
252 }
253 memcpy(new_dev, sdev, sizeof(*sdev));
254
255 spi_devs[spi_next_dev++] = new_dev;
256}
257
258static void __init intel_scu_i2c_device_register(int bus,
259 struct i2c_board_info *idev)
260{
261 struct i2c_board_info *new_dev;
262
263 if (i2c_next_dev == MAX_SCU_I2C) {
264 pr_err("too many SCU I2C devices");
265 return;
266 }
267
268 new_dev = kzalloc(sizeof(*idev), GFP_KERNEL);
269 if (!new_dev) {
270 pr_err("failed to alloc mem for delayed i2c dev %s\n",
271 idev->type);
272 return;
273 }
274 memcpy(new_dev, idev, sizeof(*idev));
275
276 i2c_bus[i2c_next_dev] = bus;
277 i2c_devs[i2c_next_dev++] = new_dev;
278}
279
280/* Called by IPC driver */
281void intel_scu_devices_create(void)
282{
283 int i;
284
285 for (i = 0; i < ipc_next_dev; i++)
286 platform_device_add(ipc_devs[i]);
287
288 for (i = 0; i < spi_next_dev; i++)
289 spi_register_board_info(spi_devs[i], 1);
290
291 for (i = 0; i < i2c_next_dev; i++) {
292 struct i2c_adapter *adapter;
293 struct i2c_client *client;
294
295 adapter = i2c_get_adapter(i2c_bus[i]);
296 if (adapter) {
297 client = i2c_new_device(adapter, i2c_devs[i]);
298 if (!client)
299 pr_err("can't create i2c device %s\n",
300 i2c_devs[i]->type);
301 } else
302 i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
303 }
304 intel_scu_notifier_post(SCU_AVAILABLE, NULL);
305}
306EXPORT_SYMBOL_GPL(intel_scu_devices_create);
307
308/* Called by IPC driver */
309void intel_scu_devices_destroy(void)
310{
311 int i;
312
313 intel_scu_notifier_post(SCU_DOWN, NULL);
314
315 for (i = 0; i < ipc_next_dev; i++)
316 platform_device_del(ipc_devs[i]);
317}
318EXPORT_SYMBOL_GPL(intel_scu_devices_destroy);
319
320static void __init install_irq_resource(struct platform_device *pdev, int irq)
321{
322 /* Single threaded */
323 static struct resource res __initdata = {
324 .name = "IRQ",
325 .flags = IORESOURCE_IRQ,
326 };
327 res.start = irq;
328 platform_device_add_resources(pdev, &res, 1);
329}
330
331static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *pentry,
332 struct devs_id *dev)
333{
334 struct platform_device *pdev;
335 void *pdata = NULL;
336
337 pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n",
338 pentry->name, pentry->irq);
339 pdata = intel_mid_sfi_get_pdata(dev, pentry);
340
341 pdev = platform_device_alloc(pentry->name, 0);
342 if (pdev == NULL) {
343 pr_err("out of memory for SFI platform device '%s'.\n",
344 pentry->name);
345 return;
346 }
347 install_irq_resource(pdev, pentry->irq);
348
349 pdev->dev.platform_data = pdata;
350 platform_device_add(pdev);
351}
352
353static void __init sfi_handle_spi_dev(struct sfi_device_table_entry *pentry,
354 struct devs_id *dev)
355{
356 struct spi_board_info spi_info;
357 void *pdata = NULL;
358
359 memset(&spi_info, 0, sizeof(spi_info));
360 strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
361 spi_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq);
362 spi_info.bus_num = pentry->host_num;
363 spi_info.chip_select = pentry->addr;
364 spi_info.max_speed_hz = pentry->max_freq;
365 pr_debug("SPI bus=%d, name=%16.16s, irq=0x%2x, max_freq=%d, cs=%d\n",
366 spi_info.bus_num,
367 spi_info.modalias,
368 spi_info.irq,
369 spi_info.max_speed_hz,
370 spi_info.chip_select);
371
372 pdata = intel_mid_sfi_get_pdata(dev, &spi_info);
373
374 spi_info.platform_data = pdata;
375 if (dev->delay)
376 intel_scu_spi_device_register(&spi_info);
377 else
378 spi_register_board_info(&spi_info, 1);
379}
380
381static void __init sfi_handle_i2c_dev(struct sfi_device_table_entry *pentry,
382 struct devs_id *dev)
383{
384 struct i2c_board_info i2c_info;
385 void *pdata = NULL;
386
387 memset(&i2c_info, 0, sizeof(i2c_info));
388 strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
389 i2c_info.irq = ((pentry->irq == (u8)0xff) ? 0 : pentry->irq);
390 i2c_info.addr = pentry->addr;
391 pr_debug("I2C bus = %d, name = %16.16s, irq = 0x%2x, addr = 0x%x\n",
392 pentry->host_num,
393 i2c_info.type,
394 i2c_info.irq,
395 i2c_info.addr);
396 pdata = intel_mid_sfi_get_pdata(dev, &i2c_info);
397 i2c_info.platform_data = pdata;
398
399 if (dev->delay)
400 intel_scu_i2c_device_register(pentry->host_num, &i2c_info);
401 else
402 i2c_register_board_info(pentry->host_num, &i2c_info, 1);
403}
404
405extern struct devs_id *const __x86_intel_mid_dev_start[],
406 *const __x86_intel_mid_dev_end[];
407
408static struct devs_id __init *get_device_id(u8 type, char *name)
409{
410 struct devs_id *const *dev_table;
411
412 for (dev_table = __x86_intel_mid_dev_start;
413 dev_table < __x86_intel_mid_dev_end; dev_table++) {
414 struct devs_id *dev = *dev_table;
415 if (dev->type == type &&
416 !strncmp(dev->name, name, SFI_NAME_LEN)) {
417 return dev;
418 }
419 }
420
421 return NULL;
422}
423
424static int __init sfi_parse_devs(struct sfi_table_header *table)
425{
426 struct sfi_table_simple *sb;
427 struct sfi_device_table_entry *pentry;
428 struct devs_id *dev = NULL;
429 int num, i;
430 int ioapic;
431 struct io_apic_irq_attr irq_attr;
432
433 sb = (struct sfi_table_simple *)table;
434 num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
435 pentry = (struct sfi_device_table_entry *)sb->pentry;
436
437 for (i = 0; i < num; i++, pentry++) {
438 int irq = pentry->irq;
439
440 if (irq != (u8)0xff) { /* native RTE case */
441 /* these SPI2 devices are not exposed to system as PCI
442 * devices, but they have separate RTE entry in IOAPIC
443 * so we have to enable them one by one here
444 */
445 ioapic = mp_find_ioapic(irq);
446 irq_attr.ioapic = ioapic;
447 irq_attr.ioapic_pin = irq;
448 irq_attr.trigger = 1;
449 irq_attr.polarity = 1;
450 io_apic_set_pci_routing(NULL, irq, &irq_attr);
451 } else
452 irq = 0; /* No irq */
453
454 dev = get_device_id(pentry->type, pentry->name);
455
456 if (!dev)
457 continue;
458
459 if (dev->device_handler) {
460 dev->device_handler(pentry, dev);
461 } else {
462 switch (pentry->type) {
463 case SFI_DEV_TYPE_IPC:
464 sfi_handle_ipc_dev(pentry, dev);
465 break;
466 case SFI_DEV_TYPE_SPI:
467 sfi_handle_spi_dev(pentry, dev);
468 break;
469 case SFI_DEV_TYPE_I2C:
470 sfi_handle_i2c_dev(pentry, dev);
471 break;
472 case SFI_DEV_TYPE_UART:
473 case SFI_DEV_TYPE_HSI:
474 default:
475 break;
476 }
477 }
478 }
479 return 0;
480}
481
482static int __init intel_mid_platform_init(void)
483{
484 sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio);
485 sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs);
486 return 0;
487}
488arch_initcall(intel_mid_platform_init);
diff --git a/arch/x86/platform/mrst/Makefile b/arch/x86/platform/mrst/Makefile
deleted file mode 100644
index af1da7e623f9..000000000000
--- a/arch/x86/platform/mrst/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
1obj-$(CONFIG_X86_INTEL_MID) += mrst.o
2obj-$(CONFIG_X86_INTEL_MID) += vrtc.o
3obj-$(CONFIG_EARLY_PRINTK_INTEL_MID) += early_printk_mrst.o
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c
deleted file mode 100644
index 3ca5957b7a34..000000000000
--- a/arch/x86/platform/mrst/mrst.c
+++ /dev/null
@@ -1,1052 +0,0 @@
1/*
2 * mrst.c: Intel Moorestown platform specific setup code
3 *
4 * (C) Copyright 2008 Intel Corporation
5 * Author: Jacob Pan (jacob.jun.pan@intel.com)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; version 2
10 * of the License.
11 */
12
13#define pr_fmt(fmt) "mrst: " fmt
14
15#include <linux/init.h>
16#include <linux/kernel.h>
17#include <linux/interrupt.h>
18#include <linux/scatterlist.h>
19#include <linux/sfi.h>
20#include <linux/intel_pmic_gpio.h>
21#include <linux/spi/spi.h>
22#include <linux/i2c.h>
23#include <linux/platform_data/pca953x.h>
24#include <linux/gpio_keys.h>
25#include <linux/input.h>
26#include <linux/platform_device.h>
27#include <linux/irq.h>
28#include <linux/module.h>
29#include <linux/notifier.h>
30#include <linux/mfd/intel_msic.h>
31#include <linux/gpio.h>
32#include <linux/i2c/tc35876x.h>
33
34#include <asm/setup.h>
35#include <asm/mpspec_def.h>
36#include <asm/hw_irq.h>
37#include <asm/apic.h>
38#include <asm/io_apic.h>
39#include <asm/mrst.h>
40#include <asm/mrst-vrtc.h>
41#include <asm/io.h>
42#include <asm/i8259.h>
43#include <asm/intel_scu_ipc.h>
44#include <asm/apb_timer.h>
45#include <asm/reboot.h>
46
47/*
48 * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
49 * cmdline option x86_mrst_timer can be used to override the configuration
50 * to prefer one or the other.
51 * at runtime, there are basically three timer configurations:
52 * 1. per cpu apbt clock only
53 * 2. per cpu always-on lapic clocks only, this is Penwell/Medfield only
54 * 3. per cpu lapic clock (C3STOP) and one apbt clock, with broadcast.
55 *
56 * by default (without cmdline option), platform code first detects cpu type
57 * to see if we are on lincroft or penwell, then set up both lapic or apbt
58 * clocks accordingly.
59 * i.e. by default, medfield uses configuration #2, moorestown uses #1.
60 * config #3 is supported but not recommended on medfield.
61 *
62 * rating and feature summary:
63 * lapic (with C3STOP) --------- 100
64 * apbt (always-on) ------------ 110
65 * lapic (always-on,ARAT) ------ 150
66 */
67
68enum mrst_timer_options mrst_timer_options;
69
70static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM];
71static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM];
72enum mrst_cpu_type __mrst_cpu_chip;
73EXPORT_SYMBOL_GPL(__mrst_cpu_chip);
74
75int sfi_mtimer_num;
76
77struct sfi_rtc_table_entry sfi_mrtc_array[SFI_MRTC_MAX];
78EXPORT_SYMBOL_GPL(sfi_mrtc_array);
79int sfi_mrtc_num;
80
81static void mrst_power_off(void)
82{
83}
84
85static void mrst_reboot(void)
86{
87 intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
88}
89
90/* parse all the mtimer info to a static mtimer array */
91static int __init sfi_parse_mtmr(struct sfi_table_header *table)
92{
93 struct sfi_table_simple *sb;
94 struct sfi_timer_table_entry *pentry;
95 struct mpc_intsrc mp_irq;
96 int totallen;
97
98 sb = (struct sfi_table_simple *)table;
99 if (!sfi_mtimer_num) {
100 sfi_mtimer_num = SFI_GET_NUM_ENTRIES(sb,
101 struct sfi_timer_table_entry);
102 pentry = (struct sfi_timer_table_entry *) sb->pentry;
103 totallen = sfi_mtimer_num * sizeof(*pentry);
104 memcpy(sfi_mtimer_array, pentry, totallen);
105 }
106
107 pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num);
108 pentry = sfi_mtimer_array;
109 for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) {
110 pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz,"
111 " irq = %d\n", totallen, (u32)pentry->phys_addr,
112 pentry->freq_hz, pentry->irq);
113 if (!pentry->irq)
114 continue;
115 mp_irq.type = MP_INTSRC;
116 mp_irq.irqtype = mp_INT;
117/* triggering mode edge bit 2-3, active high polarity bit 0-1 */
118 mp_irq.irqflag = 5;
119 mp_irq.srcbus = MP_BUS_ISA;
120 mp_irq.srcbusirq = pentry->irq; /* IRQ */
121 mp_irq.dstapic = MP_APIC_ALL;
122 mp_irq.dstirq = pentry->irq;
123 mp_save_irq(&mp_irq);
124 }
125
126 return 0;
127}
128
129struct sfi_timer_table_entry *sfi_get_mtmr(int hint)
130{
131 int i;
132 if (hint < sfi_mtimer_num) {
133 if (!sfi_mtimer_usage[hint]) {
134 pr_debug("hint taken for timer %d irq %d\n",\
135 hint, sfi_mtimer_array[hint].irq);
136 sfi_mtimer_usage[hint] = 1;
137 return &sfi_mtimer_array[hint];
138 }
139 }
140 /* take the first timer available */
141 for (i = 0; i < sfi_mtimer_num;) {
142 if (!sfi_mtimer_usage[i]) {
143 sfi_mtimer_usage[i] = 1;
144 return &sfi_mtimer_array[i];
145 }
146 i++;
147 }
148 return NULL;
149}
150
151void sfi_free_mtmr(struct sfi_timer_table_entry *mtmr)
152{
153 int i;
154 for (i = 0; i < sfi_mtimer_num;) {
155 if (mtmr->irq == sfi_mtimer_array[i].irq) {
156 sfi_mtimer_usage[i] = 0;
157 return;
158 }
159 i++;
160 }
161}
162
163/* parse all the mrtc info to a global mrtc array */
164int __init sfi_parse_mrtc(struct sfi_table_header *table)
165{
166 struct sfi_table_simple *sb;
167 struct sfi_rtc_table_entry *pentry;
168 struct mpc_intsrc mp_irq;
169
170 int totallen;
171
172 sb = (struct sfi_table_simple *)table;
173 if (!sfi_mrtc_num) {
174 sfi_mrtc_num = SFI_GET_NUM_ENTRIES(sb,
175 struct sfi_rtc_table_entry);
176 pentry = (struct sfi_rtc_table_entry *)sb->pentry;
177 totallen = sfi_mrtc_num * sizeof(*pentry);
178 memcpy(sfi_mrtc_array, pentry, totallen);
179 }
180
181 pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num);
182 pentry = sfi_mrtc_array;
183 for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
184 pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
185 totallen, (u32)pentry->phys_addr, pentry->irq);
186 mp_irq.type = MP_INTSRC;
187 mp_irq.irqtype = mp_INT;
188 mp_irq.irqflag = 0xf; /* level trigger and active low */
189 mp_irq.srcbus = MP_BUS_ISA;
190 mp_irq.srcbusirq = pentry->irq; /* IRQ */
191 mp_irq.dstapic = MP_APIC_ALL;
192 mp_irq.dstirq = pentry->irq;
193 mp_save_irq(&mp_irq);
194 }
195 return 0;
196}
197
198static unsigned long __init mrst_calibrate_tsc(void)
199{
200 unsigned long fast_calibrate;
201 u32 lo, hi, ratio, fsb;
202
203 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
204 pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
205 ratio = (hi >> 8) & 0x1f;
206 pr_debug("ratio is %d\n", ratio);
207 if (!ratio) {
208 pr_err("read a zero ratio, should be incorrect!\n");
209 pr_err("force tsc ratio to 16 ...\n");
210 ratio = 16;
211 }
212 rdmsr(MSR_FSB_FREQ, lo, hi);
213 if ((lo & 0x7) == 0x7)
214 fsb = PENWELL_FSB_FREQ_83SKU;
215 else
216 fsb = PENWELL_FSB_FREQ_100SKU;
217 fast_calibrate = ratio * fsb;
218 pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
219 lapic_timer_frequency = fsb * 1000 / HZ;
220 /* mark tsc clocksource as reliable */
221 set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
222
223 if (fast_calibrate)
224 return fast_calibrate;
225
226 return 0;
227}
228
229static void __init mrst_time_init(void)
230{
231 sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
232 switch (mrst_timer_options) {
233 case MRST_TIMER_APBT_ONLY:
234 break;
235 case MRST_TIMER_LAPIC_APBT:
236 x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
237 x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
238 break;
239 default:
240 if (!boot_cpu_has(X86_FEATURE_ARAT))
241 break;
242 x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
243 x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
244 return;
245 }
246 /* we need at least one APB timer */
247 pre_init_apic_IRQ0();
248 apbt_time_init();
249}
250
251static void mrst_arch_setup(void)
252{
253 if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
254 __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
255 else {
256 pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
257 boot_cpu_data.x86, boot_cpu_data.x86_model);
258 __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL;
259 }
260}
261
262/* MID systems don't have i8042 controller */
263static int mrst_i8042_detect(void)
264{
265 return 0;
266}
267
268/*
269 * Moorestown does not have external NMI source nor port 0x61 to report
270 * NMI status. The possible NMI sources are from pmu as a result of NMI
271 * watchdog or lock debug. Reading io port 0x61 results in 0xff which
272 * misled NMI handler.
273 */
274static unsigned char mrst_get_nmi_reason(void)
275{
276 return 0;
277}
278
279/*
280 * Moorestown specific x86_init function overrides and early setup
281 * calls.
282 */
283void __init x86_mrst_early_setup(void)
284{
285 x86_init.resources.probe_roms = x86_init_noop;
286 x86_init.resources.reserve_resources = x86_init_noop;
287
288 x86_init.timers.timer_init = mrst_time_init;
289 x86_init.timers.setup_percpu_clockev = x86_init_noop;
290
291 x86_init.irqs.pre_vector_init = x86_init_noop;
292
293 x86_init.oem.arch_setup = mrst_arch_setup;
294
295 x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock;
296
297 x86_platform.calibrate_tsc = mrst_calibrate_tsc;
298 x86_platform.i8042_detect = mrst_i8042_detect;
299 x86_init.timers.wallclock_init = mrst_rtc_init;
300 x86_platform.get_nmi_reason = mrst_get_nmi_reason;
301
302 x86_init.pci.init = pci_mrst_init;
303 x86_init.pci.fixup_irqs = x86_init_noop;
304
305 legacy_pic = &null_legacy_pic;
306
307 /* Moorestown specific power_off/restart method */
308 pm_power_off = mrst_power_off;
309 machine_ops.emergency_restart = mrst_reboot;
310
311 /* Avoid searching for BIOS MP tables */
312 x86_init.mpparse.find_smp_config = x86_init_noop;
313 x86_init.mpparse.get_smp_config = x86_init_uint_noop;
314 set_bit(MP_BUS_ISA, mp_bus_not_pci);
315}
316
317/*
318 * if user does not want to use per CPU apb timer, just give it a lower rating
319 * than local apic timer and skip the late per cpu timer init.
320 */
321static inline int __init setup_x86_mrst_timer(char *arg)
322{
323 if (!arg)
324 return -EINVAL;
325
326 if (strcmp("apbt_only", arg) == 0)
327 mrst_timer_options = MRST_TIMER_APBT_ONLY;
328 else if (strcmp("lapic_and_apbt", arg) == 0)
329 mrst_timer_options = MRST_TIMER_LAPIC_APBT;
330 else {
331 pr_warning("X86 MRST timer option %s not recognised"
332 " use x86_mrst_timer=apbt_only or lapic_and_apbt\n",
333 arg);
334 return -EINVAL;
335 }
336 return 0;
337}
338__setup("x86_mrst_timer=", setup_x86_mrst_timer);
339
340/*
341 * Parsing GPIO table first, since the DEVS table will need this table
342 * to map the pin name to the actual pin.
343 */
344static struct sfi_gpio_table_entry *gpio_table;
345static int gpio_num_entry;
346
347static int __init sfi_parse_gpio(struct sfi_table_header *table)
348{
349 struct sfi_table_simple *sb;
350 struct sfi_gpio_table_entry *pentry;
351 int num, i;
352
353 if (gpio_table)
354 return 0;
355 sb = (struct sfi_table_simple *)table;
356 num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry);
357 pentry = (struct sfi_gpio_table_entry *)sb->pentry;
358
359 gpio_table = kmalloc(num * sizeof(*pentry), GFP_KERNEL);
360 if (!gpio_table)
361 return -1;
362 memcpy(gpio_table, pentry, num * sizeof(*pentry));
363 gpio_num_entry = num;
364
365 pr_debug("GPIO pin info:\n");
366 for (i = 0; i < num; i++, pentry++)
367 pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s,"
368 " pin = %d\n", i,
369 pentry->controller_name,
370 pentry->pin_name,
371 pentry->pin_no);
372 return 0;
373}
374
375static int get_gpio_by_name(const char *name)
376{
377 struct sfi_gpio_table_entry *pentry = gpio_table;
378 int i;
379
380 if (!pentry)
381 return -1;
382 for (i = 0; i < gpio_num_entry; i++, pentry++) {
383 if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN))
384 return pentry->pin_no;
385 }
386 return -1;
387}
388
389/*
390 * Here defines the array of devices platform data that IAFW would export
391 * through SFI "DEVS" table, we use name and type to match the device and
392 * its platform data.
393 */
394struct devs_id {
395 char name[SFI_NAME_LEN + 1];
396 u8 type;
397 u8 delay;
398 void *(*get_platform_data)(void *info);
399};
400
401/* the offset for the mapping of global gpio pin to irq */
402#define MRST_IRQ_OFFSET 0x100
403
404static void __init *pmic_gpio_platform_data(void *info)
405{
406 static struct intel_pmic_gpio_platform_data pmic_gpio_pdata;
407 int gpio_base = get_gpio_by_name("pmic_gpio_base");
408
409 if (gpio_base == -1)
410 gpio_base = 64;
411 pmic_gpio_pdata.gpio_base = gpio_base;
412 pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET;
413 pmic_gpio_pdata.gpiointr = 0xffffeff8;
414
415 return &pmic_gpio_pdata;
416}
417
418static void __init *max3111_platform_data(void *info)
419{
420 struct spi_board_info *spi_info = info;
421 int intr = get_gpio_by_name("max3111_int");
422
423 spi_info->mode = SPI_MODE_0;
424 if (intr == -1)
425 return NULL;
426 spi_info->irq = intr + MRST_IRQ_OFFSET;
427 return NULL;
428}
429
430/* we have multiple max7315 on the board ... */
431#define MAX7315_NUM 2
432static void __init *max7315_platform_data(void *info)
433{
434 static struct pca953x_platform_data max7315_pdata[MAX7315_NUM];
435 static int nr;
436 struct pca953x_platform_data *max7315 = &max7315_pdata[nr];
437 struct i2c_board_info *i2c_info = info;
438 int gpio_base, intr;
439 char base_pin_name[SFI_NAME_LEN + 1];
440 char intr_pin_name[SFI_NAME_LEN + 1];
441
442 if (nr == MAX7315_NUM) {
443 pr_err("too many max7315s, we only support %d\n",
444 MAX7315_NUM);
445 return NULL;
446 }
447 /* we have several max7315 on the board, we only need load several
448 * instances of the same pca953x driver to cover them
449 */
450 strcpy(i2c_info->type, "max7315");
451 if (nr++) {
452 sprintf(base_pin_name, "max7315_%d_base", nr);
453 sprintf(intr_pin_name, "max7315_%d_int", nr);
454 } else {
455 strcpy(base_pin_name, "max7315_base");
456 strcpy(intr_pin_name, "max7315_int");
457 }
458
459 gpio_base = get_gpio_by_name(base_pin_name);
460 intr = get_gpio_by_name(intr_pin_name);
461
462 if (gpio_base == -1)
463 return NULL;
464 max7315->gpio_base = gpio_base;
465 if (intr != -1) {
466 i2c_info->irq = intr + MRST_IRQ_OFFSET;
467 max7315->irq_base = gpio_base + MRST_IRQ_OFFSET;
468 } else {
469 i2c_info->irq = -1;
470 max7315->irq_base = -1;
471 }
472 return max7315;
473}
474
475static void *tca6416_platform_data(void *info)
476{
477 static struct pca953x_platform_data tca6416;
478 struct i2c_board_info *i2c_info = info;
479 int gpio_base, intr;
480 char base_pin_name[SFI_NAME_LEN + 1];
481 char intr_pin_name[SFI_NAME_LEN + 1];
482
483 strcpy(i2c_info->type, "tca6416");
484 strcpy(base_pin_name, "tca6416_base");
485 strcpy(intr_pin_name, "tca6416_int");
486
487 gpio_base = get_gpio_by_name(base_pin_name);
488 intr = get_gpio_by_name(intr_pin_name);
489
490 if (gpio_base == -1)
491 return NULL;
492 tca6416.gpio_base = gpio_base;
493 if (intr != -1) {
494 i2c_info->irq = intr + MRST_IRQ_OFFSET;
495 tca6416.irq_base = gpio_base + MRST_IRQ_OFFSET;
496 } else {
497 i2c_info->irq = -1;
498 tca6416.irq_base = -1;
499 }
500 return &tca6416;
501}
502
503static void *mpu3050_platform_data(void *info)
504{
505 struct i2c_board_info *i2c_info = info;
506 int intr = get_gpio_by_name("mpu3050_int");
507
508 if (intr == -1)
509 return NULL;
510
511 i2c_info->irq = intr + MRST_IRQ_OFFSET;
512 return NULL;
513}
514
515static void __init *emc1403_platform_data(void *info)
516{
517 static short intr2nd_pdata;
518 struct i2c_board_info *i2c_info = info;
519 int intr = get_gpio_by_name("thermal_int");
520 int intr2nd = get_gpio_by_name("thermal_alert");
521
522 if (intr == -1 || intr2nd == -1)
523 return NULL;
524
525 i2c_info->irq = intr + MRST_IRQ_OFFSET;
526 intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET;
527
528 return &intr2nd_pdata;
529}
530
531static void __init *lis331dl_platform_data(void *info)
532{
533 static short intr2nd_pdata;
534 struct i2c_board_info *i2c_info = info;
535 int intr = get_gpio_by_name("accel_int");
536 int intr2nd = get_gpio_by_name("accel_2");
537
538 if (intr == -1 || intr2nd == -1)
539 return NULL;
540
541 i2c_info->irq = intr + MRST_IRQ_OFFSET;
542 intr2nd_pdata = intr2nd + MRST_IRQ_OFFSET;
543
544 return &intr2nd_pdata;
545}
546
547static void __init *no_platform_data(void *info)
548{
549 return NULL;
550}
551
552static struct resource msic_resources[] = {
553 {
554 .start = INTEL_MSIC_IRQ_PHYS_BASE,
555 .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
556 .flags = IORESOURCE_MEM,
557 },
558};
559
560static struct intel_msic_platform_data msic_pdata;
561
562static struct platform_device msic_device = {
563 .name = "intel_msic",
564 .id = -1,
565 .dev = {
566 .platform_data = &msic_pdata,
567 },
568 .num_resources = ARRAY_SIZE(msic_resources),
569 .resource = msic_resources,
570};
571
572static inline bool mrst_has_msic(void)
573{
574 return mrst_identify_cpu() == MRST_CPU_CHIP_PENWELL;
575}
576
577static int msic_scu_status_change(struct notifier_block *nb,
578 unsigned long code, void *data)
579{
580 if (code == SCU_DOWN) {
581 platform_device_unregister(&msic_device);
582 return 0;
583 }
584
585 return platform_device_register(&msic_device);
586}
587
588static int __init msic_init(void)
589{
590 static struct notifier_block msic_scu_notifier = {
591 .notifier_call = msic_scu_status_change,
592 };
593
594 /*
595 * We need to be sure that the SCU IPC is ready before MSIC device
596 * can be registered.
597 */
598 if (mrst_has_msic())
599 intel_scu_notifier_add(&msic_scu_notifier);
600
601 return 0;
602}
603arch_initcall(msic_init);
604
605/*
606 * msic_generic_platform_data - sets generic platform data for the block
607 * @info: pointer to the SFI device table entry for this block
608 * @block: MSIC block
609 *
610 * Function sets IRQ number from the SFI table entry for given device to
611 * the MSIC platform data.
612 */
613static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
614{
615 struct sfi_device_table_entry *entry = info;
616
617 BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
618 msic_pdata.irq[block] = entry->irq;
619
620 return no_platform_data(info);
621}
622
623static void *msic_battery_platform_data(void *info)
624{
625 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
626}
627
628static void *msic_gpio_platform_data(void *info)
629{
630 static struct intel_msic_gpio_pdata pdata;
631 int gpio = get_gpio_by_name("msic_gpio_base");
632
633 if (gpio < 0)
634 return NULL;
635
636 pdata.gpio_base = gpio;
637 msic_pdata.gpio = &pdata;
638
639 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
640}
641
642static void *msic_audio_platform_data(void *info)
643{
644 struct platform_device *pdev;
645
646 pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
647 if (IS_ERR(pdev)) {
648 pr_err("failed to create audio platform device\n");
649 return NULL;
650 }
651
652 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
653}
654
655static void *msic_power_btn_platform_data(void *info)
656{
657 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
658}
659
660static void *msic_ocd_platform_data(void *info)
661{
662 static struct intel_msic_ocd_pdata pdata;
663 int gpio = get_gpio_by_name("ocd_gpio");
664
665 if (gpio < 0)
666 return NULL;
667
668 pdata.gpio = gpio;
669 msic_pdata.ocd = &pdata;
670
671 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
672}
673
674static void *msic_thermal_platform_data(void *info)
675{
676 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL);
677}
678
679/* tc35876x DSI-LVDS bridge chip and panel platform data */
680static void *tc35876x_platform_data(void *data)
681{
682 static struct tc35876x_platform_data pdata;
683
684 /* gpio pins set to -1 will not be used by the driver */
685 pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
686 pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
687 pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
688
689 return &pdata;
690}
691
692static const struct devs_id __initconst device_ids[] = {
693 {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data},
694 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data},
695 {"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data},
696 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data},
697 {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
698 {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data},
699 {"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data},
700 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data},
701 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data},
702 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data},
703 {"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data},
704 {"i2c_disp_brig", SFI_DEV_TYPE_I2C, 0, &tc35876x_platform_data},
705
706 /* MSIC subdevices */
707 {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data},
708 {"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data},
709 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data},
710 {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data},
711 {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data},
712 {"msic_thermal", SFI_DEV_TYPE_IPC, 1, &msic_thermal_platform_data},
713
714 {},
715};
716
717#define MAX_IPCDEVS 24
718static struct platform_device *ipc_devs[MAX_IPCDEVS];
719static int ipc_next_dev;
720
721#define MAX_SCU_SPI 24
722static struct spi_board_info *spi_devs[MAX_SCU_SPI];
723static int spi_next_dev;
724
725#define MAX_SCU_I2C 24
726static struct i2c_board_info *i2c_devs[MAX_SCU_I2C];
727static int i2c_bus[MAX_SCU_I2C];
728static int i2c_next_dev;
729
730static void __init intel_scu_device_register(struct platform_device *pdev)
731{
732 if(ipc_next_dev == MAX_IPCDEVS)
733 pr_err("too many SCU IPC devices");
734 else
735 ipc_devs[ipc_next_dev++] = pdev;
736}
737
738static void __init intel_scu_spi_device_register(struct spi_board_info *sdev)
739{
740 struct spi_board_info *new_dev;
741
742 if (spi_next_dev == MAX_SCU_SPI) {
743 pr_err("too many SCU SPI devices");
744 return;
745 }
746
747 new_dev = kzalloc(sizeof(*sdev), GFP_KERNEL);
748 if (!new_dev) {
749 pr_err("failed to alloc mem for delayed spi dev %s\n",
750 sdev->modalias);
751 return;
752 }
753 memcpy(new_dev, sdev, sizeof(*sdev));
754
755 spi_devs[spi_next_dev++] = new_dev;
756}
757
758static void __init intel_scu_i2c_device_register(int bus,
759 struct i2c_board_info *idev)
760{
761 struct i2c_board_info *new_dev;
762
763 if (i2c_next_dev == MAX_SCU_I2C) {
764 pr_err("too many SCU I2C devices");
765 return;
766 }
767
768 new_dev = kzalloc(sizeof(*idev), GFP_KERNEL);
769 if (!new_dev) {
770 pr_err("failed to alloc mem for delayed i2c dev %s\n",
771 idev->type);
772 return;
773 }
774 memcpy(new_dev, idev, sizeof(*idev));
775
776 i2c_bus[i2c_next_dev] = bus;
777 i2c_devs[i2c_next_dev++] = new_dev;
778}
779
780BLOCKING_NOTIFIER_HEAD(intel_scu_notifier);
781EXPORT_SYMBOL_GPL(intel_scu_notifier);
782
783/* Called by IPC driver */
784void intel_scu_devices_create(void)
785{
786 int i;
787
788 for (i = 0; i < ipc_next_dev; i++)
789 platform_device_add(ipc_devs[i]);
790
791 for (i = 0; i < spi_next_dev; i++)
792 spi_register_board_info(spi_devs[i], 1);
793
794 for (i = 0; i < i2c_next_dev; i++) {
795 struct i2c_adapter *adapter;
796 struct i2c_client *client;
797
798 adapter = i2c_get_adapter(i2c_bus[i]);
799 if (adapter) {
800 client = i2c_new_device(adapter, i2c_devs[i]);
801 if (!client)
802 pr_err("can't create i2c device %s\n",
803 i2c_devs[i]->type);
804 } else
805 i2c_register_board_info(i2c_bus[i], i2c_devs[i], 1);
806 }
807 intel_scu_notifier_post(SCU_AVAILABLE, NULL);
808}
809EXPORT_SYMBOL_GPL(intel_scu_devices_create);
810
811/* Called by IPC driver */
812void intel_scu_devices_destroy(void)
813{
814 int i;
815
816 intel_scu_notifier_post(SCU_DOWN, NULL);
817
818 for (i = 0; i < ipc_next_dev; i++)
819 platform_device_del(ipc_devs[i]);
820}
821EXPORT_SYMBOL_GPL(intel_scu_devices_destroy);
822
823static void __init install_irq_resource(struct platform_device *pdev, int irq)
824{
825 /* Single threaded */
826 static struct resource __initdata res = {
827 .name = "IRQ",
828 .flags = IORESOURCE_IRQ,
829 };
830 res.start = irq;
831 platform_device_add_resources(pdev, &res, 1);
832}
833
834static void __init sfi_handle_ipc_dev(struct sfi_device_table_entry *entry)
835{
836 const struct devs_id *dev = device_ids;
837 struct platform_device *pdev;
838 void *pdata = NULL;
839
840 while (dev->name[0]) {
841 if (dev->type == SFI_DEV_TYPE_IPC &&
842 !strncmp(dev->name, entry->name, SFI_NAME_LEN)) {
843 pdata = dev->get_platform_data(entry);
844 break;
845 }
846 dev++;
847 }
848
849 /*
850 * On Medfield the platform device creation is handled by the MSIC
851 * MFD driver so we don't need to do it here.
852 */
853 if (mrst_has_msic())
854 return;
855
856 pdev = platform_device_alloc(entry->name, 0);
857 if (pdev == NULL) {
858 pr_err("out of memory for SFI platform device '%s'.\n",
859 entry->name);
860 return;
861 }
862 install_irq_resource(pdev, entry->irq);
863
864 pdev->dev.platform_data = pdata;
865 intel_scu_device_register(pdev);
866}
867
868static void __init sfi_handle_spi_dev(struct spi_board_info *spi_info)
869{
870 const struct devs_id *dev = device_ids;
871 void *pdata = NULL;
872
873 while (dev->name[0]) {
874 if (dev->type == SFI_DEV_TYPE_SPI &&
875 !strncmp(dev->name, spi_info->modalias, SFI_NAME_LEN)) {
876 pdata = dev->get_platform_data(spi_info);
877 break;
878 }
879 dev++;
880 }
881 spi_info->platform_data = pdata;
882 if (dev->delay)
883 intel_scu_spi_device_register(spi_info);
884 else
885 spi_register_board_info(spi_info, 1);
886}
887
888static void __init sfi_handle_i2c_dev(int bus, struct i2c_board_info *i2c_info)
889{
890 const struct devs_id *dev = device_ids;
891 void *pdata = NULL;
892
893 while (dev->name[0]) {
894 if (dev->type == SFI_DEV_TYPE_I2C &&
895 !strncmp(dev->name, i2c_info->type, SFI_NAME_LEN)) {
896 pdata = dev->get_platform_data(i2c_info);
897 break;
898 }
899 dev++;
900 }
901 i2c_info->platform_data = pdata;
902
903 if (dev->delay)
904 intel_scu_i2c_device_register(bus, i2c_info);
905 else
906 i2c_register_board_info(bus, i2c_info, 1);
907 }
908
909
910static int __init sfi_parse_devs(struct sfi_table_header *table)
911{
912 struct sfi_table_simple *sb;
913 struct sfi_device_table_entry *pentry;
914 struct spi_board_info spi_info;
915 struct i2c_board_info i2c_info;
916 int num, i, bus;
917 int ioapic;
918 struct io_apic_irq_attr irq_attr;
919
920 sb = (struct sfi_table_simple *)table;
921 num = SFI_GET_NUM_ENTRIES(sb, struct sfi_device_table_entry);
922 pentry = (struct sfi_device_table_entry *)sb->pentry;
923
924 for (i = 0; i < num; i++, pentry++) {
925 int irq = pentry->irq;
926
927 if (irq != (u8)0xff) { /* native RTE case */
928 /* these SPI2 devices are not exposed to system as PCI
929 * devices, but they have separate RTE entry in IOAPIC
930 * so we have to enable them one by one here
931 */
932 ioapic = mp_find_ioapic(irq);
933 irq_attr.ioapic = ioapic;
934 irq_attr.ioapic_pin = irq;
935 irq_attr.trigger = 1;
936 irq_attr.polarity = 1;
937 io_apic_set_pci_routing(NULL, irq, &irq_attr);
938 } else
939 irq = 0; /* No irq */
940
941 switch (pentry->type) {
942 case SFI_DEV_TYPE_IPC:
943 pr_debug("info[%2d]: IPC bus, name = %16.16s, "
944 "irq = 0x%2x\n", i, pentry->name, pentry->irq);
945 sfi_handle_ipc_dev(pentry);
946 break;
947 case SFI_DEV_TYPE_SPI:
948 memset(&spi_info, 0, sizeof(spi_info));
949 strncpy(spi_info.modalias, pentry->name, SFI_NAME_LEN);
950 spi_info.irq = irq;
951 spi_info.bus_num = pentry->host_num;
952 spi_info.chip_select = pentry->addr;
953 spi_info.max_speed_hz = pentry->max_freq;
954 pr_debug("info[%2d]: SPI bus = %d, name = %16.16s, "
955 "irq = 0x%2x, max_freq = %d, cs = %d\n", i,
956 spi_info.bus_num,
957 spi_info.modalias,
958 spi_info.irq,
959 spi_info.max_speed_hz,
960 spi_info.chip_select);
961 sfi_handle_spi_dev(&spi_info);
962 break;
963 case SFI_DEV_TYPE_I2C:
964 memset(&i2c_info, 0, sizeof(i2c_info));
965 bus = pentry->host_num;
966 strncpy(i2c_info.type, pentry->name, SFI_NAME_LEN);
967 i2c_info.irq = irq;
968 i2c_info.addr = pentry->addr;
969 pr_debug("info[%2d]: I2C bus = %d, name = %16.16s, "
970 "irq = 0x%2x, addr = 0x%x\n", i, bus,
971 i2c_info.type,
972 i2c_info.irq,
973 i2c_info.addr);
974 sfi_handle_i2c_dev(bus, &i2c_info);
975 break;
976 case SFI_DEV_TYPE_UART:
977 case SFI_DEV_TYPE_HSI:
978 default:
979 ;
980 }
981 }
982 return 0;
983}
984
985static int __init mrst_platform_init(void)
986{
987 sfi_table_parse(SFI_SIG_GPIO, NULL, NULL, sfi_parse_gpio);
988 sfi_table_parse(SFI_SIG_DEVS, NULL, NULL, sfi_parse_devs);
989 return 0;
990}
991arch_initcall(mrst_platform_init);
992
993/*
994 * we will search these buttons in SFI GPIO table (by name)
995 * and register them dynamically. Please add all possible
996 * buttons here, we will shrink them if no GPIO found.
997 */
998static struct gpio_keys_button gpio_button[] = {
999 {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000},
1000 {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20},
1001 {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20},
1002 {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20},
1003 {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20},
1004 {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20},
1005 {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20},
1006 {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20},
1007 {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20},
1008 {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20},
1009};
1010
1011static struct gpio_keys_platform_data mrst_gpio_keys = {
1012 .buttons = gpio_button,
1013 .rep = 1,
1014 .nbuttons = -1, /* will fill it after search */
1015};
1016
1017static struct platform_device pb_device = {
1018 .name = "gpio-keys",
1019 .id = -1,
1020 .dev = {
1021 .platform_data = &mrst_gpio_keys,
1022 },
1023};
1024
1025/*
1026 * Shrink the non-existent buttons, register the gpio button
1027 * device if there is some
1028 */
1029static int __init pb_keys_init(void)
1030{
1031 struct gpio_keys_button *gb = gpio_button;
1032 int i, num, good = 0;
1033
1034 num = sizeof(gpio_button) / sizeof(struct gpio_keys_button);
1035 for (i = 0; i < num; i++) {
1036 gb[i].gpio = get_gpio_by_name(gb[i].desc);
1037 pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc, gb[i].gpio);
1038 if (gb[i].gpio == -1)
1039 continue;
1040
1041 if (i != good)
1042 gb[good] = gb[i];
1043 good++;
1044 }
1045
1046 if (good) {
1047 mrst_gpio_keys.nbuttons = good;
1048 return platform_device_register(&pb_device);
1049 }
1050 return 0;
1051}
1052late_initcall(pb_keys_init);