blob: 40915698b9b725a9cfc4e6c49e643de65ce90818 [file] [log] [blame]
Thomas Gleixner3f4110a2009-08-29 14:54:20 +02001/*
Kuppuswamy Sathyanarayanan05454c22013-10-17 15:35:27 -07002 * intel-mid.c: Intel MID platform setup code
Thomas Gleixner3f4110a2009-08-29 14:54:20 +02003 *
Kuppuswamy Sathyanarayanan05454c22013-10-17 15:35:27 -07004 * (C) Copyright 2008, 2012 Intel Corporation
Thomas Gleixner3f4110a2009-08-29 14:54:20 +02005 * Author: Jacob Pan (jacob.jun.pan@intel.com)
Kuppuswamy Sathyanarayanan05454c22013-10-17 15:35:27 -07006 * Author: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@intel.com>
Thomas Gleixner3f4110a2009-08-29 14:54:20 +02007 *
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 */
Feng Tang1da4b1c2010-11-09 11:22:58 +000013
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -070014#define pr_fmt(fmt) "intel_mid: " fmt
Feng Tang1da4b1c2010-11-09 11:22:58 +000015
Thomas Gleixner3f4110a2009-08-29 14:54:20 +020016#include <linux/init.h>
Jacob Pan16ab5392010-02-12 03:08:30 -080017#include <linux/kernel.h>
Feng Tangefe3ed92011-08-26 11:25:14 +010018#include <linux/interrupt.h>
19#include <linux/scatterlist.h>
Jacob Pan16ab5392010-02-12 03:08:30 -080020#include <linux/sfi.h>
21#include <linux/irq.h>
Feng Tangcf089452010-02-12 03:37:38 -080022#include <linux/module.h>
Alan Cox42c25442011-09-07 16:06:51 +030023#include <linux/notifier.h>
Thomas Gleixner3f4110a2009-08-29 14:54:20 +020024
25#include <asm/setup.h>
Jacob Pan16ab5392010-02-12 03:08:30 -080026#include <asm/mpspec_def.h>
27#include <asm/hw_irq.h>
28#include <asm/apic.h>
29#include <asm/io_apic.h>
Kuppuswamy Sathyanarayanan05454c22013-10-17 15:35:27 -070030#include <asm/intel-mid.h>
31#include <asm/intel_mid_vrtc.h>
Jacob Pan5b78b672010-02-12 02:29:11 -080032#include <asm/io.h>
33#include <asm/i8259.h>
Feng Tang1da4b1c2010-11-09 11:22:58 +000034#include <asm/intel_scu_ipc.h>
Jacob Pan3746c6b2010-02-12 05:01:12 -080035#include <asm/apb_timer.h>
Alek Ducfb505a2010-11-10 16:50:08 +000036#include <asm/reboot.h>
Thomas Gleixner3f4110a2009-08-29 14:54:20 +020037
Jacob Pana875c012010-05-19 12:01:25 -070038/*
39 * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock,
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -070040 * cmdline option x86_intel_mid_timer can be used to override the configuration
Jacob Pana875c012010-05-19 12:01:25 -070041 * 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
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -070059enum intel_mid_timer_options intel_mid_timer_options;
Jacob Pana875c012010-05-19 12:01:25 -070060
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -070061enum intel_mid_cpu_type __intel_mid_cpu_chip;
62EXPORT_SYMBOL_GPL(__intel_mid_cpu_chip);
Jacob Pana0c173b2010-05-19 12:01:24 -070063
Kuppuswamy Sathyanarayanan49c72a02013-10-17 15:35:32 -070064static void __init ipc_device_handler(struct sfi_device_table_entry *pentry,
65 struct devs_id *dev);
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -070066static void intel_mid_power_off(void)
Jacob Pan48bc5562011-11-16 16:07:22 +000067{
Jacob Pan48bc5562011-11-16 16:07:22 +000068}
69
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -070070static void intel_mid_reboot(void)
Jacob Pan48bc5562011-11-16 16:07:22 +000071{
Alan Cox1a8359e2012-01-26 17:33:30 +000072 intel_scu_ipc_simple_command(IPCMSG_COLD_BOOT, 0);
Jacob Pan48bc5562011-11-16 16:07:22 +000073}
74
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -070075static unsigned long __init intel_mid_calibrate_tsc(void)
Jacob Pan3746c6b2010-02-12 05:01:12 -080076{
Alan Cox1a8359e2012-01-26 17:33:30 +000077 unsigned long fast_calibrate;
78 u32 lo, hi, ratio, fsb;
Jacob Pan3746c6b2010-02-12 05:01:12 -080079
Alan Cox1a8359e2012-01-26 17:33:30 +000080 rdmsr(MSR_IA32_PERF_STATUS, lo, hi);
81 pr_debug("IA32 perf status is 0x%x, 0x%0x\n", lo, hi);
82 ratio = (hi >> 8) & 0x1f;
83 pr_debug("ratio is %d\n", ratio);
84 if (!ratio) {
85 pr_err("read a zero ratio, should be incorrect!\n");
86 pr_err("force tsc ratio to 16 ...\n");
87 ratio = 16;
Dirk Brandewie0a915322011-11-10 13:42:53 +000088 }
Alan Cox1a8359e2012-01-26 17:33:30 +000089 rdmsr(MSR_FSB_FREQ, lo, hi);
90 if ((lo & 0x7) == 0x7)
91 fsb = PENWELL_FSB_FREQ_83SKU;
92 else
93 fsb = PENWELL_FSB_FREQ_100SKU;
94 fast_calibrate = ratio * fsb;
95 pr_debug("read penwell tsc %lu khz\n", fast_calibrate);
96 lapic_timer_frequency = fsb * 1000 / HZ;
97 /* mark tsc clocksource as reliable */
98 set_cpu_cap(&boot_cpu_data, X86_FEATURE_TSC_RELIABLE);
Kuppuswamy Sathyanarayanan05454c22013-10-17 15:35:27 -070099
Jacob Pan3746c6b2010-02-12 05:01:12 -0800100 if (fast_calibrate)
101 return fast_calibrate;
102
103 return 0;
104}
105
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700106static void __init intel_mid_time_init(void)
Jacob Pan3746c6b2010-02-12 05:01:12 -0800107{
Jacob Pan7f05dec2010-11-09 11:28:43 +0000108 sfi_table_parse(SFI_SIG_MTMR, NULL, NULL, sfi_parse_mtmr);
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700109 switch (intel_mid_timer_options) {
110 case INTEL_MID_TIMER_APBT_ONLY:
Jacob Pana875c012010-05-19 12:01:25 -0700111 break;
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700112 case INTEL_MID_TIMER_LAPIC_APBT:
Jacob Pana875c012010-05-19 12:01:25 -0700113 x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
114 x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
115 break;
116 default:
117 if (!boot_cpu_has(X86_FEATURE_ARAT))
118 break;
119 x86_init.timers.setup_percpu_clockev = setup_boot_APIC_clock;
120 x86_cpuinit.setup_percpu_clockev = setup_secondary_APIC_clock;
121 return;
122 }
123 /* we need at least one APB timer */
Jacob Pan3746c6b2010-02-12 05:01:12 -0800124 pre_init_apic_IRQ0();
125 apbt_time_init();
126}
127
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700128static void __cpuinit intel_mid_arch_setup(void)
Jacob Pan3746c6b2010-02-12 05:01:12 -0800129{
Jacob Pana0c173b2010-05-19 12:01:24 -0700130 if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27)
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700131 __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
Jacob Pana0c173b2010-05-19 12:01:24 -0700132 else {
Alan Cox1a8359e2012-01-26 17:33:30 +0000133 pr_err("Unknown Intel MID CPU (%d:%d), default to Penwell\n",
Jacob Pana0c173b2010-05-19 12:01:24 -0700134 boot_cpu_data.x86, boot_cpu_data.x86_model);
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700135 __intel_mid_cpu_chip = INTEL_MID_CPU_CHIP_PENWELL;
Jacob Pana0c173b2010-05-19 12:01:24 -0700136 }
Jacob Pana0c173b2010-05-19 12:01:24 -0700137}
Jacob Pan3746c6b2010-02-12 05:01:12 -0800138
Feng Tang6d2cce62010-07-05 23:03:19 +0800139/* MID systems don't have i8042 controller */
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700140static int intel_mid_i8042_detect(void)
Feng Tang6d2cce62010-07-05 23:03:19 +0800141{
142 return 0;
143}
144
Jacob Pan3746c6b2010-02-12 05:01:12 -0800145/*
Jacob Pan064a59b2011-11-10 13:43:05 +0000146 * Moorestown does not have external NMI source nor port 0x61 to report
147 * NMI status. The possible NMI sources are from pmu as a result of NMI
148 * watchdog or lock debug. Reading io port 0x61 results in 0xff which
149 * misled NMI handler.
150 */
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700151static unsigned char intel_mid_get_nmi_reason(void)
Jacob Pan064a59b2011-11-10 13:43:05 +0000152{
153 return 0;
154}
155
156/*
Thomas Gleixner3f4110a2009-08-29 14:54:20 +0200157 * Moorestown specific x86_init function overrides and early setup
158 * calls.
159 */
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700160void __init x86_intel_mid_early_setup(void)
Thomas Gleixner3f4110a2009-08-29 14:54:20 +0200161{
162 x86_init.resources.probe_roms = x86_init_noop;
163 x86_init.resources.reserve_resources = x86_init_noop;
Jacob Pan5b78b672010-02-12 02:29:11 -0800164
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700165 x86_init.timers.timer_init = intel_mid_time_init;
Jacob Pana875c012010-05-19 12:01:25 -0700166 x86_init.timers.setup_percpu_clockev = x86_init_noop;
Jacob Pan3746c6b2010-02-12 05:01:12 -0800167
168 x86_init.irqs.pre_vector_init = x86_init_noop;
169
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700170 x86_init.oem.arch_setup = intel_mid_arch_setup;
Jacob Pana0c173b2010-05-19 12:01:24 -0700171
Jacob Pana875c012010-05-19 12:01:25 -0700172 x86_cpuinit.setup_percpu_clockev = apbt_setup_secondary_clock;
Jacob Pan3746c6b2010-02-12 05:01:12 -0800173
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700174 x86_platform.calibrate_tsc = intel_mid_calibrate_tsc;
175 x86_platform.i8042_detect = intel_mid_i8042_detect;
176 x86_init.timers.wallclock_init = intel_mid_rtc_init;
177 x86_platform.get_nmi_reason = intel_mid_get_nmi_reason;
Jacob Pan064a59b2011-11-10 13:43:05 +0000178
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700179 x86_init.pci.init = intel_mid_pci_init;
Jacob Panaf2730f2010-02-12 10:31:47 -0800180 x86_init.pci.fixup_irqs = x86_init_noop;
181
Jacob Pan5b78b672010-02-12 02:29:11 -0800182 legacy_pic = &null_legacy_pic;
Jacob Panfea24e22010-05-14 14:41:20 -0700183
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700184 pm_power_off = intel_mid_power_off;
185 machine_ops.emergency_restart = intel_mid_reboot;
Alek Ducfb505a2010-11-10 16:50:08 +0000186
Jacob Panfea24e22010-05-14 14:41:20 -0700187 /* Avoid searching for BIOS MP tables */
188 x86_init.mpparse.find_smp_config = x86_init_noop;
189 x86_init.mpparse.get_smp_config = x86_init_uint_noop;
Jacob Pan9d90e492011-04-08 11:23:00 -0700190 set_bit(MP_BUS_ISA, mp_bus_not_pci);
Thomas Gleixner3f4110a2009-08-29 14:54:20 +0200191}
Jacob Pana875c012010-05-19 12:01:25 -0700192
193/*
194 * if user does not want to use per CPU apb timer, just give it a lower rating
195 * than local apic timer and skip the late per cpu timer init.
196 */
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700197static inline int __init setup_x86_intel_mid_timer(char *arg)
Jacob Pana875c012010-05-19 12:01:25 -0700198{
199 if (!arg)
200 return -EINVAL;
201
202 if (strcmp("apbt_only", arg) == 0)
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700203 intel_mid_timer_options = INTEL_MID_TIMER_APBT_ONLY;
Jacob Pana875c012010-05-19 12:01:25 -0700204 else if (strcmp("lapic_and_apbt", arg) == 0)
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700205 intel_mid_timer_options = INTEL_MID_TIMER_LAPIC_APBT;
Jacob Pana875c012010-05-19 12:01:25 -0700206 else {
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700207 pr_warn("X86 INTEL_MID timer option %s not recognised"
208 " use x86_intel_mid_timer=apbt_only or lapic_and_apbt\n",
Jacob Pana875c012010-05-19 12:01:25 -0700209 arg);
210 return -EINVAL;
211 }
212 return 0;
213}
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700214__setup("x86_intel_mid_timer=", setup_x86_intel_mid_timer);
Feng Tang1da4b1c2010-11-09 11:22:58 +0000215
Feng Tang1da4b1c2010-11-09 11:22:58 +0000216/* the offset for the mapping of global gpio pin to irq */
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700217#define INTEL_MID_IRQ_OFFSET 0x100
Feng Tang1da4b1c2010-11-09 11:22:58 +0000218
219static void __init *pmic_gpio_platform_data(void *info)
220{
221 static struct intel_pmic_gpio_platform_data pmic_gpio_pdata;
222 int gpio_base = get_gpio_by_name("pmic_gpio_base");
223
224 if (gpio_base == -1)
225 gpio_base = 64;
226 pmic_gpio_pdata.gpio_base = gpio_base;
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700227 pmic_gpio_pdata.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
Feng Tang1da4b1c2010-11-09 11:22:58 +0000228 pmic_gpio_pdata.gpiointr = 0xffffeff8;
229
230 return &pmic_gpio_pdata;
231}
232
233static void __init *max3111_platform_data(void *info)
234{
235 struct spi_board_info *spi_info = info;
236 int intr = get_gpio_by_name("max3111_int");
237
Feng Tangefe3ed92011-08-26 11:25:14 +0100238 spi_info->mode = SPI_MODE_0;
Feng Tang1da4b1c2010-11-09 11:22:58 +0000239 if (intr == -1)
240 return NULL;
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700241 spi_info->irq = intr + INTEL_MID_IRQ_OFFSET;
Feng Tang1da4b1c2010-11-09 11:22:58 +0000242 return NULL;
243}
244
245/* we have multiple max7315 on the board ... */
246#define MAX7315_NUM 2
247static void __init *max7315_platform_data(void *info)
248{
249 static struct pca953x_platform_data max7315_pdata[MAX7315_NUM];
250 static int nr;
251 struct pca953x_platform_data *max7315 = &max7315_pdata[nr];
252 struct i2c_board_info *i2c_info = info;
253 int gpio_base, intr;
254 char base_pin_name[SFI_NAME_LEN + 1];
255 char intr_pin_name[SFI_NAME_LEN + 1];
256
257 if (nr == MAX7315_NUM) {
258 pr_err("too many max7315s, we only support %d\n",
259 MAX7315_NUM);
260 return NULL;
261 }
262 /* we have several max7315 on the board, we only need load several
263 * instances of the same pca953x driver to cover them
264 */
265 strcpy(i2c_info->type, "max7315");
266 if (nr++) {
267 sprintf(base_pin_name, "max7315_%d_base", nr);
268 sprintf(intr_pin_name, "max7315_%d_int", nr);
269 } else {
270 strcpy(base_pin_name, "max7315_base");
271 strcpy(intr_pin_name, "max7315_int");
272 }
273
274 gpio_base = get_gpio_by_name(base_pin_name);
275 intr = get_gpio_by_name(intr_pin_name);
276
277 if (gpio_base == -1)
278 return NULL;
279 max7315->gpio_base = gpio_base;
280 if (intr != -1) {
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700281 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
282 max7315->irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
Feng Tang1da4b1c2010-11-09 11:22:58 +0000283 } else {
284 i2c_info->irq = -1;
285 max7315->irq_base = -1;
286 }
287 return max7315;
288}
289
Jekyll Lai28744b32011-11-16 18:01:20 +0000290static void *tca6416_platform_data(void *info)
291{
292 static struct pca953x_platform_data tca6416;
293 struct i2c_board_info *i2c_info = info;
294 int gpio_base, intr;
295 char base_pin_name[SFI_NAME_LEN + 1];
296 char intr_pin_name[SFI_NAME_LEN + 1];
297
298 strcpy(i2c_info->type, "tca6416");
299 strcpy(base_pin_name, "tca6416_base");
300 strcpy(intr_pin_name, "tca6416_int");
301
302 gpio_base = get_gpio_by_name(base_pin_name);
303 intr = get_gpio_by_name(intr_pin_name);
304
305 if (gpio_base == -1)
306 return NULL;
307 tca6416.gpio_base = gpio_base;
308 if (intr != -1) {
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700309 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
310 tca6416.irq_base = gpio_base + INTEL_MID_IRQ_OFFSET;
Jekyll Lai28744b32011-11-16 18:01:20 +0000311 } else {
312 i2c_info->irq = -1;
313 tca6416.irq_base = -1;
314 }
315 return &tca6416;
316}
317
318static void *mpu3050_platform_data(void *info)
319{
320 struct i2c_board_info *i2c_info = info;
321 int intr = get_gpio_by_name("mpu3050_int");
322
323 if (intr == -1)
324 return NULL;
325
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700326 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
Jekyll Lai28744b32011-11-16 18:01:20 +0000327 return NULL;
328}
329
Feng Tang1da4b1c2010-11-09 11:22:58 +0000330static void __init *emc1403_platform_data(void *info)
331{
332 static short intr2nd_pdata;
333 struct i2c_board_info *i2c_info = info;
334 int intr = get_gpio_by_name("thermal_int");
335 int intr2nd = get_gpio_by_name("thermal_alert");
336
337 if (intr == -1 || intr2nd == -1)
338 return NULL;
339
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700340 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
341 intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
Feng Tang1da4b1c2010-11-09 11:22:58 +0000342
343 return &intr2nd_pdata;
344}
345
346static void __init *lis331dl_platform_data(void *info)
347{
348 static short intr2nd_pdata;
349 struct i2c_board_info *i2c_info = info;
350 int intr = get_gpio_by_name("accel_int");
351 int intr2nd = get_gpio_by_name("accel_2");
352
353 if (intr == -1 || intr2nd == -1)
354 return NULL;
355
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700356 i2c_info->irq = intr + INTEL_MID_IRQ_OFFSET;
357 intr2nd_pdata = intr2nd + INTEL_MID_IRQ_OFFSET;
Feng Tang1da4b1c2010-11-09 11:22:58 +0000358
359 return &intr2nd_pdata;
360}
361
Vinod Koul86071532010-11-10 17:40:48 +0000362static void __init *no_platform_data(void *info)
363{
364 return NULL;
365}
366
Mika Westerberg360545c2011-10-18 12:41:22 +0300367static struct resource msic_resources[] = {
368 {
369 .start = INTEL_MSIC_IRQ_PHYS_BASE,
370 .end = INTEL_MSIC_IRQ_PHYS_BASE + 64 - 1,
371 .flags = IORESOURCE_MEM,
372 },
373};
374
375static struct intel_msic_platform_data msic_pdata;
376
377static struct platform_device msic_device = {
378 .name = "intel_msic",
379 .id = -1,
380 .dev = {
381 .platform_data = &msic_pdata,
382 },
383 .num_resources = ARRAY_SIZE(msic_resources),
384 .resource = msic_resources,
385};
386
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700387static inline bool intel_mid_has_msic(void)
Mika Westerberg360545c2011-10-18 12:41:22 +0300388{
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700389 return intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_PENWELL;
Mika Westerberg360545c2011-10-18 12:41:22 +0300390}
391
392static int msic_scu_status_change(struct notifier_block *nb,
393 unsigned long code, void *data)
394{
395 if (code == SCU_DOWN) {
396 platform_device_unregister(&msic_device);
397 return 0;
398 }
399
400 return platform_device_register(&msic_device);
401}
402
403static int __init msic_init(void)
404{
405 static struct notifier_block msic_scu_notifier = {
406 .notifier_call = msic_scu_status_change,
407 };
408
409 /*
410 * We need to be sure that the SCU IPC is ready before MSIC device
411 * can be registered.
412 */
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700413 if (intel_mid_has_msic())
Mika Westerberg360545c2011-10-18 12:41:22 +0300414 intel_scu_notifier_add(&msic_scu_notifier);
415
416 return 0;
417}
418arch_initcall(msic_init);
419
420/*
421 * msic_generic_platform_data - sets generic platform data for the block
422 * @info: pointer to the SFI device table entry for this block
423 * @block: MSIC block
424 *
425 * Function sets IRQ number from the SFI table entry for given device to
426 * the MSIC platform data.
427 */
428static void *msic_generic_platform_data(void *info, enum intel_msic_block block)
429{
430 struct sfi_device_table_entry *entry = info;
431
432 BUG_ON(block < 0 || block >= INTEL_MSIC_BLOCK_LAST);
433 msic_pdata.irq[block] = entry->irq;
434
435 return no_platform_data(info);
436}
437
438static void *msic_battery_platform_data(void *info)
439{
440 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_BATTERY);
441}
442
443static void *msic_gpio_platform_data(void *info)
444{
445 static struct intel_msic_gpio_pdata pdata;
446 int gpio = get_gpio_by_name("msic_gpio_base");
447
448 if (gpio < 0)
449 return NULL;
450
451 pdata.gpio_base = gpio;
452 msic_pdata.gpio = &pdata;
453
454 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_GPIO);
455}
456
457static void *msic_audio_platform_data(void *info)
458{
459 struct platform_device *pdev;
460
461 pdev = platform_device_register_simple("sst-platform", -1, NULL, 0);
462 if (IS_ERR(pdev)) {
463 pr_err("failed to create audio platform device\n");
464 return NULL;
465 }
466
467 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_AUDIO);
468}
469
470static void *msic_power_btn_platform_data(void *info)
471{
472 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_POWER_BTN);
473}
474
475static void *msic_ocd_platform_data(void *info)
476{
477 static struct intel_msic_ocd_pdata pdata;
478 int gpio = get_gpio_by_name("ocd_gpio");
479
480 if (gpio < 0)
481 return NULL;
482
483 pdata.gpio = gpio;
484 msic_pdata.ocd = &pdata;
485
486 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_OCD);
487}
488
Mika Westerbergecfdb0a2012-01-26 17:36:08 +0000489static void *msic_thermal_platform_data(void *info)
490{
491 return msic_generic_platform_data(info, INTEL_MSIC_BLOCK_THERMAL);
492}
493
Kirill A. Shutemov026abc32012-03-08 16:02:20 +0000494/* tc35876x DSI-LVDS bridge chip and panel platform data */
495static void *tc35876x_platform_data(void *data)
496{
Kuppuswamy Sathyanarayanand8059302013-10-17 15:35:26 -0700497 static struct tc35876x_platform_data pdata;
Kirill A. Shutemov026abc32012-03-08 16:02:20 +0000498
Kuppuswamy Sathyanarayanand8059302013-10-17 15:35:26 -0700499 /* gpio pins set to -1 will not be used by the driver */
500 pdata.gpio_bridge_reset = get_gpio_by_name("LCMB_RXEN");
501 pdata.gpio_panel_bl_en = get_gpio_by_name("6S6P_BL_EN");
502 pdata.gpio_panel_vadd = get_gpio_by_name("EN_VREG_LCD_V3P3");
Kirill A. Shutemov026abc32012-03-08 16:02:20 +0000503
Kuppuswamy Sathyanarayanand8059302013-10-17 15:35:26 -0700504 return &pdata;
Kirill A. Shutemov026abc32012-03-08 16:02:20 +0000505}
506
Feng Tang1da4b1c2010-11-09 11:22:58 +0000507static const struct devs_id __initconst device_ids[] = {
Kuppuswamy Sathyanarayanan3fd79ae2013-10-17 15:35:31 -0700508 {"bma023", SFI_DEV_TYPE_I2C, 1, &no_platform_data, NULL},
509 {"pmic_gpio", SFI_DEV_TYPE_SPI, 1, &pmic_gpio_platform_data, NULL},
Kuppuswamy Sathyanarayanan49c72a02013-10-17 15:35:32 -0700510 {"pmic_gpio", SFI_DEV_TYPE_IPC, 1, &pmic_gpio_platform_data, &ipc_device_handler},
Kuppuswamy Sathyanarayanan3fd79ae2013-10-17 15:35:31 -0700511 {"spi_max3111", SFI_DEV_TYPE_SPI, 0, &max3111_platform_data, NULL},
512 {"i2c_max7315", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data, NULL},
513 {"i2c_max7315_2", SFI_DEV_TYPE_I2C, 1, &max7315_platform_data, NULL},
514 {"tca6416", SFI_DEV_TYPE_I2C, 1, &tca6416_platform_data, NULL},
515 {"emc1403", SFI_DEV_TYPE_I2C, 1, &emc1403_platform_data, NULL},
516 {"i2c_accel", SFI_DEV_TYPE_I2C, 0, &lis331dl_platform_data, NULL},
Kuppuswamy Sathyanarayanan49c72a02013-10-17 15:35:32 -0700517 {"pmic_audio", SFI_DEV_TYPE_IPC, 1, &no_platform_data, &ipc_device_handler},
Kuppuswamy Sathyanarayanan3fd79ae2013-10-17 15:35:31 -0700518 {"mpu3050", SFI_DEV_TYPE_I2C, 1, &mpu3050_platform_data, NULL},
519 {"i2c_disp_brig", SFI_DEV_TYPE_I2C, 0, &tc35876x_platform_data, NULL},
Mika Westerberg360545c2011-10-18 12:41:22 +0300520
521 /* MSIC subdevices */
Kuppuswamy Sathyanarayanan49c72a02013-10-17 15:35:32 -0700522 {"msic_battery", SFI_DEV_TYPE_IPC, 1, &msic_battery_platform_data, &ipc_device_handler},
523 {"msic_gpio", SFI_DEV_TYPE_IPC, 1, &msic_gpio_platform_data, &ipc_device_handler},
524 {"msic_audio", SFI_DEV_TYPE_IPC, 1, &msic_audio_platform_data, &ipc_device_handler},
525 {"msic_power_btn", SFI_DEV_TYPE_IPC, 1, &msic_power_btn_platform_data, &ipc_device_handler},
526 {"msic_ocd", SFI_DEV_TYPE_IPC, 1, &msic_ocd_platform_data, &ipc_device_handler},
527 {"msic_thermal", SFI_DEV_TYPE_IPC, 1, &msic_thermal_platform_data, &ipc_device_handler},
Kuppuswamy Sathyanarayanan3fd79ae2013-10-17 15:35:31 -0700528 { 0 }
Feng Tang1da4b1c2010-11-09 11:22:58 +0000529};
530
Kuppuswamy Sathyanarayanan49c72a02013-10-17 15:35:32 -0700531static void __init ipc_device_handler(struct sfi_device_table_entry *pentry,
532 struct devs_id *dev)
533{
534 struct platform_device *pdev;
535 void *pdata = NULL;
536 static struct resource res __initdata = {
537 .name = "IRQ",
538 .flags = IORESOURCE_IRQ,
539 };
540
541 pr_debug("IPC bus, name = %16.16s, irq = 0x%2x\n",
542 pentry->name, pentry->irq);
543
544 /*
545 * We need to call platform init of IPC devices to fill misc_pdata
546 * structure. It will be used in msic_init for initialization.
547 */
548 if (dev != NULL)
549 pdata = dev->get_platform_data(pentry);
550
551 /*
552 * On Medfield the platform device creation is handled by the MSIC
553 * MFD driver so we don't need to do it here.
554 */
555 if (intel_mid_has_msic())
556 return;
557
558 pdev = platform_device_alloc(pentry->name, 0);
559 if (pdev == NULL) {
560 pr_err("out of memory for SFI platform device '%s'.\n",
561 pentry->name);
562 return;
563 }
564 res.start = pentry->irq;
565 platform_device_add_resources(pdev, &res, 1);
566
567 pdev->dev.platform_data = pdata;
568 intel_scu_device_register(pdev);
569}
570
Feng Tang1da4b1c2010-11-09 11:22:58 +0000571
572/*
573 * we will search these buttons in SFI GPIO table (by name)
574 * and register them dynamically. Please add all possible
575 * buttons here, we will shrink them if no GPIO found.
576 */
577static struct gpio_keys_button gpio_button[] = {
578 {KEY_POWER, -1, 1, "power_btn", EV_KEY, 0, 3000},
579 {KEY_PROG1, -1, 1, "prog_btn1", EV_KEY, 0, 20},
580 {KEY_PROG2, -1, 1, "prog_btn2", EV_KEY, 0, 20},
581 {SW_LID, -1, 1, "lid_switch", EV_SW, 0, 20},
582 {KEY_VOLUMEUP, -1, 1, "vol_up", EV_KEY, 0, 20},
583 {KEY_VOLUMEDOWN, -1, 1, "vol_down", EV_KEY, 0, 20},
584 {KEY_CAMERA, -1, 1, "camera_full", EV_KEY, 0, 20},
585 {KEY_CAMERA_FOCUS, -1, 1, "camera_half", EV_KEY, 0, 20},
586 {SW_KEYPAD_SLIDE, -1, 1, "MagSw1", EV_SW, 0, 20},
587 {SW_KEYPAD_SLIDE, -1, 1, "MagSw2", EV_SW, 0, 20},
588};
589
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700590static struct gpio_keys_platform_data intel_mid_gpio_keys = {
Feng Tang1da4b1c2010-11-09 11:22:58 +0000591 .buttons = gpio_button,
592 .rep = 1,
593 .nbuttons = -1, /* will fill it after search */
594};
595
596static struct platform_device pb_device = {
597 .name = "gpio-keys",
598 .id = -1,
599 .dev = {
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700600 .platform_data = &intel_mid_gpio_keys,
Feng Tang1da4b1c2010-11-09 11:22:58 +0000601 },
602};
603
604/*
605 * Shrink the non-existent buttons, register the gpio button
606 * device if there is some
607 */
608static int __init pb_keys_init(void)
609{
610 struct gpio_keys_button *gb = gpio_button;
611 int i, num, good = 0;
612
613 num = sizeof(gpio_button) / sizeof(struct gpio_keys_button);
614 for (i = 0; i < num; i++) {
615 gb[i].gpio = get_gpio_by_name(gb[i].desc);
Kuppuswamy Sathyanarayanand8059302013-10-17 15:35:26 -0700616 pr_debug("info[%2d]: name = %s, gpio = %d\n", i, gb[i].desc,
617 gb[i].gpio);
Feng Tang1da4b1c2010-11-09 11:22:58 +0000618 if (gb[i].gpio == -1)
619 continue;
620
621 if (i != good)
622 gb[good] = gb[i];
623 good++;
624 }
625
626 if (good) {
Kuppuswamy Sathyanarayanan712b6aa2013-10-17 15:35:29 -0700627 intel_mid_gpio_keys.nbuttons = good;
Feng Tang1da4b1c2010-11-09 11:22:58 +0000628 return platform_device_register(&pb_device);
629 }
630 return 0;
631}
Kuppuswamy Sathyanarayananaeedb372013-10-17 15:35:33 -0700632late_initcall(pb_keys_init);