diff options
| -rw-r--r-- | arch/x86/Kconfig | 2 | ||||
| -rw-r--r-- | arch/x86/include/asm/mrst.h | 4 | ||||
| -rw-r--r-- | arch/x86/platform/mrst/mrst.c | 515 | ||||
| -rw-r--r-- | drivers/platform/x86/intel_scu_ipc.c | 5 | ||||
| -rw-r--r-- | include/linux/sfi.h | 8 |
5 files changed, 527 insertions, 7 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e8327686d3c5..b306b84fc8c8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -385,6 +385,8 @@ config X86_MRST | |||
| 385 | depends on X86_EXTENDED_PLATFORM | 385 | depends on X86_EXTENDED_PLATFORM |
| 386 | depends on X86_IO_APIC | 386 | depends on X86_IO_APIC |
| 387 | select APB_TIMER | 387 | select APB_TIMER |
| 388 | select I2C | ||
| 389 | select SPI | ||
| 388 | ---help--- | 390 | ---help--- |
| 389 | Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin | 391 | Moorestown is Intel's Low Power Intel Architecture (LPIA) based Moblin |
| 390 | Internet Device(MID) platform. Moorestown consists of two chips: | 392 | Internet Device(MID) platform. Moorestown consists of two chips: |
diff --git a/arch/x86/include/asm/mrst.h b/arch/x86/include/asm/mrst.h index 4a711a684b17..283debd29fc0 100644 --- a/arch/x86/include/asm/mrst.h +++ b/arch/x86/include/asm/mrst.h | |||
| @@ -50,4 +50,8 @@ extern void mrst_early_console_init(void); | |||
| 50 | 50 | ||
| 51 | extern struct console early_hsu_console; | 51 | extern struct console early_hsu_console; |
| 52 | extern void hsu_early_console_init(void); | 52 | extern void hsu_early_console_init(void); |
| 53 | |||
| 54 | extern void intel_scu_devices_create(void); | ||
| 55 | extern void intel_scu_devices_destroy(void); | ||
| 56 | |||
| 53 | #endif /* _ASM_X86_MRST_H */ | 57 | #endif /* _ASM_X86_MRST_H */ |
diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index 79ae68154e87..cfa1af24edd5 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c | |||
| @@ -9,9 +9,19 @@ | |||
| 9 | * as published by the Free Software Foundation; version 2 | 9 | * as published by the Free Software Foundation; version 2 |
| 10 | * of the License. | 10 | * of the License. |
| 11 | */ | 11 | */ |
| 12 | |||
| 13 | #define pr_fmt(fmt) "mrst: " fmt | ||
| 14 | |||
| 12 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 13 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 14 | #include <linux/sfi.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/i2c/pca953x.h> | ||
| 22 | #include <linux/gpio_keys.h> | ||
| 23 | #include <linux/input.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
| 16 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 17 | 27 | ||
| @@ -23,8 +33,10 @@ | |||
| 23 | #include <asm/mrst.h> | 33 | #include <asm/mrst.h> |
| 24 | #include <asm/io.h> | 34 | #include <asm/io.h> |
| 25 | #include <asm/i8259.h> | 35 | #include <asm/i8259.h> |
| 36 | #include <asm/intel_scu_ipc.h> | ||
| 26 | #include <asm/apb_timer.h> | 37 | #include <asm/apb_timer.h> |
| 27 | 38 | ||
| 39 | |||
| 28 | /* | 40 | /* |
| 29 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, | 41 | * the clockevent devices on Moorestown/Medfield can be APBT or LAPIC clock, |
| 30 | * cmdline option x86_mrst_timer can be used to override the configuration | 42 | * cmdline option x86_mrst_timer can be used to override the configuration |
| @@ -102,10 +114,10 @@ static int __init sfi_parse_mtmr(struct sfi_table_header *table) | |||
| 102 | memcpy(sfi_mtimer_array, pentry, totallen); | 114 | memcpy(sfi_mtimer_array, pentry, totallen); |
| 103 | } | 115 | } |
| 104 | 116 | ||
| 105 | printk(KERN_INFO "SFI: MTIMER info (num = %d):\n", sfi_mtimer_num); | 117 | pr_debug("SFI MTIMER info (num = %d):\n", sfi_mtimer_num); |
| 106 | pentry = sfi_mtimer_array; | 118 | pentry = sfi_mtimer_array; |
| 107 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { | 119 | for (totallen = 0; totallen < sfi_mtimer_num; totallen++, pentry++) { |
| 108 | printk(KERN_INFO "timer[%d]: paddr = 0x%08x, freq = %dHz," | 120 | pr_debug("timer[%d]: paddr = 0x%08x, freq = %dHz," |
| 109 | " irq = %d\n", totallen, (u32)pentry->phys_addr, | 121 | " irq = %d\n", totallen, (u32)pentry->phys_addr, |
| 110 | pentry->freq_hz, pentry->irq); | 122 | pentry->freq_hz, pentry->irq); |
| 111 | if (!pentry->irq) | 123 | if (!pentry->irq) |
| @@ -176,10 +188,10 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table) | |||
| 176 | memcpy(sfi_mrtc_array, pentry, totallen); | 188 | memcpy(sfi_mrtc_array, pentry, totallen); |
| 177 | } | 189 | } |
| 178 | 190 | ||
| 179 | printk(KERN_INFO "SFI: RTC info (num = %d):\n", sfi_mrtc_num); | 191 | pr_debug("SFI RTC info (num = %d):\n", sfi_mrtc_num); |
| 180 | pentry = sfi_mrtc_array; | 192 | pentry = sfi_mrtc_array; |
| 181 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { | 193 | for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) { |
| 182 | printk(KERN_INFO "RTC[%d]: paddr = 0x%08x, irq = %d\n", | 194 | pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n", |
| 183 | totallen, (u32)pentry->phys_addr, pentry->irq); | 195 | totallen, (u32)pentry->phys_addr, pentry->irq); |
| 184 | mp_irq.type = MP_IOAPIC; | 196 | mp_irq.type = MP_IOAPIC; |
| 185 | mp_irq.irqtype = mp_INT; | 197 | mp_irq.irqtype = mp_INT; |
| @@ -309,3 +321,498 @@ static inline int __init setup_x86_mrst_timer(char *arg) | |||
| 309 | return 0; | 321 | return 0; |
| 310 | } | 322 | } |
| 311 | __setup("x86_mrst_timer=", setup_x86_mrst_timer); | 323 | __setup("x86_mrst_timer=", setup_x86_mrst_timer); |
| 324 | |||
| 325 | /* | ||
| 326 | * Parsing GPIO table first, since the DEVS table will need this table | ||
| 327 | * to map the pin name to the actual pin. | ||
| 328 | */ | ||
| 329 | static struct sfi_gpio_table_entry *gpio_table; | ||
| 330 | static int gpio_num_entry; | ||
| 331 | |||
| 332 | static int __init sfi_parse_gpio(struct sfi_table_header *table) | ||
| 333 | { | ||
| 334 | struct sfi_table_simple *sb; | ||
| 335 | struct sfi_gpio_table_entry *pentry; | ||
| 336 | int num, i; | ||
| 337 | |||
| 338 | if (gpio_table) | ||
| 339 | return 0; | ||
| 340 | sb = (struct sfi_table_simple *)table; | ||
| 341 | num = SFI_GET_NUM_ENTRIES(sb, struct sfi_gpio_table_entry); | ||
| 342 | pentry = (struct sfi_gpio_table_entry *)sb->pentry; | ||
| 343 | |||
| 344 | gpio_table = (struct sfi_gpio_table_entry *) | ||
| 345 | kmalloc(num * sizeof(*pentry), GFP_KERNEL); | ||
| 346 | if (!gpio_table) | ||
| 347 | return -1; | ||
| 348 | memcpy(gpio_table, pentry, num * sizeof(*pentry)); | ||
| 349 | gpio_num_entry = num; | ||
| 350 | |||
| 351 | pr_debug("GPIO pin info:\n"); | ||
| 352 | for (i = 0; i < num; i++, pentry++) | ||
| 353 | pr_debug("info[%2d]: controller = %16.16s, pin_name = %16.16s," | ||
| 354 | " pin = %d\n", i, | ||
| 355 | pentry->controller_name, | ||
| 356 | pentry->pin_name, | ||
| 357 | pentry->pin_no); | ||
| 358 | return 0; | ||
| 359 | } | ||
| 360 | |||
| 361 | static int get_gpio_by_name(const char *name) | ||
| 362 | { | ||
| 363 | struct sfi_gpio_table_entry *pentry = gpio_table; | ||
| 364 | int i; | ||
| 365 | |||
| 366 | if (!pentry) | ||
| 367 | return -1; | ||
| 368 | for (i = 0; i < gpio_num_entry; i++, pentry++) { | ||
| 369 | if (!strncmp(name, pentry->pin_name, SFI_NAME_LEN)) | ||
| 370 | return pentry->pin_no; | ||
| 371 | } | ||
| 372 | return -1; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 376 | * Here defines the array of devices platform data that IAFW would export | ||
| 377 | * through SFI "DEVS" table, we use name and type to match the device and | ||
| 378 | * its platform data. | ||
| 379 | */ | ||
| 380 | struct devs_id { | ||
| 381 | char name[SFI_NAME_LEN + 1]; | ||
| 382 | u8 type; | ||
| 383 | u8 delay; | ||
| 384 | void *(*get_platform_data)(void *info); | ||
| 385 | }; | ||
| 386 | |||
| 387 | /* the offset for the mapping of global gpio pin to irq */ | ||
| 388 | #define MRST_IRQ_OFFSET 0x100 | ||
| 389 | |||
| 390 | static void __init *pmic_gpio_platform_data(void *info) | ||
| 391 | { | ||
| 392 | static struct intel_pmic_gpio_platform_data pmic_gpio_pdata; | ||
| 393 | int gpio_base = get_gpio_by_name("pmic_gpio_base"); | ||
| 394 | |||
| 395 | if (gpio_base == -1) | ||
| 396 | gpio_base = 64; | ||
| 397 | pmic_gpio_pdata.gpio_base = gpio_base; | ||
| 398 | pmic_gpio_pdata.irq_base = gpio_base + MRST_IRQ_OFFSET; | ||
| 399 | pmic_gpio_pdata.gpiointr = 0xffffeff8; | ||
| 400 | |||
| 401 | return &pmic_gpio_pdata; | ||
| 402 | } | ||
| 403 | |||
| 404 | static void __init *max3111_platform_data(void *info) | ||
| 405 | { | ||
| 406 | struct spi_board_info *spi_info = info; | ||
| 407 | int intr = get_gpio_by_name("max3111_int"); | ||
| 408 | |||
| 409 | if (intr == -1) | ||
| 410 | return NULL; | ||
| 411 | spi_info->irq = intr + MRST_IRQ_OFFSET; | ||
| 412 | return NULL; | ||
| 413 | } | ||
