diff options
Diffstat (limited to 'drivers')
234 files changed, 12384 insertions, 2483 deletions
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 4bc1c4178f50..78418ce4fc78 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -1207,6 +1207,15 @@ int acpi_check_mem_region(resource_size_t start, resource_size_t n, | |||
1207 | EXPORT_SYMBOL(acpi_check_mem_region); | 1207 | EXPORT_SYMBOL(acpi_check_mem_region); |
1208 | 1208 | ||
1209 | /* | 1209 | /* |
1210 | * Let drivers know whether the resource checks are effective | ||
1211 | */ | ||
1212 | int acpi_resources_are_enforced(void) | ||
1213 | { | ||
1214 | return acpi_enforce_resources == ENFORCE_RESOURCES_STRICT; | ||
1215 | } | ||
1216 | EXPORT_SYMBOL(acpi_resources_are_enforced); | ||
1217 | |||
1218 | /* | ||
1210 | * Acquire a spinlock. | 1219 | * Acquire a spinlock. |
1211 | * | 1220 | * |
1212 | * handle is a pointer to the spinlock_t. | 1221 | * handle is a pointer to the spinlock_t. |
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index bf6b13206d00..9fc630ce1ddb 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -162,7 +162,7 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, | |||
162 | topology_remove_dev(cpu); | 162 | topology_remove_dev(cpu); |
163 | break; | 163 | break; |
164 | } | 164 | } |
165 | return rc ? NOTIFY_BAD : NOTIFY_OK; | 165 | return notifier_from_errno(rc); |
166 | } | 166 | } |
167 | 167 | ||
168 | static int __cpuinit topology_sysfs_init(void) | 168 | static int __cpuinit topology_sysfs_init(void) |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index e21175be25d0..f09fc0e2062d 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -1121,5 +1121,12 @@ config DEVPORT | |||
1121 | 1121 | ||
1122 | source "drivers/s390/char/Kconfig" | 1122 | source "drivers/s390/char/Kconfig" |
1123 | 1123 | ||
1124 | config RAMOOPS | ||
1125 | tristate "Log panic/oops to a RAM buffer" | ||
1126 | default n | ||
1127 | help | ||
1128 | This enables panic and oops messages to be logged to a circular | ||
1129 | buffer in RAM where it can be read back at some later point. | ||
1130 | |||
1124 | endmenu | 1131 | endmenu |
1125 | 1132 | ||
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index d39be4cf1f5d..88d6eac69754 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -108,6 +108,7 @@ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o | |||
108 | obj-$(CONFIG_TCG_TPM) += tpm/ | 108 | obj-$(CONFIG_TCG_TPM) += tpm/ |
109 | 109 | ||
110 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o | 110 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o |
111 | obj-$(CONFIG_RAMOOPS) += ramoops.o | ||
111 | 112 | ||
112 | obj-$(CONFIG_JS_RTC) += js-rtc.o | 113 | obj-$(CONFIG_JS_RTC) += js-rtc.o |
113 | js-rtc-y = rtc.o | 114 | js-rtc-y = rtc.o |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 67ea3a60de74..70312da4c968 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -384,7 +384,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
384 | { | 384 | { |
385 | u32 httfea,baseaddr,enuscr; | 385 | u32 httfea,baseaddr,enuscr; |
386 | struct pci_dev *dev1; | 386 | struct pci_dev *dev1; |
387 | int i; | 387 | int i, ret; |
388 | unsigned size = amd64_fetch_size(); | 388 | unsigned size = amd64_fetch_size(); |
389 | 389 | ||
390 | dev_info(&pdev->dev, "setting up ULi AGP\n"); | 390 | dev_info(&pdev->dev, "setting up ULi AGP\n"); |
@@ -400,15 +400,18 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
400 | 400 | ||
401 | if (i == ARRAY_SIZE(uli_sizes)) { | 401 | if (i == ARRAY_SIZE(uli_sizes)) { |
402 | dev_info(&pdev->dev, "no ULi size found for %d\n", size); | 402 | dev_info(&pdev->dev, "no ULi size found for %d\n", size); |
403 | return -ENODEV; | 403 | ret = -ENODEV; |
404 | goto put; | ||
404 | } | 405 | } |
405 | 406 | ||
406 | /* shadow x86-64 registers into ULi registers */ | 407 | /* shadow x86-64 registers into ULi registers */ |
407 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); | 408 | pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea); |
408 | 409 | ||
409 | /* if x86-64 aperture base is beyond 4G, exit here */ | 410 | /* if x86-64 aperture base is beyond 4G, exit here */ |
410 | if ((httfea & 0x7fff) >> (32 - 25)) | 411 | if ((httfea & 0x7fff) >> (32 - 25)) { |
411 | return -ENODEV; | 412 | ret = -ENODEV; |
413 | goto put; | ||
414 | } | ||
412 | 415 | ||
413 | httfea = (httfea& 0x7fff) << 25; | 416 | httfea = (httfea& 0x7fff) << 25; |
414 | 417 | ||
@@ -420,9 +423,10 @@ static int __devinit uli_agp_init(struct pci_dev *pdev) | |||
420 | enuscr= httfea+ (size * 1024 * 1024) - 1; | 423 | enuscr= httfea+ (size * 1024 * 1024) - 1; |
421 | pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea); | 424 | pci_write_config_dword(dev1, ULI_X86_64_HTT_FEA_REG, httfea); |
422 | pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr); | 425 | pci_write_config_dword(dev1, ULI_X86_64_ENU_SCR_REG, enuscr); |
423 | 426 | ret = 0; | |
427 | put: | ||
424 | pci_dev_put(dev1); | 428 | pci_dev_put(dev1); |
425 | return 0; | 429 | return ret; |
426 | } | 430 | } |
427 | 431 | ||
428 | 432 | ||
@@ -441,7 +445,7 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
441 | { | 445 | { |
442 | u32 tmp, apbase, apbar, aplimit; | 446 | u32 tmp, apbase, apbar, aplimit; |
443 | struct pci_dev *dev1; | 447 | struct pci_dev *dev1; |
444 | int i; | 448 | int i, ret; |
445 | unsigned size = amd64_fetch_size(); | 449 | unsigned size = amd64_fetch_size(); |
446 | 450 | ||
447 | dev_info(&pdev->dev, "setting up Nforce3 AGP\n"); | 451 | dev_info(&pdev->dev, "setting up Nforce3 AGP\n"); |
@@ -458,7 +462,8 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
458 | 462 | ||
459 | if (i == ARRAY_SIZE(nforce3_sizes)) { | 463 | if (i == ARRAY_SIZE(nforce3_sizes)) { |
460 | dev_info(&pdev->dev, "no NForce3 size found for %d\n", size); | 464 | dev_info(&pdev->dev, "no NForce3 size found for %d\n", size); |
461 | return -ENODEV; | 465 | ret = -ENODEV; |
466 | goto put; | ||
462 | } | 467 | } |
463 | 468 | ||
464 | pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); | 469 | pci_read_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, &tmp); |
@@ -472,7 +477,8 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
472 | /* if x86-64 aperture base is beyond 4G, exit here */ | 477 | /* if x86-64 aperture base is beyond 4G, exit here */ |
473 | if ( (apbase & 0x7fff) >> (32 - 25) ) { | 478 | if ( (apbase & 0x7fff) >> (32 - 25) ) { |
474 | dev_info(&pdev->dev, "aperture base > 4G\n"); | 479 | dev_info(&pdev->dev, "aperture base > 4G\n"); |
475 | return -ENODEV; | 480 | ret = -ENODEV; |
481 | goto put; | ||
476 | } | 482 | } |
477 | 483 | ||
478 | apbase = (apbase & 0x7fff) << 25; | 484 | apbase = (apbase & 0x7fff) << 25; |
@@ -488,9 +494,11 @@ static int nforce3_agp_init(struct pci_dev *pdev) | |||
488 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); | 494 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APBASE2, apbase); |
489 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); | 495 | pci_write_config_dword(dev1, NVIDIA_X86_64_1_APLIMIT2, aplimit); |
490 | 496 | ||
497 | ret = 0; | ||
498 | put: | ||
491 | pci_dev_put(dev1); | 499 | pci_dev_put(dev1); |
492 | 500 | ||
493 | return 0; | 501 | return ret; |
494 | } | 502 | } |
495 | 503 | ||
496 | static int __devinit agp_amd64_probe(struct pci_dev *pdev, | 504 | static int __devinit agp_amd64_probe(struct pci_dev *pdev, |
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 56b27671adc4..4f8d60c25a98 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c | |||
@@ -84,6 +84,7 @@ static char *serial_version = "4.30"; | |||
84 | #include <linux/smp_lock.h> | 84 | #include <linux/smp_lock.h> |
85 | #include <linux/init.h> | 85 | #include <linux/init.h> |
86 | #include <linux/bitops.h> | 86 | #include <linux/bitops.h> |
87 | #include <linux/platform_device.h> | ||
87 | 88 | ||
88 | #include <asm/setup.h> | 89 | #include <asm/setup.h> |
89 | 90 | ||
@@ -1954,29 +1955,16 @@ static const struct tty_operations serial_ops = { | |||
1954 | /* | 1955 | /* |
1955 | * The serial driver boot-time initialization code! | 1956 | * The serial driver boot-time initialization code! |
1956 | */ | 1957 | */ |
1957 | static int __init rs_init(void) | 1958 | static int __init amiga_serial_probe(struct platform_device *pdev) |
1958 | { | 1959 | { |
1959 | unsigned long flags; | 1960 | unsigned long flags; |
1960 | struct serial_state * state; | 1961 | struct serial_state * state; |
1961 | int error; | 1962 | int error; |
1962 | 1963 | ||
1963 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_SERIAL)) | ||
1964 | return -ENODEV; | ||
1965 | |||
1966 | serial_driver = alloc_tty_driver(1); | 1964 | serial_driver = alloc_tty_driver(1); |
1967 | if (!serial_driver) | 1965 | if (!serial_driver) |
1968 | return -ENOMEM; | 1966 | return -ENOMEM; |
1969 | 1967 | ||
1970 | /* | ||
1971 | * We request SERDAT and SERPER only, because the serial registers are | ||
1972 | * too spreaded over the custom register space | ||
1973 | */ | ||
1974 | if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, | ||
1975 | "amiserial [Paula]")) { | ||
1976 | error = -EBUSY; | ||
1977 | goto fail_put_tty_driver; | ||
1978 | } | ||
1979 | |||
1980 | IRQ_ports = NULL; | 1968 | IRQ_ports = NULL; |
1981 | 1969 | ||
1982 | show_serial_version(); | 1970 | show_serial_version(); |
@@ -1998,7 +1986,7 @@ static int __init rs_init(void) | |||
1998 | 1986 | ||
1999 | error = tty_register_driver(serial_driver); | 1987 | error = tty_register_driver(serial_driver); |
2000 | if (error) | 1988 | if (error) |
2001 | goto fail_release_mem_region; | 1989 | goto fail_put_tty_driver; |
2002 | 1990 | ||
2003 | state = rs_table; | 1991 | state = rs_table; |
2004 | state->magic = SSTATE_MAGIC; | 1992 | state->magic = SSTATE_MAGIC; |
@@ -2050,23 +2038,24 @@ static int __init rs_init(void) | |||
2050 | ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ | 2038 | ciab.ddra |= (SER_DTR | SER_RTS); /* outputs */ |
2051 | ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ | 2039 | ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR); /* inputs */ |
2052 | 2040 | ||
2041 | platform_set_drvdata(pdev, state); | ||
2042 | |||
2053 | return 0; | 2043 | return 0; |
2054 | 2044 | ||
2055 | fail_free_irq: | 2045 | fail_free_irq: |
2056 | free_irq(IRQ_AMIGA_TBE, state); | 2046 | free_irq(IRQ_AMIGA_TBE, state); |
2057 | fail_unregister: | 2047 | fail_unregister: |
2058 | tty_unregister_driver(serial_driver); | 2048 | tty_unregister_driver(serial_driver); |
2059 | fail_release_mem_region: | ||
2060 | release_mem_region(CUSTOM_PHYSADDR+0x30, 4); | ||
2061 | fail_put_tty_driver: | 2049 | fail_put_tty_driver: |
2062 | put_tty_driver(serial_driver); | 2050 | put_tty_driver(serial_driver); |
2063 | return error; | 2051 | return error; |
2064 | } | 2052 | } |
2065 | 2053 | ||
2066 | static __exit void rs_exit(void) | 2054 | static int __exit amiga_serial_remove(struct platform_device *pdev) |
2067 | { | 2055 | { |
2068 | int error; | 2056 | int error; |
2069 | struct async_struct *info = rs_table[0].info; | 2057 | struct serial_state *state = platform_get_drvdata(pdev); |
2058 | struct async_struct *info = state->info; | ||
2070 | 2059 | ||
2071 | /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ | 2060 | /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ |
2072 | tasklet_kill(&info->tlet); | 2061 | tasklet_kill(&info->tlet); |
@@ -2075,19 +2064,38 @@ static __exit void rs_exit(void) | |||
2075 | error); | 2064 | error); |
2076 | put_tty_driver(serial_driver); | 2065 | put_tty_driver(serial_driver); |
2077 | 2066 | ||
2078 | if (info) { | 2067 | rs_table[0].info = NULL; |
2079 | rs_table[0].info = NULL; | 2068 | kfree(info); |
2080 | kfree(info); | ||
2081 | } | ||
2082 | 2069 | ||
2083 | free_irq(IRQ_AMIGA_TBE, rs_table); | 2070 | free_irq(IRQ_AMIGA_TBE, rs_table); |
2084 | free_irq(IRQ_AMIGA_RBF, rs_table); | 2071 | free_irq(IRQ_AMIGA_RBF, rs_table); |
2085 | 2072 | ||
2086 | release_mem_region(CUSTOM_PHYSADDR+0x30, 4); | 2073 | platform_set_drvdata(pdev, NULL); |
2074 | |||
2075 | return error; | ||
2076 | } | ||
2077 | |||
2078 | static struct platform_driver amiga_serial_driver = { | ||
2079 | .remove = __exit_p(amiga_serial_remove), | ||
2080 | .driver = { | ||
2081 | .name = "amiga-serial", | ||
2082 | .owner = THIS_MODULE, | ||
2083 | }, | ||
2084 | }; | ||
2085 | |||
2086 | static int __init amiga_serial_init(void) | ||
2087 | { | ||
2088 | return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe); | ||
2089 | } | ||
2090 | |||
2091 | module_init(amiga_serial_init); | ||
2092 | |||
2093 | static void __exit amiga_serial_exit(void) | ||
2094 | { | ||
2095 | platform_driver_unregister(&amiga_serial_driver); | ||
2087 | } | 2096 | } |
2088 | 2097 | ||
2089 | module_init(rs_init) | 2098 | module_exit(amiga_serial_exit); |
2090 | module_exit(rs_exit) | ||
2091 | 2099 | ||
2092 | 2100 | ||
2093 | #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) | 2101 | #if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE) |
@@ -2154,3 +2162,4 @@ console_initcall(amiserial_console_init); | |||
2154 | #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ | 2162 | #endif /* CONFIG_SERIAL_CONSOLE && !MODULE */ |
2155 | 2163 | ||
2156 | MODULE_LICENSE("GPL"); | 2164 | MODULE_LICENSE("GPL"); |
2165 | MODULE_ALIAS("platform:amiga-serial"); | ||
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c index 63313a33ba5f..f4ae0e0fb631 100644 --- a/drivers/char/applicom.c +++ b/drivers/char/applicom.c | |||
@@ -703,14 +703,9 @@ static long ac_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
703 | /* In general, the device is only openable by root anyway, so we're not | 703 | /* In general, the device is only openable by root anyway, so we're not |
704 | particularly concerned that bogus ioctls can flood the console. */ | 704 | particularly concerned that bogus ioctls can flood the console. */ |
705 | 705 | ||
706 | adgl = kmalloc(sizeof(struct st_ram_io), GFP_KERNEL); | 706 | adgl = memdup_user(argp, sizeof(struct st_ram_io)); |
707 | if (!adgl) | 707 | if (IS_ERR(adgl)) |
708 | return -ENOMEM; | 708 | return PTR_ERR(adgl); |
709 | |||
710 | if (copy_from_user(adgl, argp, sizeof(struct st_ram_io))) { | ||
711 | kfree(adgl); | ||
712 | return -EFAULT; | ||
713 | } | ||
714 | 709 | ||
715 | lock_kernel(); | 710 | lock_kernel(); |
716 | IndexCard = adgl->num_card-1; | 711 | IndexCard = adgl->num_card-1; |
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index c6ad4234378d..4f3f8c9ec262 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
@@ -2505,12 +2505,11 @@ static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, | |||
2505 | return rv; | 2505 | return rv; |
2506 | } | 2506 | } |
2507 | 2507 | ||
2508 | printk(KERN_INFO | 2508 | dev_info(intf->si_dev, "Found new BMC (man_id: 0x%6.6x, " |
2509 | "ipmi: Found new BMC (man_id: 0x%6.6x, " | 2509 | "prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", |
2510 | " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", | 2510 | bmc->id.manufacturer_id, |
2511 | bmc->id.manufacturer_id, | 2511 | bmc->id.product_id, |
2512 | bmc->id.product_id, | 2512 | bmc->id.device_id); |
2513 | bmc->id.device_id); | ||
2514 | } | 2513 | } |
2515 | 2514 | ||
2516 | /* | 2515 | /* |
@@ -4037,8 +4036,8 @@ static void ipmi_request_event(void) | |||
4037 | 4036 | ||
4038 | static struct timer_list ipmi_timer; | 4037 | static struct timer_list ipmi_timer; |
4039 | 4038 | ||
4040 | /* Call every ~100 ms. */ | 4039 | /* Call every ~1000 ms. */ |
4041 | #define IPMI_TIMEOUT_TIME 100 | 4040 | #define IPMI_TIMEOUT_TIME 1000 |
4042 | 4041 | ||
4043 | /* How many jiffies does it take to get to the timeout time. */ | 4042 | /* How many jiffies does it take to get to the timeout time. */ |
4044 | #define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000) | 4043 | #define IPMI_TIMEOUT_JIFFIES ((IPMI_TIMEOUT_TIME * HZ) / 1000) |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 47ffe4a90a95..35603dd4e6c5 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
@@ -107,6 +107,14 @@ enum si_type { | |||
107 | }; | 107 | }; |
108 | static char *si_to_str[] = { "kcs", "smic", "bt" }; | 108 | static char *si_to_str[] = { "kcs", "smic", "bt" }; |
109 | 109 | ||
110 | enum ipmi_addr_src { | ||
111 | SI_INVALID = 0, SI_HOTMOD, SI_HARDCODED, SI_SPMI, SI_ACPI, SI_SMBIOS, | ||
112 | SI_PCI, SI_DEVICETREE, SI_DEFAULT | ||
113 | }; | ||
114 | static char *ipmi_addr_src_to_str[] = { NULL, "hotmod", "hardcoded", "SPMI", | ||
115 | "ACPI", "SMBIOS", "PCI", | ||
116 | "device-tree", "default" }; | ||
117 | |||
110 | #define DEVICE_NAME "ipmi_si" | 118 | #define DEVICE_NAME "ipmi_si" |
111 | 119 | ||
112 | static struct platform_driver ipmi_driver = { | 120 | static struct platform_driver ipmi_driver = { |
@@ -188,7 +196,7 @@ struct smi_info { | |||
188 | int (*irq_setup)(struct smi_info *info); | 196 | int (*irq_setup)(struct smi_info *info); |
189 | void (*irq_cleanup)(struct smi_info *info); | 197 | void (*irq_cleanup)(struct smi_info *info); |
190 | unsigned int io_size; | 198 | unsigned int io_size; |
191 | char *addr_source; /* ACPI, PCI, SMBIOS, hardcode, default. */ | 199 | enum ipmi_addr_src addr_source; /* ACPI, PCI, SMBIOS, hardcode, etc. */ |
192 | void (*addr_source_cleanup)(struct smi_info *info); | 200 | void (*addr_source_cleanup)(struct smi_info *info); |
193 | void *addr_source_data; | 201 | void *addr_source_data; |
194 | 202 | ||
@@ -300,6 +308,7 @@ static int num_max_busy_us; | |||
300 | 308 | ||
301 | static int unload_when_empty = 1; | 309 | static int unload_when_empty = 1; |
302 | 310 | ||
311 | static int add_smi(struct smi_info *smi); | ||
303 | static int try_smi_init(struct smi_info *smi); | 312 | static int try_smi_init(struct smi_info *smi); |
304 | static void cleanup_one_si(struct smi_info *to_clean); | 313 | static void cleanup_one_si(struct smi_info *to_clean); |
305 | 314 | ||
@@ -314,9 +323,14 @@ static void deliver_recv_msg(struct smi_info *smi_info, | |||
314 | { | 323 | { |
315 | /* Deliver the message to the upper layer with the lock | 324 | /* Deliver the message to the upper layer with the lock |
316 | released. */ | 325 | released. */ |
317 | spin_unlock(&(smi_info->si_lock)); | 326 | |
318 | ipmi_smi_msg_received(smi_info->intf, msg); | 327 | if (smi_info->run_to_completion) { |
319 | spin_lock(&(smi_info->si_lock)); | 328 | ipmi_smi_msg_received(smi_info->intf, msg); |
329 | } else { | ||
330 | spin_unlock(&(smi_info->si_lock)); | ||
331 | ipmi_smi_msg_received(smi_info->intf, msg); | ||
332 | spin_lock(&(smi_info->si_lock)); | ||
333 | } | ||
320 | } | 334 | } |
321 | 335 | ||
322 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) | 336 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) |
@@ -445,6 +459,9 @@ static inline void disable_si_irq(struct smi_info *smi_info) | |||
445 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 459 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
446 | start_disable_irq(smi_info); | 460 | start_disable_irq(smi_info); |
447 | smi_info->interrupt_disabled = 1; | 461 | smi_info->interrupt_disabled = 1; |
462 | if (!atomic_read(&smi_info->stop_operation)) | ||
463 | mod_timer(&smi_info->si_timer, | ||
464 | jiffies + SI_TIMEOUT_JIFFIES); | ||
448 | } | 465 | } |
449 | } | 466 | } |
450 | 467 | ||
@@ -576,9 +593,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
576 | smi_info->handlers->get_result(smi_info->si_sm, msg, 3); | 593 | smi_info->handlers->get_result(smi_info->si_sm, msg, 3); |
577 | if (msg[2] != 0) { | 594 | if (msg[2] != 0) { |
578 | /* Error clearing flags */ | 595 | /* Error clearing flags */ |
579 | printk(KERN_WARNING | 596 | dev_warn(smi_info->dev, |
580 | "ipmi_si: Error clearing flags: %2.2x\n", | 597 | "Error clearing flags: %2.2x\n", msg[2]); |
581 | msg[2]); | ||
582 | } | 598 | } |
583 | if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ) | 599 | if (smi_info->si_state == SI_CLEARING_FLAGS_THEN_SET_IRQ) |
584 | start_enable_irq(smi_info); | 600 | start_enable_irq(smi_info); |
@@ -670,9 +686,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
670 | /* We got the flags from the SMI, now handle them. */ | 686 | /* We got the flags from the SMI, now handle them. */ |
671 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 687 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
672 | if (msg[2] != 0) { | 688 | if (msg[2] != 0) { |
673 | printk(KERN_WARNING | 689 | dev_warn(smi_info->dev, "Could not enable interrupts" |
674 | "ipmi_si: Could not enable interrupts" | 690 | ", failed get, using polled mode.\n"); |
675 | ", failed get, using polled mode.\n"); | ||
676 | smi_info->si_state = SI_NORMAL; | 691 | smi_info->si_state = SI_NORMAL; |
677 | } else { | 692 | } else { |
678 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 693 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
@@ -693,11 +708,11 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
693 | 708 | ||
694 | /* We got the flags from the SMI, now handle them. */ | 709 | /* We got the flags from the SMI, now handle them. */ |
695 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 710 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
696 | if (msg[2] != 0) { | 711 | if (msg[2] != 0) |
697 | printk(KERN_WARNING | 712 | dev_warn(smi_info->dev, "Could not enable interrupts" |
698 | "ipmi_si: Could not enable interrupts" | 713 | ", failed set, using polled mode.\n"); |
699 | ", failed set, using polled mode.\n"); | 714 | else |
700 | } | 715 | smi_info->interrupt_disabled = 0; |
701 | smi_info->si_state = SI_NORMAL; | 716 | smi_info->si_state = SI_NORMAL; |
702 | break; | 717 | break; |
703 | } | 718 | } |
@@ -709,9 +724,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
709 | /* We got the flags from the SMI, now handle them. */ | 724 | /* We got the flags from the SMI, now handle them. */ |
710 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 725 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
711 | if (msg[2] != 0) { | 726 | if (msg[2] != 0) { |
712 | printk(KERN_WARNING | 727 | dev_warn(smi_info->dev, "Could not disable interrupts" |
713 | "ipmi_si: Could not disable interrupts" | 728 | ", failed get.\n"); |
714 | ", failed get.\n"); | ||
715 | smi_info->si_state = SI_NORMAL; | 729 | smi_info->si_state = SI_NORMAL; |
716 | } else { | 730 | } else { |
717 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); | 731 | msg[0] = (IPMI_NETFN_APP_REQUEST << 2); |
@@ -733,9 +747,8 @@ static void handle_transaction_done(struct smi_info *smi_info) | |||
733 | /* We got the flags from the SMI, now handle them. */ | 747 | /* We got the flags from the SMI, now handle them. */ |
734 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); | 748 | smi_info->handlers->get_result(smi_info->si_sm, msg, 4); |
735 | if (msg[2] != 0) { | 749 | if (msg[2] != 0) { |
736 | printk(KERN_WARNING | 750 | dev_warn(smi_info->dev, "Could not disable interrupts" |
737 | "ipmi_si: Could not disable interrupts" | 751 | ", failed set.\n"); |
738 | ", failed set.\n"); | ||
739 | } | 752 | } |
740 | smi_info->si_state = SI_NORMAL; | 753 | smi_info->si_state = SI_NORMAL; |
741 | break; | 754 | break; |
@@ -877,6 +890,11 @@ static void sender(void *send_info, | |||
877 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 890 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
878 | #endif | 891 | #endif |
879 | 892 | ||
893 | mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); | ||
894 | |||
895 | if (smi_info->thread) | ||
896 | wake_up_process(smi_info->thread); | ||
897 | |||
880 | if (smi_info->run_to_completion) { | 898 | if (smi_info->run_to_completion) { |
881 | /* | 899 | /* |
882 | * If we are running to completion, then throw it in | 900 | * If we are running to completion, then throw it in |
@@ -997,6 +1015,8 @@ static int ipmi_thread(void *data) | |||
997 | ; /* do nothing */ | 1015 | ; /* do nothing */ |
998 | else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) | 1016 | else if (smi_result == SI_SM_CALL_WITH_DELAY && busy_wait) |
999 | schedule(); | 1017 | schedule(); |
1018 | else if (smi_result == SI_SM_IDLE) | ||
1019 | schedule_timeout_interruptible(100); | ||
1000 | else | 1020 | else |
1001 | schedule_timeout_interruptible(0); | 1021 | schedule_timeout_interruptible(0); |
1002 | } | 1022 | } |
@@ -1039,6 +1059,7 @@ static void smi_timeout(unsigned long data) | |||
1039 | unsigned long flags; | 1059 | unsigned long flags; |
1040 | unsigned long jiffies_now; | 1060 | unsigned long jiffies_now; |
1041 | long time_diff; | 1061 | long time_diff; |
1062 | long timeout; | ||
1042 | #ifdef DEBUG_TIMING | 1063 | #ifdef DEBUG_TIMING |
1043 | struct timeval t; | 1064 | struct timeval t; |
1044 | #endif | 1065 | #endif |
@@ -1059,9 +1080,9 @@ static void smi_timeout(unsigned long data) | |||
1059 | 1080 | ||
1060 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { | 1081 | if ((smi_info->irq) && (!smi_info->interrupt_disabled)) { |
1061 | /* Running with interrupts, only do long timeouts. */ | 1082 | /* Running with interrupts, only do long timeouts. */ |
1062 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 1083 | timeout = jiffies + SI_TIMEOUT_JIFFIES; |
1063 | smi_inc_stat(smi_info, long_timeouts); | 1084 | smi_inc_stat(smi_info, long_timeouts); |
1064 | goto do_add_timer; | 1085 | goto do_mod_timer; |
1065 | } | 1086 | } |
1066 | 1087 | ||
1067 | /* | 1088 | /* |
@@ -1070,14 +1091,15 @@ static void smi_timeout(unsigned long data) | |||
1070 | */ | 1091 | */ |
1071 | if (smi_result == SI_SM_CALL_WITH_DELAY) { | 1092 | if (smi_result == SI_SM_CALL_WITH_DELAY) { |
1072 | smi_inc_stat(smi_info, short_timeouts); | 1093 | smi_inc_stat(smi_info, short_timeouts); |
1073 | smi_info->si_timer.expires = jiffies + 1; | 1094 | timeout = jiffies + 1; |
1074 | } else { | 1095 | } else { |
1075 | smi_inc_stat(smi_info, long_timeouts); | 1096 | smi_inc_stat(smi_info, long_timeouts); |
1076 | smi_info->si_timer.expires = jiffies + SI_TIMEOUT_JIFFIES; | 1097 | timeout = jiffies + SI_TIMEOUT_JIFFIES; |
1077 | } | 1098 | } |
1078 | 1099 | ||
1079 | do_add_timer: | 1100 | do_mod_timer: |
1080 | add_timer(&(smi_info->si_timer)); | 1101 | if (smi_result != SI_SM_IDLE) |
1102 | mod_timer(&(smi_info->si_timer), timeout); | ||
1081 | } | 1103 | } |
1082 | 1104 | ||
1083 | static irqreturn_t si_irq_handler(int irq, void *data) | 1105 | static irqreturn_t si_irq_handler(int irq, void *data) |
@@ -1144,10 +1166,10 @@ static int smi_start_processing(void *send_info, | |||
1144 | new_smi->thread = kthread_run(ipmi_thread, new_smi, | 1166 | new_smi->thread = kthread_run(ipmi_thread, new_smi, |
1145 | "kipmi%d", new_smi->intf_num); | 1167 | "kipmi%d", new_smi->intf_num); |
1146 | if (IS_ERR(new_smi->thread)) { | 1168 | if (IS_ERR(new_smi->thread)) { |
1147 | printk(KERN_NOTICE "ipmi_si_intf: Could not start" | 1169 | dev_notice(new_smi->dev, "Could not start" |
1148 | " kernel thread due to error %ld, only using" | 1170 | " kernel thread due to error %ld, only using" |
1149 | " timers to drive the interface\n", | 1171 | " timers to drive the interface\n", |
1150 | PTR_ERR(new_smi->thread)); | 1172 | PTR_ERR(new_smi->thread)); |
1151 | new_smi->thread = NULL; | 1173 | new_smi->thread = NULL; |
1152 | } | 1174 | } |
1153 | } | 1175 | } |
@@ -1308,14 +1330,13 @@ static int std_irq_setup(struct smi_info *info) | |||
1308 | DEVICE_NAME, | 1330 | DEVICE_NAME, |
1309 | info); | 1331 | info); |
1310 | if (rv) { | 1332 | if (rv) { |
1311 | printk(KERN_WARNING | 1333 | dev_warn(info->dev, "%s unable to claim interrupt %d," |
1312 | "ipmi_si: %s unable to claim interrupt %d," | 1334 | " running polled\n", |
1313 | " running polled\n", | 1335 | DEVICE_NAME, info->irq); |
1314 | DEVICE_NAME, info->irq); | ||
1315 | info->irq = 0; | 1336 | info->irq = 0; |
1316 | } else { | 1337 | } else { |
1317 | info->irq_cleanup = std_irq_cleanup; | 1338 | info->irq_cleanup = std_irq_cleanup; |
1318 | printk(" Using irq %d\n", info->irq); | 1339 | dev_info(info->dev, "Using irq %d\n", info->irq); |
1319 | } | 1340 | } |
1320 | 1341 | ||
1321 | return rv; | 1342 | return rv; |
@@ -1406,8 +1427,8 @@ static int port_setup(struct smi_info *info) | |||
1406 | info->io.outputb = port_outl; | 1427 | info->io.outputb = port_outl; |
1407 | break; | 1428 | break; |
1408 | default: | 1429 | default: |
1409 | printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n", | 1430 | dev_warn(info->dev, "Invalid register size: %d\n", |
1410 | info->io.regsize); | 1431 | info->io.regsize); |
1411 | return -EINVAL; | 1432 | return -EINVAL; |
1412 | } | 1433 | } |
1413 | 1434 | ||
@@ -1529,8 +1550,8 @@ static int mem_setup(struct smi_info *info) | |||
1529 | break; | 1550 | break; |
1530 | #endif | 1551 | #endif |
1531 | default: | 1552 | default: |
1532 | printk(KERN_WARNING "ipmi_si: Invalid register size: %d\n", | 1553 | dev_warn(info->dev, "Invalid register size: %d\n", |
1533 | info->io.regsize); | 1554 | info->io.regsize); |
1534 | return -EINVAL; | 1555 | return -EINVAL; |
1535 | } | 1556 | } |
1536 | 1557 | ||
@@ -1755,7 +1776,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1755 | goto out; | 1776 | goto out; |
1756 | } | 1777 | } |
1757 | 1778 | ||
1758 | info->addr_source = "hotmod"; | 1779 | info->addr_source = SI_HOTMOD; |
1759 | info->si_type = si_type; | 1780 | info->si_type = si_type; |
1760 | info->io.addr_data = addr; | 1781 | info->io.addr_data = addr; |
1761 | info->io.addr_type = addr_space; | 1782 | info->io.addr_type = addr_space; |
@@ -1777,7 +1798,9 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
1777 | info->irq_setup = std_irq_setup; | 1798 | info->irq_setup = std_irq_setup; |
1778 | info->slave_addr = ipmb; | 1799 | info->slave_addr = ipmb; |
1779 | 1800 | ||
1780 | try_smi_init(info); | 1801 | if (!add_smi(info)) |
1802 | if (try_smi_init(info)) | ||
1803 | cleanup_one_si(info); | ||
1781 | } else { | 1804 | } else { |
1782 | /* remove */ | 1805 | /* remove */ |
1783 | struct smi_info *e, *tmp_e; | 1806 | struct smi_info *e, *tmp_e; |
@@ -1813,7 +1836,8 @@ static __devinit void hardcode_find_bmc(void) | |||
1813 | if (!info) | 1836 | if (!info) |
1814 | return; | 1837 | return; |
1815 | 1838 | ||
1816 | info->addr_source = "hardcoded"; | 1839 | info->addr_source = SI_HARDCODED; |
1840 | printk(KERN_INFO PFX "probing via hardcoded address\n"); | ||
1817 | 1841 | ||
1818 | if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { | 1842 | if (!si_type[i] || strcmp(si_type[i], "kcs") == 0) { |
1819 | info->si_type = SI_KCS; | 1843 | info->si_type = SI_KCS; |
@@ -1822,8 +1846,7 @@ static __devinit void hardcode_find_bmc(void) | |||
1822 | } else if (strcmp(si_type[i], "bt") == 0) { | 1846 | } else if (strcmp(si_type[i], "bt") == 0) { |
1823 | info->si_type = SI_BT; | 1847 | info->si_type = SI_BT; |
1824 | } else { | 1848 | } else { |
1825 | printk(KERN_WARNING | 1849 | printk(KERN_WARNING PFX "Interface type specified " |
1826 | "ipmi_si: Interface type specified " | ||
1827 | "for interface %d, was invalid: %s\n", | 1850 | "for interface %d, was invalid: %s\n", |
1828 | i, si_type[i]); | 1851 | i, si_type[i]); |
1829 | kfree(info); | 1852 | kfree(info); |
@@ -1841,11 +1864,9 @@ static __devinit void hardcode_find_bmc(void) | |||
1841 | info->io.addr_data = addrs[i]; | 1864 | info->io.addr_data = addrs[i]; |
1842 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | 1865 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; |
1843 | } else { | 1866 | } else { |
1844 | printk(KERN_WARNING | 1867 | printk(KERN_WARNING PFX "Interface type specified " |
1845 | "ipmi_si: Interface type specified " | 1868 | "for interface %d, but port and address were " |
1846 | "for interface %d, " | 1869 | "not set or set to zero.\n", i); |
1847 | "but port and address were not set or " | ||
1848 | "set to zero.\n", i); | ||
1849 | kfree(info); | 1870 | kfree(info); |
1850 | continue; | 1871 | continue; |
1851 | } | 1872 | } |
@@ -1863,7 +1884,9 @@ static __devinit void hardcode_find_bmc(void) | |||
1863 | info->irq_setup = std_irq_setup; | 1884 | info->irq_setup = std_irq_setup; |
1864 | info->slave_addr = slave_addrs[i]; | 1885 | info->slave_addr = slave_addrs[i]; |
1865 | 1886 | ||
1866 | try_smi_init(info); | 1887 | if (!add_smi(info)) |
1888 | if (try_smi_init(info)) | ||
1889 | cleanup_one_si(info); | ||
1867 | } | 1890 | } |
1868 | } | 1891 | } |
1869 | 1892 | ||
@@ -1923,15 +1946,13 @@ static int acpi_gpe_irq_setup(struct smi_info *info) | |||
1923 | &ipmi_acpi_gpe, | 1946 | &ipmi_acpi_gpe, |
1924 | info); | 1947 | info); |
1925 | if (status != AE_OK) { | 1948 | if (status != AE_OK) { |
1926 | printk(KERN_WARNING | 1949 | dev_warn(info->dev, "%s unable to claim ACPI GPE %d," |
1927 | "ipmi_si: %s unable to claim ACPI GPE %d," | 1950 | " running polled\n", DEVICE_NAME, info->irq); |
1928 | " running polled\n", | ||
1929 | DEVICE_NAME, info->irq); | ||
1930 | info->irq = 0; | 1951 | info->irq = 0; |
1931 | return -EINVAL; | 1952 | return -EINVAL; |
1932 | } else { | 1953 | } else { |
1933 | info->irq_cleanup = acpi_gpe_irq_cleanup; | 1954 | info->irq_cleanup = acpi_gpe_irq_cleanup; |
1934 | printk(" Using ACPI GPE %d\n", info->irq); | 1955 | dev_info(info->dev, "Using ACPI GPE %d\n", info->irq); |
1935 | return 0; | 1956 | return 0; |
1936 | } | 1957 | } |
1937 | } | 1958 | } |
@@ -1989,8 +2010,8 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
1989 | u8 addr_space; | 2010 | u8 addr_space; |
1990 | 2011 | ||
1991 | if (spmi->IPMIlegacy != 1) { | 2012 | if (spmi->IPMIlegacy != 1) { |
1992 | printk(KERN_INFO "IPMI: Bad SPMI legacy %d\n", spmi->IPMIlegacy); | 2013 | printk(KERN_INFO PFX "Bad SPMI legacy %d\n", spmi->IPMIlegacy); |
1993 | return -ENODEV; | 2014 | return -ENODEV; |
1994 | } | 2015 | } |
1995 | 2016 | ||
1996 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) | 2017 | if (spmi->addr.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) |
@@ -2000,11 +2021,12 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2000 | 2021 | ||
2001 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2022 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
2002 | if (!info) { | 2023 | if (!info) { |
2003 | printk(KERN_ERR "ipmi_si: Could not allocate SI data (3)\n"); | 2024 | printk(KERN_ERR PFX "Could not allocate SI data (3)\n"); |
2004 | return -ENOMEM; | 2025 | return -ENOMEM; |
2005 | } | 2026 | } |
2006 | 2027 | ||
2007 | info->addr_source = "SPMI"; | 2028 | info->addr_source = SI_SPMI; |
2029 | printk(KERN_INFO PFX "probing via SPMI\n"); | ||
2008 | 2030 | ||
2009 | /* Figure out the interface type. */ | 2031 | /* Figure out the interface type. */ |
2010 | switch (spmi->InterfaceType) { | 2032 | switch (spmi->InterfaceType) { |
@@ -2018,8 +2040,8 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2018 | info->si_type = SI_BT; | 2040 | info->si_type = SI_BT; |
2019 | break; | 2041 | break; |
2020 | default: | 2042 | default: |
2021 | printk(KERN_INFO "ipmi_si: Unknown ACPI/SPMI SI type %d\n", | 2043 | printk(KERN_INFO PFX "Unknown ACPI/SPMI SI type %d\n", |
2022 | spmi->InterfaceType); | 2044 | spmi->InterfaceType); |
2023 | kfree(info); | 2045 | kfree(info); |
2024 | return -EIO; | 2046 | return -EIO; |
2025 | } | 2047 | } |
@@ -2055,13 +2077,12 @@ static __devinit int try_init_spmi(struct SPMITable *spmi) | |||
2055 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | 2077 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
2056 | } else { | 2078 | } else { |
2057 | kfree(info); | 2079 | kfree(info); |
2058 | printk(KERN_WARNING | 2080 | printk(KERN_WARNING PFX "Unknown ACPI I/O Address type\n"); |
2059 | "ipmi_si: Unknown ACPI I/O Address type\n"); | ||
2060 | return -EIO; | 2081 | return -EIO; |
2061 | } | 2082 | } |
2062 | info->io.addr_data = spmi->addr.address; | 2083 | info->io.addr_data = spmi->addr.address; |
2063 | 2084 | ||
2064 | try_smi_init(info); | 2085 | add_smi(info); |
2065 | 2086 | ||
2066 | return 0; | 2087 | return 0; |
2067 | } | 2088 | } |
@@ -2093,6 +2114,7 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2093 | { | 2114 | { |
2094 | struct acpi_device *acpi_dev; | 2115 | struct acpi_device *acpi_dev; |
2095 | struct smi_info *info; | 2116 | struct smi_info *info; |
2117 | struct resource *res; | ||
2096 | acpi_handle handle; | 2118 | acpi_handle handle; |
2097 | acpi_status status; | 2119 | acpi_status status; |
2098 | unsigned long long tmp; | 2120 | unsigned long long tmp; |
@@ -2105,7 +2127,8 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2105 | if (!info) | 2127 | if (!info) |
2106 | return -ENOMEM; | 2128 | return -ENOMEM; |
2107 | 2129 | ||
2108 | info->addr_source = "ACPI"; | 2130 | info->addr_source = SI_ACPI; |
2131 | printk(KERN_INFO PFX "probing via ACPI\n"); | ||
2109 | 2132 | ||
2110 | handle = acpi_dev->handle; | 2133 | handle = acpi_dev->handle; |
2111 | 2134 | ||
@@ -2125,22 +2148,26 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2125 | info->si_type = SI_BT; | 2148 | info->si_type = SI_BT; |
2126 | break; | 2149 | break; |
2127 | default: | 2150 | default: |
2128 | dev_info(&dev->dev, "unknown interface type %lld\n", tmp); | 2151 | dev_info(&dev->dev, "unknown IPMI type %lld\n", tmp); |
2129 | goto err_free; | 2152 | goto err_free; |
2130 | } | 2153 | } |
2131 | 2154 | ||
2132 | if (pnp_port_valid(dev, 0)) { | 2155 | res = pnp_get_resource(dev, IORESOURCE_IO, 0); |
2156 | if (res) { | ||
2133 | info->io_setup = port_setup; | 2157 | info->io_setup = port_setup; |
2134 | info->io.addr_type = IPMI_IO_ADDR_SPACE; | 2158 | info->io.addr_type = IPMI_IO_ADDR_SPACE; |
2135 | info->io.addr_data = pnp_port_start(dev, 0); | ||
2136 | } else if (pnp_mem_valid(dev, 0)) { | ||
2137 | info->io_setup = mem_setup; | ||
2138 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
2139 | info->io.addr_data = pnp_mem_start(dev, 0); | ||
2140 | } else { | 2159 | } else { |
2160 | res = pnp_get_resource(dev, IORESOURCE_MEM, 0); | ||
2161 | if (res) { | ||
2162 | info->io_setup = mem_setup; | ||
2163 | info->io.addr_type = IPMI_MEM_ADDR_SPACE; | ||
2164 | } | ||
2165 | } | ||
2166 | if (!res) { | ||
2141 | dev_err(&dev->dev, "no I/O or memory address\n"); | 2167 | dev_err(&dev->dev, "no I/O or memory address\n"); |
2142 | goto err_free; | 2168 | goto err_free; |
2143 | } | 2169 | } |
2170 | info->io.addr_data = res->start; | ||
2144 | 2171 | ||
2145 | info->io.regspacing = DEFAULT_REGSPACING; | 2172 | info->io.regspacing = DEFAULT_REGSPACING; |
2146 | info->io.regsize = DEFAULT_REGSPACING; | 2173 | info->io.regsize = DEFAULT_REGSPACING; |
@@ -2156,10 +2183,14 @@ static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, | |||
2156 | info->irq_setup = std_irq_setup; | 2183 | info->irq_setup = std_irq_setup; |
2157 | } | 2184 | } |
2158 | 2185 | ||
2159 | info->dev = &acpi_dev->dev; | 2186 | info->dev = &dev->dev; |
2160 | pnp_set_drvdata(dev, info); | 2187 | pnp_set_drvdata(dev, info); |
2161 | 2188 | ||
2162 | return try_smi_init(info); | 2189 | dev_info(info->dev, "%pR regsize %d spacing %d irq %d\n", |
2190 | res, info->io.regsize, info->io.regspacing, | ||
2191 | info->irq); | ||
2192 | |||
2193 | return add_smi(info); | ||
2163 | 2194 | ||
2164 | err_free: | 2195 | err_free: |
2165 | kfree(info); | 2196 | kfree(info); |
@@ -2264,12 +2295,12 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2264 | 2295 | ||
2265 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 2296 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
2266 | if (!info) { | 2297 | if (!info) { |
2267 | printk(KERN_ERR | 2298 | printk(KERN_ERR PFX "Could not allocate SI data\n"); |
2268 | "ipmi_si: Could not allocate SI data\n"); | ||
2269 | return; | 2299 | return; |
2270 | } | 2300 | } |
2271 | 2301 | ||
2272 | info->addr_source = "SMBIOS"; | 2302 | info->addr_source = SI_SMBIOS; |
2303 | printk(KERN_INFO PFX "probing via SMBIOS\n"); | ||
2273 | 2304 | ||
2274 | switch (ipmi_data->type) { | 2305 | switch (ipmi_data->type) { |
2275 | case 0x01: /* KCS */ | 2306 | case 0x01: /* KCS */ |
@@ -2299,8 +2330,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2299 | 2330 | ||
2300 | default: | 2331 | default: |
2301 | kfree(info); | 2332 | kfree(info); |
2302 | printk(KERN_WARNING | 2333 | printk(KERN_WARNING PFX "Unknown SMBIOS I/O Address type: %d\n", |
2303 | "ipmi_si: Unknown SMBIOS I/O Address type: %d.\n", | ||
2304 | ipmi_data->addr_space); | 2334 | ipmi_data->addr_space); |
2305 | return; | 2335 | return; |
2306 | } | 2336 | } |
@@ -2318,7 +2348,7 @@ static __devinit void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
2318 | if (info->irq) | 2348 | if (info->irq) |
2319 | info->irq_setup = std_irq_setup; | 2349 | info->irq_setup = std_irq_setup; |
2320 | 2350 | ||
2321 | try_smi_init(info); | 2351 | add_smi(info); |
2322 | } | 2352 | } |
2323 | 2353 | ||
2324 | static void __devinit dmi_find_bmc(void) | 2354 | static void __devinit dmi_find_bmc(void) |
@@ -2368,7 +2398,8 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2368 | if (!info) | 2398 | if (!info) |
2369 | return -ENOMEM; | 2399 | return -ENOMEM; |
2370 | 2400 | ||
2371 | info->addr_source = "PCI"; | 2401 | info->addr_source = SI_PCI; |
2402 | dev_info(&pdev->dev, "probing via PCI"); | ||
2372 | 2403 | ||
2373 | switch (class_type) { | 2404 | switch (class_type) { |
2374 | case PCI_ERMC_CLASSCODE_TYPE_SMIC: | 2405 | case PCI_ERMC_CLASSCODE_TYPE_SMIC: |
@@ -2385,15 +2416,13 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2385 | 2416 | ||
2386 | default: | 2417 | default: |
2387 | kfree(info); | 2418 | kfree(info); |
2388 | printk(KERN_INFO "ipmi_si: %s: Unknown IPMI type: %d\n", | 2419 | dev_info(&pdev->dev, "Unknown IPMI type: %d\n", class_type); |
2389 | pci_name(pdev), class_type); | ||
2390 | return -ENOMEM; | 2420 | return -ENOMEM; |
2391 | } | 2421 | } |
2392 | 2422 | ||
2393 | rv = pci_enable_device(pdev); | 2423 | rv = pci_enable_device(pdev); |
2394 | if (rv) { | 2424 | if (rv) { |
2395 | printk(KERN_ERR "ipmi_si: %s: couldn't enable PCI device\n", | 2425 | dev_err(&pdev->dev, "couldn't enable PCI device\n"); |
2396 | pci_name(pdev)); | ||
2397 | kfree(info); | 2426 | kfree(info); |
2398 | return rv; | 2427 | return rv; |
2399 | } | 2428 | } |
@@ -2421,7 +2450,11 @@ static int __devinit ipmi_pci_probe(struct pci_dev *pdev, | |||
2421 | info->dev = &pdev->dev; | 2450 | info->dev = &pdev->dev; |
2422 | pci_set_drvdata(pdev, info); | 2451 | pci_set_drvdata(pdev, info); |
2423 | 2452 | ||
2424 | return try_smi_init(info); | 2453 | dev_info(&pdev->dev, "%pR regsize %d spacing %d irq %d\n", |
2454 | &pdev->resource[0], info->io.regsize, info->io.regspacing, | ||
2455 | info->irq); | ||
2456 | |||
2457 | return add_smi(info); | ||
2425 | } | 2458 | } |
2426 | 2459 | ||
2427 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) | 2460 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) |
@@ -2473,7 +2506,7 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2473 | int ret; | 2506 | int ret; |
2474 | int proplen; | 2507 | int proplen; |
2475 | 2508 | ||
2476 | dev_info(&dev->dev, PFX "probing via device tree\n"); | 2509 | dev_info(&dev->dev, "probing via device tree\n"); |
2477 | 2510 | ||
2478 | ret = of_address_to_resource(np, 0, &resource); | 2511 | ret = of_address_to_resource(np, 0, &resource); |
2479 | if (ret) { | 2512 | if (ret) { |
@@ -2503,12 +2536,12 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2503 | 2536 | ||
2504 | if (!info) { | 2537 | if (!info) { |
2505 | dev_err(&dev->dev, | 2538 | dev_err(&dev->dev, |
2506 | PFX "could not allocate memory for OF probe\n"); | 2539 | "could not allocate memory for OF probe\n"); |
2507 | return -ENOMEM; | 2540 | return -ENOMEM; |
2508 | } | 2541 | } |
2509 | 2542 | ||
2510 | info->si_type = (enum si_type) match->data; | 2543 | info->si_type = (enum si_type) match->data; |
2511 | info->addr_source = "device-tree"; | 2544 | info->addr_source = SI_DEVICETREE; |
2512 | info->irq_setup = std_irq_setup; | 2545 | info->irq_setup = std_irq_setup; |
2513 | 2546 | ||
2514 | if (resource.flags & IORESOURCE_IO) { | 2547 | if (resource.flags & IORESOURCE_IO) { |
@@ -2528,13 +2561,13 @@ static int __devinit ipmi_of_probe(struct of_device *dev, | |||
2528 | info->irq = irq_of_parse_and_map(dev->dev.of_node, 0); | 2561 | info->irq = irq_of_parse_and_map(dev->dev.of_node, 0); |
2529 | info->dev = &dev->dev; | 2562 | info->dev = &dev->dev; |
2530 | 2563 | ||
2531 | dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %x\n", | 2564 | dev_dbg(&dev->dev, "addr 0x%lx regsize %d spacing %d irq %d\n", |
2532 | info->io.addr_data, info->io.regsize, info->io.regspacing, | 2565 | info->io.addr_data, info->io.regsize, info->io.regspacing, |
2533 | info->irq); | 2566 | info->irq); |
2534 | 2567 | ||
2535 | dev_set_drvdata(&dev->dev, info); | 2568 | dev_set_drvdata(&dev->dev, info); |
2536 | 2569 | ||
2537 | return try_smi_init(info); | 2570 | return add_smi(info); |
2538 | } | 2571 | } |
2539 | 2572 | ||
2540 | static int __devexit ipmi_of_remove(struct of_device *dev) | 2573 | static int __devexit ipmi_of_remove(struct of_device *dev) |
@@ -2643,9 +2676,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2643 | 2676 | ||
2644 | rv = wait_for_msg_done(smi_info); | 2677 | rv = wait_for_msg_done(smi_info); |
2645 | if (rv) { | 2678 | if (rv) { |
2646 | printk(KERN_WARNING | 2679 | printk(KERN_WARNING PFX "Error getting response from get" |
2647 | "ipmi_si: Error getting response from get global," | 2680 | " global enables command, the event buffer is not" |
2648 | " enables command, the event buffer is not" | ||
2649 | " enabled.\n"); | 2681 | " enabled.\n"); |
2650 | goto out; | 2682 | goto out; |
2651 | } | 2683 | } |
@@ -2657,10 +2689,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2657 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || | 2689 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || |
2658 | resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || | 2690 | resp[1] != IPMI_GET_BMC_GLOBAL_ENABLES_CMD || |
2659 | resp[2] != 0) { | 2691 | resp[2] != 0) { |
2660 | printk(KERN_WARNING | 2692 | printk(KERN_WARNING PFX "Invalid return from get global" |
2661 | "ipmi_si: Invalid return from get global" | 2693 | " enables command, cannot enable the event buffer.\n"); |
2662 | " enables command, cannot enable the event" | ||
2663 | " buffer.\n"); | ||
2664 | rv = -EINVAL; | 2694 | rv = -EINVAL; |
2665 | goto out; | 2695 | goto out; |
2666 | } | 2696 | } |
@@ -2676,9 +2706,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2676 | 2706 | ||
2677 | rv = wait_for_msg_done(smi_info); | 2707 | rv = wait_for_msg_done(smi_info); |
2678 | if (rv) { | 2708 | if (rv) { |
2679 | printk(KERN_WARNING | 2709 | printk(KERN_WARNING PFX "Error getting response from set" |
2680 | "ipmi_si: Error getting response from set global," | 2710 | " global, enables command, the event buffer is not" |
2681 | " enables command, the event buffer is not" | ||
2682 | " enabled.\n"); | 2711 | " enabled.\n"); |
2683 | goto out; | 2712 | goto out; |
2684 | } | 2713 | } |
@@ -2689,10 +2718,8 @@ static int try_enable_event_buffer(struct smi_info *smi_info) | |||
2689 | if (resp_len < 3 || | 2718 | if (resp_len < 3 || |
2690 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || | 2719 | resp[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2 || |
2691 | resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { | 2720 | resp[1] != IPMI_SET_BMC_GLOBAL_ENABLES_CMD) { |
2692 | printk(KERN_WARNING | 2721 | printk(KERN_WARNING PFX "Invalid return from get global," |
2693 | "ipmi_si: Invalid return from get global," | 2722 | "enables command, not enable the event buffer.\n"); |
2694 | "enables command, not enable the event" | ||
2695 | " buffer.\n"); | ||
2696 | rv = -EINVAL; | 2723 | rv = -EINVAL; |
2697 | goto out; | 2724 | goto out; |
2698 | } | 2725 | } |
@@ -2951,7 +2978,7 @@ static __devinit void default_find_bmc(void) | |||
2951 | if (!info) | 2978 | if (!info) |
2952 | return; | 2979 | return; |
2953 | 2980 | ||
2954 | info->addr_source = NULL; | 2981 | info->addr_source = SI_DEFAULT; |
2955 | 2982 | ||
2956 | info->si_type = ipmi_defaults[i].type; | 2983 | info->si_type = ipmi_defaults[i].type; |
2957 | info->io_setup = port_setup; | 2984 | info->io_setup = port_setup; |
@@ -2963,14 +2990,16 @@ static __devinit void default_find_bmc(void) | |||
2963 | info->io.regsize = DEFAULT_REGSPACING; | 2990 | info->io.regsize = DEFAULT_REGSPACING; |
2964 | info->io.regshift = 0; | 2991 | info->io.regshift = 0; |
2965 | 2992 | ||
2966 | if (try_smi_init(info) == 0) { | 2993 | if (add_smi(info) == 0) { |
2967 | /* Found one... */ | 2994 | if ((try_smi_init(info)) == 0) { |
2968 | printk(KERN_INFO "ipmi_si: Found default %s state" | 2995 | /* Found one... */ |
2969 | " machine at %s address 0x%lx\n", | 2996 | printk(KERN_INFO PFX "Found default %s" |
2970 | si_to_str[info->si_type], | 2997 | " state machine at %s address 0x%lx\n", |
2971 | addr_space_to_str[info->io.addr_type], | 2998 | si_to_str[info->si_type], |
2972 | info->io.addr_data); | 2999 | addr_space_to_str[info->io.addr_type], |
2973 | return; | 3000 | info->io.addr_data); |
3001 | } else | ||
3002 | cleanup_one_si(info); | ||
2974 | } | 3003 | } |
2975 | } | 3004 | } |
2976 | } | 3005 | } |
@@ -2989,34 +3018,48 @@ static int is_new_interface(struct smi_info *info) | |||
2989 | return 1; | 3018 | return 1; |
2990 | } | 3019 | } |
2991 | 3020 | ||
2992 | static int try_smi_init(struct smi_info *new_smi) | 3021 | static int add_smi(struct smi_info *new_smi) |
2993 | { | 3022 | { |
2994 | int rv; | 3023 | int rv = 0; |
2995 | int i; | ||
2996 | |||
2997 | if (new_smi->addr_source) { | ||
2998 | printk(KERN_INFO "ipmi_si: Trying %s-specified %s state" | ||
2999 | " machine at %s address 0x%lx, slave address 0x%x," | ||
3000 | " irq %d\n", | ||
3001 | new_smi->addr_source, | ||
3002 | si_to_str[new_smi->si_type], | ||
3003 | addr_space_to_str[new_smi->io.addr_type], | ||
3004 | new_smi->io.addr_data, | ||
3005 | new_smi->slave_addr, new_smi->irq); | ||
3006 | } | ||
3007 | 3024 | ||
3025 | printk(KERN_INFO PFX "Adding %s-specified %s state machine", | ||
3026 | ipmi_addr_src_to_str[new_smi->addr_source], | ||
3027 | si_to_str[new_smi->si_type]); | ||
3008 | mutex_lock(&smi_infos_lock); | 3028 | mutex_lock(&smi_infos_lock); |
3009 | if (!is_new_interface(new_smi)) { | 3029 | if (!is_new_interface(new_smi)) { |
3010 | printk(KERN_WARNING "ipmi_si: duplicate interface\n"); | 3030 | printk(KERN_CONT PFX "duplicate interface\n"); |
3011 | rv = -EBUSY; | 3031 | rv = -EBUSY; |
3012 | goto out_err; | 3032 | goto out_err; |
3013 | } | 3033 | } |
3014 | 3034 | ||
3035 | printk(KERN_CONT "\n"); | ||
3036 | |||
3015 | /* So we know not to free it unless we have allocated one. */ | 3037 | /* So we know not to free it unless we have allocated one. */ |
3016 | new_smi->intf = NULL; | 3038 | new_smi->intf = NULL; |
3017 | new_smi->si_sm = NULL; | 3039 | new_smi->si_sm = NULL; |
3018 | new_smi->handlers = NULL; | 3040 | new_smi->handlers = NULL; |
3019 | 3041 | ||
3042 | list_add_tail(&new_smi->link, &smi_infos); | ||
3043 | |||
3044 | out_err: | ||
3045 | mutex_unlock(&smi_infos_lock); | ||
3046 | return rv; | ||
3047 | } | ||
3048 | |||
3049 | static int try_smi_init(struct smi_info *new_smi) | ||
3050 | { | ||
3051 | int rv = 0; | ||
3052 | int i; | ||
3053 | |||
3054 | printk(KERN_INFO PFX "Trying %s-specified %s state" | ||
3055 | " machine at %s address 0x%lx, slave address 0x%x," | ||
3056 | " irq %d\n", | ||
3057 | ipmi_addr_src_to_str[new_smi->addr_source], | ||
3058 | si_to_str[new_smi->si_type], | ||
3059 | addr_space_to_str[new_smi->io.addr_type], | ||
3060 | new_smi->io.addr_data, | ||
3061 | new_smi->slave_addr, new_smi->irq); | ||
3062 | |||
3020 | switch (new_smi->si_type) { | 3063 | switch (new_smi->si_type) { |
3021 | case SI_KCS: | 3064 | case SI_KCS: |
3022 | new_smi->handlers = &kcs_smi_handlers; | 3065 | new_smi->handlers = &kcs_smi_handlers; |
@@ -3039,7 +3082,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3039 | /* Allocate the state machine's data and initialize it. */ | 3082 | /* Allocate the state machine's data and initialize it. */ |
3040 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); | 3083 | new_smi->si_sm = kmalloc(new_smi->handlers->size(), GFP_KERNEL); |
3041 | if (!new_smi->si_sm) { | 3084 | if (!new_smi->si_sm) { |
3042 | printk(KERN_ERR "Could not allocate state machine memory\n"); | 3085 | printk(KERN_ERR PFX |
3086 | "Could not allocate state machine memory\n"); | ||
3043 | rv = -ENOMEM; | 3087 | rv = -ENOMEM; |
3044 | goto out_err; | 3088 | goto out_err; |
3045 | } | 3089 | } |
@@ -3049,7 +3093,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3049 | /* Now that we know the I/O size, we can set up the I/O. */ | 3093 | /* Now that we know the I/O size, we can set up the I/O. */ |
3050 | rv = new_smi->io_setup(new_smi); | 3094 | rv = new_smi->io_setup(new_smi); |
3051 | if (rv) { | 3095 | if (rv) { |
3052 | printk(KERN_ERR "Could not set up I/O space\n"); | 3096 | printk(KERN_ERR PFX "Could not set up I/O space\n"); |
3053 | goto out_err; | 3097 | goto out_err; |
3054 | } | 3098 | } |
3055 | 3099 | ||
@@ -3059,8 +3103,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3059 | /* Do low-level detection first. */ | 3103 | /* Do low-level detection first. */ |
3060 | if (new_smi->handlers->detect(new_smi->si_sm)) { | 3104 | if (new_smi->handlers->detect(new_smi->si_sm)) { |
3061 | if (new_smi->addr_source) | 3105 | if (new_smi->addr_source) |
3062 | printk(KERN_INFO "ipmi_si: Interface detection" | 3106 | printk(KERN_INFO PFX "Interface detection failed\n"); |
3063 | " failed\n"); | ||
3064 | rv = -ENODEV; | 3107 | rv = -ENODEV; |
3065 | goto out_err; | 3108 | goto out_err; |
3066 | } | 3109 | } |
@@ -3072,7 +3115,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3072 | rv = try_get_dev_id(new_smi); | 3115 | rv = try_get_dev_id(new_smi); |
3073 | if (rv) { | 3116 | if (rv) { |
3074 | if (new_smi->addr_source) | 3117 | if (new_smi->addr_source) |
3075 | printk(KERN_INFO "ipmi_si: There appears to be no BMC" | 3118 | printk(KERN_INFO PFX "There appears to be no BMC" |
3076 | " at this location\n"); | 3119 | " at this location\n"); |
3077 | goto out_err; | 3120 | goto out_err; |
3078 | } | 3121 | } |
@@ -3088,7 +3131,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3088 | for (i = 0; i < SI_NUM_STATS; i++) | 3131 | for (i = 0; i < SI_NUM_STATS; i++) |
3089 | atomic_set(&new_smi->stats[i], 0); | 3132 | atomic_set(&new_smi->stats[i], 0); |
3090 | 3133 | ||
3091 | new_smi->interrupt_disabled = 0; | 3134 | new_smi->interrupt_disabled = 1; |
3092 | atomic_set(&new_smi->stop_operation, 0); | 3135 | atomic_set(&new_smi->stop_operation, 0); |
3093 | new_smi->intf_num = smi_num; | 3136 | new_smi->intf_num = smi_num; |
3094 | smi_num++; | 3137 | smi_num++; |
@@ -3114,9 +3157,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3114 | new_smi->pdev = platform_device_alloc("ipmi_si", | 3157 | new_smi->pdev = platform_device_alloc("ipmi_si", |
3115 | new_smi->intf_num); | 3158 | new_smi->intf_num); |
3116 | if (!new_smi->pdev) { | 3159 | if (!new_smi->pdev) { |
3117 | printk(KERN_ERR | 3160 | printk(KERN_ERR PFX |
3118 | "ipmi_si_intf:" | 3161 | "Unable to allocate platform device\n"); |
3119 | " Unable to allocate platform device\n"); | ||
3120 | goto out_err; | 3162 | goto out_err; |
3121 | } | 3163 | } |
3122 | new_smi->dev = &new_smi->pdev->dev; | 3164 | new_smi->dev = &new_smi->pdev->dev; |
@@ -3124,9 +3166,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3124 | 3166 | ||
3125 | rv = platform_device_add(new_smi->pdev); | 3167 | rv = platform_device_add(new_smi->pdev); |
3126 | if (rv) { | 3168 | if (rv) { |
3127 | printk(KERN_ERR | 3169 | printk(KERN_ERR PFX |
3128 | "ipmi_si_intf:" | 3170 | "Unable to register system interface device:" |
3129 | " Unable to register system interface device:" | ||
3130 | " %d\n", | 3171 | " %d\n", |
3131 | rv); | 3172 | rv); |
3132 | goto out_err; | 3173 | goto out_err; |
@@ -3141,9 +3182,8 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3141 | "bmc", | 3182 | "bmc", |
3142 | new_smi->slave_addr); | 3183 | new_smi->slave_addr); |
3143 | if (rv) { | 3184 | if (rv) { |
3144 | printk(KERN_ERR | 3185 | dev_err(new_smi->dev, "Unable to register device: error %d\n", |
3145 | "ipmi_si: Unable to register device: error %d\n", | 3186 | rv); |
3146 | rv); | ||
3147 | goto out_err_stop_timer; | 3187 | goto out_err_stop_timer; |
3148 | } | 3188 | } |
3149 | 3189 | ||
@@ -3151,9 +3191,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3151 | type_file_read_proc, | 3191 | type_file_read_proc, |
3152 | new_smi); | 3192 | new_smi); |
3153 | if (rv) { | 3193 | if (rv) { |
3154 | printk(KERN_ERR | 3194 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
3155 | "ipmi_si: Unable to create proc entry: %d\n", | ||
3156 | rv); | ||
3157 | goto out_err_stop_timer; | 3195 | goto out_err_stop_timer; |
3158 | } | 3196 | } |
3159 | 3197 | ||
@@ -3161,9 +3199,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3161 | stat_file_read_proc, | 3199 | stat_file_read_proc, |
3162 | new_smi); | 3200 | new_smi); |
3163 | if (rv) { | 3201 | if (rv) { |
3164 | printk(KERN_ERR | 3202 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
3165 | "ipmi_si: Unable to create proc entry: %d\n", | ||
3166 | rv); | ||
3167 | goto out_err_stop_timer; | 3203 | goto out_err_stop_timer; |
3168 | } | 3204 | } |
3169 | 3205 | ||
@@ -3171,18 +3207,12 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3171 | param_read_proc, | 3207 | param_read_proc, |
3172 | new_smi); | 3208 | new_smi); |
3173 | if (rv) { | 3209 | if (rv) { |
3174 | printk(KERN_ERR | 3210 | dev_err(new_smi->dev, "Unable to create proc entry: %d\n", rv); |
3175 | "ipmi_si: Unable to create proc entry: %d\n", | ||
3176 | rv); | ||
3177 | goto out_err_stop_timer; | 3211 | goto out_err_stop_timer; |
3178 | } | 3212 | } |
3179 | 3213 | ||
3180 | list_add_tail(&new_smi->link, &smi_infos); | 3214 | dev_info(new_smi->dev, "IPMI %s interface initialized\n", |
3181 | 3215 | si_to_str[new_smi->si_type]); | |
3182 | mutex_unlock(&smi_infos_lock); | ||
3183 | |||
3184 | printk(KERN_INFO "IPMI %s interface initialized\n", | ||
3185 | si_to_str[new_smi->si_type]); | ||
3186 | 3216 | ||
3187 | return 0; | 3217 | return 0; |
3188 | 3218 | ||
@@ -3191,11 +3221,17 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3191 | wait_for_timer_and_thread(new_smi); | 3221 | wait_for_timer_and_thread(new_smi); |
3192 | 3222 | ||
3193 | out_err: | 3223 | out_err: |
3194 | if (new_smi->intf) | 3224 | new_smi->interrupt_disabled = 1; |
3225 | |||
3226 | if (new_smi->intf) { | ||
3195 | ipmi_unregister_smi(new_smi->intf); | 3227 | ipmi_unregister_smi(new_smi->intf); |
3228 | new_smi->intf = NULL; | ||
3229 | } | ||
3196 | 3230 | ||
3197 | if (new_smi->irq_cleanup) | 3231 | if (new_smi->irq_cleanup) { |
3198 | new_smi->irq_cleanup(new_smi); | 3232 | new_smi->irq_cleanup(new_smi); |
3233 | new_smi->irq_cleanup = NULL; | ||
3234 | } | ||
3199 | 3235 | ||
3200 | /* | 3236 | /* |
3201 | * Wait until we know that we are out of any interrupt | 3237 | * Wait until we know that we are out of any interrupt |
@@ -3208,18 +3244,21 @@ static int try_smi_init(struct smi_info *new_smi) | |||
3208 | if (new_smi->handlers) | 3244 | if (new_smi->handlers) |
3209 | new_smi->handlers->cleanup(new_smi->si_sm); | 3245 | new_smi->handlers->cleanup(new_smi->si_sm); |
3210 | kfree(new_smi->si_sm); | 3246 | kfree(new_smi->si_sm); |
3247 | new_smi->si_sm = NULL; | ||
3211 | } | 3248 | } |
3212 | if (new_smi->addr_source_cleanup) | 3249 | if (new_smi->addr_source_cleanup) { |
3213 | new_smi->addr_source_cleanup(new_smi); | 3250 | new_smi->addr_source_cleanup(new_smi); |
3214 | if (new_smi->io_cleanup) | 3251 | new_smi->addr_source_cleanup = NULL; |
3252 | } | ||
3253 | if (new_smi->io_cleanup) { | ||
3215 | new_smi->io_cleanup(new_smi); | 3254 | new_smi->io_cleanup(new_smi); |
3255 | new_smi->io_cleanup = NULL; | ||
3256 | } | ||
3216 | 3257 | ||
3217 | if (new_smi->dev_registered) | 3258 | if (new_smi->dev_registered) { |
3218 | platform_device_unregister(new_smi->pdev); | 3259 | platform_device_unregister(new_smi->pdev); |
3219 | 3260 | new_smi->dev_registered = 0; | |
3220 | kfree(new_smi); | 3261 | } |
3221 | |||
3222 | mutex_unlock(&smi_infos_lock); | ||
3223 | 3262 | ||
3224 | return rv; | 3263 | return rv; |
3225 | } | 3264 | } |
@@ -3229,6 +3268,8 @@ static __devinit int init_ipmi_si(void) | |||
3229 | int i; | 3268 | int i; |
3230 | char *str; | 3269 | char *str; |
3231 | int rv; | 3270 | int rv; |
3271 | struct smi_info *e; | ||
3272 | enum ipmi_addr_src type = SI_INVALID; | ||
3232 | 3273 | ||
3233 | if (initialized) | 3274 | if (initialized) |
3234 | return 0; | 3275 | return 0; |
@@ -3237,9 +3278,7 @@ static __devinit int init_ipmi_si(void) | |||
3237 | /* Register the device drivers. */ | 3278 | /* Register the device drivers. */ |
3238 | rv = driver_register(&ipmi_driver.driver); | 3279 | rv = driver_register(&ipmi_driver.driver); |
3239 | if (rv) { | 3280 | if (rv) { |
3240 | printk(KERN_ERR | 3281 | printk(KERN_ERR PFX "Unable to register driver: %d\n", rv); |
3241 | "init_ipmi_si: Unable to register driver: %d\n", | ||
3242 | rv); | ||
3243 | return rv; | 3282 | return rv; |
3244 | } | 3283 | } |
3245 | 3284 | ||
@@ -3263,38 +3302,81 @@ static __devinit int init_ipmi_si(void) | |||
3263 | 3302 | ||
3264 | hardcode_find_bmc(); | 3303 | hardcode_find_bmc(); |
3265 | 3304 | ||
3266 | #ifdef CONFIG_DMI | 3305 | /* If the user gave us a device, they presumably want us to use it */ |
3267 | dmi_find_bmc(); | 3306 | mutex_lock(&smi_infos_lock); |
3268 | #endif | 3307 | if (!list_empty(&smi_infos)) { |
3308 | mutex_unlock(&smi_infos_lock); | ||
3309 | return 0; | ||
3310 | } | ||
3311 | mutex_unlock(&smi_infos_lock); | ||
3269 | 3312 | ||
3270 | #ifdef CONFIG_ACPI | 3313 | #ifdef CONFIG_PCI |
3271 | spmi_find_bmc(); | 3314 | rv = pci_register_driver(&ipmi_pci_driver); |
3315 | if (rv) | ||
3316 | printk(KERN_ERR PFX "Unable to register PCI driver: %d\n", rv); | ||
3272 | #endif | 3317 | #endif |
3318 | |||
3273 | #ifdef CONFIG_ACPI | 3319 | #ifdef CONFIG_ACPI |
3274 | pnp_register_driver(&ipmi_pnp_driver); | 3320 | pnp_register_driver(&ipmi_pnp_driver); |
3275 | #endif | 3321 | #endif |
3276 | 3322 | ||
3277 | #ifdef CONFIG_PCI | 3323 | #ifdef CONFIG_DMI |
3278 | rv = pci_register_driver(&ipmi_pci_driver); | 3324 | dmi_find_bmc(); |
3279 | if (rv) | 3325 | #endif |
3280 | printk(KERN_ERR | 3326 | |
3281 | "init_ipmi_si: Unable to register PCI driver: %d\n", | 3327 | #ifdef CONFIG_ACPI |
3282 | rv); | 3328 | spmi_find_bmc(); |
3283 | #endif | 3329 | #endif |
3284 | 3330 | ||
3285 | #ifdef CONFIG_PPC_OF | 3331 | #ifdef CONFIG_PPC_OF |
3286 | of_register_platform_driver(&ipmi_of_platform_driver); | 3332 | of_register_platform_driver(&ipmi_of_platform_driver); |
3287 | #endif | 3333 | #endif |
3288 | 3334 | ||
3335 | /* We prefer devices with interrupts, but in the case of a machine | ||
3336 | with multiple BMCs we assume that there will be several instances | ||
3337 | of a given type so if we succeed in registering a type then also | ||
3338 | try to register everything else of the same type */ | ||
3339 | |||
3340 | mutex_lock(&smi_infos_lock); | ||
3341 | list_for_each_entry(e, &smi_infos, link) { | ||
3342 | /* Try to register a device if it has an IRQ and we either | ||
3343 | haven't successfully registered a device yet or this | ||
3344 | device has the same type as one we successfully registered */ | ||
3345 | if (e->irq && (!type || e->addr_source == type)) { | ||
3346 | if (!try_smi_init(e)) { | ||
3347 | type = e->addr_source; | ||
3348 | } | ||
3349 | } | ||
3350 | } | ||
3351 | |||
3352 | /* type will only have been set if we successfully registered an si */ | ||
3353 | if (type) { | ||
3354 | mutex_unlock(&smi_infos_lock); | ||
3355 | return 0; | ||
3356 | } | ||
3357 | |||
3358 | /* Fall back to the preferred device */ | ||
3359 | |||
3360 | list_for_each_entry(e, &smi_infos, link) { | ||
3361 | if (!e->irq && (!type || e->addr_source == type)) { | ||
3362 | if (!try_smi_init(e)) { | ||
3363 | type = e->addr_source; | ||
3364 | } | ||
3365 | } | ||
3366 | } | ||
3367 | mutex_unlock(&smi_infos_lock); | ||
3368 | |||
3369 | if (type) | ||
3370 | return 0; | ||
3371 | |||
3289 | if (si_trydefaults) { | 3372 | if (si_trydefaults) { |
3290 | mutex_lock(&smi_infos_lock); | 3373 | mutex_lock(&smi_infos_lock); |
3291 | if (list_empty(&smi_infos)) { | 3374 | if (list_empty(&smi_infos)) { |
3292 | /* No BMC was found, try defaults. */ | 3375 | /* No BMC was found, try defaults. */ |
3293 | mutex_unlock(&smi_infos_lock); | 3376 | mutex_unlock(&smi_infos_lock); |
3294 | default_find_bmc(); | 3377 | default_find_bmc(); |
3295 | } else { | 3378 | } else |
3296 | mutex_unlock(&smi_infos_lock); | 3379 | mutex_unlock(&smi_infos_lock); |
3297 | } | ||
3298 | } | 3380 | } |
3299 | 3381 | ||
3300 | mutex_lock(&smi_infos_lock); | 3382 | mutex_lock(&smi_infos_lock); |
@@ -3308,8 +3390,8 @@ static __devinit int init_ipmi_si(void) | |||
3308 | of_unregister_platform_driver(&ipmi_of_platform_driver); | 3390 | of_unregister_platform_driver(&ipmi_of_platform_driver); |
3309 | #endif | 3391 | #endif |
3310 | driver_unregister(&ipmi_driver.driver); | 3392 | driver_unregister(&ipmi_driver.driver); |
3311 | printk(KERN_WARNING | 3393 | printk(KERN_WARNING PFX |
3312 | "ipmi_si: Unable to find any System Interface(s)\n"); | 3394 | "Unable to find any System Interface(s)\n"); |
3313 | return -ENODEV; | 3395 | return -ENODEV; |
3314 | } else { | 3396 | } else { |
3315 | mutex_unlock(&smi_infos_lock); | 3397 | mutex_unlock(&smi_infos_lock); |
@@ -3320,7 +3402,7 @@ module_init(init_ipmi_si); | |||
3320 | 3402 | ||
3321 | static void cleanup_one_si(struct smi_info *to_clean) | 3403 | static void cleanup_one_si(struct smi_info *to_clean) |
3322 | { | 3404 | { |
3323 | int rv; | 3405 | int rv = 0; |
3324 | unsigned long flags; | 3406 | unsigned long flags; |
3325 | 3407 | ||
3326 | if (!to_clean) | 3408 | if (!to_clean) |
@@ -3364,14 +3446,16 @@ static void cleanup_one_si(struct smi_info *to_clean) | |||
3364 | schedule_timeout_uninterruptible(1); | 3446 | schedule_timeout_uninterruptible(1); |
3365 | } | 3447 | } |
3366 | 3448 | ||
3367 | rv = ipmi_unregister_smi(to_clean->intf); | 3449 | if (to_clean->intf) |
3450 | rv = ipmi_unregister_smi(to_clean->intf); | ||
3451 | |||
3368 | if (rv) { | 3452 | if (rv) { |
3369 | printk(KERN_ERR | 3453 | printk(KERN_ERR PFX "Unable to unregister device: errno=%d\n", |
3370 | "ipmi_si: Unable to unregister device: errno=%d\n", | ||
3371 | rv); | 3454 | rv); |
3372 | } | 3455 | } |
3373 | 3456 | ||
3374 | to_clean->handlers->cleanup(to_clean->si_sm); | 3457 | if (to_clean->handlers) |
3458 | to_clean->handlers->cleanup(to_clean->si_sm); | ||
3375 | 3459 | ||
3376 | kfree(to_clean->si_sm); | 3460 | kfree(to_clean->si_sm); |
3377 | 3461 | ||
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index fdd37543aa79..02abfddce45a 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
@@ -287,12 +287,10 @@ static int register_device (int minor, struct pp_struct *pp) | |||
287 | char *name; | 287 | char *name; |
288 | int fl; | 288 | int fl; |
289 | 289 | ||
290 | name = kmalloc (strlen (CHRDEV) + 3, GFP_KERNEL); | 290 | name = kasprintf(GFP_KERNEL, CHRDEV "%x", minor); |
291 | if (name == NULL) | 291 | if (name == NULL) |
292 | return -ENOMEM; | 292 | return -ENOMEM; |
293 | 293 | ||
294 | sprintf (name, CHRDEV "%x", minor); | ||
295 | |||
296 | port = parport_find_number (minor); | 294 | port = parport_find_number (minor); |
297 | if (!port) { | 295 | if (!port) { |
298 | printk (KERN_WARNING "%s: no associated port!\n", name); | 296 | printk (KERN_WARNING "%s: no associated port!\n", name); |
diff --git a/drivers/char/ramoops.c b/drivers/char/ramoops.c new file mode 100644 index 000000000000..74f00b5ffa36 --- /dev/null +++ b/drivers/char/ramoops.c | |||
@@ -0,0 +1,162 @@ | |||
1 | /* | ||
2 | * RAM Oops/Panic logger | ||
3 | * | ||
4 | * Copyright (C) 2010 Marco Stornelli <marco.stornelli@gmail.com> | ||
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 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/kmsg_dump.h> | ||
25 | #include <linux/time.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/ioport.h> | ||
28 | |||
29 | #define RAMOOPS_KERNMSG_HDR "====" | ||
30 | #define RAMOOPS_HEADER_SIZE (5 + sizeof(struct timeval)) | ||
31 | |||
32 | #define RECORD_SIZE 4096 | ||
33 | |||
34 | static ulong mem_address; | ||
35 | module_param(mem_address, ulong, 0400); | ||
36 | MODULE_PARM_DESC(mem_address, | ||
37 | "start of reserved RAM used to store oops/panic logs"); | ||
38 | |||
39 | static ulong mem_size; | ||
40 | module_param(mem_size, ulong, 0400); | ||
41 | MODULE_PARM_DESC(mem_size, | ||
42 | "size of reserved RAM used to store oops/panic logs"); | ||
43 | |||
44 | static int dump_oops = 1; | ||
45 | module_param(dump_oops, int, 0600); | ||
46 | MODULE_PARM_DESC(dump_oops, | ||
47 | "set to 1 to dump oopses, 0 to only dump panics (default 1)"); | ||
48 | |||
49 | static struct ramoops_context { | ||
50 | struct kmsg_dumper dump; | ||
51 | void *virt_addr; | ||
52 | phys_addr_t phys_addr; | ||
53 | unsigned long size; | ||
54 | int count; | ||
55 | int max_count; | ||
56 | } oops_cxt; | ||
57 | |||
58 | static void ramoops_do_dump(struct kmsg_dumper *dumper, | ||
59 | enum kmsg_dump_reason reason, const char *s1, unsigned long l1, | ||
60 | const char *s2, unsigned long l2) | ||
61 | { | ||
62 | struct ramoops_context *cxt = container_of(dumper, | ||
63 | struct ramoops_context, dump); | ||
64 | unsigned long s1_start, s2_start; | ||
65 | unsigned long l1_cpy, l2_cpy; | ||
66 | int res; | ||
67 | char *buf; | ||
68 | struct timeval timestamp; | ||
69 | |||
70 | /* Only dump oopses if dump_oops is set */ | ||
71 | if (reason == KMSG_DUMP_OOPS && !dump_oops) | ||
72 | return; | ||
73 | |||
74 | buf = (char *)(cxt->virt_addr + (cxt->count * RECORD_SIZE)); | ||
75 | memset(buf, '\0', RECORD_SIZE); | ||
76 | res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); | ||
77 | buf += res; | ||
78 | do_gettimeofday(×tamp); | ||
79 | res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec); | ||
80 | buf += res; | ||
81 | |||
82 | l2_cpy = min(l2, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE)); | ||
83 | l1_cpy = min(l1, (unsigned long)(RECORD_SIZE - RAMOOPS_HEADER_SIZE) - l2_cpy); | ||
84 | |||
85 | s2_start = l2 - l2_cpy; | ||
86 | s1_start = l1 - l1_cpy; | ||
87 | |||
88 | memcpy(buf, s1 + s1_start, l1_cpy); | ||
89 | memcpy(buf + l1_cpy, s2 + s2_start, l2_cpy); | ||
90 | |||
91 | cxt->count = (cxt->count + 1) % cxt->max_count; | ||
92 | } | ||
93 | |||
94 | static int __init ramoops_init(void) | ||
95 | { | ||
96 | struct ramoops_context *cxt = &oops_cxt; | ||
97 | int err = -EINVAL; | ||
98 | |||
99 | if (!mem_size) { | ||
100 | printk(KERN_ERR "ramoops: invalid size specification"); | ||
101 | goto fail3; | ||
102 | } | ||
103 | |||
104 | rounddown_pow_of_two(mem_size); | ||
105 | |||
106 | if (mem_size < RECORD_SIZE) { | ||
107 | printk(KERN_ERR "ramoops: size too small"); | ||
108 | goto fail3; | ||
109 | } | ||
110 | |||
111 | cxt->max_count = mem_size / RECORD_SIZE; | ||
112 | cxt->count = 0; | ||
113 | cxt->size = mem_size; | ||
114 | cxt->phys_addr = mem_address; | ||
115 | |||
116 | if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) { | ||
117 | printk(KERN_ERR "ramoops: request mem region failed"); | ||
118 | err = -EINVAL; | ||
119 | goto fail3; | ||
120 | } | ||
121 | |||
122 | cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size); | ||
123 | if (!cxt->virt_addr) { | ||
124 | printk(KERN_ERR "ramoops: ioremap failed"); | ||
125 | goto fail2; | ||
126 | } | ||
127 | |||
128 | cxt->dump.dump = ramoops_do_dump; | ||
129 | err = kmsg_dump_register(&cxt->dump); | ||
130 | if (err) { | ||
131 | printk(KERN_ERR "ramoops: registering kmsg dumper failed"); | ||
132 | goto fail1; | ||
133 | } | ||
134 | |||
135 | return 0; | ||
136 | |||
137 | fail1: | ||
138 | iounmap(cxt->virt_addr); | ||
139 | fail2: | ||
140 | release_mem_region(cxt->phys_addr, cxt->size); | ||
141 | fail3: | ||
142 | return err; | ||
143 | } | ||
144 | |||
145 | static void __exit ramoops_exit(void) | ||
146 | { | ||
147 | struct ramoops_context *cxt = &oops_cxt; | ||
148 | |||
149 | if (kmsg_dump_unregister(&cxt->dump) < 0) | ||
150 | printk(KERN_WARNING "ramoops: could not unregister kmsg_dumper"); | ||
151 | |||
152 | iounmap(cxt->virt_addr); | ||
153 | release_mem_region(cxt->phys_addr, cxt->size); | ||
154 | } | ||
155 | |||
156 | |||
157 | module_init(ramoops_init); | ||
158 | module_exit(ramoops_exit); | ||
159 | |||
160 | MODULE_LICENSE("GPL"); | ||
161 | MODULE_AUTHOR("Marco Stornelli <marco.stornelli@gmail.com>"); | ||
162 | MODULE_DESCRIPTION("RAM Oops/Panic logger/driver"); | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index bd1d1164fec5..7cdb6ee569cd 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -3967,13 +3967,9 @@ static int con_font_set(struct vc_data *vc, struct console_font_op *op) | |||
3967 | font.charcount = op->charcount; | 3967 | font.charcount = op->charcount; |
3968 | font.height = op->height; | 3968 | font.height = op->height; |
3969 | font.width = op->width; | 3969 | font.width = op->width; |
3970 | font.data = kmalloc(size, GFP_KERNEL); | 3970 | font.data = memdup_user(op->data, size); |
3971 | if (!font.data) | 3971 | if (IS_ERR(font.data)) |
3972 | return -ENOMEM; | 3972 | return PTR_ERR(font.data); |
3973 | if (copy_from_user(font.data, op->data, size)) { | ||
3974 | kfree(font.data); | ||
3975 | return -EFAULT; | ||
3976 | } | ||
3977 | acquire_console_sem(); | 3973 | acquire_console_sem(); |
3978 | if (vc->vc_sw->con_font_set) | 3974 | if (vc->vc_sw->con_font_set) |
3979 | rc = vc->vc_sw->con_font_set(vc, &font, op->flags); | 3975 | rc = vc->vc_sw->con_font_set(vc, &font, op->flags); |
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index adc10a2ac5f6..996c1bdb5a34 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
@@ -774,7 +774,7 @@ static void i5000_clear_error(struct mem_ctl_info *mci) | |||
774 | static void i5000_check_error(struct mem_ctl_info *mci) | 774 | static void i5000_check_error(struct mem_ctl_info *mci) |
775 | { | 775 | { |
776 | struct i5000_error_info info; | 776 | struct i5000_error_info info; |
777 | debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); | 777 | debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); |
778 | i5000_get_error_info(mci, &info); | 778 | i5000_get_error_info(mci, &info); |
779 | i5000_process_error_info(mci, &info, 1); | 779 | i5000_process_error_info(mci, &info, 1); |
780 | } | 780 | } |
@@ -1353,8 +1353,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) | |||
1353 | int num_dimms_per_channel; | 1353 | int num_dimms_per_channel; |
1354 | int num_csrows; | 1354 | int num_csrows; |
1355 | 1355 | ||
1356 | debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", | 1356 | debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n", |
1357 | __func__, | 1357 | __FILE__, __func__, |
1358 | pdev->bus->number, | 1358 | pdev->bus->number, |
1359 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); | 1359 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); |
1360 | 1360 | ||
@@ -1389,7 +1389,7 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) | |||
1389 | return -ENOMEM; | 1389 | return -ENOMEM; |
1390 | 1390 | ||
1391 | kobject_get(&mci->edac_mci_kobj); | 1391 | kobject_get(&mci->edac_mci_kobj); |
1392 | debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); | 1392 | debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); |
1393 | 1393 | ||
1394 | mci->dev = &pdev->dev; /* record ptr to the generic device */ | 1394 | mci->dev = &pdev->dev; /* record ptr to the generic device */ |
1395 | 1395 | ||
@@ -1432,8 +1432,8 @@ static int i5000_probe1(struct pci_dev *pdev, int dev_idx) | |||
1432 | 1432 | ||
1433 | /* add this new MC control structure to EDAC's list of MCs */ | 1433 | /* add this new MC control structure to EDAC's list of MCs */ |
1434 | if (edac_mc_add_mc(mci)) { | 1434 | if (edac_mc_add_mc(mci)) { |
1435 | debugf0("MC: " __FILE__ | 1435 | debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n", |
1436 | ": %s(): failed edac_mc_add_mc()\n", __func__); | 1436 | __FILE__, __func__); |
1437 | /* FIXME: perhaps some code should go here that disables error | 1437 | /* FIXME: perhaps some code should go here that disables error |
1438 | * reporting if we just enabled it | 1438 | * reporting if we just enabled it |
1439 | */ | 1439 | */ |
@@ -1478,7 +1478,7 @@ static int __devinit i5000_init_one(struct pci_dev *pdev, | |||
1478 | { | 1478 | { |
1479 | int rc; | 1479 | int rc; |
1480 | 1480 | ||
1481 | debugf0("MC: " __FILE__ ": %s()\n", __func__); | 1481 | debugf0("MC: %s: %s()\n", __FILE__, __func__); |
1482 | 1482 | ||
1483 | /* wake up device */ | 1483 | /* wake up device */ |
1484 | rc = pci_enable_device(pdev); | 1484 | rc = pci_enable_device(pdev); |
@@ -1497,7 +1497,7 @@ static void __devexit i5000_remove_one(struct pci_dev *pdev) | |||
1497 | { | 1497 | { |
1498 | struct mem_ctl_info *mci; | 1498 | struct mem_ctl_info *mci; |
1499 | 1499 | ||
1500 | debugf0(__FILE__ ": %s()\n", __func__); | 1500 | debugf0("%s: %s()\n", __FILE__, __func__); |
1501 | 1501 | ||
1502 | if (i5000_pci) | 1502 | if (i5000_pci) |
1503 | edac_pci_release_generic_ctl(i5000_pci); | 1503 | edac_pci_release_generic_ctl(i5000_pci); |
@@ -1544,7 +1544,7 @@ static int __init i5000_init(void) | |||
1544 | { | 1544 | { |
1545 | int pci_rc; | 1545 | int pci_rc; |
1546 | 1546 | ||
1547 | debugf2("MC: " __FILE__ ": %s()\n", __func__); | 1547 | debugf2("MC: %s: %s()\n", __FILE__, __func__); |
1548 | 1548 | ||
1549 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ | 1549 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ |
1550 | opstate_init(); | 1550 | opstate_init(); |
@@ -1560,7 +1560,7 @@ static int __init i5000_init(void) | |||
1560 | */ | 1560 | */ |
1561 | static void __exit i5000_exit(void) | 1561 | static void __exit i5000_exit(void) |
1562 | { | 1562 | { |
1563 | debugf2("MC: " __FILE__ ": %s()\n", __func__); | 1563 | debugf2("MC: %s: %s()\n", __FILE__, __func__); |
1564 | pci_unregister_driver(&i5000_driver); | 1564 | pci_unregister_driver(&i5000_driver); |
1565 | } | 1565 | } |
1566 | 1566 | ||
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index f99d10655ed4..010c1d6526f5 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c | |||
@@ -694,7 +694,7 @@ static void i5400_clear_error(struct mem_ctl_info *mci) | |||
694 | static void i5400_check_error(struct mem_ctl_info *mci) | 694 | static void i5400_check_error(struct mem_ctl_info *mci) |
695 | { | 695 | { |
696 | struct i5400_error_info info; | 696 | struct i5400_error_info info; |
697 | debugf4("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); | 697 | debugf4("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); |
698 | i5400_get_error_info(mci, &info); | 698 | i5400_get_error_info(mci, &info); |
699 | i5400_process_error_info(mci, &info); | 699 | i5400_process_error_info(mci, &info); |
700 | } | 700 | } |
@@ -1227,8 +1227,8 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) | |||
1227 | if (dev_idx >= ARRAY_SIZE(i5400_devs)) | 1227 | if (dev_idx >= ARRAY_SIZE(i5400_devs)) |
1228 | return -EINVAL; | 1228 | return -EINVAL; |
1229 | 1229 | ||
1230 | debugf0("MC: " __FILE__ ": %s(), pdev bus %u dev=0x%x fn=0x%x\n", | 1230 | debugf0("MC: %s: %s(), pdev bus %u dev=0x%x fn=0x%x\n", |
1231 | __func__, | 1231 | __FILE__, __func__, |
1232 | pdev->bus->number, | 1232 | pdev->bus->number, |
1233 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); | 1233 | PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn)); |
1234 | 1234 | ||
@@ -1256,7 +1256,7 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) | |||
1256 | if (mci == NULL) | 1256 | if (mci == NULL) |
1257 | return -ENOMEM; | 1257 | return -ENOMEM; |
1258 | 1258 | ||
1259 | debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); | 1259 | debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); |
1260 | 1260 | ||
1261 | mci->dev = &pdev->dev; /* record ptr to the generic device */ | 1261 | mci->dev = &pdev->dev; /* record ptr to the generic device */ |
1262 | 1262 | ||
@@ -1299,8 +1299,8 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) | |||
1299 | 1299 | ||
1300 | /* add this new MC control structure to EDAC's list of MCs */ | 1300 | /* add this new MC control structure to EDAC's list of MCs */ |
1301 | if (edac_mc_add_mc(mci)) { | 1301 | if (edac_mc_add_mc(mci)) { |
1302 | debugf0("MC: " __FILE__ | 1302 | debugf0("MC: %s: %s(): failed edac_mc_add_mc()\n", |
1303 | ": %s(): failed edac_mc_add_mc()\n", __func__); | 1303 | __FILE__, __func__); |
1304 | /* FIXME: perhaps some code should go here that disables error | 1304 | /* FIXME: perhaps some code should go here that disables error |
1305 | * reporting if we just enabled it | 1305 | * reporting if we just enabled it |
1306 | */ | 1306 | */ |
@@ -1344,7 +1344,7 @@ static int __devinit i5400_init_one(struct pci_dev *pdev, | |||
1344 | { | 1344 | { |
1345 | int rc; | 1345 | int rc; |
1346 | 1346 | ||
1347 | debugf0("MC: " __FILE__ ": %s()\n", __func__); | 1347 | debugf0("MC: %s: %s()\n", __FILE__, __func__); |
1348 | 1348 | ||
1349 | /* wake up device */ | 1349 | /* wake up device */ |
1350 | rc = pci_enable_device(pdev); | 1350 | rc = pci_enable_device(pdev); |
@@ -1363,7 +1363,7 @@ static void __devexit i5400_remove_one(struct pci_dev *pdev) | |||
1363 | { | 1363 | { |
1364 | struct mem_ctl_info *mci; | 1364 | struct mem_ctl_info *mci; |
1365 | 1365 | ||
1366 | debugf0(__FILE__ ": %s()\n", __func__); | 1366 | debugf0("%s: %s()\n", __FILE__, __func__); |
1367 | 1367 | ||
1368 | if (i5400_pci) | 1368 | if (i5400_pci) |
1369 | edac_pci_release_generic_ctl(i5400_pci); | 1369 | edac_pci_release_generic_ctl(i5400_pci); |
@@ -1409,7 +1409,7 @@ static int __init i5400_init(void) | |||
1409 | { | 1409 | { |
1410 | int pci_rc; | 1410 | int pci_rc; |
1411 | 1411 | ||
1412 | debugf2("MC: " __FILE__ ": %s()\n", __func__); | 1412 | debugf2("MC: %s: %s()\n", __FILE__, __func__); |
1413 | 1413 | ||
1414 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ | 1414 | /* Ensure that the OPSTATE is set correctly for POLL or NMI */ |
1415 | opstate_init(); | 1415 | opstate_init(); |
@@ -1425,7 +1425,7 @@ static int __init i5400_init(void) | |||
1425 | */ | 1425 | */ |
1426 | static void __exit i5400_exit(void) | 1426 | static void __exit i5400_exit(void) |
1427 | { | 1427 | { |
1428 | debugf2("MC: " __FILE__ ": %s()\n", __func__); | 1428 | debugf2("MC: %s: %s()\n", __FILE__, __func__); |
1429 | pci_unregister_driver(&i5400_driver); | 1429 | pci_unregister_driver(&i5400_driver); |
1430 | } | 1430 | } |
1431 | 1431 | ||
diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index 2bf2c5051bfe..a2fa1feed724 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c | |||
@@ -178,7 +178,7 @@ static void i82443bxgx_edacmc_check(struct mem_ctl_info *mci) | |||
178 | { | 178 | { |
179 | struct i82443bxgx_edacmc_error_info info; | 179 | struct i82443bxgx_edacmc_error_info info; |
180 | 180 | ||
181 | debugf1("MC%d: " __FILE__ ": %s()\n", mci->mc_idx, __func__); | 181 | debugf1("MC%d: %s: %s()\n", mci->mc_idx, __FILE__, __func__); |
182 | i82443bxgx_edacmc_get_error_info(mci, &info); | 182 | i82443bxgx_edacmc_get_error_info(mci, &info); |
183 | i82443bxgx_edacmc_process_error_info(mci, &info, 1); | 183 | i82443bxgx_edacmc_process_error_info(mci, &info, 1); |
184 | } | 184 | } |
@@ -198,13 +198,13 @@ static void i82443bxgx_init_csrows(struct mem_ctl_info *mci, | |||
198 | for (index = 0; index < mci->nr_csrows; index++) { | 198 | for (index = 0; index < mci->nr_csrows; index++) { |
199 | csrow = &mci->csrows[index]; | 199 | csrow = &mci->csrows[index]; |
200 | pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); | 200 | pci_read_config_byte(pdev, I82443BXGX_DRB + index, &drbar); |
201 | debugf1("MC%d: " __FILE__ ": %s() Row=%d DRB = %#0x\n", | 201 | debugf1("MC%d: %s: %s() Row=%d DRB = %#0x\n", |
202 | mci->mc_idx, __func__, index, drbar); | 202 | mci->mc_idx, __FILE__, __func__, index, drbar); |
203 | row_high_limit = ((u32) drbar << 23); | 203 | row_high_limit = ((u32) drbar << 23); |
204 | /* find the DRAM Chip Select Base address and mask */ | 204 | /* find the DRAM Chip Select Base address and mask */ |
205 | debugf1("MC%d: " __FILE__ ": %s() Row=%d, " | 205 | debugf1("MC%d: %s: %s() Row=%d, " |
206 | "Boundry Address=%#0x, Last = %#0x \n", | 206 | "Boundry Address=%#0x, Last = %#0x\n", |
207 | mci->mc_idx, __func__, index, row_high_limit, | 207 | mci->mc_idx, __FILE__, __func__, index, row_high_limit, |
208 | row_high_limit_last); | 208 | row_high_limit_last); |
209 | 209 | ||
210 | /* 440GX goes to 2GB, represented with a DRB of 0. */ | 210 | /* 440GX goes to 2GB, represented with a DRB of 0. */ |
@@ -237,7 +237,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) | |||
237 | enum mem_type mtype; | 237 | enum mem_type mtype; |
238 | enum edac_type edac_mode; | 238 | enum edac_type edac_mode; |
239 | 239 | ||
240 | debugf0("MC: " __FILE__ ": %s()\n", __func__); | 240 | debugf0("MC: %s: %s()\n", __FILE__, __func__); |
241 | 241 | ||
242 | /* Something is really hosed if PCI config space reads from | 242 | /* Something is really hosed if PCI config space reads from |
243 | * the MC aren't working. | 243 | * the MC aren't working. |
@@ -250,7 +250,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) | |||
250 | if (mci == NULL) | 250 | if (mci == NULL) |
251 | return -ENOMEM; | 251 | return -ENOMEM; |
252 | 252 | ||
253 | debugf0("MC: " __FILE__ ": %s(): mci = %p\n", __func__, mci); | 253 | debugf0("MC: %s: %s(): mci = %p\n", __FILE__, __func__, mci); |
254 | mci->dev = &pdev->dev; | 254 | mci->dev = &pdev->dev; |
255 | mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR; | 255 | mci->mtype_cap = MEM_FLAG_EDO | MEM_FLAG_SDR | MEM_FLAG_RDR; |
256 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; | 256 | mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_EC | EDAC_FLAG_SECDED; |
@@ -336,7 +336,7 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx) | |||
336 | __func__); | 336 | __func__); |
337 | } | 337 | } |
338 | 338 | ||
339 | debugf3("MC: " __FILE__ ": %s(): success\n", __func__); | 339 | debugf3("MC: %s: %s(): success\n", __FILE__, __func__); |
340 | return 0; | 340 | return 0; |
341 | 341 | ||
342 | fail: | 342 | fail: |
@@ -352,7 +352,7 @@ static int __devinit i82443bxgx_edacmc_init_one(struct pci_dev *pdev, | |||
352 | { | 352 | { |
353 | int rc; | 353 | int rc; |
354 | 354 | ||
355 | debugf0("MC: " __FILE__ ": %s()\n", __func__); | 355 | debugf0("MC: %s: %s()\n", __FILE__, __func__); |
356 | 356 | ||
357 | /* don't need to call pci_enable_device() */ | 357 | /* don't need to call pci_enable_device() */ |
358 | rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); | 358 | rc = i82443bxgx_edacmc_probe1(pdev, ent->driver_data); |
@@ -367,7 +367,7 @@ static void __devexit i82443bxgx_edacmc_remove_one(struct pci_dev *pdev) | |||
367 | { | 367 | { |
368 | struct mem_ctl_info *mci; | 368 | struct mem_ctl_info *mci; |
369 | 369 | ||
370 | debugf0(__FILE__ ": %s()\n", __func__); | 370 | debugf0("%s: %s()\n", __FILE__, __func__); |
371 | 371 | ||
372 | if (i82443bxgx_pci) | 372 | if (i82443bxgx_pci) |
373 | edac_pci_release_generic_ctl(i82443bxgx_pci); | 373 | edac_pci_release_generic_ctl(i82443bxgx_pci); |
diff --git a/drivers/firewire/core-card.c b/drivers/firewire/core-card.c index 5045156c5313..9dcb30466ec0 100644 --- a/drivers/firewire/core-card.c +++ b/drivers/firewire/core-card.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
33 | #include <linux/timer.h> | ||
34 | #include <linux/workqueue.h> | 33 | #include <linux/workqueue.h> |
35 | 34 | ||
36 | #include <asm/atomic.h> | 35 | #include <asm/atomic.h> |
@@ -63,7 +62,7 @@ static size_t config_rom_length = 1 + 4 + 1 + 1; | |||
63 | #define BIB_CRC(v) ((v) << 0) | 62 | #define BIB_CRC(v) ((v) << 0) |
64 | #define BIB_CRC_LENGTH(v) ((v) << 16) | 63 | #define BIB_CRC_LENGTH(v) ((v) << 16) |
65 | #define BIB_INFO_LENGTH(v) ((v) << 24) | 64 | #define BIB_INFO_LENGTH(v) ((v) << 24) |
66 | 65 | #define BIB_BUS_NAME 0x31333934 /* "1394" */ | |
67 | #define BIB_LINK_SPEED(v) ((v) << 0) | 66 | #define BIB_LINK_SPEED(v) ((v) << 0) |
68 | #define BIB_GENERATION(v) ((v) << 4) | 67 | #define BIB_GENERATION(v) ((v) << 4) |
69 | #define BIB_MAX_ROM(v) ((v) << 8) | 68 | #define BIB_MAX_ROM(v) ((v) << 8) |
@@ -73,7 +72,8 @@ static size_t config_rom_length = 1 + 4 + 1 + 1; | |||
73 | #define BIB_BMC ((1) << 28) | 72 | #define BIB_BMC ((1) << 28) |
74 | #define BIB_ISC ((1) << 29) | 73 | #define BIB_ISC ((1) << 29) |
75 | #define BIB_CMC ((1) << 30) | 74 | #define BIB_CMC ((1) << 30) |
76 | #define BIB_IMC ((1) << 31) | 75 | #define BIB_IRMC ((1) << 31) |
76 | #define NODE_CAPABILITIES 0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */ | ||
77 | 77 | ||
78 | static void generate_config_rom(struct fw_card *card, __be32 *config_rom) | 78 | static void generate_config_rom(struct fw_card *card, __be32 *config_rom) |
79 | { | 79 | { |
@@ -91,18 +91,18 @@ static void generate_config_rom(struct fw_card *card, __be32 *config_rom) | |||
91 | 91 | ||
92 | config_rom[0] = cpu_to_be32( | 92 | config_rom[0] = cpu_to_be32( |
93 | BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0)); | 93 | BIB_CRC_LENGTH(4) | BIB_INFO_LENGTH(4) | BIB_CRC(0)); |
94 | config_rom[1] = cpu_to_be32(0x31333934); | 94 | config_rom[1] = cpu_to_be32(BIB_BUS_NAME); |
95 | config_rom[2] = cpu_to_be32( | 95 | config_rom[2] = cpu_to_be32( |
96 | BIB_LINK_SPEED(card->link_speed) | | 96 | BIB_LINK_SPEED(card->link_speed) | |
97 | BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | | 97 | BIB_GENERATION(card->config_rom_generation++ % 14 + 2) | |
98 | BIB_MAX_ROM(2) | | 98 | BIB_MAX_ROM(2) | |
99 | BIB_MAX_RECEIVE(card->max_receive) | | 99 | BIB_MAX_RECEIVE(card->max_receive) | |
100 | BIB_BMC | BIB_ISC | BIB_CMC | BIB_IMC); | 100 | BIB_BMC | BIB_ISC | BIB_CMC | BIB_IRMC); |
101 | config_rom[3] = cpu_to_be32(card->guid >> 32); | 101 | config_rom[3] = cpu_to_be32(card->guid >> 32); |
102 | config_rom[4] = cpu_to_be32(card->guid); | 102 | config_rom[4] = cpu_to_be32(card->guid); |
103 | 103 | ||
104 | /* Generate root directory. */ | 104 | /* Generate root directory. */ |
105 | config_rom[6] = cpu_to_be32(0x0c0083c0); /* node capabilities */ | 105 | config_rom[6] = cpu_to_be32(NODE_CAPABILITIES); |
106 | i = 7; | 106 | i = 7; |
107 | j = 7 + descriptor_count; | 107 | j = 7 + descriptor_count; |
108 | 108 | ||
@@ -407,13 +407,6 @@ static void fw_card_bm_work(struct work_struct *work) | |||
407 | fw_card_put(card); | 407 | fw_card_put(card); |
408 | } | 408 | } |
409 | 409 | ||
410 | static void flush_timer_callback(unsigned long data) | ||
411 | { | ||
412 | struct fw_card *card = (struct fw_card *)data; | ||
413 | |||
414 | fw_flush_transactions(card); | ||
415 | } | ||
416 | |||
417 | void fw_card_initialize(struct fw_card *card, | 410 | void fw_card_initialize(struct fw_card *card, |
418 | const struct fw_card_driver *driver, | 411 | const struct fw_card_driver *driver, |
419 | struct device *device) | 412 | struct device *device) |
@@ -432,8 +425,6 @@ void fw_card_initialize(struct fw_card *card, | |||
432 | init_completion(&card->done); | 425 | init_completion(&card->done); |
433 | INIT_LIST_HEAD(&card->transaction_list); | 426 | INIT_LIST_HEAD(&card->transaction_list); |
434 | spin_lock_init(&card->lock); | 427 | spin_lock_init(&card->lock); |
435 | setup_timer(&card->flush_timer, | ||
436 | flush_timer_callback, (unsigned long)card); | ||
437 | 428 | ||
438 | card->local_node = NULL; | 429 | card->local_node = NULL; |
439 | 430 | ||
@@ -558,7 +549,6 @@ void fw_core_remove_card(struct fw_card *card) | |||
558 | wait_for_completion(&card->done); | 549 | wait_for_completion(&card->done); |
559 | 550 | ||
560 | WARN_ON(!list_empty(&card->transaction_list)); | 551 | WARN_ON(!list_empty(&card->transaction_list)); |
561 | del_timer_sync(&card->flush_timer); | ||
562 | } | 552 | } |
563 | EXPORT_SYMBOL(fw_core_remove_card); | 553 | EXPORT_SYMBOL(fw_core_remove_card); |
564 | 554 | ||
diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 14a34d99eea2..5bf106b9d791 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c | |||
@@ -227,7 +227,7 @@ static int fw_device_op_open(struct inode *inode, struct file *file) | |||
227 | list_add_tail(&client->link, &device->client_list); | 227 | list_add_tail(&client->link, &device->client_list); |
228 | mutex_unlock(&device->client_list_mutex); | 228 | mutex_unlock(&device->client_list_mutex); |
229 | 229 | ||
230 | return 0; | 230 | return nonseekable_open(inode, file); |
231 | } | 231 | } |
232 | 232 | ||
233 | static void queue_event(struct client *client, struct event *event, | 233 | static void queue_event(struct client *client, struct event *event, |
@@ -1496,13 +1496,13 @@ static unsigned int fw_device_op_poll(struct file *file, poll_table * pt) | |||
1496 | 1496 | ||
1497 | const struct file_operations fw_device_ops = { | 1497 | const struct file_operations fw_device_ops = { |
1498 | .owner = THIS_MODULE, | 1498 | .owner = THIS_MODULE, |
1499 | .llseek = no_llseek, | ||
1499 | .open = fw_device_op_open, | 1500 | .open = fw_device_op_open, |
1500 | .read = fw_device_op_read, | 1501 | .read = fw_device_op_read, |
1501 | .unlocked_ioctl = fw_device_op_ioctl, | 1502 | .unlocked_ioctl = fw_device_op_ioctl, |
1502 | .poll = fw_device_op_poll, | ||
1503 | .release = fw_device_op_release, | ||
1504 | .mmap = fw_device_op_mmap, | 1503 | .mmap = fw_device_op_mmap, |
1505 | 1504 | .release = fw_device_op_release, | |
1505 | .poll = fw_device_op_poll, | ||
1506 | #ifdef CONFIG_COMPAT | 1506 | #ifdef CONFIG_COMPAT |
1507 | .compat_ioctl = fw_device_op_compat_ioctl, | 1507 | .compat_ioctl = fw_device_op_compat_ioctl, |
1508 | #endif | 1508 | #endif |
diff --git a/drivers/firewire/core-transaction.c b/drivers/firewire/core-transaction.c index 673b03f8b4ec..fdc33ff06dc1 100644 --- a/drivers/firewire/core-transaction.c +++ b/drivers/firewire/core-transaction.c | |||
@@ -81,7 +81,7 @@ static int close_transaction(struct fw_transaction *transaction, | |||
81 | spin_lock_irqsave(&card->lock, flags); | 81 | spin_lock_irqsave(&card->lock, flags); |
82 | list_for_each_entry(t, &card->transaction_list, link) { | 82 | list_for_each_entry(t, &card->transaction_list, link) { |
83 | if (t == transaction) { | 83 | if (t == transaction) { |
84 | list_del(&t->link); | 84 | list_del_init(&t->link); |
85 | card->tlabel_mask &= ~(1ULL << t->tlabel); | 85 | card->tlabel_mask &= ~(1ULL << t->tlabel); |
86 | break; | 86 | break; |
87 | } | 87 | } |
@@ -89,6 +89,7 @@ static int close_transaction(struct fw_transaction *transaction, | |||
89 | spin_unlock_irqrestore(&card->lock, flags); | 89 | spin_unlock_irqrestore(&card->lock, flags); |
90 | 90 | ||
91 | if (&t->link != &card->transaction_list) { | 91 | if (&t->link != &card->transaction_list) { |
92 | del_timer_sync(&t->split_timeout_timer); | ||
92 | t->callback(card, rcode, NULL, 0, t->callback_data); | 93 | t->callback(card, rcode, NULL, 0, t->callback_data); |
93 | return 0; | 94 | return 0; |
94 | } | 95 | } |
@@ -121,6 +122,31 @@ int fw_cancel_transaction(struct fw_card *card, | |||
121 | } | 122 | } |
122 | EXPORT_SYMBOL(fw_cancel_transaction); | 123 | EXPORT_SYMBOL(fw_cancel_transaction); |
123 | 124 | ||
125 | static void split_transaction_timeout_callback(unsigned long data) | ||
126 | { | ||
127 | struct fw_transaction *t = (struct fw_transaction *)data; | ||
128 | struct fw_card *card = t->card; | ||
129 | unsigned long flags; | ||
130 | |||
131 | spin_lock_irqsave(&card->lock, flags); | ||
132 | if (list_empty(&t->link)) { | ||
133 | spin_unlock_irqrestore(&card->lock, flags); | ||
134 | return; | ||
135 | } | ||
136 | list_del(&t->link); | ||
137 | card->tlabel_mask &= ~(1ULL << t->tlabel); | ||
138 | spin_unlock_irqrestore(&card->lock, flags); | ||
139 | |||
140 | card->driver->cancel_packet(card, &t->packet); | ||
141 | |||
142 | /* | ||
143 | * At this point cancel_packet will never call the transaction | ||
144 | * callback, since we just took the transaction out of the list. | ||
145 | * So do it here. | ||
146 | */ | ||
147 | t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data); | ||
148 | } | ||
149 | |||
124 | static void transmit_complete_callback(struct fw_packet *packet, | 150 | static void transmit_complete_callback(struct fw_packet *packet, |
125 | struct fw_card *card, int status) | 151 | struct fw_card *card, int status) |
126 | { | 152 | { |
@@ -229,6 +255,23 @@ static void fw_fill_request(struct fw_packet *packet, int tcode, int tlabel, | |||
229 | packet->payload_mapped = false; | 255 | packet->payload_mapped = false; |
230 | } | 256 | } |
231 | 257 | ||
258 | static int allocate_tlabel(struct fw_card *card) | ||
259 | { | ||
260 | int tlabel; | ||
261 | |||
262 | tlabel = card->current_tlabel; | ||
263 | while (card->tlabel_mask & (1ULL << tlabel)) { | ||
264 | tlabel = (tlabel + 1) & 0x3f; | ||
265 | if (tlabel == card->current_tlabel) | ||
266 | return -EBUSY; | ||
267 | } | ||
268 | |||
269 | card->current_tlabel = (tlabel + 1) & 0x3f; | ||
270 | card->tlabel_mask |= 1ULL << tlabel; | ||
271 | |||
272 | return tlabel; | ||
273 | } | ||
274 | |||
232 | /** | 275 | /** |
233 | * This function provides low-level access to the IEEE1394 transaction | 276 | * This function provides low-level access to the IEEE1394 transaction |
234 | * logic. Most C programs would use either fw_read(), fw_write() or | 277 | * logic. Most C programs would use either fw_read(), fw_write() or |
@@ -277,31 +320,26 @@ void fw_send_request(struct fw_card *card, struct fw_transaction *t, int tcode, | |||
277 | int tlabel; | 320 | int tlabel; |
278 | 321 | ||
279 | /* | 322 | /* |
280 | * Bump the flush timer up 100ms first of all so we | ||
281 | * don't race with a flush timer callback. | ||
282 | */ | ||
283 | |||
284 | mod_timer(&card->flush_timer, jiffies + DIV_ROUND_UP(HZ, 10)); | ||
285 | |||
286 | /* | ||
287 | * Allocate tlabel from the bitmap and put the transaction on | 323 | * Allocate tlabel from the bitmap and put the transaction on |
288 | * the list while holding the card spinlock. | 324 | * the list while holding the card spinlock. |
289 | */ | 325 | */ |
290 | 326 | ||
291 | spin_lock_irqsave(&card->lock, flags); | 327 | spin_lock_irqsave(&card->lock, flags); |
292 | 328 | ||
293 | tlabel = card->current_tlabel; | 329 | tlabel = allocate_tlabel(card); |
294 | if (card->tlabel_mask & (1ULL << tlabel)) { | 330 | if (tlabel < 0) { |
295 | spin_unlock_irqrestore(&card->lock, flags); | 331 | spin_unlock_irqrestore(&card->lock, flags); |
296 | callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data); | 332 | callback(card, RCODE_SEND_ERROR, NULL, 0, callback_data); |
297 | return; | 333 | return; |
298 | } | 334 | } |
299 | 335 | ||
300 | card->current_tlabel = (card->current_tlabel + 1) & 0x3f; | ||
301 | card->tlabel_mask |= (1ULL << tlabel); | ||
302 | |||
303 | t->node_id = destination_id; | 336 | t->node_id = destination_id; |
304 | t->tlabel = tlabel; | 337 | t->tlabel = tlabel; |
338 | t->card = card; | ||
339 | setup_timer(&t->split_timeout_timer, | ||
340 | split_transaction_timeout_callback, (unsigned long)t); | ||
341 | /* FIXME: start this timer later, relative to t->timestamp */ | ||
342 | mod_timer(&t->split_timeout_timer, jiffies + DIV_ROUND_UP(HZ, 10)); | ||
305 | t->callback = callback; | 343 | t->callback = callback; |
306 | t->callback_data = callback_data; | 344 | t->callback_data = callback_data; |
307 | 345 | ||
@@ -347,11 +385,13 @@ int fw_run_transaction(struct fw_card *card, int tcode, int destination_id, | |||
347 | struct transaction_callback_data d; | 385 | struct transaction_callback_data d; |
348 | struct fw_transaction t; | 386 | struct fw_transaction t; |
349 | 387 | ||
388 | init_timer_on_stack(&t.split_timeout_timer); | ||
350 | init_completion(&d.done); | 389 | init_completion(&d.done); |
351 | d.payload = payload; | 390 | d.payload = payload; |
352 | fw_send_request(card, &t, tcode, destination_id, generation, speed, | 391 | fw_send_request(card, &t, tcode, destination_id, generation, speed, |
353 | offset, payload, length, transaction_callback, &d); | 392 | offset, payload, length, transaction_callback, &d); |
354 | wait_for_completion(&d.done); | 393 | wait_for_completion(&d.done); |
394 | destroy_timer_on_stack(&t.split_timeout_timer); | ||
355 | 395 | ||
356 | return d.rcode; | 396 | return d.rcode; |
357 | } | 397 | } |
@@ -394,30 +434,6 @@ void fw_send_phy_config(struct fw_card *card, | |||
394 | mutex_unlock(&phy_config_mutex); | 434 | mutex_unlock(&phy_config_mutex); |
395 | } | 435 | } |
396 | 436 | ||
397 | void fw_flush_transactions(struct fw_card *card) | ||
398 | { | ||
399 | struct fw_transaction *t, *next; | ||
400 | struct list_head list; | ||
401 | unsigned long flags; | ||
402 | |||
403 | INIT_LIST_HEAD(&list); | ||
404 | spin_lock_irqsave(&card->lock, flags); | ||
405 | list_splice_init(&card->transaction_list, &list); | ||
406 | card->tlabel_mask = 0; | ||
407 | spin_unlock_irqrestore(&card->lock, flags); | ||
408 | |||
409 | list_for_each_entry_safe(t, next, &list, link) { | ||
410 | card->driver->cancel_packet(card, &t->packet); | ||
411 | |||
412 | /* | ||
413 | * At this point cancel_packet will never call the | ||
414 | * transaction callback, since we just took all the | ||
415 | * transactions out of the list. So do it here. | ||
416 | */ | ||
417 | t->callback(card, RCODE_CANCELLED, NULL, 0, t->callback_data); | ||
418 | } | ||
419 | } | ||
420 | |||
421 | static struct fw_address_handler *lookup_overlapping_address_handler( | 437 | static struct fw_address_handler *lookup_overlapping_address_handler( |
422 | struct list_head *list, unsigned long long offset, size_t length) | 438 | struct list_head *list, unsigned long long offset, size_t length) |
423 | { | 439 | { |
@@ -827,8 +843,8 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) | |||
827 | spin_lock_irqsave(&card->lock, flags); | 843 | spin_lock_irqsave(&card->lock, flags); |
828 | list_for_each_entry(t, &card->transaction_list, link) { | 844 | list_for_each_entry(t, &card->transaction_list, link) { |
829 | if (t->node_id == source && t->tlabel == tlabel) { | 845 | if (t->node_id == source && t->tlabel == tlabel) { |
830 | list_del(&t->link); | 846 | list_del_init(&t->link); |
831 | card->tlabel_mask &= ~(1 << t->tlabel); | 847 | card->tlabel_mask &= ~(1ULL << t->tlabel); |
832 | break; | 848 | break; |
833 | } | 849 | } |
834 | } | 850 | } |
@@ -869,6 +885,8 @@ void fw_core_handle_response(struct fw_card *card, struct fw_packet *p) | |||
869 | break; | 885 | break; |
870 | } | 886 | } |
871 | 887 | ||
888 | del_timer_sync(&t->split_timeout_timer); | ||
889 | |||
872 | /* | 890 | /* |
873 | * The response handler may be executed while the request handler | 891 | * The response handler may be executed while the request handler |
874 | * is still pending. Cancel the request handler. | 892 | * is still pending. Cancel the request handler. |
diff --git a/drivers/firewire/core.h b/drivers/firewire/core.h index fb0321300cce..0ecfcd95f4c5 100644 --- a/drivers/firewire/core.h +++ b/drivers/firewire/core.h | |||
@@ -27,7 +27,12 @@ struct fw_packet; | |||
27 | #define PHY_LINK_ACTIVE 0x80 | 27 | #define PHY_LINK_ACTIVE 0x80 |
28 | #define PHY_CONTENDER 0x40 | 28 | #define PHY_CONTENDER 0x40 |
29 | #define PHY_BUS_RESET 0x40 | 29 | #define PHY_BUS_RESET 0x40 |
30 | #define PHY_EXTENDED_REGISTERS 0xe0 | ||
30 | #define PHY_BUS_SHORT_RESET 0x40 | 31 | #define PHY_BUS_SHORT_RESET 0x40 |
32 | #define PHY_INT_STATUS_BITS 0x3c | ||
33 | #define PHY_ENABLE_ACCEL 0x02 | ||
34 | #define PHY_ENABLE_MULTI 0x01 | ||
35 | #define PHY_PAGE_SELECT 0xe0 | ||
31 | 36 | ||
32 | #define BANDWIDTH_AVAILABLE_INITIAL 4915 | 37 | #define BANDWIDTH_AVAILABLE_INITIAL 4915 |
33 | #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) | 38 | #define BROADCAST_CHANNEL_INITIAL (1 << 31 | 31) |
@@ -215,7 +220,6 @@ void fw_core_handle_request(struct fw_card *card, struct fw_packet *request); | |||
215 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); | 220 | void fw_core_handle_response(struct fw_card *card, struct fw_packet *packet); |
216 | void fw_fill_response(struct fw_packet *response, u32 *request_header, | 221 | void fw_fill_response(struct fw_packet *response, u32 *request_header, |
217 | int rcode, void *payload, size_t length); | 222 | int rcode, void *payload, size_t length); |
218 | void fw_flush_transactions(struct fw_card *card); | ||
219 | void fw_send_phy_config(struct fw_card *card, | 223 | void fw_send_phy_config(struct fw_card *card, |
220 | int node_id, int generation, int gap_count); | 224 | int node_id, int generation, int gap_count); |
221 | 225 | ||
diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index a3b083a7403a..9f627e758cfc 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c | |||
@@ -236,13 +236,15 @@ static char ohci_driver_name[] = KBUILD_MODNAME; | |||
236 | #define QUIRK_CYCLE_TIMER 1 | 236 | #define QUIRK_CYCLE_TIMER 1 |
237 | #define QUIRK_RESET_PACKET 2 | 237 | #define QUIRK_RESET_PACKET 2 |
238 | #define QUIRK_BE_HEADERS 4 | 238 | #define QUIRK_BE_HEADERS 4 |
239 | #define QUIRK_NO_1394A 8 | ||
239 | 240 | ||
240 | /* In case of multiple matches in ohci_quirks[], only the first one is used. */ | 241 | /* In case of multiple matches in ohci_quirks[], only the first one is used. */ |
241 | static const struct { | 242 | static const struct { |
242 | unsigned short vendor, device, flags; | 243 | unsigned short vendor, device, flags; |
243 | } ohci_quirks[] = { | 244 | } ohci_quirks[] = { |
244 | {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER | | 245 | {PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_TSB12LV22, QUIRK_CYCLE_TIMER | |
245 | QUIRK_RESET_PACKET}, | 246 | QUIRK_RESET_PACKET | |
247 | QUIRK_NO_1394A}, | ||
246 | {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, | 248 | {PCI_VENDOR_ID_TI, PCI_ANY_ID, QUIRK_RESET_PACKET}, |
247 | {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, | 249 | {PCI_VENDOR_ID_AL, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, |
248 | {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, | 250 | {PCI_VENDOR_ID_NEC, PCI_ANY_ID, QUIRK_CYCLE_TIMER}, |
@@ -257,15 +259,16 @@ MODULE_PARM_DESC(quirks, "Chip quirks (default = 0" | |||
257 | ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER) | 259 | ", nonatomic cycle timer = " __stringify(QUIRK_CYCLE_TIMER) |
258 | ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) | 260 | ", reset packet generation = " __stringify(QUIRK_RESET_PACKET) |
259 | ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) | 261 | ", AR/selfID endianess = " __stringify(QUIRK_BE_HEADERS) |
262 | ", no 1394a enhancements = " __stringify(QUIRK_NO_1394A) | ||
260 | ")"); | 263 | ")"); |
261 | 264 | ||
262 | #ifdef CONFIG_FIREWIRE_OHCI_DEBUG | ||
263 | |||
264 | #define OHCI_PARAM_DEBUG_AT_AR 1 | 265 | #define OHCI_PARAM_DEBUG_AT_AR 1 |
265 | #define OHCI_PARAM_DEBUG_SELFIDS 2 | 266 | #define OHCI_PARAM_DEBUG_SELFIDS 2 |
266 | #define OHCI_PARAM_DEBUG_IRQS 4 | 267 | #define OHCI_PARAM_DEBUG_IRQS 4 |
267 | #define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */ | 268 | #define OHCI_PARAM_DEBUG_BUSRESETS 8 /* only effective before chip init */ |
268 | 269 | ||
270 | #ifdef CONFIG_FIREWIRE_OHCI_DEBUG | ||
271 | |||
269 | static int param_debug; | 272 | static int param_debug; |
270 | module_param_named(debug, param_debug, int, 0644); | 273 | module_param_named(debug, param_debug, int, 0644); |
271 | MODULE_PARM_DESC(debug, "Verbose logging (default = 0" | 274 | MODULE_PARM_DESC(debug, "Verbose logging (default = 0" |
@@ -438,9 +441,10 @@ static void log_ar_at_event(char dir, int speed, u32 *header, int evt) | |||
438 | 441 | ||
439 | #else | 442 | #else |
440 | 443 | ||
441 | #define log_irqs(evt) | 444 | #define param_debug 0 |
442 | #define log_selfids(node_id, generation, self_id_count, sid) | 445 | static inline void log_irqs(u32 evt) {} |
443 | #define log_ar_at_event(dir, speed, header, evt) | 446 | static inline void log_selfids(int node_id, int generation, int self_id_count, u32 *s) {} |
447 | static inline void log_ar_at_event(char dir, int speed, u32 *header, int evt) {} | ||
444 | 448 | ||
445 | #endif /* CONFIG_FIREWIRE_OHCI_DEBUG */ | 449 | #endif /* CONFIG_FIREWIRE_OHCI_DEBUG */ |
446 | 450 | ||
@@ -460,27 +464,71 @@ static inline void flush_writes(const struct fw_ohci *ohci) | |||
460 | reg_read(ohci, OHCI1394_Version); | 464 | reg_read(ohci, OHCI1394_Version); |
461 | } | 465 | } |
462 | 466 | ||
463 | static int ohci_update_phy_reg(struct fw_card *card, int addr, | 467 | static int read_phy_reg(struct fw_ohci *ohci, int addr) |
464 | int clear_bits, int set_bits) | ||
465 | { | 468 | { |
466 | struct fw_ohci *ohci = fw_ohci(card); | 469 | u32 val; |
467 | u32 val, old; | 470 | int i; |
468 | 471 | ||
469 | reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); | 472 | reg_write(ohci, OHCI1394_PhyControl, OHCI1394_PhyControl_Read(addr)); |
470 | flush_writes(ohci); | 473 | for (i = 0; i < 10; i++) { |
471 | msleep(2); | 474 | val = reg_read(ohci, OHCI1394_PhyControl); |
472 | val = reg_read(ohci, OHCI1394_PhyControl); | 475 | if (val & OHCI1394_PhyControl_ReadDone) |
473 | if ((val & OHCI1394_PhyControl_ReadDone) == 0) { | 476 | return OHCI1394_PhyControl_ReadData(val); |
474 | fw_error("failed to set phy reg bits.\n"); | 477 | |
475 | return -EBUSY; | 478 | msleep(1); |
476 | } | 479 | } |
480 | fw_error("failed to read phy reg\n"); | ||
481 | |||
482 | return -EBUSY; | ||
483 | } | ||
484 | |||
485 | static int write_phy_reg(const struct fw_ohci *ohci, int addr, u32 val) | ||
486 | { | ||
487 | int i; | ||
477 | 488 | ||
478 | old = OHCI1394_PhyControl_ReadData(val); | ||
479 | old = (old & ~clear_bits) | set_bits; | ||
480 | reg_write(ohci, OHCI1394_PhyControl, | 489 | reg_write(ohci, OHCI1394_PhyControl, |
481 | OHCI1394_PhyControl_Write(addr, old)); | 490 | OHCI1394_PhyControl_Write(addr, val)); |
491 | for (i = 0; i < 100; i++) { | ||
492 | val = reg_read(ohci, OHCI1394_PhyControl); | ||
493 | if (!(val & OHCI1394_PhyControl_WritePending)) | ||
494 | return 0; | ||
482 | 495 | ||
483 | return 0; | 496 | msleep(1); |
497 | } | ||
498 | fw_error("failed to write phy reg\n"); | ||
499 | |||
500 | return -EBUSY; | ||
501 | } | ||
502 | |||
503 | static int ohci_update_phy_reg(struct fw_card *card, int addr, | ||
504 | int clear_bits, int set_bits) | ||
505 | { | ||
506 | struct fw_ohci *ohci = fw_ohci(card); | ||
507 | int ret; | ||
508 | |||
509 | ret = read_phy_reg(ohci, addr); | ||
510 | if (ret < 0) | ||
511 | return ret; | ||
512 | |||
513 | /* | ||
514 | * The interrupt status bits are cleared by writing a one bit. | ||
515 | * Avoid clearing them unless explicitly requested in set_bits. | ||
516 | */ | ||
517 | if (addr == 5) | ||
518 | clear_bits |= PHY_INT_STATUS_BITS; | ||
519 | |||
520 | return write_phy_reg(ohci, addr, (ret & ~clear_bits) | set_bits); | ||
521 | } | ||
522 | |||
523 | static int read_paged_phy_reg(struct fw_ohci *ohci, int page, int addr) | ||
524 | { | ||
525 | int ret; | ||
526 | |||
527 | ret = ohci_update_phy_reg(&ohci->card, 7, PHY_PAGE_SELECT, page << 5); | ||
528 | if (ret < 0) | ||
529 | return ret; | ||
530 | |||
531 | return read_phy_reg(ohci, addr); | ||
484 | } | 532 | } |
485 | 533 | ||
486 | static int ar_context_add_page(struct ar_context *ctx) | 534 | static int ar_context_add_page(struct ar_context *ctx) |
@@ -1495,13 +1543,64 @@ static void copy_config_rom(__be32 *dest, const __be32 *src, size_t length) | |||
1495 | memset(&dest[length], 0, CONFIG_ROM_SIZE - size); | 1543 | memset(&dest[length], 0, CONFIG_ROM_SIZE - size); |
1496 | } | 1544 | } |
1497 | 1545 | ||
1546 | static int configure_1394a_enhancements(struct fw_ohci *ohci) | ||
1547 | { | ||
1548 | bool enable_1394a; | ||
1549 | int ret, clear, set, offset; | ||
1550 | |||
1551 | /* Check if the driver should configure link and PHY. */ | ||
1552 | if (!(reg_read(ohci, OHCI1394_HCControlSet) & | ||
1553 | OHCI1394_HCControl_programPhyEnable)) | ||
1554 | return 0; | ||
1555 | |||
1556 | /* Paranoia: check whether the PHY supports 1394a, too. */ | ||
1557 | enable_1394a = false; | ||
1558 | ret = read_phy_reg(ohci, 2); | ||
1559 | if (ret < 0) | ||
1560 | return ret; | ||
1561 | if ((ret & PHY_EXTENDED_REGISTERS) == PHY_EXTENDED_REGISTERS) { | ||
1562 | ret = read_paged_phy_reg(ohci, 1, 8); | ||
1563 | if (ret < 0) | ||
1564 | return ret; | ||
1565 | if (ret >= 1) | ||
1566 | enable_1394a = true; | ||
1567 | } | ||
1568 | |||
1569 | if (ohci->quirks & QUIRK_NO_1394A) | ||
1570 | enable_1394a = false; | ||
1571 | |||
1572 | /* Configure PHY and link consistently. */ | ||
1573 | if (enable_1394a) { | ||
1574 | clear = 0; | ||
1575 | set = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; | ||
1576 | } else { | ||
1577 | clear = PHY_ENABLE_ACCEL | PHY_ENABLE_MULTI; | ||
1578 | set = 0; | ||
1579 | } | ||
1580 | ret = ohci_update_phy_reg(&ohci->card, 5, clear, set); | ||
1581 | if (ret < 0) | ||
1582 | return ret; | ||
1583 | |||
1584 | if (enable_1394a) | ||
1585 | offset = OHCI1394_HCControlSet; | ||
1586 | else | ||
1587 | offset = OHCI1394_HCControlClear; | ||
1588 | reg_write(ohci, offset, OHCI1394_HCControl_aPhyEnhanceEnable); | ||
1589 | |||
1590 | /* Clean up: configuration has been taken care of. */ | ||
1591 | reg_write(ohci, OHCI1394_HCControlClear, | ||
1592 | OHCI1394_HCControl_programPhyEnable); | ||
1593 | |||
1594 | return 0; | ||
1595 | } | ||
1596 | |||
1498 | static int ohci_enable(struct fw_card *card, | 1597 | static int ohci_enable(struct fw_card *card, |
1499 | const __be32 *config_rom, size_t length) | 1598 | const __be32 *config_rom, size_t length) |
1500 | { | 1599 | { |
1501 | struct fw_ohci *ohci = fw_ohci(card); | 1600 | struct fw_ohci *ohci = fw_ohci(card); |
1502 | struct pci_dev *dev = to_pci_dev(card->device); | 1601 | struct pci_dev *dev = to_pci_dev(card->device); |
1503 | u32 lps; | 1602 | u32 lps; |
1504 | int i; | 1603 | int i, ret; |
1505 | 1604 | ||
1506 | if (software_reset(ohci)) { | 1605 | if (software_reset(ohci)) { |
1507 | fw_error("Failed to reset ohci card.\n"); | 1606 | fw_error("Failed to reset ohci card.\n"); |
@@ -1565,10 +1664,14 @@ static int ohci_enable(struct fw_card *card, | |||
1565 | if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) | 1664 | if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS) |
1566 | reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); | 1665 | reg_write(ohci, OHCI1394_IntMaskSet, OHCI1394_busReset); |
1567 | 1666 | ||
1667 | ret = configure_1394a_enhancements(ohci); | ||
1668 | if (ret < 0) | ||
1669 | return ret; | ||
1670 | |||
1568 | /* Activate link_on bit and contender bit in our self ID packets.*/ | 1671 | /* Activate link_on bit and contender bit in our self ID packets.*/ |
1569 | if (ohci_update_phy_reg(card, 4, 0, | 1672 | ret = ohci_update_phy_reg(card, 4, 0, PHY_LINK_ACTIVE | PHY_CONTENDER); |
1570 | PHY_LINK_ACTIVE | PHY_CONTENDER) < 0) | 1673 | if (ret < 0) |
1571 | return -EIO; | 1674 | return ret; |
1572 | 1675 | ||
1573 | /* | 1676 | /* |
1574 | * When the link is not yet enabled, the atomic config rom | 1677 | * When the link is not yet enabled, the atomic config rom |
@@ -2304,7 +2407,7 @@ static const struct fw_card_driver ohci_driver = { | |||
2304 | }; | 2407 | }; |
2305 | 2408 | ||
2306 | #ifdef CONFIG_PPC_PMAC | 2409 | #ifdef CONFIG_PPC_PMAC |
2307 | static void ohci_pmac_on(struct pci_dev *dev) | 2410 | static void pmac_ohci_on(struct pci_dev *dev) |
2308 | { | 2411 | { |
2309 | if (machine_is(powermac)) { | 2412 | if (machine_is(powermac)) { |
2310 | struct device_node *ofn = pci_device_to_OF_node(dev); | 2413 | struct device_node *ofn = pci_device_to_OF_node(dev); |
@@ -2316,7 +2419,7 @@ static void ohci_pmac_on(struct pci_dev *dev) | |||
2316 | } | 2419 | } |
2317 | } | 2420 | } |
2318 | 2421 | ||
2319 | static void ohci_pmac_off(struct pci_dev *dev) | 2422 | static void pmac_ohci_off(struct pci_dev *dev) |
2320 | { | 2423 | { |
2321 | if (machine_is(powermac)) { | 2424 | if (machine_is(powermac)) { |
2322 | struct device_node *ofn = pci_device_to_OF_node(dev); | 2425 | struct device_node *ofn = pci_device_to_OF_node(dev); |
@@ -2328,15 +2431,15 @@ static void ohci_pmac_off(struct pci_dev *dev) | |||
2328 | } | 2431 | } |
2329 | } | 2432 | } |
2330 | #else | 2433 | #else |
2331 | #define ohci_pmac_on(dev) | 2434 | static inline void pmac_ohci_on(struct pci_dev *dev) {} |
2332 | #define ohci_pmac_off(dev) | 2435 | static inline void pmac_ohci_off(struct pci_dev *dev) {} |
2333 | #endif /* CONFIG_PPC_PMAC */ | 2436 | #endif /* CONFIG_PPC_PMAC */ |
2334 | 2437 | ||
2335 | static int __devinit pci_probe(struct pci_dev *dev, | 2438 | static int __devinit pci_probe(struct pci_dev *dev, |
2336 | const struct pci_device_id *ent) | 2439 | const struct pci_device_id *ent) |
2337 | { | 2440 | { |
2338 | struct fw_ohci *ohci; | 2441 | struct fw_ohci *ohci; |
2339 | u32 bus_options, max_receive, link_speed, version; | 2442 | u32 bus_options, max_receive, link_speed, version, link_enh; |
2340 | u64 guid; | 2443 | u64 guid; |
2341 | int i, err, n_ir, n_it; | 2444 | int i, err, n_ir, n_it; |
2342 | size_t size; | 2445 | size_t size; |
@@ -2349,7 +2452,7 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2349 | 2452 | ||
2350 | fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); | 2453 | fw_card_initialize(&ohci->card, &ohci_driver, &dev->dev); |
2351 | 2454 | ||
2352 | ohci_pmac_on(dev); | 2455 | pmac_ohci_on(dev); |
2353 | 2456 | ||
2354 | err = pci_enable_device(dev); | 2457 | err = pci_enable_device(dev); |
2355 | if (err) { | 2458 | if (err) { |
@@ -2389,6 +2492,23 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2389 | if (param_quirks) | 2492 | if (param_quirks) |
2390 | ohci->quirks = param_quirks; | 2493 | ohci->quirks = param_quirks; |
2391 | 2494 | ||
2495 | /* TI OHCI-Lynx and compatible: set recommended configuration bits. */ | ||
2496 | if (dev->vendor == PCI_VENDOR_ID_TI) { | ||
2497 | pci_read_config_dword(dev, PCI_CFG_TI_LinkEnh, &link_enh); | ||
2498 | |||
2499 | /* adjust latency of ATx FIFO: use 1.7 KB threshold */ | ||
2500 | link_enh &= ~TI_LinkEnh_atx_thresh_mask; | ||
2501 | link_enh |= TI_LinkEnh_atx_thresh_1_7K; | ||
2502 | |||
2503 | /* use priority arbitration for asynchronous responses */ | ||
2504 | link_enh |= TI_LinkEnh_enab_unfair; | ||
2505 | |||
2506 | /* required for aPhyEnhanceEnable to work */ | ||
2507 | link_enh |= TI_LinkEnh_enab_accel; | ||
2508 | |||
2509 | pci_write_config_dword(dev, PCI_CFG_TI_LinkEnh, link_enh); | ||
2510 | } | ||
2511 | |||
2392 | ar_context_init(&ohci->ar_request_ctx, ohci, | 2512 | ar_context_init(&ohci->ar_request_ctx, ohci, |
2393 | OHCI1394_AsReqRcvContextControlSet); | 2513 | OHCI1394_AsReqRcvContextControlSet); |
2394 | 2514 | ||
@@ -2466,7 +2586,7 @@ static int __devinit pci_probe(struct pci_dev *dev, | |||
2466 | pci_disable_device(dev); | 2586 | pci_disable_device(dev); |
2467 | fail_free: | 2587 | fail_free: |
2468 | kfree(&ohci->card); | 2588 | kfree(&ohci->card); |
2469 | ohci_pmac_off(dev); | 2589 | pmac_ohci_off(dev); |
2470 | fail: | 2590 | fail: |
2471 | if (err == -ENOMEM) | 2591 | if (err == -ENOMEM) |
2472 | fw_error("Out of memory\n"); | 2592 | fw_error("Out of memory\n"); |
@@ -2509,7 +2629,7 @@ static void pci_remove(struct pci_dev *dev) | |||
2509 | pci_release_region(dev, 0); | 2629 | pci_release_region(dev, 0); |
2510 | pci_disable_device(dev); | 2630 | pci_disable_device(dev); |
2511 | kfree(&ohci->card); | 2631 | kfree(&ohci->card); |
2512 | ohci_pmac_off(dev); | 2632 | pmac_ohci_off(dev); |
2513 | 2633 | ||
2514 | fw_notify("Removed fw-ohci device.\n"); | 2634 | fw_notify("Removed fw-ohci device.\n"); |
2515 | } | 2635 | } |
@@ -2530,7 +2650,7 @@ static int pci_suspend(struct pci_dev *dev, pm_message_t state) | |||
2530 | err = pci_set_power_state(dev, pci_choose_state(dev, state)); | 2650 | err = pci_set_power_state(dev, pci_choose_state(dev, state)); |
2531 | if (err) | 2651 | if (err) |
2532 | fw_error("pci_set_power_state failed with %d\n", err); | 2652 | fw_error("pci_set_power_state failed with %d\n", err); |
2533 | ohci_pmac_off(dev); | 2653 | pmac_ohci_off(dev); |
2534 | 2654 | ||
2535 | return 0; | 2655 | return 0; |
2536 | } | 2656 | } |
@@ -2540,7 +2660,7 @@ static int pci_resume(struct pci_dev *dev) | |||
2540 | struct fw_ohci *ohci = pci_get_drvdata(dev); | 2660 | struct fw_ohci *ohci = pci_get_drvdata(dev); |
2541 | int err; | 2661 | int err; |
2542 | 2662 | ||
2543 | ohci_pmac_on(dev); | 2663 | pmac_ohci_on(dev); |
2544 | pci_set_power_state(dev, PCI_D0); | 2664 | pci_set_power_state(dev, PCI_D0); |
2545 | pci_restore_state(dev); | 2665 | pci_restore_state(dev); |
2546 | err = pci_enable_device(dev); | 2666 | err = pci_enable_device(dev); |
diff --git a/drivers/firewire/ohci.h b/drivers/firewire/ohci.h index ba492d85c516..3bc9a5d744eb 100644 --- a/drivers/firewire/ohci.h +++ b/drivers/firewire/ohci.h | |||
@@ -67,7 +67,7 @@ | |||
67 | #define OHCI1394_PhyControl_ReadDone 0x80000000 | 67 | #define OHCI1394_PhyControl_ReadDone 0x80000000 |
68 | #define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) | 68 | #define OHCI1394_PhyControl_ReadData(r) (((r) & 0x00ff0000) >> 16) |
69 | #define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) | 69 | #define OHCI1394_PhyControl_Write(addr, data) (((addr) << 8) | (data) | 0x00004000) |
70 | #define OHCI1394_PhyControl_WriteDone 0x00004000 | 70 | #define OHCI1394_PhyControl_WritePending 0x00004000 |
71 | #define OHCI1394_IsochronousCycleTimer 0x0F0 | 71 | #define OHCI1394_IsochronousCycleTimer 0x0F0 |
72 | #define OHCI1394_AsReqFilterHiSet 0x100 | 72 | #define OHCI1394_AsReqFilterHiSet 0x100 |
73 | #define OHCI1394_AsReqFilterHiClear 0x104 | 73 | #define OHCI1394_AsReqFilterHiClear 0x104 |
@@ -154,4 +154,12 @@ | |||
154 | 154 | ||
155 | #define OHCI1394_phy_tcode 0xe | 155 | #define OHCI1394_phy_tcode 0xe |
156 | 156 | ||
157 | /* TI extensions */ | ||
158 | |||
159 | #define PCI_CFG_TI_LinkEnh 0xf4 | ||
160 | #define TI_LinkEnh_enab_accel 0x00000002 | ||
161 | #define TI_LinkEnh_enab_unfair 0x00000080 | ||
162 | #define TI_LinkEnh_atx_thresh_mask 0x00003000 | ||
163 | #define TI_LinkEnh_atx_thresh_1_7K 0x00001000 | ||
164 | |||
157 | #endif /* _FIREWIRE_OHCI_H */ | 165 | #endif /* _FIREWIRE_OHCI_H */ |
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index fee678f74a19..4fd0f276df5a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -139,6 +139,13 @@ config GPIO_MAX732X | |||
139 | Board setup code must specify the model to use, and the start | 139 | Board setup code must specify the model to use, and the start |
140 | number for these GPIOs. | 140 | number for these GPIOs. |
141 | 141 | ||
142 | config GPIO_MAX732X_IRQ | ||
143 | bool "Interrupt controller support for MAX732x" | ||
144 | depends on GPIO_MAX732X=y && GENERIC_HARDIRQS | ||
145 | help | ||
146 | Say yes here to enable the max732x to be used as an interrupt | ||
147 | controller. It requires the driver to be built in the kernel. | ||
148 | |||
142 | config GPIO_PCA953X | 149 | config GPIO_PCA953X |
143 | tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" | 150 | tristate "PCA953x, PCA955x, TCA64xx, and MAX7310 I/O ports" |
144 | depends on I2C | 151 | depends on I2C |
@@ -264,10 +271,10 @@ config GPIO_BT8XX | |||
264 | If unsure, say N. | 271 | If unsure, say N. |
265 | 272 | ||
266 | config GPIO_LANGWELL | 273 | config GPIO_LANGWELL |
267 | bool "Intel Moorestown Platform Langwell GPIO support" | 274 | bool "Intel Langwell/Penwell GPIO support" |
268 | depends on PCI | 275 | depends on PCI |
269 | help | 276 | help |
270 | Say Y here to support Intel Moorestown platform GPIO. | 277 | Say Y here to support Intel Langwell/Penwell GPIO. |
271 | 278 | ||
272 | config GPIO_TIMBERDALE | 279 | config GPIO_TIMBERDALE |
273 | bool "Support for timberdale GPIO IP" | 280 | bool "Support for timberdale GPIO IP" |
diff --git a/drivers/gpio/cs5535-gpio.c b/drivers/gpio/cs5535-gpio.c index 0c3c498f2260..f73a1555e49d 100644 --- a/drivers/gpio/cs5535-gpio.c +++ b/drivers/gpio/cs5535-gpio.c | |||
@@ -197,7 +197,7 @@ static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) | |||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | static char *cs5535_gpio_names[] = { | 200 | static const char * const cs5535_gpio_names[] = { |
201 | "GPIO0", "GPIO1", "GPIO2", "GPIO3", | 201 | "GPIO0", "GPIO1", "GPIO2", "GPIO3", |
202 | "GPIO4", "GPIO5", "GPIO6", "GPIO7", | 202 | "GPIO4", "GPIO5", "GPIO6", "GPIO7", |
203 | "GPIO8", "GPIO9", "GPIO10", "GPIO11", | 203 | "GPIO8", "GPIO9", "GPIO10", "GPIO11", |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index cae1b8c5b08c..3ca36542e338 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -722,7 +722,7 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
722 | unsigned long flags; | 722 | unsigned long flags; |
723 | struct gpio_desc *desc; | 723 | struct gpio_desc *desc; |
724 | int status = -EINVAL; | 724 | int status = -EINVAL; |
725 | char *ioname = NULL; | 725 | const char *ioname = NULL; |
726 | 726 | ||
727 | /* can't export until sysfs is available ... */ | 727 | /* can't export until sysfs is available ... */ |
728 | if (!gpio_class.p) { | 728 | if (!gpio_class.p) { |
@@ -753,7 +753,7 @@ int gpio_export(unsigned gpio, bool direction_may_change) | |||
753 | struct device *dev; | 753 | struct device *dev; |
754 | 754 | ||
755 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), | 755 | dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), |
756 | desc, ioname ? ioname : "gpio%d", gpio); | 756 | desc, ioname ? ioname : "gpio%u", gpio); |
757 | if (!IS_ERR(dev)) { | 757 | if (!IS_ERR(dev)) { |
758 | status = sysfs_create_group(&dev->kobj, | 758 | status = sysfs_create_group(&dev->kobj, |
759 | &gpio_attr_group); | 759 | &gpio_attr_group); |
@@ -1106,7 +1106,7 @@ unlock: | |||
1106 | fail: | 1106 | fail: |
1107 | /* failures here can mean systems won't boot... */ | 1107 | /* failures here can mean systems won't boot... */ |
1108 | if (status) | 1108 | if (status) |
1109 | pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n", | 1109 | pr_err("gpiochip_add: gpios %d..%d (%s) failed to register\n", |
1110 | chip->base, chip->base + chip->ngpio - 1, | 1110 | chip->base, chip->base + chip->ngpio - 1, |
1111 | chip->label ? : "generic"); | 1111 | chip->label ? : "generic"); |
1112 | return status; | 1112 | return status; |
@@ -1447,6 +1447,49 @@ fail: | |||
1447 | } | 1447 | } |
1448 | EXPORT_SYMBOL_GPL(gpio_direction_output); | 1448 | EXPORT_SYMBOL_GPL(gpio_direction_output); |
1449 | 1449 | ||
1450 | /** | ||
1451 | * gpio_set_debounce - sets @debounce time for a @gpio | ||
1452 | * @gpio: the gpio to set debounce time | ||
1453 | * @debounce: debounce time is microseconds | ||
1454 | */ | ||
1455 | int gpio_set_debounce(unsigned gpio, unsigned debounce) | ||
1456 | { | ||
1457 | unsigned long flags; | ||
1458 | struct gpio_chip *chip; | ||
1459 | struct gpio_desc *desc = &gpio_desc[gpio]; | ||
1460 | int status = -EINVAL; | ||
1461 | |||
1462 | spin_lock_irqsave(&gpio_lock, flags); | ||
1463 | |||
1464 | if (!gpio_is_valid(gpio)) | ||
1465 | goto fail; | ||
1466 | chip = desc->chip; | ||
1467 | if (!chip || !chip->set || !chip->set_debounce) | ||
1468 | goto fail; | ||
1469 | gpio -= chip->base; | ||
1470 | if (gpio >= chip->ngpio) | ||
1471 | goto fail; | ||
1472 | status = gpio_ensure_requested(desc, gpio); | ||
1473 | if (status < 0) | ||
1474 | goto fail; | ||
1475 | |||
1476 | /* now we know the gpio is valid and chip won't vanish */ | ||
1477 | |||
1478 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
1479 | |||
1480 | might_sleep_if(extra_checks && chip->can_sleep); | ||
1481 | |||
1482 | return chip->set_debounce(chip, gpio, debounce); | ||
1483 | |||
1484 | fail: | ||
1485 | spin_unlock_irqrestore(&gpio_lock, flags); | ||
1486 | if (status) | ||
1487 | pr_debug("%s: gpio-%d status %d\n", | ||
1488 | __func__, gpio, status); | ||
1489 | |||
1490 | return status; | ||
1491 | } | ||
1492 | EXPORT_SYMBOL_GPL(gpio_set_debounce); | ||
1450 | 1493 | ||
1451 | /* I/O calls are only valid after configuration completed; the relevant | 1494 | /* I/O calls are only valid after configuration completed; the relevant |
1452 | * "is this a valid GPIO" error checks should already have been done. | 1495 | * "is this a valid GPIO" error checks should already have been done. |
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c index 41a9388f2fde..48fc43c4bdd1 100644 --- a/drivers/gpio/it8761e_gpio.c +++ b/drivers/gpio/it8761e_gpio.c | |||
@@ -217,7 +217,10 @@ gpiochip_add_err: | |||
217 | static void __exit it8761e_gpio_exit(void) | 217 | static void __exit it8761e_gpio_exit(void) |
218 | { | 218 | { |
219 | if (gpio_ba) { | 219 | if (gpio_ba) { |
220 | gpiochip_remove(&it8761e_gpio_chip); | 220 | int ret = gpiochip_remove(&it8761e_gpio_chip); |
221 | |||
222 | WARN(ret, "%s(): gpiochip_remove() failed, ret=%d\n", | ||
223 | __func__, ret); | ||
221 | 224 | ||
222 | release_region(gpio_ba, GPIO_IOSIZE); | 225 | release_region(gpio_ba, GPIO_IOSIZE); |
223 | gpio_ba = 0; | 226 | gpio_ba = 0; |
diff --git a/drivers/gpio/langwell_gpio.c b/drivers/gpio/langwell_gpio.c index 00c3a14127af..8383a8d7f994 100644 --- a/drivers/gpio/langwell_gpio.c +++ b/drivers/gpio/langwell_gpio.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | /* Supports: | 18 | /* Supports: |
19 | * Moorestown platform Langwell chip. | 19 | * Moorestown platform Langwell chip. |
20 | * Medfield platform Penwell chip. | ||
20 | */ | 21 | */ |
21 | 22 | ||
22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
@@ -31,44 +32,65 @@ | |||
31 | #include <linux/gpio.h> | 32 | #include <linux/gpio.h> |
32 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
33 | 34 | ||
34 | struct lnw_gpio_register { | 35 | /* |
35 | u32 GPLR[2]; | 36 | * Langwell chip has 64 pins and thus there are 2 32bit registers to control |
36 | u32 GPDR[2]; | 37 | * each feature, while Penwell chip has 96 pins for each block, and need 3 32bit |
37 | u32 GPSR[2]; | 38 | * registers to control them, so we only define the order here instead of a |
38 | u32 GPCR[2]; | 39 | * structure, to get a bit offset for a pin (use GPDR as an example): |
39 | u32 GRER[2]; | 40 | * |
40 | u32 GFER[2]; | 41 | * nreg = ngpio / 32; |
41 | u32 GEDR[2]; | 42 | * reg = offset / 32; |
43 | * bit = offset % 32; | ||
44 | * reg_addr = reg_base + GPDR * nreg * 4 + reg * 4; | ||
45 | * | ||
46 | * so the bit of reg_addr is to control pin offset's GPDR feature | ||
47 | */ | ||
48 | |||
49 | enum GPIO_REG { | ||
50 | GPLR = 0, /* pin level read-only */ | ||
51 | GPDR, /* pin direction */ | ||
52 | GPSR, /* pin set */ | ||
53 | GPCR, /* pin clear */ | ||
54 | GRER, /* rising edge detect */ | ||
55 | GFER, /* falling edge detect */ | ||
56 | GEDR, /* edge detect result */ | ||
42 | }; | 57 | }; |
43 | 58 | ||
44 | struct lnw_gpio { | 59 | struct lnw_gpio { |
45 | struct gpio_chip chip; | 60 | struct gpio_chip chip; |
46 | struct lnw_gpio_register *reg_base; | 61 | void *reg_base; |
47 | spinlock_t lock; | 62 | spinlock_t lock; |
48 | unsigned irq_base; | 63 | unsigned irq_base; |
49 | }; | 64 | }; |
50 | 65 | ||
51 | static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) | 66 | static void __iomem *gpio_reg(struct gpio_chip *chip, unsigned offset, |
67 | enum GPIO_REG reg_type) | ||
52 | { | 68 | { |
53 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | 69 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); |
70 | unsigned nreg = chip->ngpio / 32; | ||
54 | u8 reg = offset / 32; | 71 | u8 reg = offset / 32; |
55 | void __iomem *gplr; | 72 | void __iomem *ptr; |
73 | |||
74 | ptr = (void __iomem *)(lnw->reg_base + reg_type * nreg * 4 + reg * 4); | ||
75 | return ptr; | ||
76 | } | ||
77 | |||
78 | static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
79 | { | ||
80 | void __iomem *gplr = gpio_reg(chip, offset, GPLR); | ||
56 | 81 | ||
57 | gplr = (void __iomem *)(&lnw->reg_base->GPLR[reg]); | ||
58 | return readl(gplr) & BIT(offset % 32); | 82 | return readl(gplr) & BIT(offset % 32); |
59 | } | 83 | } |
60 | 84 | ||
61 | static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | 85 | static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) |
62 | { | 86 | { |
63 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | ||
64 | u8 reg = offset / 32; | ||
65 | void __iomem *gpsr, *gpcr; | 87 | void __iomem *gpsr, *gpcr; |
66 | 88 | ||
67 | if (value) { | 89 | if (value) { |
68 | gpsr = (void __iomem *)(&lnw->reg_base->GPSR[reg]); | 90 | gpsr = gpio_reg(chip, offset, GPSR); |
69 | writel(BIT(offset % 32), gpsr); | 91 | writel(BIT(offset % 32), gpsr); |
70 | } else { | 92 | } else { |
71 | gpcr = (void __iomem *)(&lnw->reg_base->GPCR[reg]); | 93 | gpcr = gpio_reg(chip, offset, GPCR); |
72 | writel(BIT(offset % 32), gpcr); | 94 | writel(BIT(offset % 32), gpcr); |
73 | } | 95 | } |
74 | } | 96 | } |
@@ -76,12 +98,10 @@ static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | |||
76 | static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | 98 | static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) |
77 | { | 99 | { |
78 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | 100 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); |
79 | u8 reg = offset / 32; | 101 | void __iomem *gpdr = gpio_reg(chip, offset, GPDR); |
80 | u32 value; | 102 | u32 value; |
81 | unsigned long flags; | 103 | unsigned long flags; |
82 | void __iomem *gpdr; | ||
83 | 104 | ||
84 | gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]); | ||
85 | spin_lock_irqsave(&lnw->lock, flags); | 105 | spin_lock_irqsave(&lnw->lock, flags); |
86 | value = readl(gpdr); | 106 | value = readl(gpdr); |
87 | value &= ~BIT(offset % 32); | 107 | value &= ~BIT(offset % 32); |
@@ -94,12 +114,10 @@ static int lnw_gpio_direction_output(struct gpio_chip *chip, | |||
94 | unsigned offset, int value) | 114 | unsigned offset, int value) |
95 | { | 115 | { |
96 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); | 116 | struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); |
97 | u8 reg = offset / 32; | 117 | void __iomem *gpdr = gpio_reg(chip, offset, GPDR); |
98 | unsigned long flags; | 118 | unsigned long flags; |
99 | void __iomem *gpdr; | ||
100 | 119 | ||
101 | lnw_gpio_set(chip, offset, value); | 120 | lnw_gpio_set(chip, offset, value); |
102 | gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]); | ||
103 | spin_lock_irqsave(&lnw->lock, flags); | 121 | spin_lock_irqsave(&lnw->lock, flags); |
104 | value = readl(gpdr); | 122 | value = readl(gpdr); |
105 | value |= BIT(offset % 32);; | 123 | value |= BIT(offset % 32);; |
@@ -118,11 +136,10 @@ static int lnw_irq_type(unsigned irq, unsigned type) | |||
118 | { | 136 | { |
119 | struct lnw_gpio *lnw = get_irq_chip_data(irq); | 137 | struct lnw_gpio *lnw = get_irq_chip_data(irq); |
120 | u32 gpio = irq - lnw->irq_base; | 138 | u32 gpio = irq - lnw->irq_base; |
121 | u8 reg = gpio / 32; | ||
122 | unsigned long flags; | 139 | unsigned long flags; |
123 | u32 value; | 140 | u32 value; |
124 | void __iomem *grer = (void __iomem *)(&lnw->reg_base->GRER[reg]); | 141 | void __iomem *grer = gpio_reg(&lnw->chip, gpio, GRER); |
125 | void __iomem *gfer = (void __iomem *)(&lnw->reg_base->GFER[reg]); | 142 | void __iomem *gfer = gpio_reg(&lnw->chip, gpio, GFER); |
126 | 143 | ||
127 | if (gpio >= lnw->chip.ngpio) | 144 | if (gpio >= lnw->chip.ngpio) |
128 | return -EINVAL; | 145 | return -EINVAL; |
@@ -158,8 +175,10 @@ static struct irq_chip lnw_irqchip = { | |||
158 | .set_type = lnw_irq_type, | 175 | .set_type = lnw_irq_type, |
159 | }; | 176 | }; |
160 | 177 | ||
161 | static struct pci_device_id lnw_gpio_ids[] = { | 178 | static DEFINE_PCI_DEVICE_TABLE(lnw_gpio_ids) = { /* pin number */ |
162 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f) }, | 179 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f), .driver_data = 64 }, |
180 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081f), .driver_data = 96 }, | ||
181 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x081a), .driver_data = 96 }, | ||
163 | { 0, } | 182 | { 0, } |
164 | }; | 183 | }; |
165 | MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); | 184 | MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); |
@@ -167,17 +186,17 @@ MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); | |||
167 | static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) | 186 | static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) |
168 | { | 187 | { |
169 | struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq); | 188 | struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq); |
170 | u32 reg, gpio; | 189 | u32 base, gpio; |
171 | void __iomem *gedr; | 190 | void __iomem *gedr; |
172 | u32 gedr_v; | 191 | u32 gedr_v; |
173 | 192 | ||
174 | /* check GPIO controller to check which pin triggered the interrupt */ | 193 | /* check GPIO controller to check which pin triggered the interrupt */ |
175 | for (reg = 0; reg < lnw->chip.ngpio / 32; reg++) { | 194 | for (base = 0; base < lnw->chip.ngpio; base += 32) { |
176 | gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]); | 195 | gedr = gpio_reg(&lnw->chip, base, GEDR); |
177 | gedr_v = readl(gedr); | 196 | gedr_v = readl(gedr); |
178 | if (!gedr_v) | 197 | if (!gedr_v) |
179 | continue; | 198 | continue; |
180 | for (gpio = reg*32; gpio < reg*32+32; gpio++) | 199 | for (gpio = base; gpio < base + 32; gpio++) |
181 | if (gedr_v & BIT(gpio % 32)) { | 200 | if (gedr_v & BIT(gpio % 32)) { |
182 | pr_debug("pin %d triggered\n", gpio); | 201 | pr_debug("pin %d triggered\n", gpio); |
183 | generic_handle_irq(lnw->irq_base + gpio); | 202 | generic_handle_irq(lnw->irq_base + gpio); |
@@ -245,7 +264,7 @@ static int __devinit lnw_gpio_probe(struct pci_dev *pdev, | |||
245 | lnw->chip.set = lnw_gpio_set; | 264 | lnw->chip.set = lnw_gpio_set; |
246 | lnw->chip.to_irq = lnw_gpio_to_irq; | 265 | lnw->chip.to_irq = lnw_gpio_to_irq; |
247 | lnw->chip.base = gpio_base; | 266 | lnw->chip.base = gpio_base; |
248 | lnw->chip.ngpio = 64; | 267 | lnw->chip.ngpio = id->driver_data; |
249 | lnw->chip.can_sleep = 0; | 268 | lnw->chip.can_sleep = 0; |
250 | pci_set_drvdata(pdev, lnw); | 269 | pci_set_drvdata(pdev, lnw); |
251 | retval = gpiochip_add(&lnw->chip); | 270 | retval = gpiochip_add(&lnw->chip); |
diff --git a/drivers/gpio/max732x.c b/drivers/gpio/max732x.c index f7868243af89..9cad60f9e962 100644 --- a/drivers/gpio/max732x.c +++ b/drivers/gpio/max732x.c | |||
@@ -17,7 +17,8 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/string.h> | 18 | #include <linux/string.h> |
19 | #include <linux/gpio.h> | 19 | #include <linux/gpio.h> |
20 | 20 | #include <linux/interrupt.h> | |
21 | #include <linux/irq.h> | ||
21 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
22 | #include <linux/i2c/max732x.h> | 23 | #include <linux/i2c/max732x.h> |
23 | 24 | ||
@@ -31,7 +32,8 @@ | |||
31 | * - Open Drain I/O | 32 | * - Open Drain I/O |
32 | * | 33 | * |
33 | * designated by 'O', 'I' and 'P' individually according to MAXIM's | 34 | * designated by 'O', 'I' and 'P' individually according to MAXIM's |
34 | * datasheets. | 35 | * datasheets. 'I' and 'P' ports are interrupt capables, some with |
36 | * a dedicated interrupt mask. | ||
35 | * | 37 | * |
36 | * There are two groups of I/O ports, each group usually includes | 38 | * There are two groups of I/O ports, each group usually includes |
37 | * up to 8 I/O ports, and is accessed by a specific I2C address: | 39 | * up to 8 I/O ports, and is accessed by a specific I2C address: |
@@ -44,7 +46,8 @@ | |||
44 | * | 46 | * |
45 | * Within each group of ports, there are five known combinations of | 47 | * Within each group of ports, there are five known combinations of |
46 | * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for | 48 | * I/O ports: 4I4O, 4P4O, 8I, 8P, 8O, see the definitions below for |
47 | * the detailed organization of these ports. | 49 | * the detailed organization of these ports. Only Goup A is interrupt |
50 | * capable. | ||
48 | * | 51 | * |
49 | * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16', | 52 | * GPIO numbers start from 'gpio_base + 0' to 'gpio_base + 8/16', |
50 | * and GPIOs from GROUP_A are numbered before those from GROUP_B | 53 | * and GPIOs from GROUP_A are numbered before those from GROUP_B |
@@ -68,16 +71,47 @@ | |||
68 | #define GROUP_A(x) ((x) & 0xffff) /* I2C Addr: 0b'110xxxx */ | 71 | #define GROUP_A(x) ((x) & 0xffff) /* I2C Addr: 0b'110xxxx */ |
69 | #define GROUP_B(x) ((x) << 16) /* I2C Addr: 0b'101xxxx */ | 72 | #define GROUP_B(x) ((x) << 16) /* I2C Addr: 0b'101xxxx */ |
70 | 73 | ||
74 | #define INT_NONE 0x0 /* No interrupt capability */ | ||
75 | #define INT_NO_MASK 0x1 /* Has interrupts, no mask */ | ||
76 | #define INT_INDEP_MASK 0x2 /* Has interrupts, independent mask */ | ||
77 | #define INT_MERGED_MASK 0x3 /* Has interrupts, merged mask */ | ||
78 | |||
79 | #define INT_CAPS(x) (((uint64_t)(x)) << 32) | ||
80 | |||
81 | enum { | ||
82 | MAX7319, | ||
83 | MAX7320, | ||
84 | MAX7321, | ||
85 | MAX7322, | ||
86 | MAX7323, | ||
87 | MAX7324, | ||
88 | MAX7325, | ||
89 | MAX7326, | ||
90 | MAX7327, | ||
91 | }; | ||
92 | |||
93 | static uint64_t max732x_features[] = { | ||
94 | [MAX7319] = GROUP_A(IO_8I) | INT_CAPS(INT_MERGED_MASK), | ||
95 | [MAX7320] = GROUP_B(IO_8O), | ||
96 | [MAX7321] = GROUP_A(IO_8P) | INT_CAPS(INT_NO_MASK), | ||
97 | [MAX7322] = GROUP_A(IO_4I4O) | INT_CAPS(INT_MERGED_MASK), | ||
98 | [MAX7323] = GROUP_A(IO_4P4O) | INT_CAPS(INT_INDEP_MASK), | ||
99 | [MAX7324] = GROUP_A(IO_8I) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK), | ||
100 | [MAX7325] = GROUP_A(IO_8P) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK), | ||
101 | [MAX7326] = GROUP_A(IO_4I4O) | GROUP_B(IO_8O) | INT_CAPS(INT_MERGED_MASK), | ||
102 | [MAX7327] = GROUP_A(IO_4P4O) | GROUP_B(IO_8O) | INT_CAPS(INT_NO_MASK), | ||
103 | }; | ||
104 | |||
71 | static const struct i2c_device_id max732x_id[] = { | 105 | static const struct i2c_device_id max732x_id[] = { |
72 | { "max7319", GROUP_A(IO_8I) }, | 106 | { "max7319", MAX7319 }, |
73 | { "max7320", GROUP_B(IO_8O) }, | 107 | { "max7320", MAX7320 }, |
74 | { "max7321", GROUP_A(IO_8P) }, | 108 | { "max7321", MAX7321 }, |
75 | { "max7322", GROUP_A(IO_4I4O) }, | 109 | { "max7322", MAX7322 }, |
76 | { "max7323", GROUP_A(IO_4P4O) }, | 110 | { "max7323", MAX7323 }, |
77 | { "max7324", GROUP_A(IO_8I) | GROUP_B(IO_8O) }, | 111 | { "max7324", MAX7324 }, |
78 | { "max7325", GROUP_A(IO_8P) | GROUP_B(IO_8O) }, | 112 | { "max7325", MAX7325 }, |
79 | { "max7326", GROUP_A(IO_4I4O) | GROUP_B(IO_8O) }, | 113 | { "max7326", MAX7326 }, |
80 | { "max7327", GROUP_A(IO_4P4O) | GROUP_B(IO_8O) }, | 114 | { "max7327", MAX7327 }, |
81 | { }, | 115 | { }, |
82 | }; | 116 | }; |
83 | MODULE_DEVICE_TABLE(i2c, max732x_id); | 117 | MODULE_DEVICE_TABLE(i2c, max732x_id); |
@@ -96,9 +130,19 @@ struct max732x_chip { | |||
96 | 130 | ||
97 | struct mutex lock; | 131 | struct mutex lock; |
98 | uint8_t reg_out[2]; | 132 | uint8_t reg_out[2]; |
133 | |||
134 | #ifdef CONFIG_GPIO_MAX732X_IRQ | ||
135 | struct mutex irq_lock; | ||
136 | int irq_base; | ||
137 | uint8_t irq_mask; | ||
138 | uint8_t irq_mask_cur; | ||
139 | uint8_t irq_trig_raise; | ||
140 | uint8_t irq_trig_fall; | ||
141 | uint8_t irq_features; | ||
142 | #endif | ||
99 | }; | 143 | }; |
100 | 144 | ||
101 | static int max732x_write(struct max732x_chip *chip, int group_a, uint8_t val) | 145 | static int max732x_writeb(struct max732x_chip *chip, int group_a, uint8_t val) |
102 | { | 146 | { |
103 | struct i2c_client *client; | 147 | struct i2c_client *client; |
104 | int ret; | 148 | int ret; |
@@ -113,7 +157,7 @@ static int max732x_write(struct max732x_chip *chip, int group_a, uint8_t val) | |||
113 | return 0; | 157 | return 0; |
114 | } | 158 | } |
115 | 159 | ||
116 | static int max732x_read(struct max732x_chip *chip, int group_a, uint8_t *val) | 160 | static int max732x_readb(struct max732x_chip *chip, int group_a, uint8_t *val) |
117 | { | 161 | { |
118 | struct i2c_client *client; | 162 | struct i2c_client *client; |
119 | int ret; | 163 | int ret; |
@@ -142,7 +186,7 @@ static int max732x_gpio_get_value(struct gpio_chip *gc, unsigned off) | |||
142 | 186 | ||
143 | chip = container_of(gc, struct max732x_chip, gpio_chip); | 187 | chip = container_of(gc, struct max732x_chip, gpio_chip); |
144 | 188 | ||
145 | ret = max732x_read(chip, is_group_a(chip, off), ®_val); | 189 | ret = max732x_readb(chip, is_group_a(chip, off), ®_val); |
146 | if (ret < 0) | 190 | if (ret < 0) |
147 | return 0; | 191 | return 0; |
148 | 192 | ||
@@ -162,7 +206,7 @@ static void max732x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) | |||
162 | reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0]; | 206 | reg_out = (off > 7) ? chip->reg_out[1] : chip->reg_out[0]; |
163 | reg_out = (val) ? reg_out | mask : reg_out & ~mask; | 207 | reg_out = (val) ? reg_out | mask : reg_out & ~mask; |
164 | 208 | ||
165 | ret = max732x_write(chip, is_group_a(chip, off), reg_out); | 209 | ret = max732x_writeb(chip, is_group_a(chip, off), reg_out); |
166 | if (ret < 0) | 210 | if (ret < 0) |
167 | goto out; | 211 | goto out; |
168 | 212 | ||
@@ -188,6 +232,13 @@ static int max732x_gpio_direction_input(struct gpio_chip *gc, unsigned off) | |||
188 | return -EACCES; | 232 | return -EACCES; |
189 | } | 233 | } |
190 | 234 | ||
235 | /* | ||
236 | * Open-drain pins must be set to high impedance (which is | ||
237 | * equivalent to output-high) to be turned into an input. | ||
238 | */ | ||
239 | if ((mask & chip->dir_output)) | ||
240 | max732x_gpio_set_value(gc, off, 1); | ||
241 | |||
191 | return 0; | 242 | return 0; |
192 | } | 243 | } |
193 | 244 | ||
@@ -209,12 +260,278 @@ static int max732x_gpio_direction_output(struct gpio_chip *gc, | |||
209 | return 0; | 260 | return 0; |
210 | } | 261 | } |
211 | 262 | ||
263 | #ifdef CONFIG_GPIO_MAX732X_IRQ | ||
264 | static int max732x_writew(struct max732x_chip *chip, uint16_t val) | ||
265 | { | ||
266 | int ret; | ||
267 | |||
268 | val = cpu_to_le16(val); | ||
269 | |||
270 | ret = i2c_master_send(chip->client_group_a, (char *)&val, 2); | ||
271 | if (ret < 0) { | ||
272 | dev_err(&chip->client_group_a->dev, "failed writing\n"); | ||
273 | return ret; | ||
274 | } | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static int max732x_readw(struct max732x_chip *chip, uint16_t *val) | ||
280 | { | ||
281 | int ret; | ||
282 | |||
283 | ret = i2c_master_recv(chip->client_group_a, (char *)val, 2); | ||
284 | if (ret < 0) { | ||
285 | dev_err(&chip->client_group_a->dev, "failed reading\n"); | ||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | *val = le16_to_cpu(*val); | ||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static void max732x_irq_update_mask(struct max732x_chip *chip) | ||
294 | { | ||
295 | uint16_t msg; | ||
296 | |||
297 | if (chip->irq_mask == chip->irq_mask_cur) | ||
298 | return; | ||
299 | |||
300 | chip->irq_mask = chip->irq_mask_cur; | ||
301 | |||
302 | if (chip->irq_features == INT_NO_MASK) | ||
303 | return; | ||
304 | |||
305 | mutex_lock(&chip->lock); | ||
306 | |||
307 | switch (chip->irq_features) { | ||
308 | case INT_INDEP_MASK: | ||
309 | msg = (chip->irq_mask << 8) | chip->reg_out[0]; | ||
310 | max732x_writew(chip, msg); | ||
311 | break; | ||
312 | |||
313 | case INT_MERGED_MASK: | ||
314 | msg = chip->irq_mask | chip->reg_out[0]; | ||
315 | max732x_writeb(chip, 1, (uint8_t)msg); | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | mutex_unlock(&chip->lock); | ||
320 | } | ||
321 | |||
322 | static int max732x_gpio_to_irq(struct gpio_chip *gc, unsigned off) | ||
323 | { | ||
324 | struct max732x_chip *chip; | ||
325 | |||
326 | chip = container_of(gc, struct max732x_chip, gpio_chip); | ||
327 | return chip->irq_base + off; | ||
328 | } | ||
329 | |||
330 | static void max732x_irq_mask(unsigned int irq) | ||
331 | { | ||
332 | struct max732x_chip *chip = get_irq_chip_data(irq); | ||
333 | |||
334 | chip->irq_mask_cur &= ~(1 << (irq - chip->irq_base)); | ||
335 | } | ||
336 | |||
337 | static void max732x_irq_unmask(unsigned int irq) | ||
338 | { | ||
339 | struct max732x_chip *chip = get_irq_chip_data(irq); | ||
340 | |||
341 | chip->irq_mask_cur |= 1 << (irq - chip->irq_base); | ||
342 | } | ||
343 | |||
344 | static void max732x_irq_bus_lock(unsigned int irq) | ||
345 | { | ||
346 | struct max732x_chip *chip = get_irq_chip_data(irq); | ||
347 | |||
348 | mutex_lock(&chip->irq_lock); | ||
349 | chip->irq_mask_cur = chip->irq_mask; | ||
350 | } | ||
351 | |||
352 | static void max732x_irq_bus_sync_unlock(unsigned int irq) | ||
353 | { | ||
354 | struct max732x_chip *chip = get_irq_chip_data(irq); | ||
355 | |||
356 | max732x_irq_update_mask(chip); | ||
357 | mutex_unlock(&chip->irq_lock); | ||
358 | } | ||
359 | |||
360 | static int max732x_irq_set_type(unsigned int irq, unsigned int type) | ||
361 | { | ||
362 | struct max732x_chip *chip = get_irq_chip_data(irq); | ||
363 | uint16_t off = irq - chip->irq_base; | ||
364 | uint16_t mask = 1 << off; | ||
365 | |||
366 | if (!(mask & chip->dir_input)) { | ||
367 | dev_dbg(&chip->client->dev, "%s port %d is output only\n", | ||
368 | chip->client->name, off); | ||
369 | return -EACCES; | ||
370 | } | ||
371 | |||
372 | if (!(type & IRQ_TYPE_EDGE_BOTH)) { | ||
373 | dev_err(&chip->client->dev, "irq %d: unsupported type %d\n", | ||
374 | irq, type); | ||
375 | return -EINVAL; | ||
376 | } | ||
377 | |||
378 | if (type & IRQ_TYPE_EDGE_FALLING) | ||
379 | chip->irq_trig_fall |= mask; | ||
380 | else | ||
381 | chip->irq_trig_fall &= ~mask; | ||
382 | |||
383 | if (type & IRQ_TYPE_EDGE_RISING) | ||
384 | chip->irq_trig_raise |= mask; | ||
385 | else | ||
386 | chip->irq_trig_raise &= ~mask; | ||
387 | |||
388 | return max732x_gpio_direction_input(&chip->gpio_chip, off); | ||
389 | } | ||
390 | |||
391 | static struct irq_chip max732x_irq_chip = { | ||
392 | .name = "max732x", | ||
393 | .mask = max732x_irq_mask, | ||
394 | .unmask = max732x_irq_unmask, | ||
395 | .bus_lock = max732x_irq_bus_lock, | ||
396 | .bus_sync_unlock = max732x_irq_bus_sync_unlock, | ||
397 | .set_type = max732x_irq_set_type, | ||
398 | }; | ||
399 | |||
400 | static uint8_t max732x_irq_pending(struct max732x_chip *chip) | ||
401 | { | ||
402 | uint8_t cur_stat; | ||
403 | uint8_t old_stat; | ||
404 | uint8_t trigger; | ||
405 | uint8_t pending; | ||
406 | uint16_t status; | ||
407 | int ret; | ||
408 | |||
409 | ret = max732x_readw(chip, &status); | ||
410 | if (ret) | ||
411 | return 0; | ||
412 | |||
413 | trigger = status >> 8; | ||
414 | trigger &= chip->irq_mask; | ||
415 | |||
416 | if (!trigger) | ||
417 | return 0; | ||
418 | |||
419 | cur_stat = status & 0xFF; | ||
420 | cur_stat &= chip->irq_mask; | ||
421 | |||
422 | old_stat = cur_stat ^ trigger; | ||
423 | |||
424 | pending = (old_stat & chip->irq_trig_fall) | | ||
425 | (cur_stat & chip->irq_trig_raise); | ||
426 | pending &= trigger; | ||
427 | |||
428 | return pending; | ||
429 | } | ||
430 | |||
431 | static irqreturn_t max732x_irq_handler(int irq, void *devid) | ||
432 | { | ||
433 | struct max732x_chip *chip = devid; | ||
434 | uint8_t pending; | ||
435 | uint8_t level; | ||
436 | |||
437 | pending = max732x_irq_pending(chip); | ||
438 | |||
439 | if (!pending) | ||
440 | return IRQ_HANDLED; | ||
441 | |||
442 | do { | ||
443 | level = __ffs(pending); | ||
444 | handle_nested_irq(level + chip->irq_base); | ||
445 | |||
446 | pending &= ~(1 << level); | ||
447 | } while (pending); | ||
448 | |||
449 | return IRQ_HANDLED; | ||
450 | } | ||
451 | |||
452 | static int max732x_irq_setup(struct max732x_chip *chip, | ||
453 | const struct i2c_device_id *id) | ||
454 | { | ||
455 | struct i2c_client *client = chip->client; | ||
456 | struct max732x_platform_data *pdata = client->dev.platform_data; | ||
457 | int has_irq = max732x_features[id->driver_data] >> 32; | ||
458 | int ret; | ||
459 | |||
460 | if (pdata->irq_base && has_irq != INT_NONE) { | ||
461 | int lvl; | ||
462 | |||
463 | chip->irq_base = pdata->irq_base; | ||
464 | chip->irq_features = has_irq; | ||
465 | mutex_init(&chip->irq_lock); | ||
466 | |||
467 | for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) { | ||
468 | int irq = lvl + chip->irq_base; | ||
469 | |||
470 | if (!(chip->dir_input & (1 << lvl))) | ||
471 | continue; | ||
472 | |||
473 | set_irq_chip_data(irq, chip); | ||
474 | set_irq_chip_and_handler(irq, &max732x_irq_chip, | ||
475 | handle_edge_irq); | ||
476 | set_irq_nested_thread(irq, 1); | ||
477 | #ifdef CONFIG_ARM | ||
478 | set_irq_flags(irq, IRQF_VALID); | ||
479 | #else | ||
480 | set_irq_noprobe(irq); | ||
481 | #endif | ||
482 | } | ||
483 | |||
484 | ret = request_threaded_irq(client->irq, | ||
485 | NULL, | ||
486 | max732x_irq_handler, | ||
487 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
488 | dev_name(&client->dev), chip); | ||
489 | if (ret) { | ||
490 | dev_err(&client->dev, "failed to request irq %d\n", | ||
491 | client->irq); | ||
492 | goto out_failed; | ||
493 | } | ||
494 | |||
495 | chip->gpio_chip.to_irq = max732x_gpio_to_irq; | ||
496 | } | ||
497 | |||
498 | return 0; | ||
499 | |||
500 | out_failed: | ||
501 | chip->irq_base = 0; | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | static void max732x_irq_teardown(struct max732x_chip *chip) | ||
506 | { | ||
507 | if (chip->irq_base) | ||
508 | free_irq(chip->client->irq, chip); | ||
509 | } | ||
510 | #else /* CONFIG_GPIO_MAX732X_IRQ */ | ||
511 | static int max732x_irq_setup(struct max732x_chip *chip, | ||
512 | const struct i2c_device_id *id) | ||
513 | { | ||
514 | struct i2c_client *client = chip->client; | ||
515 | struct max732x_platform_data *pdata = client->dev.platform_data; | ||
516 | int has_irq = max732x_features[id->driver_data] >> 32; | ||
517 | |||
518 | if (pdata->irq_base && has_irq != INT_NONE) | ||
519 | dev_warn(&client->dev, "interrupt support not compiled in\n"); | ||
520 | |||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | static void max732x_irq_teardown(struct max732x_chip *chip) | ||
525 | { | ||
526 | } | ||
527 | #endif | ||
528 | |||
212 | static int __devinit max732x_setup_gpio(struct max732x_chip *chip, | 529 | static int __devinit max732x_setup_gpio(struct max732x_chip *chip, |
213 | const struct i2c_device_id *id, | 530 | const struct i2c_device_id *id, |
214 | unsigned gpio_start) | 531 | unsigned gpio_start) |
215 | { | 532 | { |
216 | struct gpio_chip *gc = &chip->gpio_chip; | 533 | struct gpio_chip *gc = &chip->gpio_chip; |
217 | uint32_t id_data = id->driver_data; | 534 | uint32_t id_data = (uint32_t)max732x_features[id->driver_data]; |
218 | int i, port = 0; | 535 | int i, port = 0; |
219 | 536 | ||
220 | for (i = 0; i < 16; i++, id_data >>= 2) { | 537 | for (i = 0; i < 16; i++, id_data >>= 2) { |
@@ -285,14 +602,14 @@ static int __devinit max732x_probe(struct i2c_client *client, | |||
285 | switch (client->addr & 0x70) { | 602 | switch (client->addr & 0x70) { |
286 | case 0x60: | 603 | case 0x60: |
287 | chip->client_group_a = client; | 604 | chip->client_group_a = client; |
288 | if (nr_port > 7) { | 605 | if (nr_port > 8) { |
289 | c = i2c_new_dummy(client->adapter, addr_b); | 606 | c = i2c_new_dummy(client->adapter, addr_b); |
290 | chip->client_group_b = chip->client_dummy = c; | 607 | chip->client_group_b = chip->client_dummy = c; |
291 | } | 608 | } |
292 | break; | 609 | break; |
293 | case 0x50: | 610 | case 0x50: |
294 | chip->client_group_b = client; | 611 | chip->client_group_b = client; |
295 | if (nr_port > 7) { | 612 | if (nr_port > 8) { |
296 | c = i2c_new_dummy(client->adapter, addr_a); | 613 | c = i2c_new_dummy(client->adapter, addr_a); |
297 | chip->client_group_a = chip->client_dummy = c; | 614 | chip->client_group_a = chip->client_dummy = c; |
298 | } | 615 | } |
@@ -306,9 +623,13 @@ static int __devinit max732x_probe(struct i2c_client *client, | |||
306 | 623 | ||
307 | mutex_init(&chip->lock); | 624 | mutex_init(&chip->lock); |
308 | 625 | ||
309 | max732x_read(chip, is_group_a(chip, 0), &chip->reg_out[0]); | 626 | max732x_readb(chip, is_group_a(chip, 0), &chip->reg_out[0]); |
310 | if (nr_port > 7) | 627 | if (nr_port > 8) |
311 | max732x_read(chip, is_group_a(chip, 8), &chip->reg_out[1]); | 628 | max732x_readb(chip, is_group_a(chip, 8), &chip->reg_out[1]); |
629 | |||
630 | ret = max732x_irq_setup(chip, id); | ||
631 | if (ret) | ||
632 | goto out_failed; | ||
312 | 633 | ||
313 | ret = gpiochip_add(&chip->gpio_chip); | 634 | ret = gpiochip_add(&chip->gpio_chip); |
314 | if (ret) | 635 | if (ret) |
@@ -325,6 +646,7 @@ static int __devinit max732x_probe(struct i2c_client *client, | |||
325 | return 0; | 646 | return 0; |
326 | 647 | ||
327 | out_failed: | 648 | out_failed: |
649 | max732x_irq_teardown(chip); | ||
328 | kfree(chip); | 650 | kfree(chip); |
329 | return ret; | 651 | return ret; |
330 | } | 652 | } |
@@ -352,6 +674,8 @@ static int __devexit max732x_remove(struct i2c_client *client) | |||
352 | return ret; | 674 | return ret; |
353 | } | 675 | } |
354 | 676 | ||
677 | max732x_irq_teardown(chip); | ||
678 | |||
355 | /* unregister any dummy i2c_client */ | 679 | /* unregister any dummy i2c_client */ |
356 | if (chip->client_dummy) | 680 | if (chip->client_dummy) |
357 | i2c_unregister_device(chip->client_dummy); | 681 | i2c_unregister_device(chip->client_dummy); |
diff --git a/drivers/gpio/pca953x.c b/drivers/gpio/pca953x.c index f156ab3bb6ed..a2b12aa1f2b9 100644 --- a/drivers/gpio/pca953x.c +++ b/drivers/gpio/pca953x.c | |||
@@ -73,7 +73,7 @@ struct pca953x_chip { | |||
73 | struct i2c_client *client; | 73 | struct i2c_client *client; |
74 | struct pca953x_platform_data *dyn_pdata; | 74 | struct pca953x_platform_data *dyn_pdata; |
75 | struct gpio_chip gpio_chip; | 75 | struct gpio_chip gpio_chip; |
76 | char **names; | 76 | const char *const *names; |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) | 79 | static int pca953x_write_reg(struct pca953x_chip *chip, int reg, uint16_t val) |
diff --git a/drivers/gpio/pl061.c b/drivers/gpio/pl061.c index 105701a1f05b..ee568c8fcbd0 100644 --- a/drivers/gpio/pl061.c +++ b/drivers/gpio/pl061.c | |||
@@ -164,7 +164,7 @@ static int pl061_irq_type(unsigned irq, unsigned trigger) | |||
164 | unsigned long flags; | 164 | unsigned long flags; |
165 | u8 gpiois, gpioibe, gpioiev; | 165 | u8 gpiois, gpioibe, gpioiev; |
166 | 166 | ||
167 | if (offset < 0 || offset > PL061_GPIO_NR) | 167 | if (offset < 0 || offset >= PL061_GPIO_NR) |
168 | return -EINVAL; | 168 | return -EINVAL; |
169 | 169 | ||
170 | spin_lock_irqsave(&chip->irq_lock, flags); | 170 | spin_lock_irqsave(&chip->irq_lock, flags); |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index f569ae88ab38..c1981861bbbd 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -147,7 +147,10 @@ drm_edid_block_valid(u8 *raw_edid) | |||
147 | csum += raw_edid[i]; | 147 | csum += raw_edid[i]; |
148 | if (csum) { | 148 | if (csum) { |
149 | DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); | 149 | DRM_ERROR("EDID checksum is invalid, remainder is %d\n", csum); |
150 | goto bad; | 150 | |
151 | /* allow CEA to slide through, switches mangle this */ | ||
152 | if (raw_edid[0] != 0x02) | ||
153 | goto bad; | ||
151 | } | 154 | } |
152 | 155 | ||
153 | /* per-block-type checks */ | 156 | /* per-block-type checks */ |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7e663a79829f..266b0ff441af 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -241,7 +241,8 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
241 | if (nv_encoder && nv_connector->native_mode) { | 241 | if (nv_encoder && nv_connector->native_mode) { |
242 | unsigned status = connector_status_connected; | 242 | unsigned status = connector_status_connected; |
243 | 243 | ||
244 | #ifdef CONFIG_ACPI | 244 | #if defined(CONFIG_ACPI_BUTTON) || \ |
245 | (defined(CONFIG_ACPI_BUTTON_MODULE) && defined(MODULE)) | ||
245 | if (!nouveau_ignorelid && !acpi_lid_open()) | 246 | if (!nouveau_ignorelid && !acpi_lid_open()) |
246 | status = connector_status_unknown; | 247 | status = connector_status_unknown; |
247 | #endif | 248 | #endif |
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 0616c96e4b67..704a25d04ac9 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c | |||
@@ -253,7 +253,11 @@ nv40_graph_init(struct drm_device *dev) | |||
253 | 253 | ||
254 | if (!dev_priv->engine.graph.ctxprog) { | 254 | if (!dev_priv->engine.graph.ctxprog) { |
255 | struct nouveau_grctx ctx = {}; | 255 | struct nouveau_grctx ctx = {}; |
256 | uint32_t cp[256]; | 256 | uint32_t *cp; |
257 | |||
258 | cp = kmalloc(sizeof(*cp) * 256, GFP_KERNEL); | ||
259 | if (!cp) | ||
260 | return -ENOMEM; | ||
257 | 261 | ||
258 | ctx.dev = dev; | 262 | ctx.dev = dev; |
259 | ctx.mode = NOUVEAU_GRCTX_PROG; | 263 | ctx.mode = NOUVEAU_GRCTX_PROG; |
@@ -265,6 +269,8 @@ nv40_graph_init(struct drm_device *dev) | |||
265 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); | 269 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_INDEX, 0); |
266 | for (i = 0; i < ctx.ctxprog_len; i++) | 270 | for (i = 0; i < ctx.ctxprog_len; i++) |
267 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); | 271 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_UCODE_DATA, cp[i]); |
272 | |||
273 | kfree(cp); | ||
268 | } | 274 | } |
269 | 275 | ||
270 | /* No context present currently */ | 276 | /* No context present currently */ |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 03dd6c41dc19..f3f2827017ef 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -707,6 +707,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode | |||
707 | break; | 707 | break; |
708 | case ATOM_DCPLL: | 708 | case ATOM_DCPLL: |
709 | case ATOM_PPLL_INVALID: | 709 | case ATOM_PPLL_INVALID: |
710 | default: | ||
710 | pll = &rdev->clock.dcpll; | 711 | pll = &rdev->clock.dcpll; |
711 | break; | 712 | break; |
712 | } | 713 | } |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 66a37fb75839..669feb689bfc 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -576,6 +576,7 @@ typedef int (*radeon_packet3_check_t)(struct radeon_cs_parser *p, | |||
576 | */ | 576 | */ |
577 | int radeon_agp_init(struct radeon_device *rdev); | 577 | int radeon_agp_init(struct radeon_device *rdev); |
578 | void radeon_agp_resume(struct radeon_device *rdev); | 578 | void radeon_agp_resume(struct radeon_device *rdev); |
579 | void radeon_agp_suspend(struct radeon_device *rdev); | ||
579 | void radeon_agp_fini(struct radeon_device *rdev); | 580 | void radeon_agp_fini(struct radeon_device *rdev); |
580 | 581 | ||
581 | 582 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 28e473f1f56f..f40dfb77f9b1 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c | |||
@@ -270,3 +270,8 @@ void radeon_agp_fini(struct radeon_device *rdev) | |||
270 | } | 270 | } |
271 | #endif | 271 | #endif |
272 | } | 272 | } |
273 | |||
274 | void radeon_agp_suspend(struct radeon_device *rdev) | ||
275 | { | ||
276 | radeon_agp_fini(rdev); | ||
277 | } | ||
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 6e733fdc3349..24ea683f7cf5 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c | |||
@@ -680,10 +680,18 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
680 | uint8_t dac; | 680 | uint8_t dac; |
681 | union atom_supported_devices *supported_devices; | 681 | union atom_supported_devices *supported_devices; |
682 | int i, j, max_device; | 682 | int i, j, max_device; |
683 | struct bios_connector bios_connectors[ATOM_MAX_SUPPORTED_DEVICE]; | 683 | struct bios_connector *bios_connectors; |
684 | size_t bc_size = sizeof(*bios_connectors) * ATOM_MAX_SUPPORTED_DEVICE; | ||
684 | 685 | ||
685 | if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, &data_offset)) | 686 | bios_connectors = kzalloc(bc_size, GFP_KERNEL); |
687 | if (!bios_connectors) | ||
688 | return false; | ||
689 | |||
690 | if (!atom_parse_data_header(ctx, index, &size, &frev, &crev, | ||
691 | &data_offset)) { | ||
692 | kfree(bios_connectors); | ||
686 | return false; | 693 | return false; |
694 | } | ||
687 | 695 | ||
688 | supported_devices = | 696 | supported_devices = |
689 | (union atom_supported_devices *)(ctx->bios + data_offset); | 697 | (union atom_supported_devices *)(ctx->bios + data_offset); |
@@ -851,6 +859,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct | |||
851 | 859 | ||
852 | radeon_link_encoder_connector(dev); | 860 | radeon_link_encoder_connector(dev); |
853 | 861 | ||
862 | kfree(bios_connectors); | ||
854 | return true; | 863 | return true; |
855 | } | 864 | } |
856 | 865 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index a20b612ffe75..fdc3fdf78acb 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -754,6 +754,8 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state) | |||
754 | /* evict remaining vram memory */ | 754 | /* evict remaining vram memory */ |
755 | radeon_bo_evict_vram(rdev); | 755 | radeon_bo_evict_vram(rdev); |
756 | 756 | ||
757 | radeon_agp_suspend(rdev); | ||
758 | |||
757 | pci_save_state(dev->pdev); | 759 | pci_save_state(dev->pdev); |
758 | if (state.event == PM_EVENT_SUSPEND) { | 760 | if (state.event == PM_EVENT_SUSPEND) { |
759 | /* Shut down the device */ | 761 | /* Shut down the device */ |
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 76ba59b9fea1..132278fa6240 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -347,6 +347,14 @@ config HID_QUANTA | |||
347 | ---help--- | 347 | ---help--- |
348 | Support for Quanta Optical Touch dual-touch panels. | 348 | Support for Quanta Optical Touch dual-touch panels. |
349 | 349 | ||
350 | config HID_ROCCAT | ||
351 | tristate "Roccat special event support" | ||
352 | depends on USB_HID | ||
353 | ---help--- | ||
354 | Support for Roccat special events. | ||
355 | Say Y here if you have a Roccat mouse or keyboard and want OSD or | ||
356 | macro execution support. | ||
357 | |||
350 | config HID_ROCCAT_KONE | 358 | config HID_ROCCAT_KONE |
351 | tristate "Roccat Kone Mouse support" | 359 | tristate "Roccat Kone Mouse support" |
352 | depends on USB_HID | 360 | depends on USB_HID |
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 22e47eaeea32..987fa0627367 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile | |||
@@ -48,6 +48,7 @@ obj-$(CONFIG_HID_QUANTA) += hid-quanta.o | |||
48 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o | 48 | obj-$(CONFIG_HID_PANTHERLORD) += hid-pl.o |
49 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o | 49 | obj-$(CONFIG_HID_PETALYNX) += hid-petalynx.o |
50 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o | 50 | obj-$(CONFIG_HID_PICOLCD) += hid-picolcd.o |
51 | obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o | ||
51 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o | 52 | obj-$(CONFIG_HID_ROCCAT_KONE) += hid-roccat-kone.o |
52 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o | 53 | obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o |
53 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o | 54 | obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e10e314d38cc..aa0f7dcabcd7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -1301,6 +1301,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
1301 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, | 1301 | { HID_USB_DEVICE(USB_VENDOR_ID_GREENASIA, 0x0012) }, |
1302 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 1302 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
1303 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 1303 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
1304 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | ||
1304 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, | 1305 | { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, |
1305 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, | 1306 | { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) }, |
1306 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, | 1307 | { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) }, |
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 56f314fbd4f9..c94026768570 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c | |||
@@ -811,7 +811,7 @@ static const char *relatives[REL_MAX + 1] = { | |||
811 | [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", | 811 | [REL_WHEEL] = "Wheel", [REL_MISC] = "Misc", |
812 | }; | 812 | }; |
813 | 813 | ||
814 | static const char *absolutes[ABS_MAX + 1] = { | 814 | static const char *absolutes[ABS_CNT] = { |
815 | [ABS_X] = "X", [ABS_Y] = "Y", | 815 | [ABS_X] = "X", [ABS_Y] = "Y", |
816 | [ABS_Z] = "Z", [ABS_RX] = "Rx", | 816 | [ABS_Z] = "Z", [ABS_RX] = "Rx", |
817 | [ABS_RY] = "Ry", [ABS_RZ] = "Rz", | 817 | [ABS_RY] = "Ry", [ABS_RZ] = "Rz", |
diff --git a/drivers/hid/hid-gyration.c b/drivers/hid/hid-gyration.c index 62416e6baeca..3975e039c3dd 100644 --- a/drivers/hid/hid-gyration.c +++ b/drivers/hid/hid-gyration.c | |||
@@ -73,6 +73,7 @@ static int gyration_event(struct hid_device *hdev, struct hid_field *field, | |||
73 | static const struct hid_device_id gyration_devices[] = { | 73 | static const struct hid_device_id gyration_devices[] = { |
74 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, | 74 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) }, |
75 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, | 75 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, |
76 | { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, | ||
76 | { } | 77 | { } |
77 | }; | 78 | }; |
78 | MODULE_DEVICE_TABLE(hid, gyration_devices); | 79 | MODULE_DEVICE_TABLE(hid, gyration_devices); |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9776896cc4fc..6af77ed0b555 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -282,6 +282,7 @@ | |||
282 | #define USB_VENDOR_ID_GYRATION 0x0c16 | 282 | #define USB_VENDOR_ID_GYRATION 0x0c16 |
283 | #define USB_DEVICE_ID_GYRATION_REMOTE 0x0002 | 283 | #define USB_DEVICE_ID_GYRATION_REMOTE 0x0002 |
284 | #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003 | 284 | #define USB_DEVICE_ID_GYRATION_REMOTE_2 0x0003 |
285 | #define USB_DEVICE_ID_GYRATION_REMOTE_3 0x0008 | ||
285 | 286 | ||
286 | #define USB_VENDOR_ID_HAPP 0x078b | 287 | #define USB_VENDOR_ID_HAPP 0x078b |
287 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 | 288 | #define USB_DEVICE_ID_UGCI_DRIVING 0x0010 |
diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 66e694054ba2..17f2dc04f883 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include "hid-ids.h" | 39 | #include "hid-ids.h" |
40 | #include "hid-roccat.h" | ||
40 | #include "hid-roccat-kone.h" | 41 | #include "hid-roccat-kone.h" |
41 | 42 | ||
42 | static void kone_set_settings_checksum(struct kone_settings *settings) | 43 | static void kone_set_settings_checksum(struct kone_settings *settings) |
@@ -263,7 +264,7 @@ static int kone_get_firmware_version(struct usb_device *usb_dev, int *result) | |||
263 | return 0; | 264 | return 0; |
264 | } | 265 | } |
265 | 266 | ||
266 | static ssize_t kone_sysfs_read_settings(struct kobject *kobj, | 267 | static ssize_t kone_sysfs_read_settings(struct file *fp, struct kobject *kobj, |
267 | struct bin_attribute *attr, char *buf, | 268 | struct bin_attribute *attr, char *buf, |
268 | loff_t off, size_t count) { | 269 | loff_t off, size_t count) { |
269 | struct device *dev = container_of(kobj, struct device, kobj); | 270 | struct device *dev = container_of(kobj, struct device, kobj); |
@@ -287,7 +288,7 @@ static ssize_t kone_sysfs_read_settings(struct kobject *kobj, | |||
287 | * This function keeps values in kone_device up to date and assumes that in | 288 | * This function keeps values in kone_device up to date and assumes that in |
288 | * case of error the old data is still valid | 289 | * case of error the old data is still valid |
289 | */ | 290 | */ |
290 | static ssize_t kone_sysfs_write_settings(struct kobject *kobj, | 291 | static ssize_t kone_sysfs_write_settings(struct file *fp, struct kobject *kobj, |
291 | struct bin_attribute *attr, char *buf, | 292 | struct bin_attribute *attr, char *buf, |
292 | loff_t off, size_t count) { | 293 | loff_t off, size_t count) { |
293 | struct device *dev = container_of(kobj, struct device, kobj); | 294 | struct device *dev = container_of(kobj, struct device, kobj); |
@@ -342,31 +343,31 @@ static ssize_t kone_sysfs_read_profilex(struct kobject *kobj, | |||
342 | return count; | 343 | return count; |
343 | } | 344 | } |
344 | 345 | ||
345 | static ssize_t kone_sysfs_read_profile1(struct kobject *kobj, | 346 | static ssize_t kone_sysfs_read_profile1(struct file *fp, struct kobject *kobj, |
346 | struct bin_attribute *attr, char *buf, | 347 | struct bin_attribute *attr, char *buf, |
347 | loff_t off, size_t count) { | 348 | loff_t off, size_t count) { |
348 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1); | 349 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 1); |
349 | } | 350 | } |
350 | 351 | ||
351 | static ssize_t kone_sysfs_read_profile2(struct kobject *kobj, | 352 | static ssize_t kone_sysfs_read_profile2(struct file *fp, struct kobject *kobj, |
352 | struct bin_attribute *attr, char *buf, | 353 | struct bin_attribute *attr, char *buf, |
353 | loff_t off, size_t count) { | 354 | loff_t off, size_t count) { |
354 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2); | 355 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 2); |
355 | } | 356 | } |
356 | 357 | ||
357 | static ssize_t kone_sysfs_read_profile3(struct kobject *kobj, | 358 | static ssize_t kone_sysfs_read_profile3(struct file *fp, struct kobject *kobj, |
358 | struct bin_attribute *attr, char *buf, | 359 | struct bin_attribute *attr, char *buf, |
359 | loff_t off, size_t count) { | 360 | loff_t off, size_t count) { |
360 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3); | 361 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 3); |
361 | } | 362 | } |
362 | 363 | ||
363 | static ssize_t kone_sysfs_read_profile4(struct kobject *kobj, | 364 | static ssize_t kone_sysfs_read_profile4(struct file *fp, struct kobject *kobj, |
364 | struct bin_attribute *attr, char *buf, | 365 | struct bin_attribute *attr, char *buf, |
365 | loff_t off, size_t count) { | 366 | loff_t off, size_t count) { |
366 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4); | 367 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 4); |
367 | } | 368 | } |
368 | 369 | ||
369 | static ssize_t kone_sysfs_read_profile5(struct kobject *kobj, | 370 | static ssize_t kone_sysfs_read_profile5(struct file *fp, struct kobject *kobj, |
370 | struct bin_attribute *attr, char *buf, | 371 | struct bin_attribute *attr, char *buf, |
371 | loff_t off, size_t count) { | 372 | loff_t off, size_t count) { |
372 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5); | 373 | return kone_sysfs_read_profilex(kobj, attr, buf, off, count, 5); |
@@ -404,31 +405,31 @@ static ssize_t kone_sysfs_write_profilex(struct kobject *kobj, | |||
404 | return sizeof(struct kone_profile); | 405 | return sizeof(struct kone_profile); |
405 | } | 406 | } |
406 | 407 | ||
407 | static ssize_t kone_sysfs_write_profile1(struct kobject *kobj, | 408 | static ssize_t kone_sysfs_write_profile1(struct file *fp, struct kobject *kobj, |
408 | struct bin_attribute *attr, char *buf, | 409 | struct bin_attribute *attr, char *buf, |
409 | loff_t off, size_t count) { | 410 | loff_t off, size_t count) { |
410 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1); | 411 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 1); |
411 | } | 412 | } |
412 | 413 | ||
413 | static ssize_t kone_sysfs_write_profile2(struct kobject *kobj, | 414 | static ssize_t kone_sysfs_write_profile2(struct file *fp, struct kobject *kobj, |
414 | struct bin_attribute *attr, char *buf, | 415 | struct bin_attribute *attr, char *buf, |
415 | loff_t off, size_t count) { | 416 | loff_t off, size_t count) { |
416 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2); | 417 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 2); |
417 | } | 418 | } |
418 | 419 | ||
419 | static ssize_t kone_sysfs_write_profile3(struct kobject *kobj, | 420 | static ssize_t kone_sysfs_write_profile3(struct file *fp, struct kobject *kobj, |
420 | struct bin_attribute *attr, char *buf, | 421 | struct bin_attribute *attr, char *buf, |
421 | loff_t off, size_t count) { | 422 | loff_t off, size_t count) { |
422 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3); | 423 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 3); |
423 | } | 424 | } |
424 | 425 | ||
425 | static ssize_t kone_sysfs_write_profile4(struct kobject *kobj, | 426 | static ssize_t kone_sysfs_write_profile4(struct file *fp, struct kobject *kobj, |
426 | struct bin_attribute *attr, char *buf, | 427 | struct bin_attribute *attr, char *buf, |
427 | loff_t off, size_t count) { | 428 | loff_t off, size_t count) { |
428 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4); | 429 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 4); |
429 | } | 430 | } |
430 | 431 | ||
431 | static ssize_t kone_sysfs_write_profile5(struct kobject *kobj, | 432 | static ssize_t kone_sysfs_write_profile5(struct file *fp, struct kobject *kobj, |
432 | struct bin_attribute *attr, char *buf, | 433 | struct bin_attribute *attr, char *buf, |
433 | loff_t off, size_t count) { | 434 | loff_t off, size_t count) { |
434 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5); | 435 | return kone_sysfs_write_profilex(kobj, attr, buf, off, count, 5); |
@@ -849,6 +850,16 @@ static int kone_init_specials(struct hid_device *hdev) | |||
849 | "couldn't init struct kone_device\n"); | 850 | "couldn't init struct kone_device\n"); |
850 | goto exit_free; | 851 | goto exit_free; |
851 | } | 852 | } |
853 | |||
854 | retval = roccat_connect(hdev); | ||
855 | if (retval < 0) { | ||
856 | dev_err(&hdev->dev, "couldn't init char dev\n"); | ||
857 | /* be tolerant about not getting chrdev */ | ||
858 | } else { | ||
859 | kone->roccat_claimed = 1; | ||
860 | kone->chrdev_minor = retval; | ||
861 | } | ||
862 | |||
852 | retval = kone_create_sysfs_attributes(intf); | 863 | retval = kone_create_sysfs_attributes(intf); |
853 | if (retval) { | 864 | if (retval) { |
854 | dev_err(&hdev->dev, "cannot create sysfs files\n"); | 865 | dev_err(&hdev->dev, "cannot create sysfs files\n"); |
@@ -868,10 +879,14 @@ exit_free: | |||
868 | static void kone_remove_specials(struct hid_device *hdev) | 879 | static void kone_remove_specials(struct hid_device *hdev) |
869 | { | 880 | { |
870 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); | 881 | struct usb_interface *intf = to_usb_interface(hdev->dev.parent); |
882 | struct kone_device *kone; | ||
871 | 883 | ||
872 | if (intf->cur_altsetting->desc.bInterfaceProtocol | 884 | if (intf->cur_altsetting->desc.bInterfaceProtocol |
873 | == USB_INTERFACE_PROTOCOL_MOUSE) { | 885 | == USB_INTERFACE_PROTOCOL_MOUSE) { |
874 | kone_remove_sysfs_attributes(intf); | 886 | kone_remove_sysfs_attributes(intf); |
887 | kone = hid_get_drvdata(hdev); | ||
888 | if (kone->roccat_claimed) | ||
889 | roccat_disconnect(kone->chrdev_minor); | ||
875 | kfree(hid_get_drvdata(hdev)); | 890 | kfree(hid_get_drvdata(hdev)); |
876 | } | 891 | } |
877 | } | 892 | } |
@@ -930,6 +945,37 @@ static void kone_keep_values_up_to_date(struct kone_device *kone, | |||
930 | } | 945 | } |
931 | } | 946 | } |
932 | 947 | ||
948 | static void kone_report_to_chrdev(struct kone_device const *kone, | ||
949 | struct kone_mouse_event const *event) | ||
950 | { | ||
951 | struct kone_roccat_report roccat_report; | ||
952 | |||
953 | switch (event->event) { | ||
954 | case kone_mouse_event_switch_profile: | ||
955 | case kone_mouse_event_switch_dpi: | ||
956 | case kone_mouse_event_osd_profile: | ||
957 | case kone_mouse_event_osd_dpi: | ||
958 | roccat_report.event = event->event; | ||
959 | roccat_report.value = event->value; | ||
960 | roccat_report.key = 0; | ||
961 | roccat_report_event(kone->chrdev_minor, | ||
962 | (uint8_t *)&roccat_report, | ||
963 | sizeof(struct kone_roccat_report)); | ||
964 | break; | ||
965 | case kone_mouse_event_call_overlong_macro: | ||
966 | if (event->value == kone_keystroke_action_press) { | ||
967 | roccat_report.event = kone_mouse_event_call_overlong_macro; | ||
968 | roccat_report.value = kone->actual_profile; | ||
969 | roccat_report.key = event->macro_key; | ||
970 | roccat_report_event(kone->chrdev_minor, | ||
971 | (uint8_t *)&roccat_report, | ||
972 | sizeof(struct kone_roccat_report)); | ||
973 | } | ||
974 | break; | ||
975 | } | ||
976 | |||
977 | } | ||
978 | |||
933 | /* | 979 | /* |
934 | * Is called for keyboard- and mousepart. | 980 | * Is called for keyboard- and mousepart. |
935 | * Only mousepart gets informations about special events in its extended event | 981 | * Only mousepart gets informations about special events in its extended event |
@@ -958,6 +1004,9 @@ static int kone_raw_event(struct hid_device *hdev, struct hid_report *report, | |||
958 | 1004 | ||
959 | kone_keep_values_up_to_date(kone, event); | 1005 | kone_keep_values_up_to_date(kone, event); |
960 | 1006 | ||
1007 | if (kone->roccat_claimed) | ||
1008 | kone_report_to_chrdev(kone, event); | ||
1009 | |||
961 | return 0; /* always do further processing */ | 1010 | return 0; /* always do further processing */ |
962 | } | 1011 | } |
963 | 1012 | ||
diff --git a/drivers/hid/hid-roccat-kone.h b/drivers/hid/hid-roccat-kone.h index b413b10a7f8a..003e6f81c195 100644 --- a/drivers/hid/hid-roccat-kone.h +++ b/drivers/hid/hid-roccat-kone.h | |||
@@ -189,6 +189,12 @@ enum kone_commands { | |||
189 | kone_command_firmware = 0xe5a | 189 | kone_command_firmware = 0xe5a |
190 | }; | 190 | }; |
191 | 191 | ||
192 | struct kone_roccat_report { | ||
193 | uint8_t event; | ||
194 | uint8_t value; /* holds dpi or profile value */ | ||
195 | uint8_t key; /* macro key on overlong macro execution */ | ||
196 | }; | ||
197 | |||
192 | #pragma pack(pop) | 198 | #pragma pack(pop) |
193 | 199 | ||
194 | struct kone_device { | 200 | struct kone_device { |
@@ -219,6 +225,9 @@ struct kone_device { | |||
219 | * so it's read only once | 225 | * so it's read only once |
220 | */ | 226 | */ |
221 | int firmware_version; | 227 | int firmware_version; |
228 | |||
229 | int roccat_claimed; | ||
230 | int chrdev_minor; | ||
222 | }; | 231 | }; |
223 | 232 | ||
224 | #endif | 233 | #endif |
diff --git a/drivers/hid/hid-roccat.c b/drivers/hid/hid-roccat.c new file mode 100644 index 000000000000..e05d48edb66f --- /dev/null +++ b/drivers/hid/hid-roccat.c | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * Roccat driver for Linux | ||
3 | * | ||
4 | * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
5 | */ | ||
6 | |||
7 | /* | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the Free | ||
10 | * Software Foundation; either version 2 of the License, or (at your option) | ||
11 | * any later version. | ||
12 | */ | ||
13 | |||
14 | /* | ||
15 | * Module roccat is a char device used to report special events of roccat | ||
16 | * hardware to userland. These events include requests for on-screen-display of | ||
17 | * profile or dpi settings or requests for execution of macro sequences that are | ||
18 | * not stored in device. The information in these events depends on hid device | ||
19 | * implementation and contains data that is not available in a single hid event | ||
20 | * or else hidraw could have been used. | ||
21 | * It is inspired by hidraw, but uses only one circular buffer for all readers. | ||
22 | */ | ||
23 | |||
24 | #include <linux/cdev.h> | ||
25 | #include <linux/poll.h> | ||
26 | #include <linux/sched.h> | ||
27 | |||
28 | #include "hid-roccat.h" | ||
29 | |||
30 | #define ROCCAT_FIRST_MINOR 0 | ||
31 | #define ROCCAT_MAX_DEVICES 8 | ||
32 | |||
33 | /* should be a power of 2 for performance reason */ | ||
34 | #define ROCCAT_CBUF_SIZE 16 | ||
35 | |||
36 | struct roccat_report { | ||
37 | uint8_t *value; | ||
38 | int len; | ||
39 | }; | ||
40 | |||
41 | struct roccat_device { | ||
42 | unsigned int minor; | ||
43 | int open; | ||
44 | int exist; | ||
45 | wait_queue_head_t wait; | ||
46 | struct device *dev; | ||
47 | struct hid_device *hid; | ||
48 | struct list_head readers; | ||
49 | /* protects modifications of readers list */ | ||
50 | struct mutex readers_lock; | ||
51 | |||
52 | /* | ||
53 | * circular_buffer has one writer and multiple readers with their own | ||
54 | * read pointers | ||
55 | */ | ||
56 | struct roccat_report cbuf[ROCCAT_CBUF_SIZE]; | ||
57 | int cbuf_end; | ||
58 | struct mutex cbuf_lock; | ||
59 | }; | ||
60 | |||
61 | struct roccat_reader { | ||
62 | struct list_head node; | ||
63 | struct roccat_device *device; | ||
64 | int cbuf_start; | ||
65 | }; | ||
66 | |||
67 | static int roccat_major; | ||
68 | static struct class *roccat_class; | ||
69 | static struct cdev roccat_cdev; | ||
70 | |||
71 | static struct roccat_device *devices[ROCCAT_MAX_DEVICES]; | ||
72 | /* protects modifications of devices array */ | ||
73 | static DEFINE_MUTEX(devices_lock); | ||
74 | |||
75 | static ssize_t roccat_read(struct file *file, char __user *buffer, | ||
76 | size_t count, loff_t *ppos) | ||
77 | { | ||
78 | struct roccat_reader *reader = file->private_data; | ||
79 | struct roccat_device *device = reader->device; | ||
80 | struct roccat_report *report; | ||
81 | ssize_t retval = 0, len; | ||
82 | DECLARE_WAITQUEUE(wait, current); | ||
83 | |||
84 | mutex_lock(&device->cbuf_lock); | ||
85 | |||
86 | /* no data? */ | ||
87 | if (reader->cbuf_start == device->cbuf_end) { | ||
88 | add_wait_queue(&device->wait, &wait); | ||
89 | set_current_state(TASK_INTERRUPTIBLE); | ||
90 | |||
91 | /* wait for data */ | ||
92 | while (reader->cbuf_start == device->cbuf_end) { | ||
93 | if (file->f_flags & O_NONBLOCK) { | ||
94 | retval = -EAGAIN; | ||
95 | break; | ||
96 | } | ||
97 | if (signal_pending(current)) { | ||
98 | retval = -ERESTARTSYS; | ||
99 | break; | ||
100 | } | ||
101 | if (!device->exist) { | ||
102 | retval = -EIO; | ||
103 | break; | ||
104 | } | ||
105 | |||
106 | mutex_unlock(&device->cbuf_lock); | ||
107 | schedule(); | ||
108 | mutex_lock(&device->cbuf_lock); | ||
109 | set_current_state(TASK_INTERRUPTIBLE); | ||
110 | } | ||
111 | |||
112 | set_current_state(TASK_RUNNING); | ||
113 | remove_wait_queue(&device->wait, &wait); | ||
114 | } | ||
115 | |||
116 | /* here we either have data or a reason to return if retval is set */ | ||
117 | if (retval) | ||
118 | goto exit_unlock; | ||
119 | |||
120 | report = &device->cbuf[reader->cbuf_start]; | ||
121 | /* | ||
122 | * If report is larger than requested amount of data, rest of report | ||
123 | * is lost! | ||
124 | */ | ||
125 | len = report->len > count ? count : report->len; | ||
126 | |||
127 | if (copy_to_user(buffer, report->value, len)) { | ||
128 | retval = -EFAULT; | ||
129 | goto exit_unlock; | ||
130 | } | ||
131 | retval += len; | ||
132 | reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE; | ||
133 | |||
134 | exit_unlock: | ||
135 | mutex_unlock(&device->cbuf_lock); | ||
136 | return retval; | ||
137 | } | ||
138 | |||
139 | static unsigned int roccat_poll(struct file *file, poll_table *wait) | ||
140 | { | ||
141 | struct roccat_reader *reader = file->private_data; | ||
142 | poll_wait(file, &reader->device->wait, wait); | ||
143 | if (reader->cbuf_start != reader->device->cbuf_end) | ||
144 | return POLLIN | POLLRDNORM; | ||
145 | if (!reader->device->exist) | ||
146 | return POLLERR | POLLHUP; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | static int roccat_open(struct inode *inode, struct file *file) | ||
151 | { | ||
152 | unsigned int minor = iminor(inode); | ||
153 | struct roccat_reader *reader; | ||
154 | struct roccat_device *device; | ||
155 | int error = 0; | ||
156 | |||
157 | reader = kzalloc(sizeof(struct roccat_reader), GFP_KERNEL); | ||
158 | if (!reader) | ||
159 | return -ENOMEM; | ||
160 | |||
161 | mutex_lock(&devices_lock); | ||
162 | |||
163 | device = devices[minor]; | ||
164 | |||
165 | mutex_lock(&device->readers_lock); | ||
166 | |||
167 | if (!device) { | ||
168 | printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", | ||
169 | minor); | ||
170 | error = -ENODEV; | ||
171 | goto exit_unlock; | ||
172 | } | ||
173 | |||
174 | if (!device->open++) { | ||
175 | /* power on device on adding first reader */ | ||
176 | if (device->hid->ll_driver->power) { | ||
177 | error = device->hid->ll_driver->power(device->hid, | ||
178 | PM_HINT_FULLON); | ||
179 | if (error < 0) { | ||
180 | --device->open; | ||
181 | goto exit_unlock; | ||
182 | } | ||
183 | } | ||
184 | error = device->hid->ll_driver->open(device->hid); | ||
185 | if (error < 0) { | ||
186 | if (device->hid->ll_driver->power) | ||
187 | device->hid->ll_driver->power(device->hid, | ||
188 | PM_HINT_NORMAL); | ||
189 | --device->open; | ||
190 | goto exit_unlock; | ||
191 | } | ||
192 | } | ||
193 | |||
194 | reader->device = device; | ||
195 | /* new reader doesn't get old events */ | ||
196 | reader->cbuf_start = device->cbuf_end; | ||
197 | |||
198 | list_add_tail(&reader->node, &device->readers); | ||
199 | file->private_data = reader; | ||
200 | |||
201 | exit_unlock: | ||
202 | mutex_unlock(&device->readers_lock); | ||
203 | mutex_unlock(&devices_lock); | ||
204 | return error; | ||
205 | } | ||
206 | |||
207 | static int roccat_release(struct inode *inode, struct file *file) | ||
208 | { | ||
209 | unsigned int minor = iminor(inode); | ||
210 | struct roccat_reader *reader = file->private_data; | ||
211 | struct roccat_device *device; | ||
212 | |||
213 | mutex_lock(&devices_lock); | ||
214 | |||
215 | device = devices[minor]; | ||
216 | if (!device) { | ||
217 | mutex_unlock(&devices_lock); | ||
218 | printk(KERN_EMERG "roccat device with minor %d doesn't exist\n", | ||
219 | minor); | ||
220 | return -ENODEV; | ||
221 | } | ||
222 | |||
223 | mutex_lock(&device->readers_lock); | ||
224 | list_del(&reader->node); | ||
225 | mutex_unlock(&device->readers_lock); | ||
226 | kfree(reader); | ||
227 | |||
228 | if (!--device->open) { | ||
229 | /* removing last reader */ | ||
230 | if (device->exist) { | ||
231 | if (device->hid->ll_driver->power) | ||
232 | device->hid->ll_driver->power(device->hid, | ||
233 | PM_HINT_NORMAL); | ||
234 | device->hid->ll_driver->close(device->hid); | ||
235 | } else { | ||
236 | kfree(device); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | mutex_unlock(&devices_lock); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | /* | ||
246 | * roccat_report_event() - output data to readers | ||
247 | * @minor: minor device number returned by roccat_connect() | ||
248 | * @data: pointer to data | ||
249 | * @len: size of data | ||
250 | * | ||
251 | * Return value is zero on success, a negative error code on failure. | ||
252 | * | ||
253 | * This is called from interrupt handler. | ||
254 | */ | ||
255 | int roccat_report_event(int minor, u8 const *data, int len) | ||
256 | { | ||
257 | struct roccat_device *device; | ||
258 | struct roccat_reader *reader; | ||
259 | struct roccat_report *report; | ||
260 | uint8_t *new_value; | ||
261 | |||
262 | new_value = kmemdup(data, len, GFP_ATOMIC); | ||
263 | if (!new_value) | ||
264 | return -ENOMEM; | ||
265 | |||
266 | device = devices[minor]; | ||
267 | |||
268 | report = &device->cbuf[device->cbuf_end]; | ||
269 | |||
270 | /* passing NULL is safe */ | ||
271 | kfree(report->value); | ||
272 | |||
273 | report->value = new_value; | ||
274 | report->len = len; | ||
275 | device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE; | ||
276 | |||
277 | list_for_each_entry(reader, &device->readers, node) { | ||
278 | /* | ||
279 | * As we already inserted one element, the buffer can't be | ||
280 | * empty. If start and end are equal, buffer is full and we | ||
281 | * increase start, so that slow reader misses one event, but | ||
282 | * gets the newer ones in the right order. | ||
283 | */ | ||
284 | if (reader->cbuf_start == device->cbuf_end) | ||
285 | reader->cbuf_start = (reader->cbuf_start + 1) % ROCCAT_CBUF_SIZE; | ||
286 | } | ||
287 | |||
288 | wake_up_interruptible(&device->wait); | ||
289 | return 0; | ||
290 | } | ||
291 | EXPORT_SYMBOL_GPL(roccat_report_event); | ||
292 | |||
293 | /* | ||
294 | * roccat_connect() - create a char device for special event output | ||
295 | * @hid: the hid device the char device should be connected to. | ||
296 | * | ||
297 | * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on | ||
298 | * success, a negative error code on failure. | ||
299 | */ | ||
300 | int roccat_connect(struct hid_device *hid) | ||
301 | { | ||
302 | unsigned int minor; | ||
303 | struct roccat_device *device; | ||
304 | int temp; | ||
305 | |||
306 | device = kzalloc(sizeof(struct roccat_device), GFP_KERNEL); | ||
307 | if (!device) | ||
308 | return -ENOMEM; | ||
309 | |||
310 | mutex_lock(&devices_lock); | ||
311 | |||
312 | for (minor = 0; minor < ROCCAT_MAX_DEVICES; ++minor) { | ||
313 | if (devices[minor]) | ||
314 | continue; | ||
315 | break; | ||
316 | } | ||
317 | |||
318 | if (minor < ROCCAT_MAX_DEVICES) { | ||
319 | devices[minor] = device; | ||
320 | } else { | ||
321 | mutex_unlock(&devices_lock); | ||
322 | kfree(device); | ||
323 | return -EINVAL; | ||
324 | } | ||
325 | |||
326 | device->dev = device_create(roccat_class, &hid->dev, | ||
327 | MKDEV(roccat_major, minor), NULL, | ||
328 | "%s%s%d", "roccat", hid->driver->name, minor); | ||
329 | |||
330 | if (IS_ERR(device->dev)) { | ||
331 | devices[minor] = NULL; | ||
332 | mutex_unlock(&devices_lock); | ||
333 | temp = PTR_ERR(device->dev); | ||
334 | kfree(device); | ||
335 | return temp; | ||
336 | } | ||
337 | |||
338 | mutex_unlock(&devices_lock); | ||
339 | |||
340 | init_waitqueue_head(&device->wait); | ||
341 | INIT_LIST_HEAD(&device->readers); | ||
342 | mutex_init(&device->readers_lock); | ||
343 | mutex_init(&device->cbuf_lock); | ||
344 | device->minor = minor; | ||
345 | device->hid = hid; | ||
346 | device->exist = 1; | ||
347 | device->cbuf_end = 0; | ||
348 | |||
349 | return minor; | ||
350 | } | ||
351 | EXPORT_SYMBOL_GPL(roccat_connect); | ||
352 | |||
353 | /* roccat_disconnect() - remove char device from hid device | ||
354 | * @minor: the minor device number returned by roccat_connect() | ||
355 | */ | ||
356 | void roccat_disconnect(int minor) | ||
357 | { | ||
358 | struct roccat_device *device; | ||
359 | |||
360 | mutex_lock(&devices_lock); | ||
361 | device = devices[minor]; | ||
362 | devices[minor] = NULL; | ||
363 | mutex_unlock(&devices_lock); | ||
364 | |||
365 | device->exist = 0; /* TODO exist maybe not needed */ | ||
366 | |||
367 | device_destroy(roccat_class, MKDEV(roccat_major, minor)); | ||
368 | |||
369 | if (device->open) { | ||
370 | device->hid->ll_driver->close(device->hid); | ||
371 | wake_up_interruptible(&device->wait); | ||
372 | } else { | ||
373 | kfree(device); | ||
374 | } | ||
375 | } | ||
376 | EXPORT_SYMBOL_GPL(roccat_disconnect); | ||
377 | |||
378 | static const struct file_operations roccat_ops = { | ||
379 | .owner = THIS_MODULE, | ||
380 | .read = roccat_read, | ||
381 | .poll = roccat_poll, | ||
382 | .open = roccat_open, | ||
383 | .release = roccat_release, | ||
384 | }; | ||
385 | |||
386 | static int __init roccat_init(void) | ||
387 | { | ||
388 | int retval; | ||
389 | dev_t dev_id; | ||
390 | |||
391 | retval = alloc_chrdev_region(&dev_id, ROCCAT_FIRST_MINOR, | ||
392 | ROCCAT_MAX_DEVICES, "roccat"); | ||
393 | |||
394 | roccat_major = MAJOR(dev_id); | ||
395 | |||
396 | if (retval < 0) { | ||
397 | printk(KERN_WARNING "roccat: can't get major number\n"); | ||
398 | return retval; | ||
399 | } | ||
400 | |||
401 | roccat_class = class_create(THIS_MODULE, "roccat"); | ||
402 | if (IS_ERR(roccat_class)) { | ||
403 | retval = PTR_ERR(roccat_class); | ||
404 | unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); | ||
405 | return retval; | ||
406 | } | ||
407 | |||
408 | cdev_init(&roccat_cdev, &roccat_ops); | ||
409 | cdev_add(&roccat_cdev, dev_id, ROCCAT_MAX_DEVICES); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static void __exit roccat_exit(void) | ||
415 | { | ||
416 | dev_t dev_id = MKDEV(roccat_major, 0); | ||
417 | |||
418 | cdev_del(&roccat_cdev); | ||
419 | class_destroy(roccat_class); | ||
420 | unregister_chrdev_region(dev_id, ROCCAT_MAX_DEVICES); | ||
421 | } | ||
422 | |||
423 | module_init(roccat_init); | ||
424 | module_exit(roccat_exit); | ||
425 | |||
426 | MODULE_AUTHOR("Stefan Achatz"); | ||
427 | MODULE_DESCRIPTION("USB Roccat char device"); | ||
428 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hid/hid-roccat.h b/drivers/hid/hid-roccat.h new file mode 100644 index 000000000000..d8aae0c1fa7e --- /dev/null +++ b/drivers/hid/hid-roccat.h | |||
@@ -0,0 +1,31 @@ | |||
1 | #ifndef __HID_ROCCAT_H | ||
2 | #define __HID_ROCCAT_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.net> | ||
6 | */ | ||
7 | |||
8 | /* | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/hid.h> | ||
16 | #include <linux/types.h> | ||
17 | |||
18 | #if defined(CONFIG_HID_ROCCAT) || defined (CONFIG_HID_ROCCAT_MODULE) | ||
19 | int roccat_connect(struct hid_device *hid); | ||
20 | void roccat_disconnect(int minor); | ||
21 | int roccat_report_event(int minor, u8 const *data, int len); | ||
22 | #else | ||
23 | static inline int roccat_connect(struct hid_device *hid) { return -1; } | ||
24 | static inline void roccat_disconnect(int minor) {} | ||
25 | static inline int roccat_report_event(int minor, u8 const *data, int len) | ||
26 | { | ||
27 | return 0; | ||
28 | } | ||
29 | #endif | ||
30 | |||
31 | #endif | ||
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 6a9ac754ca5d..e19cf8eb6ccf 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -447,13 +447,14 @@ config SENSORS_IT87 | |||
447 | will be called it87. | 447 | will be called it87. |
448 | 448 | ||
449 | config SENSORS_LM63 | 449 | config SENSORS_LM63 |
450 | tristate "National Semiconductor LM63" | 450 | tristate "National Semiconductor LM63 and LM64" |
451 | depends on I2C | 451 | depends on I2C |
452 | help | 452 | help |
453 | If you say yes here you get support for the National Semiconductor | 453 | If you say yes here you get support for the National |
454 | LM63 remote diode digital temperature sensor with integrated fan | 454 | Semiconductor LM63 and LM64 remote diode digital temperature |
455 | control. Such chips are found on the Tyan S4882 (Thunder K8QS Pro) | 455 | sensors with integrated fan control. Such chips are found |
456 | motherboard, among others. | 456 | on the Tyan S4882 (Thunder K8QS Pro) motherboard, among |
457 | others. | ||
457 | 458 | ||
458 | This driver can also be built as a module. If so, the module | 459 | This driver can also be built as a module. If so, the module |
459 | will be called lm63. | 460 | will be called lm63. |
@@ -492,7 +493,8 @@ config SENSORS_LM75 | |||
492 | - NXP's LM75A | 493 | - NXP's LM75A |
493 | - ST Microelectronics STDS75 | 494 | - ST Microelectronics STDS75 |
494 | - TelCom (now Microchip) TCN75 | 495 | - TelCom (now Microchip) TCN75 |
495 | - Texas Instruments TMP100, TMP101, TMP75, TMP175, TMP275 | 496 | - Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, |
497 | TMP275 | ||
496 | 498 | ||
497 | This driver supports driver model based binding through board | 499 | This driver supports driver model based binding through board |
498 | specific I2C device tables. | 500 | specific I2C device tables. |
@@ -749,6 +751,16 @@ config SENSORS_DME1737 | |||
749 | This driver can also be built as a module. If so, the module | 751 | This driver can also be built as a module. If so, the module |
750 | will be called dme1737. | 752 | will be called dme1737. |
751 | 753 | ||
754 | config SENSORS_EMC1403 | ||
755 | tristate "SMSC EMC1403 thermal sensor" | ||
756 | depends on I2C | ||
757 | help | ||
758 | If you say yes here you get support for the SMSC EMC1403 | ||
759 | temperature monitoring chip. | ||
760 | |||
761 | Threshold values can be configured using sysfs. | ||
762 | Data from the different diodes are accessible via sysfs. | ||
763 | |||
752 | config SENSORS_SMSC47M1 | 764 | config SENSORS_SMSC47M1 |
753 | tristate "SMSC LPC47M10x and compatibles" | 765 | tristate "SMSC LPC47M10x and compatibles" |
754 | help | 766 | help |
@@ -831,6 +843,16 @@ config SENSORS_THMC50 | |||
831 | This driver can also be built as a module. If so, the module | 843 | This driver can also be built as a module. If so, the module |
832 | will be called thmc50. | 844 | will be called thmc50. |
833 | 845 | ||
846 | config SENSORS_TMP102 | ||
847 | tristate "Texas Instruments TMP102" | ||
848 | depends on I2C && EXPERIMENTAL | ||
849 | help | ||
850 | If you say yes here you get support for Texas Instruments TMP102 | ||
851 | sensor chips. | ||
852 | |||
853 | This driver can also be built as a module. If so, the module | ||
854 | will be called tmp102. | ||
855 | |||
834 | config SENSORS_TMP401 | 856 | config SENSORS_TMP401 |
835 | tristate "Texas Instruments TMP401 and compatibles" | 857 | tristate "Texas Instruments TMP401 and compatibles" |
836 | depends on I2C && EXPERIMENTAL | 858 | depends on I2C && EXPERIMENTAL |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 86920fb34118..2138ceb1a713 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o | |||
41 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o | 41 | obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o |
42 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o | 42 | obj-$(CONFIG_SENSORS_DME1737) += dme1737.o |
43 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o | 43 | obj-$(CONFIG_SENSORS_DS1621) += ds1621.o |
44 | obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o | ||
44 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o | 45 | obj-$(CONFIG_SENSORS_F71805F) += f71805f.o |
45 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o | 46 | obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o |
46 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o | 47 | obj-$(CONFIG_SENSORS_F75375S) += f75375s.o |
@@ -90,6 +91,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o | |||
90 | obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o | 91 | obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o |
91 | obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o | 92 | obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o |
92 | obj-$(CONFIG_SENSORS_THMC50) += thmc50.o | 93 | obj-$(CONFIG_SENSORS_THMC50) += thmc50.o |
94 | obj-$(CONFIG_SENSORS_TMP102) += tmp102.o | ||
93 | obj-$(CONFIG_SENSORS_TMP401) += tmp401.o | 95 | obj-$(CONFIG_SENSORS_TMP401) += tmp401.o |
94 | obj-$(CONFIG_SENSORS_TMP421) += tmp421.o | 96 | obj-$(CONFIG_SENSORS_TMP421) += tmp421.o |
95 | obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o | 97 | obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o |
diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 1644b92e7cc4..15c1a9616af3 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) | 36 | #define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) |
37 | #define ADM1031_REG_PWM (0x22) | 37 | #define ADM1031_REG_PWM (0x22) |
38 | #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) | 38 | #define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) |
39 | #define ADM1031_REG_FAN_FILTER (0x23) | ||
39 | 40 | ||
40 | #define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) | 41 | #define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) |
41 | #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) | 42 | #define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) |
@@ -61,6 +62,9 @@ | |||
61 | #define ADM1031_CONF2_TACH2_ENABLE 0x08 | 62 | #define ADM1031_CONF2_TACH2_ENABLE 0x08 |
62 | #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) | 63 | #define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) |
63 | 64 | ||
65 | #define ADM1031_UPDATE_RATE_MASK 0x1c | ||
66 | #define ADM1031_UPDATE_RATE_SHIFT 2 | ||
67 | |||
64 | /* Addresses to scan */ | 68 | /* Addresses to scan */ |
65 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; | 69 | static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; |
66 | 70 | ||
@@ -75,6 +79,7 @@ struct adm1031_data { | |||
75 | int chip_type; | 79 | int chip_type; |
76 | char valid; /* !=0 if following fields are valid */ | 80 | char valid; /* !=0 if following fields are valid */ |
77 | unsigned long last_updated; /* In jiffies */ | 81 | unsigned long last_updated; /* In jiffies */ |
82 | unsigned int update_rate; /* In milliseconds */ | ||
78 | /* The chan_select_table contains the possible configurations for | 83 | /* The chan_select_table contains the possible configurations for |
79 | * auto fan control. | 84 | * auto fan control. |
80 | */ | 85 | */ |
@@ -738,6 +743,57 @@ static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); | |||
738 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); | 743 | static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); |
739 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); | 744 | static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); |
740 | 745 | ||
746 | /* Update Rate */ | ||
747 | static const unsigned int update_rates[] = { | ||
748 | 16000, 8000, 4000, 2000, 1000, 500, 250, 125, | ||
749 | }; | ||
750 | |||
751 | static ssize_t show_update_rate(struct device *dev, | ||
752 | struct device_attribute *attr, char *buf) | ||
753 | { | ||
754 | struct i2c_client *client = to_i2c_client(dev); | ||
755 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
756 | |||
757 | return sprintf(buf, "%u\n", data->update_rate); | ||
758 | } | ||
759 | |||
760 | static ssize_t set_update_rate(struct device *dev, | ||
761 | struct device_attribute *attr, | ||
762 | const char *buf, size_t count) | ||
763 | { | ||
764 | struct i2c_client *client = to_i2c_client(dev); | ||
765 | struct adm1031_data *data = i2c_get_clientdata(client); | ||
766 | unsigned long val; | ||
767 | int i, err; | ||
768 | u8 reg; | ||
769 | |||
770 | err = strict_strtoul(buf, 10, &val); | ||
771 | if (err) | ||
772 | return err; | ||
773 | |||
774 | /* find the nearest update rate from the table */ | ||
775 | for (i = 0; i < ARRAY_SIZE(update_rates) - 1; i++) { | ||
776 | if (val >= update_rates[i]) | ||
777 | break; | ||
778 | } | ||
779 | /* if not found, we point to the last entry (lowest update rate) */ | ||
780 | |||
781 | /* set the new update rate while preserving other settings */ | ||
782 | reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); | ||
783 | reg &= ~ADM1031_UPDATE_RATE_MASK; | ||
784 | reg |= i << ADM1031_UPDATE_RATE_SHIFT; | ||
785 | adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); | ||
786 | |||
787 | mutex_lock(&data->update_lock); | ||
788 | data->update_rate = update_rates[i]; | ||
789 | mutex_unlock(&data->update_lock); | ||
790 | |||
791 | return count; | ||
792 | } | ||
793 | |||
794 | static DEVICE_ATTR(update_rate, S_IRUGO | S_IWUSR, show_update_rate, | ||
795 | set_update_rate); | ||
796 | |||
741 | static struct attribute *adm1031_attributes[] = { | 797 | static struct attribute *adm1031_attributes[] = { |
742 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 798 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
743 | &sensor_dev_attr_fan1_div.dev_attr.attr, | 799 | &sensor_dev_attr_fan1_div.dev_attr.attr, |
@@ -774,6 +830,7 @@ static struct attribute *adm1031_attributes[] = { | |||
774 | 830 | ||
775 | &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, | 831 | &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, |
776 | 832 | ||
833 | &dev_attr_update_rate.attr, | ||
777 | &dev_attr_alarms.attr, | 834 | &dev_attr_alarms.attr, |
778 | 835 | ||
779 | NULL | 836 | NULL |
@@ -900,6 +957,7 @@ static void adm1031_init_client(struct i2c_client *client) | |||
900 | { | 957 | { |
901 | unsigned int read_val; | 958 | unsigned int read_val; |
902 | unsigned int mask; | 959 | unsigned int mask; |
960 | int i; | ||
903 | struct adm1031_data *data = i2c_get_clientdata(client); | 961 | struct adm1031_data *data = i2c_get_clientdata(client); |
904 | 962 | ||
905 | mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); | 963 | mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); |
@@ -919,18 +977,24 @@ static void adm1031_init_client(struct i2c_client *client) | |||
919 | ADM1031_CONF1_MONITOR_ENABLE); | 977 | ADM1031_CONF1_MONITOR_ENABLE); |
920 | } | 978 | } |
921 | 979 | ||
980 | /* Read the chip's update rate */ | ||
981 | mask = ADM1031_UPDATE_RATE_MASK; | ||
982 | read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); | ||
983 | i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; | ||
984 | data->update_rate = update_rates[i]; | ||
922 | } | 985 | } |
923 | 986 | ||
924 | static struct adm1031_data *adm1031_update_device(struct device *dev) | 987 | static struct adm1031_data *adm1031_update_device(struct device *dev) |
925 | { | 988 | { |
926 | struct i2c_client *client = to_i2c_client(dev); | 989 | struct i2c_client *client = to_i2c_client(dev); |
927 | struct adm1031_data *data = i2c_get_clientdata(client); | 990 | struct adm1031_data *data = i2c_get_clientdata(client); |
991 | unsigned long next_update; | ||
928 | int chan; | 992 | int chan; |
929 | 993 | ||
930 | mutex_lock(&data->update_lock); | 994 | mutex_lock(&data->update_lock); |
931 | 995 | ||
932 | if (time_after(jiffies, data->last_updated + HZ + HZ / 2) | 996 | next_update = data->last_updated + msecs_to_jiffies(data->update_rate); |
933 | || !data->valid) { | 997 | if (time_after(jiffies, next_update) || !data->valid) { |
934 | 998 | ||
935 | dev_dbg(&client->dev, "Starting adm1031 update\n"); | 999 | dev_dbg(&client->dev, "Starting adm1031 update\n"); |
936 | for (chan = 0; | 1000 | for (chan = 0; |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index f085c18d2905..b6598aa557a0 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
@@ -148,6 +148,20 @@ static const char *temperature_sensors_sets[][41] = { | |||
148 | /* Set 18: MacBook Pro 2,2 */ | 148 | /* Set 18: MacBook Pro 2,2 */ |
149 | { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0", | 149 | { "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "TM0P", "TTF0", |
150 | "Th0H", "Th1H", "Tm0P", "Ts0P", NULL }, | 150 | "Th0H", "Th1H", "Tm0P", "Ts0P", NULL }, |
151 | /* Set 19: Macbook Pro 5,3 */ | ||
152 | { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TG0D", | ||
153 | "TG0F", "TG0H", "TG0P", "TG0T", "TN0D", "TN0P", "TTF0", "Th2H", | ||
154 | "Tm0P", "Ts0P", "Ts0S", NULL }, | ||
155 | /* Set 20: MacBook Pro 5,4 */ | ||
156 | { "TB0T", "TB1T", "TB2T", "TB3T", "TC0D", "TC0F", "TC0P", "TN0D", | ||
157 | "TN0P", "TTF0", "Th2H", "Ts0P", "Ts0S", NULL }, | ||
158 | /* Set 21: MacBook Pro 6,2 */ | ||
159 | { "TB0T", "TB1T", "TB2T", "TC0C", "TC0D", "TC0P", "TC1C", "TG0D", | ||
160 | "TG0P", "TG0T", "TMCD", "TP0P", "TPCD", "Th1H", "Th2H", "Tm0P", | ||
161 | "Ts0P", "Ts0S", NULL }, | ||
162 | /* Set 22: MacBook Pro 7,1 */ | ||
163 | { "TB0T", "TB1T", "TB2T", "TC0D", "TC0P", "TN0D", "TN0P", "TN0S", | ||
164 | "TN1D", "TN1F", "TN1G", "TN1S", "Th1H", "Ts0P", "Ts0S", NULL }, | ||
151 | }; | 165 | }; |
152 | 166 | ||
153 | /* List of keys used to read/write fan speeds */ | 167 | /* List of keys used to read/write fan speeds */ |
@@ -646,6 +660,17 @@ out: | |||
646 | return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right); | 660 | return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right); |
647 | } | 661 | } |
648 | 662 | ||
663 | /* Displays sensor key as label */ | ||
664 | static ssize_t applesmc_show_sensor_label(struct device *dev, | ||
665 | struct device_attribute *devattr, char *sysfsbuf) | ||
666 | { | ||
667 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
668 | const char *key = | ||
669 | temperature_sensors_sets[applesmc_temperature_set][attr->index]; | ||
670 | |||
671 | return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", key); | ||
672 | } | ||
673 | |||
649 | /* Displays degree Celsius * 1000 */ | 674 | /* Displays degree Celsius * 1000 */ |
650 | static ssize_t applesmc_show_temperature(struct device *dev, | 675 | static ssize_t applesmc_show_temperature(struct device *dev, |
651 | struct device_attribute *devattr, char *sysfsbuf) | 676 | struct device_attribute *devattr, char *sysfsbuf) |
@@ -1113,6 +1138,86 @@ static const struct attribute_group fan_attribute_groups[] = { | |||
1113 | /* | 1138 | /* |
1114 | * Temperature sensors sysfs entries. | 1139 | * Temperature sensors sysfs entries. |
1115 | */ | 1140 | */ |
1141 | static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, | ||
1142 | applesmc_show_sensor_label, NULL, 0); | ||
1143 | static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, | ||
1144 | applesmc_show_sensor_label, NULL, 1); | ||
1145 | static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, | ||
1146 | applesmc_show_sensor_label, NULL, 2); | ||
1147 | static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, | ||
1148 | applesmc_show_sensor_label, NULL, 3); | ||
1149 | static SENSOR_DEVICE_ATTR(temp5_label, S_IRUGO, | ||
1150 | applesmc_show_sensor_label, NULL, 4); | ||
1151 | static SENSOR_DEVICE_ATTR(temp6_label, S_IRUGO, | ||
1152 | applesmc_show_sensor_label, NULL, 5); | ||
1153 | static SENSOR_DEVICE_ATTR(temp7_label, S_IRUGO, | ||
1154 | applesmc_show_sensor_label, NULL, 6); | ||
1155 | static SENSOR_DEVICE_ATTR(temp8_label, S_IRUGO, | ||
1156 | applesmc_show_sensor_label, NULL, 7); | ||
1157 | static SENSOR_DEVICE_ATTR(temp9_label, S_IRUGO, | ||
1158 | applesmc_show_sensor_label, NULL, 8); | ||
1159 | static SENSOR_DEVICE_ATTR(temp10_label, S_IRUGO, | ||
1160 | applesmc_show_sensor_label, NULL, 9); | ||
1161 | static SENSOR_DEVICE_ATTR(temp11_label, S_IRUGO, | ||
1162 | applesmc_show_sensor_label, NULL, 10); | ||
1163 | static SENSOR_DEVICE_ATTR(temp12_label, S_IRUGO, | ||
1164 | applesmc_show_sensor_label, NULL, 11); | ||
1165 | static SENSOR_DEVICE_ATTR(temp13_label, S_IRUGO, | ||
1166 | applesmc_show_sensor_label, NULL, 12); | ||
1167 | static SENSOR_DEVICE_ATTR(temp14_label, S_IRUGO, | ||
1168 | applesmc_show_sensor_label, NULL, 13); | ||
1169 | static SENSOR_DEVICE_ATTR(temp15_label, S_IRUGO, | ||
1170 | applesmc_show_sensor_label, NULL, 14); | ||
1171 | static SENSOR_DEVICE_ATTR(temp16_label, S_IRUGO, | ||
1172 | applesmc_show_sensor_label, NULL, 15); | ||
1173 | static SENSOR_DEVICE_ATTR(temp17_label, S_IRUGO, | ||
1174 | applesmc_show_sensor_label, NULL, 16); | ||
1175 | static SENSOR_DEVICE_ATTR(temp18_label, S_IRUGO, | ||
1176 | applesmc_show_sensor_label, NULL, 17); | ||
1177 | static SENSOR_DEVICE_ATTR(temp19_label, S_IRUGO, | ||
1178 | applesmc_show_sensor_label, NULL, 18); | ||
1179 | static SENSOR_DEVICE_ATTR(temp20_label, S_IRUGO, | ||
1180 | applesmc_show_sensor_label, NULL, 19); | ||
1181 | static SENSOR_DEVICE_ATTR(temp21_label, S_IRUGO, | ||
1182 | applesmc_show_sensor_label, NULL, 20); | ||
1183 | static SENSOR_DEVICE_ATTR(temp22_label, S_IRUGO, | ||
1184 | applesmc_show_sensor_label, NULL, 21); | ||
1185 | static SENSOR_DEVICE_ATTR(temp23_label, S_IRUGO, | ||
1186 | applesmc_show_sensor_label, NULL, 22); | ||
1187 | static SENSOR_DEVICE_ATTR(temp24_label, S_IRUGO, | ||
1188 | applesmc_show_sensor_label, NULL, 23); | ||
1189 | static SENSOR_DEVICE_ATTR(temp25_label, S_IRUGO, | ||
1190 | applesmc_show_sensor_label, NULL, 24); | ||
1191 | static SENSOR_DEVICE_ATTR(temp26_label, S_IRUGO, | ||
1192 | applesmc_show_sensor_label, NULL, 25); | ||
1193 | static SENSOR_DEVICE_ATTR(temp27_label, S_IRUGO, | ||
1194 | applesmc_show_sensor_label, NULL, 26); | ||
1195 | static SENSOR_DEVICE_ATTR(temp28_label, S_IRUGO, | ||
1196 | applesmc_show_sensor_label, NULL, 27); | ||
1197 | static SENSOR_DEVICE_ATTR(temp29_label, S_IRUGO, | ||
1198 | applesmc_show_sensor_label, NULL, 28); | ||
1199 | static SENSOR_DEVICE_ATTR(temp30_label, S_IRUGO, | ||
1200 | applesmc_show_sensor_label, NULL, 29); | ||
1201 | static SENSOR_DEVICE_ATTR(temp31_label, S_IRUGO, | ||
1202 | applesmc_show_sensor_label, NULL, 30); | ||
1203 | static SENSOR_DEVICE_ATTR(temp32_label, S_IRUGO, | ||
1204 | applesmc_show_sensor_label, NULL, 31); | ||
1205 | static SENSOR_DEVICE_ATTR(temp33_label, S_IRUGO, | ||
1206 | applesmc_show_sensor_label, NULL, 32); | ||
1207 | static SENSOR_DEVICE_ATTR(temp34_label, S_IRUGO, | ||
1208 | applesmc_show_sensor_label, NULL, 33); | ||
1209 | static SENSOR_DEVICE_ATTR(temp35_label, S_IRUGO, | ||
1210 | applesmc_show_sensor_label, NULL, 34); | ||
1211 | static SENSOR_DEVICE_ATTR(temp36_label, S_IRUGO, | ||
1212 | applesmc_show_sensor_label, NULL, 35); | ||
1213 | static SENSOR_DEVICE_ATTR(temp37_label, S_IRUGO, | ||
1214 | applesmc_show_sensor_label, NULL, 36); | ||
1215 | static SENSOR_DEVICE_ATTR(temp38_label, S_IRUGO, | ||
1216 | applesmc_show_sensor_label, NULL, 37); | ||
1217 | static SENSOR_DEVICE_ATTR(temp39_label, S_IRUGO, | ||
1218 | applesmc_show_sensor_label, NULL, 38); | ||
1219 | static SENSOR_DEVICE_ATTR(temp40_label, S_IRUGO, | ||
1220 | applesmc_show_sensor_label, NULL, 39); | ||
1116 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, | 1221 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, |
1117 | applesmc_show_temperature, NULL, 0); | 1222 | applesmc_show_temperature, NULL, 0); |
1118 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, | 1223 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, |
@@ -1194,6 +1299,50 @@ static SENSOR_DEVICE_ATTR(temp39_input, S_IRUGO, | |||
1194 | static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO, | 1299 | static SENSOR_DEVICE_ATTR(temp40_input, S_IRUGO, |
1195 | applesmc_show_temperature, NULL, 39); | 1300 | applesmc_show_temperature, NULL, 39); |
1196 | 1301 | ||
1302 | static struct attribute *label_attributes[] = { | ||
1303 | &sensor_dev_attr_temp1_label.dev_attr.attr, | ||
1304 | &sensor_dev_attr_temp2_label.dev_attr.attr, | ||
1305 | &sensor_dev_attr_temp3_label.dev_attr.attr, | ||
1306 | &sensor_dev_attr_temp4_label.dev_attr.attr, | ||
1307 | &sensor_dev_attr_temp5_label.dev_attr.attr, | ||
1308 | &sensor_dev_attr_temp6_label.dev_attr.attr, | ||
1309 | &sensor_dev_attr_temp7_label.dev_attr.attr, | ||
1310 | &sensor_dev_attr_temp8_label.dev_attr.attr, | ||
1311 | &sensor_dev_attr_temp9_label.dev_attr.attr, | ||
1312 | &sensor_dev_attr_temp10_label.dev_attr.attr, | ||
1313 | &sensor_dev_attr_temp11_label.dev_attr.attr, | ||
1314 | &sensor_dev_attr_temp12_label.dev_attr.attr, | ||
1315 | &sensor_dev_attr_temp13_label.dev_attr.attr, | ||
1316 | &sensor_dev_attr_temp14_label.dev_attr.attr, | ||
1317 | &sensor_dev_attr_temp15_label.dev_attr.attr, | ||
1318 | &sensor_dev_attr_temp16_label.dev_attr.attr, | ||
1319 | &sensor_dev_attr_temp17_label.dev_attr.attr, | ||
1320 | &sensor_dev_attr_temp18_label.dev_attr.attr, | ||
1321 | &sensor_dev_attr_temp19_label.dev_attr.attr, | ||
1322 | &sensor_dev_attr_temp20_label.dev_attr.attr, | ||
1323 | &sensor_dev_attr_temp21_label.dev_attr.attr, | ||
1324 | &sensor_dev_attr_temp22_label.dev_attr.attr, | ||
1325 | &sensor_dev_attr_temp23_label.dev_attr.attr, | ||
1326 | &sensor_dev_attr_temp24_label.dev_attr.attr, | ||
1327 | &sensor_dev_attr_temp25_label.dev_attr.attr, | ||
1328 | &sensor_dev_attr_temp26_label.dev_attr.attr, | ||
1329 | &sensor_dev_attr_temp27_label.dev_attr.attr, | ||
1330 | &sensor_dev_attr_temp28_label.dev_attr.attr, | ||
1331 | &sensor_dev_attr_temp29_label.dev_attr.attr, | ||
1332 | &sensor_dev_attr_temp30_label.dev_attr.attr, | ||
1333 | &sensor_dev_attr_temp31_label.dev_attr.attr, | ||
1334 | &sensor_dev_attr_temp32_label.dev_attr.attr, | ||
1335 | &sensor_dev_attr_temp33_label.dev_attr.attr, | ||
1336 | &sensor_dev_attr_temp34_label.dev_attr.attr, | ||
1337 | &sensor_dev_attr_temp35_label.dev_attr.attr, | ||
1338 | &sensor_dev_attr_temp36_label.dev_attr.attr, | ||
1339 | &sensor_dev_attr_temp37_label.dev_attr.attr, | ||
1340 | &sensor_dev_attr_temp38_label.dev_attr.attr, | ||
1341 | &sensor_dev_attr_temp39_label.dev_attr.attr, | ||
1342 | &sensor_dev_attr_temp40_label.dev_attr.attr, | ||
1343 | NULL | ||
1344 | }; | ||
1345 | |||
1197 | static struct attribute *temperature_attributes[] = { | 1346 | static struct attribute *temperature_attributes[] = { |
1198 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 1347 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
1199 | &sensor_dev_attr_temp2_input.dev_attr.attr, | 1348 | &sensor_dev_attr_temp2_input.dev_attr.attr, |
@@ -1241,6 +1390,10 @@ static struct attribute *temperature_attributes[] = { | |||
1241 | static const struct attribute_group temperature_attributes_group = | 1390 | static const struct attribute_group temperature_attributes_group = |
1242 | { .attrs = temperature_attributes }; | 1391 | { .attrs = temperature_attributes }; |
1243 | 1392 | ||
1393 | static const struct attribute_group label_attributes_group = { | ||
1394 | .attrs = label_attributes | ||
1395 | }; | ||
1396 | |||
1244 | /* Module stuff */ | 1397 | /* Module stuff */ |
1245 | 1398 | ||
1246 | /* | 1399 | /* |
@@ -1363,6 +1516,14 @@ static __initdata struct dmi_match_data applesmc_dmi_data[] = { | |||
1363 | { .accelerometer = 0, .light = 0, .temperature_set = 17 }, | 1516 | { .accelerometer = 0, .light = 0, .temperature_set = 17 }, |
1364 | /* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */ | 1517 | /* MacBook Pro 2,2: accelerometer, backlight and temperature set 18 */ |
1365 | { .accelerometer = 1, .light = 1, .temperature_set = 18 }, | 1518 | { .accelerometer = 1, .light = 1, .temperature_set = 18 }, |
1519 | /* MacBook Pro 5,3: accelerometer, backlight and temperature set 19 */ | ||
1520 | { .accelerometer = 1, .light = 1, .temperature_set = 19 }, | ||
1521 | /* MacBook Pro 5,4: accelerometer, backlight and temperature set 20 */ | ||
1522 | { .accelerometer = 1, .light = 1, .temperature_set = 20 }, | ||
1523 | /* MacBook Pro 6,2: accelerometer, backlight and temperature set 21 */ | ||
1524 | { .accelerometer = 1, .light = 1, .temperature_set = 21 }, | ||
1525 | /* MacBook Pro 7,1: accelerometer, backlight and temperature set 22 */ | ||
1526 | { .accelerometer = 1, .light = 1, .temperature_set = 22 }, | ||
1366 | }; | 1527 | }; |
1367 | 1528 | ||
1368 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". | 1529 | /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". |
@@ -1376,6 +1537,22 @@ static __initdata struct dmi_system_id applesmc_whitelist[] = { | |||
1376 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1537 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
1377 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, | 1538 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, |
1378 | &applesmc_dmi_data[7]}, | 1539 | &applesmc_dmi_data[7]}, |
1540 | { applesmc_dmi_match, "Apple MacBook Pro 7", { | ||
1541 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1542 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro7") }, | ||
1543 | &applesmc_dmi_data[22]}, | ||
1544 | { applesmc_dmi_match, "Apple MacBook Pro 5,4", { | ||
1545 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1546 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,4") }, | ||
1547 | &applesmc_dmi_data[20]}, | ||
1548 | { applesmc_dmi_match, "Apple MacBook Pro 5,3", { | ||
1549 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1550 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5,3") }, | ||
1551 | &applesmc_dmi_data[19]}, | ||
1552 | { applesmc_dmi_match, "Apple MacBook Pro 6", { | ||
1553 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | ||
1554 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6") }, | ||
1555 | &applesmc_dmi_data[21]}, | ||
1379 | { applesmc_dmi_match, "Apple MacBook Pro 5", { | 1556 | { applesmc_dmi_match, "Apple MacBook Pro 5", { |
1380 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), | 1557 | DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), |
1381 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") }, | 1558 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro5") }, |
@@ -1518,7 +1695,8 @@ static int __init applesmc_init(void) | |||
1518 | for (i = 0; | 1695 | for (i = 0; |
1519 | temperature_sensors_sets[applesmc_temperature_set][i] != NULL; | 1696 | temperature_sensors_sets[applesmc_temperature_set][i] != NULL; |
1520 | i++) { | 1697 | i++) { |
1521 | if (temperature_attributes[i] == NULL) { | 1698 | if (temperature_attributes[i] == NULL || |
1699 | label_attributes[i] == NULL) { | ||
1522 | printk(KERN_ERR "applesmc: More temperature sensors " | 1700 | printk(KERN_ERR "applesmc: More temperature sensors " |
1523 | "in temperature_sensors_sets (at least %i)" | 1701 | "in temperature_sensors_sets (at least %i)" |
1524 | "than available sysfs files in " | 1702 | "than available sysfs files in " |
@@ -1530,6 +1708,10 @@ static int __init applesmc_init(void) | |||
1530 | temperature_attributes[i]); | 1708 | temperature_attributes[i]); |
1531 | if (ret) | 1709 | if (ret) |
1532 | goto out_temperature; | 1710 | goto out_temperature; |
1711 | ret = sysfs_create_file(&pdev->dev.kobj, | ||
1712 | label_attributes[i]); | ||
1713 | if (ret) | ||
1714 | goto out_temperature; | ||
1533 | } | 1715 | } |
1534 | 1716 | ||
1535 | if (applesmc_accelerometer) { | 1717 | if (applesmc_accelerometer) { |
@@ -1580,6 +1762,7 @@ out_accelerometer: | |||
1580 | if (applesmc_accelerometer) | 1762 | if (applesmc_accelerometer) |
1581 | applesmc_release_accelerometer(); | 1763 | applesmc_release_accelerometer(); |
1582 | out_temperature: | 1764 | out_temperature: |
1765 | sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group); | ||
1583 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); | 1766 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); |
1584 | out_fans: | 1767 | out_fans: |
1585 | while (fans_handled) | 1768 | while (fans_handled) |
@@ -1609,6 +1792,7 @@ static void __exit applesmc_exit(void) | |||
1609 | } | 1792 | } |
1610 | if (applesmc_accelerometer) | 1793 | if (applesmc_accelerometer) |
1611 | applesmc_release_accelerometer(); | 1794 | applesmc_release_accelerometer(); |
1795 | sysfs_remove_group(&pdev->dev.kobj, &label_attributes_group); | ||
1612 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); | 1796 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); |
1613 | while (fans_handled) | 1797 | while (fans_handled) |
1614 | sysfs_remove_group(&pdev->dev.kobj, | 1798 | sysfs_remove_group(&pdev->dev.kobj, |
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 16c420240724..653db1bda934 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c | |||
@@ -1411,6 +1411,13 @@ static int __init atk0110_init(void) | |||
1411 | { | 1411 | { |
1412 | int ret; | 1412 | int ret; |
1413 | 1413 | ||
1414 | /* Make sure it's safe to access the device through ACPI */ | ||
1415 | if (!acpi_resources_are_enforced()) { | ||
1416 | pr_err("atk: Resources not safely usable due to " | ||
1417 | "acpi_enforce_resources kernel parameter\n"); | ||
1418 | return -EBUSY; | ||
1419 | } | ||
1420 | |||
1414 | ret = acpi_bus_register_driver(&atk_driver); | 1421 | ret = acpi_bus_register_driver(&atk_driver); |
1415 | if (ret) | 1422 | if (ret) |
1416 | pr_info("atk: acpi_bus_register_driver failed: %d\n", ret); | 1423 | pr_info("atk: acpi_bus_register_driver failed: %d\n", ret); |
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index 823dd28a902c..980c17d5eeae 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c | |||
@@ -1,12 +1,14 @@ | |||
1 | /* | 1 | /* |
2 | * dme1737.c - Driver for the SMSC DME1737, Asus A8000, SMSC SCH311x and | 2 | * dme1737.c - Driver for the SMSC DME1737, Asus A8000, SMSC SCH311x, SCH5027, |
3 | * SCH5027 Super-I/O chips integrated hardware monitoring features. | 3 | * and SCH5127 Super-I/O chips integrated hardware monitoring |
4 | * Copyright (c) 2007, 2008 Juerg Haefliger <juergh@gmail.com> | 4 | * features. |
5 | * Copyright (c) 2007, 2008, 2009, 2010 Juerg Haefliger <juergh@gmail.com> | ||
5 | * | 6 | * |
6 | * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access | 7 | * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access |
7 | * the chip registers if a DME1737, A8000, or SCH5027 is found and the ISA bus | 8 | * the chip registers if a DME1737, A8000, or SCH5027 is found and the ISA bus |
8 | * if a SCH311x chip is found. Both types of chips have very similar hardware | 9 | * if a SCH311x or SCH5127 chip is found. Both types of chips have very |
9 | * monitoring capabilities but differ in the way they can be accessed. | 10 | * similar hardware monitoring capabilities but differ in the way they can be |
11 | * accessed. | ||
10 | * | 12 | * |
11 | * This program is free software; you can redistribute it and/or modify | 13 | * This program is free software; you can redistribute it and/or modify |
12 | * it under the terms of the GNU General Public License as published by | 14 | * it under the terms of the GNU General Public License as published by |
@@ -57,7 +59,7 @@ MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC " | |||
57 | /* Addresses to scan */ | 59 | /* Addresses to scan */ |
58 | static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; | 60 | static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; |
59 | 61 | ||
60 | enum chips { dme1737, sch5027, sch311x }; | 62 | enum chips { dme1737, sch5027, sch311x, sch5127 }; |
61 | 63 | ||
62 | /* --------------------------------------------------------------------- | 64 | /* --------------------------------------------------------------------- |
63 | * Registers | 65 | * Registers |
@@ -164,10 +166,29 @@ static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; | |||
164 | #define DME1737_VERSTEP_MASK 0xf8 | 166 | #define DME1737_VERSTEP_MASK 0xf8 |
165 | #define SCH311X_DEVICE 0x8c | 167 | #define SCH311X_DEVICE 0x8c |
166 | #define SCH5027_VERSTEP 0x69 | 168 | #define SCH5027_VERSTEP 0x69 |
169 | #define SCH5127_DEVICE 0x8e | ||
170 | |||
171 | /* Device ID values (global configuration register index 0x20) */ | ||
172 | #define DME1737_ID_1 0x77 | ||
173 | #define DME1737_ID_2 0x78 | ||
174 | #define SCH3112_ID 0x7c | ||
175 | #define SCH3114_ID 0x7d | ||
176 | #define SCH3116_ID 0x7f | ||
177 | #define SCH5027_ID 0x89 | ||
178 | #define SCH5127_ID 0x86 | ||
167 | 179 | ||
168 | /* Length of ISA address segment */ | 180 | /* Length of ISA address segment */ |
169 | #define DME1737_EXTENT 2 | 181 | #define DME1737_EXTENT 2 |
170 | 182 | ||
183 | /* chip-dependent features */ | ||
184 | #define HAS_TEMP_OFFSET (1 << 0) /* bit 0 */ | ||
185 | #define HAS_VID (1 << 1) /* bit 1 */ | ||
186 | #define HAS_ZONE3 (1 << 2) /* bit 2 */ | ||
187 | #define HAS_ZONE_HYST (1 << 3) /* bit 3 */ | ||
188 | #define HAS_PWM_MIN (1 << 4) /* bit 4 */ | ||
189 | #define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */ | ||
190 | #define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */ | ||
191 | |||
171 | /* --------------------------------------------------------------------- | 192 | /* --------------------------------------------------------------------- |
172 | * Data structures and manipulation thereof | 193 | * Data structures and manipulation thereof |
173 | * --------------------------------------------------------------------- */ | 194 | * --------------------------------------------------------------------- */ |
@@ -187,8 +208,7 @@ struct dme1737_data { | |||
187 | 208 | ||
188 | u8 vid; | 209 | u8 vid; |
189 | u8 pwm_rr_en; | 210 | u8 pwm_rr_en; |
190 | u8 has_pwm; | 211 | u32 has_features; |
191 | u8 has_fan; | ||
192 | 212 | ||
193 | /* Register values */ | 213 | /* Register values */ |
194 | u16 in[7]; | 214 | u16 in[7]; |
@@ -224,8 +244,11 @@ static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300, | |||
224 | 3300}; | 244 | 3300}; |
225 | static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, | 245 | static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, |
226 | 3300}; | 246 | 3300}; |
247 | static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300, | ||
248 | 3300}; | ||
227 | #define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ | 249 | #define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ |
228 | (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ | 250 | (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ |
251 | (type) == sch5127 ? IN_NOMINAL_SCH5127 : \ | ||
229 | IN_NOMINAL_DME1737) | 252 | IN_NOMINAL_DME1737) |
230 | 253 | ||
231 | /* Voltage input | 254 | /* Voltage input |
@@ -568,7 +591,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
568 | 591 | ||
569 | /* Sample register contents every 1 sec */ | 592 | /* Sample register contents every 1 sec */ |
570 | if (time_after(jiffies, data->last_update + HZ) || !data->valid) { | 593 | if (time_after(jiffies, data->last_update + HZ) || !data->valid) { |
571 | if (data->type == dme1737) { | 594 | if (data->has_features & HAS_VID) { |
572 | data->vid = dme1737_read(data, DME1737_REG_VID) & | 595 | data->vid = dme1737_read(data, DME1737_REG_VID) & |
573 | 0x3f; | 596 | 0x3f; |
574 | } | 597 | } |
@@ -599,7 +622,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
599 | DME1737_REG_TEMP_MIN(ix)); | 622 | DME1737_REG_TEMP_MIN(ix)); |
600 | data->temp_max[ix] = dme1737_read(data, | 623 | data->temp_max[ix] = dme1737_read(data, |
601 | DME1737_REG_TEMP_MAX(ix)); | 624 | DME1737_REG_TEMP_MAX(ix)); |
602 | if (data->type != sch5027) { | 625 | if (data->has_features & HAS_TEMP_OFFSET) { |
603 | data->temp_offset[ix] = dme1737_read(data, | 626 | data->temp_offset[ix] = dme1737_read(data, |
604 | DME1737_REG_TEMP_OFFSET(ix)); | 627 | DME1737_REG_TEMP_OFFSET(ix)); |
605 | } | 628 | } |
@@ -626,7 +649,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
626 | for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { | 649 | for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { |
627 | /* Skip reading registers if optional fans are not | 650 | /* Skip reading registers if optional fans are not |
628 | * present */ | 651 | * present */ |
629 | if (!(data->has_fan & (1 << ix))) { | 652 | if (!(data->has_features & HAS_FAN(ix))) { |
630 | continue; | 653 | continue; |
631 | } | 654 | } |
632 | data->fan[ix] = dme1737_read(data, | 655 | data->fan[ix] = dme1737_read(data, |
@@ -650,7 +673,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
650 | for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) { | 673 | for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) { |
651 | /* Skip reading registers if optional PWMs are not | 674 | /* Skip reading registers if optional PWMs are not |
652 | * present */ | 675 | * present */ |
653 | if (!(data->has_pwm & (1 << ix))) { | 676 | if (!(data->has_features & HAS_PWM(ix))) { |
654 | continue; | 677 | continue; |
655 | } | 678 | } |
656 | data->pwm[ix] = dme1737_read(data, | 679 | data->pwm[ix] = dme1737_read(data, |
@@ -672,12 +695,24 @@ static struct dme1737_data *dme1737_update_device(struct device *dev) | |||
672 | 695 | ||
673 | /* Thermal zone registers */ | 696 | /* Thermal zone registers */ |
674 | for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) { | 697 | for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) { |
675 | data->zone_low[ix] = dme1737_read(data, | 698 | /* Skip reading registers if zone3 is not present */ |
676 | DME1737_REG_ZONE_LOW(ix)); | 699 | if ((ix == 2) && !(data->has_features & HAS_ZONE3)) { |
677 | data->zone_abs[ix] = dme1737_read(data, | 700 | continue; |
678 | DME1737_REG_ZONE_ABS(ix)); | 701 | } |
702 | /* sch5127 zone2 registers are special */ | ||
703 | if ((ix == 1) && (data->type == sch5127)) { | ||
704 | data->zone_low[1] = dme1737_read(data, | ||
705 | DME1737_REG_ZONE_LOW(2)); | ||
706 | data->zone_abs[1] = dme1737_read(data, | ||
707 | DME1737_REG_ZONE_ABS(2)); | ||
708 | } else { | ||
709 | data->zone_low[ix] = dme1737_read(data, | ||
710 | DME1737_REG_ZONE_LOW(ix)); | ||
711 | data->zone_abs[ix] = dme1737_read(data, | ||
712 | DME1737_REG_ZONE_ABS(ix)); | ||
713 | } | ||
679 | } | 714 | } |
680 | if (data->type != sch5027) { | 715 | if (data->has_features & HAS_ZONE_HYST) { |
681 | for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { | 716 | for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { |
682 | data->zone_hyst[ix] = dme1737_read(data, | 717 | data->zone_hyst[ix] = dme1737_read(data, |
683 | DME1737_REG_ZONE_HYST(ix)); | 718 | DME1737_REG_ZONE_HYST(ix)); |
@@ -1594,10 +1629,6 @@ static struct attribute *dme1737_attr[] ={ | |||
1594 | &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, | 1629 | &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, |
1595 | &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, | 1630 | &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, |
1596 | &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr, | 1631 | &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr, |
1597 | &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, | ||
1598 | &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, | ||
1599 | &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, | ||
1600 | &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr, | ||
1601 | NULL | 1632 | NULL |
1602 | }; | 1633 | }; |
1603 | 1634 | ||
@@ -1605,27 +1636,23 @@ static const struct attribute_group dme1737_group = { | |||
1605 | .attrs = dme1737_attr, | 1636 | .attrs = dme1737_attr, |
1606 | }; | 1637 | }; |
1607 | 1638 | ||
1608 | /* The following struct holds misc attributes, which are not available in all | 1639 | /* The following struct holds temp offset attributes, which are not available |
1609 | * chips. Their creation depends on the chip type which is determined during | 1640 | * in all chips. The following chips support them: |
1610 | * module load. */ | 1641 | * DME1737, SCH311x */ |
1611 | static struct attribute *dme1737_misc_attr[] = { | 1642 | static struct attribute *dme1737_temp_offset_attr[] = { |
1612 | /* Temperatures */ | ||
1613 | &sensor_dev_attr_temp1_offset.dev_attr.attr, | 1643 | &sensor_dev_attr_temp1_offset.dev_attr.attr, |
1614 | &sensor_dev_attr_temp2_offset.dev_attr.attr, | 1644 | &sensor_dev_attr_temp2_offset.dev_attr.attr, |
1615 | &sensor_dev_attr_temp3_offset.dev_attr.attr, | 1645 | &sensor_dev_attr_temp3_offset.dev_attr.attr, |
1616 | /* Zones */ | ||
1617 | &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr, | ||
1618 | &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr, | ||
1619 | &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr, | ||
1620 | NULL | 1646 | NULL |
1621 | }; | 1647 | }; |
1622 | 1648 | ||
1623 | static const struct attribute_group dme1737_misc_group = { | 1649 | static const struct attribute_group dme1737_temp_offset_group = { |
1624 | .attrs = dme1737_misc_attr, | 1650 | .attrs = dme1737_temp_offset_attr, |
1625 | }; | 1651 | }; |
1626 | 1652 | ||
1627 | /* The following struct holds VID-related attributes. Their creation | 1653 | /* The following struct holds VID related attributes, which are not available |
1628 | depends on the chip type which is determined during module load. */ | 1654 | * in all chips. The following chips support them: |
1655 | * DME1737 */ | ||
1629 | static struct attribute *dme1737_vid_attr[] = { | 1656 | static struct attribute *dme1737_vid_attr[] = { |
1630 | &dev_attr_vrm.attr, | 1657 | &dev_attr_vrm.attr, |
1631 | &dev_attr_cpu0_vid.attr, | 1658 | &dev_attr_cpu0_vid.attr, |
@@ -1636,6 +1663,36 @@ static const struct attribute_group dme1737_vid_group = { | |||
1636 | .attrs = dme1737_vid_attr, | 1663 | .attrs = dme1737_vid_attr, |
1637 | }; | 1664 | }; |
1638 | 1665 | ||
1666 | /* The following struct holds temp zone 3 related attributes, which are not | ||
1667 | * available in all chips. The following chips support them: | ||
1668 | * DME1737, SCH311x, SCH5027 */ | ||
1669 | static struct attribute *dme1737_zone3_attr[] = { | ||
1670 | &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, | ||
1671 | &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, | ||
1672 | &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, | ||
1673 | &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr, | ||
1674 | NULL | ||
1675 | }; | ||
1676 | |||
1677 | static const struct attribute_group dme1737_zone3_group = { | ||
1678 | .attrs = dme1737_zone3_attr, | ||
1679 | }; | ||
1680 | |||
1681 | |||
1682 | /* The following struct holds temp zone hysteresis related attributes, which | ||
1683 | * are not available in all chips. The following chips support them: | ||
1684 | * DME1737, SCH311x */ | ||
1685 | static struct attribute *dme1737_zone_hyst_attr[] = { | ||
1686 | &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr, | ||
1687 | &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr, | ||
1688 | &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr, | ||
1689 | NULL | ||
1690 | }; | ||
1691 | |||
1692 | static const struct attribute_group dme1737_zone_hyst_group = { | ||
1693 | .attrs = dme1737_zone_hyst_attr, | ||
1694 | }; | ||
1695 | |||
1639 | /* The following structs hold the PWM attributes, some of which are optional. | 1696 | /* The following structs hold the PWM attributes, some of which are optional. |
1640 | * Their creation depends on the chip configuration which is determined during | 1697 | * Their creation depends on the chip configuration which is determined during |
1641 | * module load. */ | 1698 | * module load. */ |
@@ -1691,10 +1748,10 @@ static const struct attribute_group dme1737_pwm_group[] = { | |||
1691 | { .attrs = dme1737_pwm6_attr }, | 1748 | { .attrs = dme1737_pwm6_attr }, |
1692 | }; | 1749 | }; |
1693 | 1750 | ||
1694 | /* The following struct holds misc PWM attributes, which are not available in | 1751 | /* The following struct holds auto PWM min attributes, which are not available |
1695 | * all chips. Their creation depends on the chip type which is determined | 1752 | * in all chips. Their creation depends on the chip type which is determined |
1696 | * during module load. */ | 1753 | * during module load. */ |
1697 | static struct attribute *dme1737_pwm_misc_attr[] = { | 1754 | static struct attribute *dme1737_auto_pwm_min_attr[] = { |
1698 | &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, | 1755 | &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, |
1699 | &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, | 1756 | &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, |
1700 | &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, | 1757 | &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, |
@@ -1764,14 +1821,25 @@ static struct attribute *dme1737_zone_chmod_attr[] = { | |||
1764 | &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, | 1821 | &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, |
1765 | &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, | 1822 | &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, |
1766 | &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, | 1823 | &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, |
1824 | NULL | ||
1825 | }; | ||
1826 | |||
1827 | static const struct attribute_group dme1737_zone_chmod_group = { | ||
1828 | .attrs = dme1737_zone_chmod_attr, | ||
1829 | }; | ||
1830 | |||
1831 | |||
1832 | /* The permissions of the following zone 3 attributes are changed to read- | ||
1833 | * writeable if the chip is *not* locked. Otherwise they stay read-only. */ | ||
1834 | static struct attribute *dme1737_zone3_chmod_attr[] = { | ||
1767 | &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, | 1835 | &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, |
1768 | &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, | 1836 | &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, |
1769 | &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, | 1837 | &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, |
1770 | NULL | 1838 | NULL |
1771 | }; | 1839 | }; |
1772 | 1840 | ||
1773 | static const struct attribute_group dme1737_zone_chmod_group = { | 1841 | static const struct attribute_group dme1737_zone3_chmod_group = { |
1774 | .attrs = dme1737_zone_chmod_attr, | 1842 | .attrs = dme1737_zone3_chmod_attr, |
1775 | }; | 1843 | }; |
1776 | 1844 | ||
1777 | /* The permissions of the following PWM attributes are changed to read- | 1845 | /* The permissions of the following PWM attributes are changed to read- |
@@ -1887,30 +1955,35 @@ static void dme1737_remove_files(struct device *dev) | |||
1887 | int ix; | 1955 | int ix; |
1888 | 1956 | ||
1889 | for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { | 1957 | for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { |
1890 | if (data->has_fan & (1 << ix)) { | 1958 | if (data->has_features & HAS_FAN(ix)) { |
1891 | sysfs_remove_group(&dev->kobj, | 1959 | sysfs_remove_group(&dev->kobj, |
1892 | &dme1737_fan_group[ix]); | 1960 | &dme1737_fan_group[ix]); |
1893 | } | 1961 | } |
1894 | } | 1962 | } |
1895 | 1963 | ||
1896 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { | 1964 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { |
1897 | if (data->has_pwm & (1 << ix)) { | 1965 | if (data->has_features & HAS_PWM(ix)) { |
1898 | sysfs_remove_group(&dev->kobj, | 1966 | sysfs_remove_group(&dev->kobj, |
1899 | &dme1737_pwm_group[ix]); | 1967 | &dme1737_pwm_group[ix]); |
1900 | if (data->type != sch5027 && ix < 3) { | 1968 | if ((data->has_features & HAS_PWM_MIN) && ix < 3) { |
1901 | sysfs_remove_file(&dev->kobj, | 1969 | sysfs_remove_file(&dev->kobj, |
1902 | dme1737_pwm_misc_attr[ix]); | 1970 | dme1737_auto_pwm_min_attr[ix]); |
1903 | } | 1971 | } |
1904 | } | 1972 | } |
1905 | } | 1973 | } |
1906 | 1974 | ||
1907 | if (data->type != sch5027) { | 1975 | if (data->has_features & HAS_TEMP_OFFSET) { |
1908 | sysfs_remove_group(&dev->kobj, &dme1737_misc_group); | 1976 | sysfs_remove_group(&dev->kobj, &dme1737_temp_offset_group); |
1909 | } | 1977 | } |
1910 | if (data->type == dme1737) { | 1978 | if (data->has_features & HAS_VID) { |
1911 | sysfs_remove_group(&dev->kobj, &dme1737_vid_group); | 1979 | sysfs_remove_group(&dev->kobj, &dme1737_vid_group); |
1912 | } | 1980 | } |
1913 | 1981 | if (data->has_features & HAS_ZONE3) { | |
1982 | sysfs_remove_group(&dev->kobj, &dme1737_zone3_group); | ||
1983 | } | ||
1984 | if (data->has_features & HAS_ZONE_HYST) { | ||
1985 | sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group); | ||
1986 | } | ||
1914 | sysfs_remove_group(&dev->kobj, &dme1737_group); | 1987 | sysfs_remove_group(&dev->kobj, &dme1737_group); |
1915 | 1988 | ||
1916 | if (!data->client) { | 1989 | if (!data->client) { |
@@ -1934,23 +2007,31 @@ static int dme1737_create_files(struct device *dev) | |||
1934 | goto exit_remove; | 2007 | goto exit_remove; |
1935 | } | 2008 | } |
1936 | 2009 | ||
1937 | /* Create misc sysfs attributes */ | 2010 | /* Create chip-dependent sysfs attributes */ |
1938 | if ((data->type != sch5027) && | 2011 | if ((data->has_features & HAS_TEMP_OFFSET) && |
1939 | (err = sysfs_create_group(&dev->kobj, | 2012 | (err = sysfs_create_group(&dev->kobj, |
1940 | &dme1737_misc_group))) { | 2013 | &dme1737_temp_offset_group))) { |
1941 | goto exit_remove; | 2014 | goto exit_remove; |
1942 | } | 2015 | } |
1943 | 2016 | if ((data->has_features & HAS_VID) && | |
1944 | /* Create VID-related sysfs attributes */ | ||
1945 | if ((data->type == dme1737) && | ||
1946 | (err = sysfs_create_group(&dev->kobj, | 2017 | (err = sysfs_create_group(&dev->kobj, |
1947 | &dme1737_vid_group))) { | 2018 | &dme1737_vid_group))) { |
1948 | goto exit_remove; | 2019 | goto exit_remove; |
1949 | } | 2020 | } |
2021 | if ((data->has_features & HAS_ZONE3) && | ||
2022 | (err = sysfs_create_group(&dev->kobj, | ||
2023 | &dme1737_zone3_group))) { | ||
2024 | goto exit_remove; | ||
2025 | } | ||
2026 | if ((data->has_features & HAS_ZONE_HYST) && | ||
2027 | (err = sysfs_create_group(&dev->kobj, | ||
2028 | &dme1737_zone_hyst_group))) { | ||
2029 | goto exit_remove; | ||
2030 | } | ||
1950 | 2031 | ||
1951 | /* Create fan sysfs attributes */ | 2032 | /* Create fan sysfs attributes */ |
1952 | for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { | 2033 | for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { |
1953 | if (data->has_fan & (1 << ix)) { | 2034 | if (data->has_features & HAS_FAN(ix)) { |
1954 | if ((err = sysfs_create_group(&dev->kobj, | 2035 | if ((err = sysfs_create_group(&dev->kobj, |
1955 | &dme1737_fan_group[ix]))) { | 2036 | &dme1737_fan_group[ix]))) { |
1956 | goto exit_remove; | 2037 | goto exit_remove; |
@@ -1960,14 +2041,14 @@ static int dme1737_create_files(struct device *dev) | |||
1960 | 2041 | ||
1961 | /* Create PWM sysfs attributes */ | 2042 | /* Create PWM sysfs attributes */ |
1962 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { | 2043 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { |
1963 | if (data->has_pwm & (1 << ix)) { | 2044 | if (data->has_features & HAS_PWM(ix)) { |
1964 | if ((err = sysfs_create_group(&dev->kobj, | 2045 | if ((err = sysfs_create_group(&dev->kobj, |
1965 | &dme1737_pwm_group[ix]))) { | 2046 | &dme1737_pwm_group[ix]))) { |
1966 | goto exit_remove; | 2047 | goto exit_remove; |
1967 | } | 2048 | } |
1968 | if (data->type != sch5027 && ix < 3 && | 2049 | if ((data->has_features & HAS_PWM_MIN) && ix < 3 && |
1969 | (err = sysfs_create_file(&dev->kobj, | 2050 | (err = sysfs_create_file(&dev->kobj, |
1970 | dme1737_pwm_misc_attr[ix]))) { | 2051 | dme1737_auto_pwm_min_attr[ix]))) { |
1971 | goto exit_remove; | 2052 | goto exit_remove; |
1972 | } | 2053 | } |
1973 | } | 2054 | } |
@@ -1983,21 +2064,30 @@ static int dme1737_create_files(struct device *dev) | |||
1983 | dme1737_chmod_group(dev, &dme1737_zone_chmod_group, | 2064 | dme1737_chmod_group(dev, &dme1737_zone_chmod_group, |
1984 | S_IRUGO | S_IWUSR); | 2065 | S_IRUGO | S_IWUSR); |
1985 | 2066 | ||
1986 | /* Change permissions of misc sysfs attributes */ | 2067 | /* Change permissions of chip-dependent sysfs attributes */ |
1987 | if (data->type != sch5027) { | 2068 | if (data->has_features & HAS_TEMP_OFFSET) { |
1988 | dme1737_chmod_group(dev, &dme1737_misc_group, | 2069 | dme1737_chmod_group(dev, &dme1737_temp_offset_group, |
2070 | S_IRUGO | S_IWUSR); | ||
2071 | } | ||
2072 | if (data->has_features & HAS_ZONE3) { | ||
2073 | dme1737_chmod_group(dev, &dme1737_zone3_chmod_group, | ||
2074 | S_IRUGO | S_IWUSR); | ||
2075 | } | ||
2076 | if (data->has_features & HAS_ZONE_HYST) { | ||
2077 | dme1737_chmod_group(dev, &dme1737_zone_hyst_group, | ||
1989 | S_IRUGO | S_IWUSR); | 2078 | S_IRUGO | S_IWUSR); |
1990 | } | 2079 | } |
1991 | 2080 | ||
1992 | /* Change permissions of PWM sysfs attributes */ | 2081 | /* Change permissions of PWM sysfs attributes */ |
1993 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_chmod_group); ix++) { | 2082 | for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_chmod_group); ix++) { |
1994 | if (data->has_pwm & (1 << ix)) { | 2083 | if (data->has_features & HAS_PWM(ix)) { |
1995 | dme1737_chmod_group(dev, | 2084 | dme1737_chmod_group(dev, |
1996 | &dme1737_pwm_chmod_group[ix], | 2085 | &dme1737_pwm_chmod_group[ix], |
1997 | S_IRUGO | S_IWUSR); | 2086 | S_IRUGO | S_IWUSR); |
1998 | if (data->type != sch5027 && ix < 3) { | 2087 | if ((data->has_features & HAS_PWM_MIN) && |
2088 | ix < 3) { | ||
1999 | dme1737_chmod_file(dev, | 2089 | dme1737_chmod_file(dev, |
2000 | dme1737_pwm_misc_attr[ix], | 2090 | dme1737_auto_pwm_min_attr[ix], |
2001 | S_IRUGO | S_IWUSR); | 2091 | S_IRUGO | S_IWUSR); |
2002 | } | 2092 | } |
2003 | } | 2093 | } |
@@ -2005,7 +2095,7 @@ static int dme1737_create_files(struct device *dev) | |||
2005 | 2095 | ||
2006 | /* Change permissions of pwm[1-3] if in manual mode */ | 2096 | /* Change permissions of pwm[1-3] if in manual mode */ |
2007 | for (ix = 0; ix < 3; ix++) { | 2097 | for (ix = 0; ix < 3; ix++) { |
2008 | if ((data->has_pwm & (1 << ix)) && | 2098 | if ((data->has_features & HAS_PWM(ix)) && |
2009 | (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { | 2099 | (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { |
2010 | dme1737_chmod_file(dev, | 2100 | dme1737_chmod_file(dev, |
2011 | dme1737_pwm_chmod_attr[ix], | 2101 | dme1737_pwm_chmod_attr[ix], |
@@ -2052,20 +2142,20 @@ static int dme1737_init_device(struct device *dev) | |||
2052 | return -EFAULT; | 2142 | return -EFAULT; |
2053 | } | 2143 | } |
2054 | 2144 | ||
2055 | /* Determine which optional fan and pwm features are enabled/present */ | 2145 | /* Determine which optional fan and pwm features are enabled (only |
2146 | * valid for I2C devices) */ | ||
2056 | if (client) { /* I2C chip */ | 2147 | if (client) { /* I2C chip */ |
2057 | data->config2 = dme1737_read(data, DME1737_REG_CONFIG2); | 2148 | data->config2 = dme1737_read(data, DME1737_REG_CONFIG2); |
2058 | /* Check if optional fan3 input is enabled */ | 2149 | /* Check if optional fan3 input is enabled */ |
2059 | if (data->config2 & 0x04) { | 2150 | if (data->config2 & 0x04) { |
2060 | data->has_fan |= (1 << 2); | 2151 | data->has_features |= HAS_FAN(2); |
2061 | } | 2152 | } |
2062 | 2153 | ||
2063 | /* Fan4 and pwm3 are only available if the client's I2C address | 2154 | /* Fan4 and pwm3 are only available if the client's I2C address |
2064 | * is the default 0x2e. Otherwise the I/Os associated with | 2155 | * is the default 0x2e. Otherwise the I/Os associated with |
2065 | * these functions are used for addr enable/select. */ | 2156 | * these functions are used for addr enable/select. */ |
2066 | if (client->addr == 0x2e) { | 2157 | if (client->addr == 0x2e) { |
2067 | data->has_fan |= (1 << 3); | 2158 | data->has_features |= HAS_FAN(3) | HAS_PWM(2); |
2068 | data->has_pwm |= (1 << 2); | ||
2069 | } | 2159 | } |
2070 | 2160 | ||
2071 | /* Determine which of the optional fan[5-6] and pwm[5-6] | 2161 | /* Determine which of the optional fan[5-6] and pwm[5-6] |
@@ -2077,26 +2167,40 @@ static int dme1737_init_device(struct device *dev) | |||
2077 | dev_warn(dev, "Failed to query Super-IO for optional " | 2167 | dev_warn(dev, "Failed to query Super-IO for optional " |
2078 | "features.\n"); | 2168 | "features.\n"); |
2079 | } | 2169 | } |
2080 | } else { /* ISA chip */ | ||
2081 | /* Fan3 and pwm3 are always available. Fan[4-5] and pwm[5-6] | ||
2082 | * don't exist in the ISA chip. */ | ||
2083 | data->has_fan |= (1 << 2); | ||
2084 | data->has_pwm |= (1 << 2); | ||
2085 | } | 2170 | } |
2086 | 2171 | ||
2087 | /* Fan1, fan2, pwm1, and pwm2 are always present */ | 2172 | /* Fan[1-2] and pwm[1-2] are present in all chips */ |
2088 | data->has_fan |= 0x03; | 2173 | data->has_features |= HAS_FAN(0) | HAS_FAN(1) | HAS_PWM(0) | HAS_PWM(1); |
2089 | data->has_pwm |= 0x03; | 2174 | |
2175 | /* Chip-dependent features */ | ||
2176 | switch (data->type) { | ||
2177 | case dme1737: | ||
2178 | data->has_features |= HAS_TEMP_OFFSET | HAS_VID | HAS_ZONE3 | | ||
2179 | HAS_ZONE_HYST | HAS_PWM_MIN; | ||
2180 | break; | ||
2181 | case sch311x: | ||
2182 | data->has_features |= HAS_TEMP_OFFSET | HAS_ZONE3 | | ||
2183 | HAS_ZONE_HYST | HAS_PWM_MIN | HAS_FAN(2) | HAS_PWM(2); | ||
2184 | break; | ||
2185 | case sch5027: | ||
2186 | data->has_features |= HAS_ZONE3; | ||
2187 | break; | ||
2188 | case sch5127: | ||
2189 | data->has_features |= HAS_FAN(2) | HAS_PWM(2); | ||
2190 | break; | ||
2191 | default: | ||
2192 | break; | ||
2193 | } | ||
2090 | 2194 | ||
2091 | dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, " | 2195 | dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, " |
2092 | "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n", | 2196 | "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n", |
2093 | (data->has_pwm & (1 << 2)) ? "yes" : "no", | 2197 | (data->has_features & HAS_PWM(2)) ? "yes" : "no", |
2094 | (data->has_pwm & (1 << 4)) ? "yes" : "no", | 2198 | (data->has_features & HAS_PWM(4)) ? "yes" : "no", |
2095 | (data->has_pwm & (1 << 5)) ? "yes" : "no", | 2199 | (data->has_features & HAS_PWM(5)) ? "yes" : "no", |
2096 | (data->has_fan & (1 << 2)) ? "yes" : "no", | 2200 | (data->has_features & HAS_FAN(2)) ? "yes" : "no", |
2097 | (data->has_fan & (1 << 3)) ? "yes" : "no", | 2201 | (data->has_features & HAS_FAN(3)) ? "yes" : "no", |
2098 | (data->has_fan & (1 << 4)) ? "yes" : "no", | 2202 | (data->has_features & HAS_FAN(4)) ? "yes" : "no", |
2099 | (data->has_fan & (1 << 5)) ? "yes" : "no"); | 2203 | (data->has_features & HAS_FAN(5)) ? "yes" : "no"); |
2100 | 2204 | ||
2101 | reg = dme1737_read(data, DME1737_REG_TACH_PWM); | 2205 | reg = dme1737_read(data, DME1737_REG_TACH_PWM); |
2102 | /* Inform if fan-to-pwm mapping differs from the default */ | 2206 | /* Inform if fan-to-pwm mapping differs from the default */ |
@@ -2122,7 +2226,7 @@ static int dme1737_init_device(struct device *dev) | |||
2122 | for (ix = 0; ix < 3; ix++) { | 2226 | for (ix = 0; ix < 3; ix++) { |
2123 | data->pwm_config[ix] = dme1737_read(data, | 2227 | data->pwm_config[ix] = dme1737_read(data, |
2124 | DME1737_REG_PWM_CONFIG(ix)); | 2228 | DME1737_REG_PWM_CONFIG(ix)); |
2125 | if ((data->has_pwm & (1 << ix)) && | 2229 | if ((data->has_features & HAS_PWM(ix)) && |
2126 | (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) { | 2230 | (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) { |
2127 | dev_info(dev, "Switching pwm%d to " | 2231 | dev_info(dev, "Switching pwm%d to " |
2128 | "manual mode.\n", ix + 1); | 2232 | "manual mode.\n", ix + 1); |
@@ -2142,7 +2246,7 @@ static int dme1737_init_device(struct device *dev) | |||
2142 | data->pwm_acz[2] = 4; /* pwm3 -> zone3 */ | 2246 | data->pwm_acz[2] = 4; /* pwm3 -> zone3 */ |
2143 | 2247 | ||
2144 | /* Set VRM */ | 2248 | /* Set VRM */ |
2145 | if (data->type == dme1737) { | 2249 | if (data->has_features & HAS_VID) { |
2146 | data->vrm = vid_which_vrm(); | 2250 | data->vrm = vid_which_vrm(); |
2147 | } | 2251 | } |
2148 | 2252 | ||
@@ -2163,10 +2267,10 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) | |||
2163 | dme1737_sio_enter(sio_cip); | 2267 | dme1737_sio_enter(sio_cip); |
2164 | 2268 | ||
2165 | /* Check device ID | 2269 | /* Check device ID |
2166 | * The DME1737 can return either 0x78 or 0x77 as its device ID. | 2270 | * We currently know about two kinds of DME1737 and SCH5027. */ |
2167 | * The SCH5027 returns 0x89 as its device ID. */ | ||
2168 | reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); | 2271 | reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); |
2169 | if (!(reg == 0x77 || reg == 0x78 || reg == 0x89)) { | 2272 | if (!(reg == DME1737_ID_1 || reg == DME1737_ID_2 || |
2273 | reg == SCH5027_ID)) { | ||
2170 | err = -ENODEV; | 2274 | err = -ENODEV; |
2171 | goto exit; | 2275 | goto exit; |
2172 | } | 2276 | } |
@@ -2185,16 +2289,16 @@ static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) | |||
2185 | * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set | 2289 | * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set |
2186 | * to '10' if the respective feature is enabled. */ | 2290 | * to '10' if the respective feature is enabled. */ |
2187 | if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */ | 2291 | if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */ |
2188 | data->has_fan |= (1 << 5); | 2292 | data->has_features |= HAS_FAN(5); |
2189 | } | 2293 | } |
2190 | if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */ | 2294 | if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */ |
2191 | data->has_pwm |= (1 << 5); | 2295 | data->has_features |= HAS_PWM(5); |
2192 | } | 2296 | } |
2193 | if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */ | 2297 | if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */ |
2194 | data->has_fan |= (1 << 4); | 2298 | data->has_features |= HAS_FAN(4); |
2195 | } | 2299 | } |
2196 | if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */ | 2300 | if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */ |
2197 | data->has_pwm |= (1 << 4); | 2301 | data->has_features |= HAS_PWM(4); |
2198 | } | 2302 | } |
2199 | 2303 | ||
2200 | exit: | 2304 | exit: |
@@ -2222,7 +2326,6 @@ static int dme1737_i2c_detect(struct i2c_client *client, | |||
2222 | if (company == DME1737_COMPANY_SMSC && | 2326 | if (company == DME1737_COMPANY_SMSC && |
2223 | verstep == SCH5027_VERSTEP) { | 2327 | verstep == SCH5027_VERSTEP) { |
2224 | name = "sch5027"; | 2328 | name = "sch5027"; |
2225 | |||
2226 | } else if (company == DME1737_COMPANY_SMSC && | 2329 | } else if (company == DME1737_COMPANY_SMSC && |
2227 | (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) { | 2330 | (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) { |
2228 | name = "dme1737"; | 2331 | name = "dme1737"; |
@@ -2329,10 +2432,10 @@ static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr) | |||
2329 | dme1737_sio_enter(sio_cip); | 2432 | dme1737_sio_enter(sio_cip); |
2330 | 2433 | ||
2331 | /* Check device ID | 2434 | /* Check device ID |
2332 | * We currently know about SCH3112 (0x7c), SCH3114 (0x7d), and | 2435 | * We currently know about SCH3112, SCH3114, SCH3116, and SCH5127 */ |
2333 | * SCH3116 (0x7f). */ | ||
2334 | reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); | 2436 | reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); |
2335 | if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) { | 2437 | if (!(reg == SCH3112_ID || reg == SCH3114_ID || reg == SCH3116_ID || |
2438 | reg == SCH5127_ID)) { | ||
2336 | err = -ENODEV; | 2439 | err = -ENODEV; |
2337 | goto exit; | 2440 | goto exit; |
2338 | } | 2441 | } |
@@ -2424,23 +2527,42 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) | |||
2424 | platform_set_drvdata(pdev, data); | 2527 | platform_set_drvdata(pdev, data); |
2425 | 2528 | ||
2426 | /* Skip chip detection if module is loaded with force_id parameter */ | 2529 | /* Skip chip detection if module is loaded with force_id parameter */ |
2427 | if (!force_id) { | 2530 | switch (force_id) { |
2531 | case SCH3112_ID: | ||
2532 | case SCH3114_ID: | ||
2533 | case SCH3116_ID: | ||
2534 | data->type = sch311x; | ||
2535 | break; | ||
2536 | case SCH5127_ID: | ||
2537 | data->type = sch5127; | ||
2538 | break; | ||
2539 | default: | ||
2428 | company = dme1737_read(data, DME1737_REG_COMPANY); | 2540 | company = dme1737_read(data, DME1737_REG_COMPANY); |
2429 | device = dme1737_read(data, DME1737_REG_DEVICE); | 2541 | device = dme1737_read(data, DME1737_REG_DEVICE); |
2430 | 2542 | ||
2431 | if (!((company == DME1737_COMPANY_SMSC) && | 2543 | if ((company == DME1737_COMPANY_SMSC) && |
2432 | (device == SCH311X_DEVICE))) { | 2544 | (device == SCH311X_DEVICE)) { |
2545 | data->type = sch311x; | ||
2546 | } else if ((company == DME1737_COMPANY_SMSC) && | ||
2547 | (device == SCH5127_DEVICE)) { | ||
2548 | data->type = sch5127; | ||
2549 | } else { | ||
2433 | err = -ENODEV; | 2550 | err = -ENODEV; |
2434 | goto exit_kfree; | 2551 | goto exit_kfree; |
2435 | } | 2552 | } |
2436 | } | 2553 | } |
2437 | data->type = sch311x; | ||
2438 | 2554 | ||
2439 | /* Fill in the remaining client fields and initialize the mutex */ | 2555 | if (data->type == sch5127) { |
2440 | data->name = "sch311x"; | 2556 | data->name = "sch5127"; |
2557 | } else { | ||
2558 | data->name = "sch311x"; | ||
2559 | } | ||
2560 | |||
2561 | /* Initialize the mutex */ | ||
2441 | mutex_init(&data->update_lock); | 2562 | mutex_init(&data->update_lock); |
2442 | 2563 | ||
2443 | dev_info(dev, "Found a SCH311x chip at 0x%04x\n", data->addr); | 2564 | dev_info(dev, "Found a %s chip at 0x%04x\n", |
2565 | data->type == sch5127 ? "SCH5127" : "SCH311x", data->addr); | ||
2444 | 2566 | ||
2445 | /* Initialize the chip */ | 2567 | /* Initialize the chip */ |
2446 | if ((err = dme1737_init_device(dev))) { | 2568 | if ((err = dme1737_init_device(dev))) { |
diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c new file mode 100644 index 000000000000..0e4b5642638d --- /dev/null +++ b/drivers/hwmon/emc1403.c | |||
@@ -0,0 +1,344 @@ | |||
1 | /* | ||
2 | * emc1403.c - SMSC Thermal Driver | ||
3 | * | ||
4 | * Copyright (C) 2008 Intel Corp | ||
5 | * | ||
6 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; version 2 of the License. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along | ||
18 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
20 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
21 | * | ||
22 | * TODO | ||
23 | * - cache alarm and critical limit registers | ||
24 | * - add emc1404 support | ||
25 | */ | ||
26 | |||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/i2c.h> | ||
31 | #include <linux/hwmon.h> | ||
32 | #include <linux/hwmon-sysfs.h> | ||
33 | #include <linux/err.h> | ||
34 | #include <linux/sysfs.h> | ||
35 | #include <linux/mutex.h> | ||
36 | |||
37 | #define THERMAL_PID_REG 0xfd | ||
38 | #define THERMAL_SMSC_ID_REG 0xfe | ||
39 | #define THERMAL_REVISION_REG 0xff | ||
40 | |||
41 | struct thermal_data { | ||
42 | struct device *hwmon_dev; | ||
43 | struct mutex mutex; | ||
44 | /* Cache the hyst value so we don't keep re-reading it. In theory | ||
45 | we could cache it forever as nobody else should be writing it. */ | ||
46 | u8 cached_hyst; | ||
47 | unsigned long hyst_valid; | ||
48 | }; | ||
49 | |||
50 | static ssize_t show_temp(struct device *dev, | ||
51 | struct device_attribute *attr, char *buf) | ||
52 | { | ||
53 | struct i2c_client *client = to_i2c_client(dev); | ||
54 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | ||
55 | int retval = i2c_smbus_read_byte_data(client, sda->index); | ||
56 | |||
57 | if (retval < 0) | ||
58 | return retval; | ||
59 | return sprintf(buf, "%d000\n", retval); | ||
60 | } | ||
61 | |||
62 | static ssize_t show_bit(struct device *dev, | ||
63 | struct device_attribute *attr, char *buf) | ||
64 | { | ||
65 | struct i2c_client *client = to_i2c_client(dev); | ||
66 | struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); | ||
67 | int retval = i2c_smbus_read_byte_data(client, sda->nr); | ||
68 | |||
69 | if (retval < 0) | ||
70 | return retval; | ||
71 | retval &= sda->index; | ||
72 | return sprintf(buf, "%d\n", retval ? 1 : 0); | ||
73 | } | ||
74 | |||
75 | static ssize_t store_temp(struct device *dev, | ||
76 | struct device_attribute *attr, const char *buf, size_t count) | ||
77 | { | ||
78 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | ||
79 | struct i2c_client *client = to_i2c_client(dev); | ||
80 | unsigned long val; | ||
81 | int retval; | ||
82 | |||
83 | if (strict_strtoul(buf, 10, &val)) | ||
84 | return -EINVAL; | ||
85 | retval = i2c_smbus_write_byte_data(client, sda->index, | ||
86 | DIV_ROUND_CLOSEST(val, 1000)); | ||
87 | if (retval < 0) | ||
88 | return retval; | ||
89 | return count; | ||
90 | } | ||
91 | |||
92 | static ssize_t show_hyst(struct device *dev, | ||
93 | struct device_attribute *attr, char *buf) | ||
94 | { | ||
95 | struct i2c_client *client = to_i2c_client(dev); | ||
96 | struct thermal_data *data = i2c_get_clientdata(client); | ||
97 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | ||
98 | int retval; | ||
99 | int hyst; | ||
100 | |||
101 | retval = i2c_smbus_read_byte_data(client, sda->index); | ||
102 | if (retval < 0) | ||
103 | return retval; | ||
104 | |||
105 | if (time_after(jiffies, data->hyst_valid)) { | ||
106 | hyst = i2c_smbus_read_byte_data(client, 0x21); | ||
107 | if (hyst < 0) | ||
108 | return retval; | ||
109 | data->cached_hyst = hyst; | ||
110 | data->hyst_valid = jiffies + HZ; | ||
111 | } | ||
112 | return sprintf(buf, "%d000\n", retval - data->cached_hyst); | ||
113 | } | ||
114 | |||
115 | static ssize_t store_hyst(struct device *dev, | ||
116 | struct device_attribute *attr, const char *buf, size_t count) | ||
117 | { | ||
118 | struct i2c_client *client = to_i2c_client(dev); | ||
119 | struct thermal_data *data = i2c_get_clientdata(client); | ||
120 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | ||
121 | int retval; | ||
122 | int hyst; | ||
123 | unsigned long val; | ||
124 | |||
125 | if (strict_strtoul(buf, 10, &val)) | ||
126 | return -EINVAL; | ||
127 | |||
128 | mutex_lock(&data->mutex); | ||
129 | retval = i2c_smbus_read_byte_data(client, sda->index); | ||
130 | if (retval < 0) | ||
131 | goto fail; | ||
132 | |||
133 | hyst = val - retval * 1000; | ||
134 | hyst = DIV_ROUND_CLOSEST(hyst, 1000); | ||
135 | if (hyst < 0 || hyst > 255) { | ||
136 | retval = -ERANGE; | ||
137 | goto fail; | ||
138 | } | ||
139 | |||
140 | retval = i2c_smbus_write_byte_data(client, 0x21, hyst); | ||
141 | if (retval == 0) { | ||
142 | retval = count; | ||
143 | data->cached_hyst = hyst; | ||
144 | data->hyst_valid = jiffies + HZ; | ||
145 | } | ||
146 | fail: | ||
147 | mutex_unlock(&data->mutex); | ||
148 | return retval; | ||
149 | } | ||
150 | |||
151 | /* | ||
152 | * Sensors. We pass the actual i2c register to the methods. | ||
153 | */ | ||
154 | |||
155 | static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, | ||
156 | show_temp, store_temp, 0x06); | ||
157 | static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, | ||
158 | show_temp, store_temp, 0x05); | ||
159 | static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, | ||
160 | show_temp, store_temp, 0x20); | ||
161 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0x00); | ||
162 | static SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO, | ||
163 | show_bit, NULL, 0x36, 0x01); | ||
164 | static SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO, | ||
165 | show_bit, NULL, 0x35, 0x01); | ||
166 | static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, | ||
167 | show_bit, NULL, 0x37, 0x01); | ||
168 | static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR, | ||
169 | show_hyst, store_hyst, 0x20); | ||
170 | |||
171 | static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, | ||
172 | show_temp, store_temp, 0x08); | ||
173 | static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, | ||
174 | show_temp, store_temp, 0x07); | ||
175 | static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, | ||
176 | show_temp, store_temp, 0x19); | ||
177 | static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0x01); | ||
178 | static SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO, | ||
179 | show_bit, NULL, 0x36, 0x02); | ||
180 | static SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO, | ||
181 | show_bit, NULL, 0x35, 0x02); | ||
182 | static SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO, | ||
183 | show_bit, NULL, 0x37, 0x02); | ||
184 | static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO | S_IWUSR, | ||
185 | show_hyst, store_hyst, 0x19); | ||
186 | |||
187 | static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR, | ||
188 | show_temp, store_temp, 0x16); | ||
189 | static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, | ||
190 | show_temp, store_temp, 0x15); | ||
191 | static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO | S_IWUSR, | ||
192 | show_temp, store_temp, 0x1A); | ||
193 | static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 0x23); | ||
194 | static SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO, | ||
195 | show_bit, NULL, 0x36, 0x04); | ||
196 | static SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO, | ||
197 | show_bit, NULL, 0x35, 0x04); | ||
198 | static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, | ||
199 | show_bit, NULL, 0x37, 0x04); | ||
200 | static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR, | ||
201 | show_hyst, store_hyst, 0x1A); | ||
202 | |||
203 | static struct attribute *mid_att_thermal[] = { | ||
204 | &sensor_dev_attr_temp1_min.dev_attr.attr, | ||
205 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
206 | &sensor_dev_attr_temp1_crit.dev_attr.attr, | ||
207 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
208 | &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, | ||
209 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
210 | &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, | ||
211 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, | ||
212 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
213 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
214 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
215 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
216 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
217 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
218 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
219 | &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, | ||
220 | &sensor_dev_attr_temp3_min.dev_attr.attr, | ||
221 | &sensor_dev_attr_temp3_max.dev_attr.attr, | ||
222 | &sensor_dev_attr_temp3_crit.dev_attr.attr, | ||
223 | &sensor_dev_attr_temp3_input.dev_attr.attr, | ||
224 | &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, | ||
225 | &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, | ||
226 | &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, | ||
227 | &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, | ||
228 | NULL | ||
229 | }; | ||
230 | |||
231 | static const struct attribute_group m_thermal_gr = { | ||
232 | .attrs = mid_att_thermal | ||
233 | }; | ||
234 | |||
235 | static int emc1403_detect(struct i2c_client *client, | ||
236 | struct i2c_board_info *info) | ||
237 | { | ||
238 | int id; | ||
239 | /* Check if thermal chip is SMSC and EMC1403 */ | ||
240 | |||
241 | id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG); | ||
242 | if (id != 0x5d) | ||
243 | return -ENODEV; | ||
244 | |||
245 | /* Note: 0x25 is the 1404 which is very similar and this | ||
246 | driver could be extended */ | ||
247 | id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG); | ||
248 | if (id != 0x21) | ||
249 | return -ENODEV; | ||
250 | |||
251 | id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); | ||
252 | if (id != 0x01) | ||
253 | return -ENODEV; | ||
254 | |||
255 | strlcpy(info->type, "emc1403", I2C_NAME_SIZE); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int emc1403_probe(struct i2c_client *client, | ||
260 | const struct i2c_device_id *id) | ||
261 | { | ||
262 | int res; | ||
263 | struct thermal_data *data; | ||
264 | |||
265 | data = kzalloc(sizeof(struct thermal_data), GFP_KERNEL); | ||
266 | if (data == NULL) { | ||
267 | dev_warn(&client->dev, "out of memory"); | ||
268 | return -ENOMEM; | ||
269 | } | ||
270 | |||
271 | i2c_set_clientdata(client, data); | ||
272 | mutex_init(&data->mutex); | ||
273 | data->hyst_valid = jiffies - 1; /* Expired */ | ||
274 | |||
275 | res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr); | ||
276 | if (res) { | ||
277 | dev_warn(&client->dev, "create group failed\n"); | ||
278 | hwmon_device_unregister(data->hwmon_dev); | ||
279 | goto thermal_error1; | ||
280 | } | ||
281 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
282 | if (IS_ERR(data->hwmon_dev)) { | ||
283 | res = PTR_ERR(data->hwmon_dev); | ||
284 | dev_warn(&client->dev, "register hwmon dev failed\n"); | ||
285 | goto thermal_error2; | ||
286 | } | ||
287 | dev_info(&client->dev, "EMC1403 Thermal chip found\n"); | ||
288 | return res; | ||
289 | |||
290 | thermal_error2: | ||
291 | sysfs_remove_group(&client->dev.kobj, &m_thermal_gr); | ||
292 | thermal_error1: | ||
293 | kfree(data); | ||
294 | return res; | ||
295 | } | ||
296 | |||
297 | static int emc1403_remove(struct i2c_client *client) | ||
298 | { | ||
299 | struct thermal_data *data = i2c_get_clientdata(client); | ||
300 | |||
301 | hwmon_device_unregister(data->hwmon_dev); | ||
302 | sysfs_remove_group(&client->dev.kobj, &m_thermal_gr); | ||
303 | kfree(data); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | static const unsigned short emc1403_address_list[] = { | ||
308 | 0x18, 0x2a, 0x4c, 0x4d, I2C_CLIENT_END | ||
309 | }; | ||
310 | |||
311 | static const struct i2c_device_id emc1403_idtable[] = { | ||
312 | { "emc1403", 0 }, | ||
313 | { } | ||
314 | }; | ||
315 | MODULE_DEVICE_TABLE(i2c, emc1403_idtable); | ||
316 | |||
317 | static struct i2c_driver sensor_emc1403 = { | ||
318 | .class = I2C_CLASS_HWMON, | ||
319 | .driver = { | ||
320 | .name = "emc1403", | ||
321 | }, | ||
322 | .detect = emc1403_detect, | ||
323 | .probe = emc1403_probe, | ||
324 | .remove = emc1403_remove, | ||
325 | .id_table = emc1403_idtable, | ||
326 | .address_list = emc1403_address_list, | ||
327 | }; | ||
328 | |||
329 | static int __init sensor_emc1403_init(void) | ||
330 | { | ||
331 | return i2c_add_driver(&sensor_emc1403); | ||
332 | } | ||
333 | |||
334 | static void __exit sensor_emc1403_exit(void) | ||
335 | { | ||
336 | i2c_del_driver(&sensor_emc1403); | ||
337 | } | ||
338 | |||
339 | module_init(sensor_emc1403_init); | ||
340 | module_exit(sensor_emc1403_exit); | ||
341 | |||
342 | MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com"); | ||
343 | MODULE_DESCRIPTION("emc1403 Thermal Driver"); | ||
344 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index a95fa4256caa..537841ef44b9 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c | |||
@@ -856,21 +856,19 @@ static inline int superio_inb(int base, int reg) | |||
856 | static int superio_inw(int base, int reg) | 856 | static int superio_inw(int base, int reg) |
857 | { | 857 | { |
858 | int val; | 858 | int val; |
859 | outb(reg++, base); | 859 | val = superio_inb(base, reg) << 8; |
860 | val = inb(base + 1) << 8; | 860 | val |= superio_inb(base, reg + 1); |
861 | outb(reg, base); | ||
862 | val |= inb(base + 1); | ||
863 | return val; | 861 | return val; |
864 | } | 862 | } |
865 | 863 | ||
866 | static inline void superio_enter(int base) | 864 | static inline void superio_enter(int base) |
867 | { | 865 | { |
868 | /* according to the datasheet the key must be send twice! */ | 866 | /* according to the datasheet the key must be send twice! */ |
869 | outb( SIO_UNLOCK_KEY, base); | 867 | outb(SIO_UNLOCK_KEY, base); |
870 | outb( SIO_UNLOCK_KEY, base); | 868 | outb(SIO_UNLOCK_KEY, base); |
871 | } | 869 | } |
872 | 870 | ||
873 | static inline void superio_select( int base, int ld) | 871 | static inline void superio_select(int base, int ld) |
874 | { | 872 | { |
875 | outb(SIO_REG_LDSEL, base); | 873 | outb(SIO_REG_LDSEL, base); |
876 | outb(ld, base + 1); | 874 | outb(ld, base + 1); |
@@ -905,10 +903,8 @@ static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) | |||
905 | { | 903 | { |
906 | u16 val; | 904 | u16 val; |
907 | 905 | ||
908 | outb(reg++, data->addr + ADDR_REG_OFFSET); | 906 | val = f71882fg_read8(data, reg) << 8; |
909 | val = inb(data->addr + DATA_REG_OFFSET) << 8; | 907 | val |= f71882fg_read8(data, reg + 1); |
910 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
911 | val |= inb(data->addr + DATA_REG_OFFSET); | ||
912 | 908 | ||
913 | return val; | 909 | return val; |
914 | } | 910 | } |
@@ -921,10 +917,8 @@ static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) | |||
921 | 917 | ||
922 | static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) | 918 | static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) |
923 | { | 919 | { |
924 | outb(reg++, data->addr + ADDR_REG_OFFSET); | 920 | f71882fg_write8(data, reg, val >> 8); |
925 | outb(val >> 8, data->addr + DATA_REG_OFFSET); | 921 | f71882fg_write8(data, reg + 1, val & 0xff); |
926 | outb(reg, data->addr + ADDR_REG_OFFSET); | ||
927 | outb(val & 255, data->addr + DATA_REG_OFFSET); | ||
928 | } | 922 | } |
929 | 923 | ||
930 | static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) | 924 | static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) |
@@ -945,7 +939,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev) | |||
945 | mutex_lock(&data->update_lock); | 939 | mutex_lock(&data->update_lock); |
946 | 940 | ||
947 | /* Update once every 60 seconds */ | 941 | /* Update once every 60 seconds */ |
948 | if ( time_after(jiffies, data->last_limits + 60 * HZ ) || | 942 | if (time_after(jiffies, data->last_limits + 60 * HZ) || |
949 | !data->valid) { | 943 | !data->valid) { |
950 | if (data->type == f71882fg || data->type == f71889fg) { | 944 | if (data->type == f71882fg || data->type == f71889fg) { |
951 | data->in1_max = | 945 | data->in1_max = |
@@ -1127,8 +1121,12 @@ static ssize_t store_fan_full_speed(struct device *dev, | |||
1127 | const char *buf, size_t count) | 1121 | const char *buf, size_t count) |
1128 | { | 1122 | { |
1129 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1123 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1130 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1124 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1131 | long val = simple_strtol(buf, NULL, 10); | 1125 | long val; |
1126 | |||
1127 | err = strict_strtol(buf, 10, &val); | ||
1128 | if (err) | ||
1129 | return err; | ||
1132 | 1130 | ||
1133 | val = SENSORS_LIMIT(val, 23, 1500000); | 1131 | val = SENSORS_LIMIT(val, 23, 1500000); |
1134 | val = fan_to_reg(val); | 1132 | val = fan_to_reg(val); |
@@ -1157,8 +1155,12 @@ static ssize_t store_fan_beep(struct device *dev, struct device_attribute | |||
1157 | *devattr, const char *buf, size_t count) | 1155 | *devattr, const char *buf, size_t count) |
1158 | { | 1156 | { |
1159 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1157 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1160 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1158 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1161 | unsigned long val = simple_strtoul(buf, NULL, 10); | 1159 | unsigned long val; |
1160 | |||
1161 | err = strict_strtoul(buf, 10, &val); | ||
1162 | if (err) | ||
1163 | return err; | ||
1162 | 1164 | ||
1163 | mutex_lock(&data->update_lock); | 1165 | mutex_lock(&data->update_lock); |
1164 | data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); | 1166 | data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); |
@@ -1206,7 +1208,14 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute | |||
1206 | *devattr, const char *buf, size_t count) | 1208 | *devattr, const char *buf, size_t count) |
1207 | { | 1209 | { |
1208 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1210 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1209 | long val = simple_strtol(buf, NULL, 10) / 8; | 1211 | int err; |
1212 | long val; | ||
1213 | |||
1214 | err = strict_strtol(buf, 10, &val); | ||
1215 | if (err) | ||
1216 | return err; | ||
1217 | |||
1218 | val /= 8; | ||
1210 | val = SENSORS_LIMIT(val, 0, 255); | 1219 | val = SENSORS_LIMIT(val, 0, 255); |
1211 | 1220 | ||
1212 | mutex_lock(&data->update_lock); | 1221 | mutex_lock(&data->update_lock); |
@@ -1233,8 +1242,12 @@ static ssize_t store_in_beep(struct device *dev, struct device_attribute | |||
1233 | *devattr, const char *buf, size_t count) | 1242 | *devattr, const char *buf, size_t count) |
1234 | { | 1243 | { |
1235 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1244 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1236 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1245 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1237 | unsigned long val = simple_strtoul(buf, NULL, 10); | 1246 | unsigned long val; |
1247 | |||
1248 | err = strict_strtoul(buf, 10, &val); | ||
1249 | if (err) | ||
1250 | return err; | ||
1238 | 1251 | ||
1239 | mutex_lock(&data->update_lock); | 1252 | mutex_lock(&data->update_lock); |
1240 | data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); | 1253 | data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); |
@@ -1299,8 +1312,14 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute | |||
1299 | *devattr, const char *buf, size_t count) | 1312 | *devattr, const char *buf, size_t count) |
1300 | { | 1313 | { |
1301 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1314 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1302 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1315 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1303 | long val = simple_strtol(buf, NULL, 10) / 1000; | 1316 | long val; |
1317 | |||
1318 | err = strict_strtol(buf, 10, &val); | ||
1319 | if (err) | ||
1320 | return err; | ||
1321 | |||
1322 | val /= 1000; | ||
1304 | val = SENSORS_LIMIT(val, 0, 255); | 1323 | val = SENSORS_LIMIT(val, 0, 255); |
1305 | 1324 | ||
1306 | mutex_lock(&data->update_lock); | 1325 | mutex_lock(&data->update_lock); |
@@ -1333,10 +1352,16 @@ static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute | |||
1333 | *devattr, const char *buf, size_t count) | 1352 | *devattr, const char *buf, size_t count) |
1334 | { | 1353 | { |
1335 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1354 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1336 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1355 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1337 | long val = simple_strtol(buf, NULL, 10) / 1000; | ||
1338 | ssize_t ret = count; | 1356 | ssize_t ret = count; |
1339 | u8 reg; | 1357 | u8 reg; |
1358 | long val; | ||
1359 | |||
1360 | err = strict_strtol(buf, 10, &val); | ||
1361 | if (err) | ||
1362 | return err; | ||
1363 | |||
1364 | val /= 1000; | ||
1340 | 1365 | ||
1341 | mutex_lock(&data->update_lock); | 1366 | mutex_lock(&data->update_lock); |
1342 | 1367 | ||
@@ -1372,8 +1397,14 @@ static ssize_t store_temp_crit(struct device *dev, struct device_attribute | |||
1372 | *devattr, const char *buf, size_t count) | 1397 | *devattr, const char *buf, size_t count) |
1373 | { | 1398 | { |
1374 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1399 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1375 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1400 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1376 | long val = simple_strtol(buf, NULL, 10) / 1000; | 1401 | long val; |
1402 | |||
1403 | err = strict_strtol(buf, 10, &val); | ||
1404 | if (err) | ||
1405 | return err; | ||
1406 | |||
1407 | val /= 1000; | ||
1377 | val = SENSORS_LIMIT(val, 0, 255); | 1408 | val = SENSORS_LIMIT(val, 0, 255); |
1378 | 1409 | ||
1379 | mutex_lock(&data->update_lock); | 1410 | mutex_lock(&data->update_lock); |
@@ -1427,8 +1458,12 @@ static ssize_t store_temp_beep(struct device *dev, struct device_attribute | |||
1427 | *devattr, const char *buf, size_t count) | 1458 | *devattr, const char *buf, size_t count) |
1428 | { | 1459 | { |
1429 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1460 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1430 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1461 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1431 | unsigned long val = simple_strtoul(buf, NULL, 10); | 1462 | unsigned long val; |
1463 | |||
1464 | err = strict_strtoul(buf, 10, &val); | ||
1465 | if (err) | ||
1466 | return err; | ||
1432 | 1467 | ||
1433 | mutex_lock(&data->update_lock); | 1468 | mutex_lock(&data->update_lock); |
1434 | data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); | 1469 | data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); |
@@ -1490,8 +1525,13 @@ static ssize_t store_pwm(struct device *dev, | |||
1490 | size_t count) | 1525 | size_t count) |
1491 | { | 1526 | { |
1492 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1527 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1493 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1528 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1494 | long val = simple_strtol(buf, NULL, 10); | 1529 | long val; |
1530 | |||
1531 | err = strict_strtol(buf, 10, &val); | ||
1532 | if (err) | ||
1533 | return err; | ||
1534 | |||
1495 | val = SENSORS_LIMIT(val, 0, 255); | 1535 | val = SENSORS_LIMIT(val, 0, 255); |
1496 | 1536 | ||
1497 | mutex_lock(&data->update_lock); | 1537 | mutex_lock(&data->update_lock); |
@@ -1551,8 +1591,12 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute | |||
1551 | *devattr, const char *buf, size_t count) | 1591 | *devattr, const char *buf, size_t count) |
1552 | { | 1592 | { |
1553 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1593 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1554 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1594 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1555 | long val = simple_strtol(buf, NULL, 10); | 1595 | long val; |
1596 | |||
1597 | err = strict_strtol(buf, 10, &val); | ||
1598 | if (err) | ||
1599 | return err; | ||
1556 | 1600 | ||
1557 | /* Special case for F8000 pwm channel 3 which only does auto mode */ | 1601 | /* Special case for F8000 pwm channel 3 which only does auto mode */ |
1558 | if (data->type == f8000 && nr == 2 && val != 2) | 1602 | if (data->type == f8000 && nr == 2 && val != 2) |
@@ -1626,9 +1670,14 @@ static ssize_t store_pwm_auto_point_pwm(struct device *dev, | |||
1626 | const char *buf, size_t count) | 1670 | const char *buf, size_t count) |
1627 | { | 1671 | { |
1628 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1672 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1629 | int pwm = to_sensor_dev_attr_2(devattr)->index; | 1673 | int err, pwm = to_sensor_dev_attr_2(devattr)->index; |
1630 | int point = to_sensor_dev_attr_2(devattr)->nr; | 1674 | int point = to_sensor_dev_attr_2(devattr)->nr; |
1631 | long val = simple_strtol(buf, NULL, 10); | 1675 | long val; |
1676 | |||
1677 | err = strict_strtol(buf, 10, &val); | ||
1678 | if (err) | ||
1679 | return err; | ||
1680 | |||
1632 | val = SENSORS_LIMIT(val, 0, 255); | 1681 | val = SENSORS_LIMIT(val, 0, 255); |
1633 | 1682 | ||
1634 | mutex_lock(&data->update_lock); | 1683 | mutex_lock(&data->update_lock); |
@@ -1674,10 +1723,16 @@ static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, | |||
1674 | const char *buf, size_t count) | 1723 | const char *buf, size_t count) |
1675 | { | 1724 | { |
1676 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1725 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1677 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1726 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1678 | int point = to_sensor_dev_attr_2(devattr)->nr; | 1727 | int point = to_sensor_dev_attr_2(devattr)->nr; |
1679 | long val = simple_strtol(buf, NULL, 10) / 1000; | ||
1680 | u8 reg; | 1728 | u8 reg; |
1729 | long val; | ||
1730 | |||
1731 | err = strict_strtol(buf, 10, &val); | ||
1732 | if (err) | ||
1733 | return err; | ||
1734 | |||
1735 | val /= 1000; | ||
1681 | 1736 | ||
1682 | mutex_lock(&data->update_lock); | 1737 | mutex_lock(&data->update_lock); |
1683 | data->pwm_auto_point_temp[nr][point] = | 1738 | data->pwm_auto_point_temp[nr][point] = |
@@ -1716,8 +1771,12 @@ static ssize_t store_pwm_interpolate(struct device *dev, | |||
1716 | const char *buf, size_t count) | 1771 | const char *buf, size_t count) |
1717 | { | 1772 | { |
1718 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1773 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1719 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1774 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1720 | unsigned long val = simple_strtoul(buf, NULL, 10); | 1775 | unsigned long val; |
1776 | |||
1777 | err = strict_strtoul(buf, 10, &val); | ||
1778 | if (err) | ||
1779 | return err; | ||
1721 | 1780 | ||
1722 | mutex_lock(&data->update_lock); | 1781 | mutex_lock(&data->update_lock); |
1723 | data->pwm_auto_point_mapping[nr] = | 1782 | data->pwm_auto_point_mapping[nr] = |
@@ -1752,8 +1811,12 @@ static ssize_t store_pwm_auto_point_channel(struct device *dev, | |||
1752 | const char *buf, size_t count) | 1811 | const char *buf, size_t count) |
1753 | { | 1812 | { |
1754 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1813 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1755 | int nr = to_sensor_dev_attr_2(devattr)->index; | 1814 | int err, nr = to_sensor_dev_attr_2(devattr)->index; |
1756 | long val = simple_strtol(buf, NULL, 10); | 1815 | long val; |
1816 | |||
1817 | err = strict_strtol(buf, 10, &val); | ||
1818 | if (err) | ||
1819 | return err; | ||
1757 | 1820 | ||
1758 | switch (val) { | 1821 | switch (val) { |
1759 | case 1: | 1822 | case 1: |
@@ -1798,9 +1861,15 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev, | |||
1798 | const char *buf, size_t count) | 1861 | const char *buf, size_t count) |
1799 | { | 1862 | { |
1800 | struct f71882fg_data *data = dev_get_drvdata(dev); | 1863 | struct f71882fg_data *data = dev_get_drvdata(dev); |
1801 | int pwm = to_sensor_dev_attr_2(devattr)->index; | 1864 | int err, pwm = to_sensor_dev_attr_2(devattr)->index; |
1802 | int point = to_sensor_dev_attr_2(devattr)->nr; | 1865 | int point = to_sensor_dev_attr_2(devattr)->nr; |
1803 | long val = simple_strtol(buf, NULL, 10) / 1000; | 1866 | long val; |
1867 | |||
1868 | err = strict_strtol(buf, 10, &val); | ||
1869 | if (err) | ||
1870 | return err; | ||
1871 | |||
1872 | val /= 1000; | ||
1804 | 1873 | ||
1805 | if (data->type == f71889fg) | 1874 | if (data->type == f71889fg) |
1806 | val = SENSORS_LIMIT(val, -128, 127); | 1875 | val = SENSORS_LIMIT(val, -128, 127); |
@@ -2109,6 +2178,13 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, | |||
2109 | int err = -ENODEV; | 2178 | int err = -ENODEV; |
2110 | u16 devid; | 2179 | u16 devid; |
2111 | 2180 | ||
2181 | /* Don't step on other drivers' I/O space by accident */ | ||
2182 | if (!request_region(sioaddr, 2, DRVNAME)) { | ||
2183 | printk(KERN_ERR DRVNAME ": I/O address 0x%04x already in use\n", | ||
2184 | (int)sioaddr); | ||
2185 | return -EBUSY; | ||
2186 | } | ||
2187 | |||
2112 | superio_enter(sioaddr); | 2188 | superio_enter(sioaddr); |
2113 | 2189 | ||
2114 | devid = superio_inw(sioaddr, SIO_REG_MANID); | 2190 | devid = superio_inw(sioaddr, SIO_REG_MANID); |
@@ -2151,8 +2227,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, | |||
2151 | } | 2227 | } |
2152 | 2228 | ||
2153 | *address = superio_inw(sioaddr, SIO_REG_ADDR); | 2229 | *address = superio_inw(sioaddr, SIO_REG_ADDR); |
2154 | if (*address == 0) | 2230 | if (*address == 0) { |
2155 | { | ||
2156 | printk(KERN_WARNING DRVNAME ": Base address not set\n"); | 2231 | printk(KERN_WARNING DRVNAME ": Base address not set\n"); |
2157 | goto exit; | 2232 | goto exit; |
2158 | } | 2233 | } |
@@ -2164,6 +2239,7 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, | |||
2164 | (int)superio_inb(sioaddr, SIO_REG_DEVREV)); | 2239 | (int)superio_inb(sioaddr, SIO_REG_DEVREV)); |
2165 | exit: | 2240 | exit: |
2166 | superio_exit(sioaddr); | 2241 | superio_exit(sioaddr); |
2242 | release_region(sioaddr, 2); | ||
2167 | return err; | 2243 | return err; |
2168 | } | 2244 | } |
2169 | 2245 | ||
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index bf81aff7051d..776aeb3019d2 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -53,7 +53,7 @@ | |||
53 | * Address is fully defined internally and cannot be changed. | 53 | * Address is fully defined internally and cannot be changed. |
54 | */ | 54 | */ |
55 | 55 | ||
56 | static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; | 56 | static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * The LM63 registers | 59 | * The LM63 registers |
@@ -131,12 +131,15 @@ static struct lm63_data *lm63_update_device(struct device *dev); | |||
131 | static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info); | 131 | static int lm63_detect(struct i2c_client *client, struct i2c_board_info *info); |
132 | static void lm63_init_client(struct i2c_client *client); | 132 | static void lm63_init_client(struct i2c_client *client); |
133 | 133 | ||
134 | enum chips { lm63, lm64 }; | ||
135 | |||
134 | /* | 136 | /* |
135 | * Driver data (common to all clients) | 137 | * Driver data (common to all clients) |
136 | */ | 138 | */ |
137 | 139 | ||
138 | static const struct i2c_device_id lm63_id[] = { | 140 | static const struct i2c_device_id lm63_id[] = { |
139 | { "lm63", 0 }, | 141 | { "lm63", lm63 }, |
142 | { "lm64", lm64 }, | ||
140 | { } | 143 | { } |
141 | }; | 144 | }; |
142 | MODULE_DEVICE_TABLE(i2c, lm63_id); | 145 | MODULE_DEVICE_TABLE(i2c, lm63_id); |
@@ -422,6 +425,7 @@ static int lm63_detect(struct i2c_client *new_client, | |||
422 | struct i2c_adapter *adapter = new_client->adapter; | 425 | struct i2c_adapter *adapter = new_client->adapter; |
423 | u8 man_id, chip_id, reg_config1, reg_config2; | 426 | u8 man_id, chip_id, reg_config1, reg_config2; |
424 | u8 reg_alert_status, reg_alert_mask; | 427 | u8 reg_alert_status, reg_alert_mask; |
428 | int address = new_client->addr; | ||
425 | 429 | ||
426 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 430 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
427 | return -ENODEV; | 431 | return -ENODEV; |
@@ -439,7 +443,6 @@ static int lm63_detect(struct i2c_client *new_client, | |||
439 | LM63_REG_ALERT_MASK); | 443 | LM63_REG_ALERT_MASK); |
440 | 444 | ||
441 | if (man_id != 0x01 /* National Semiconductor */ | 445 | if (man_id != 0x01 /* National Semiconductor */ |
442 | || chip_id != 0x41 /* LM63 */ | ||
443 | || (reg_config1 & 0x18) != 0x00 | 446 | || (reg_config1 & 0x18) != 0x00 |
444 | || (reg_config2 & 0xF8) != 0x00 | 447 | || (reg_config2 & 0xF8) != 0x00 |
445 | || (reg_alert_status & 0x20) != 0x00 | 448 | || (reg_alert_status & 0x20) != 0x00 |
@@ -450,7 +453,12 @@ static int lm63_detect(struct i2c_client *new_client, | |||
450 | return -ENODEV; | 453 | return -ENODEV; |
451 | } | 454 | } |
452 | 455 | ||
453 | strlcpy(info->type, "lm63", I2C_NAME_SIZE); | 456 | if (chip_id == 0x41 && address == 0x4c) |
457 | strlcpy(info->type, "lm63", I2C_NAME_SIZE); | ||
458 | else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e)) | ||
459 | strlcpy(info->type, "lm64", I2C_NAME_SIZE); | ||
460 | else | ||
461 | return -ENODEV; | ||
454 | 462 | ||
455 | return 0; | 463 | return 0; |
456 | } | 464 | } |
diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 8ae2cfe2d827..56463428a419 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c | |||
@@ -46,6 +46,7 @@ enum lm75_type { /* keep sorted in alphabetical order */ | |||
46 | tcn75, | 46 | tcn75, |
47 | tmp100, | 47 | tmp100, |
48 | tmp101, | 48 | tmp101, |
49 | tmp105, | ||
49 | tmp175, | 50 | tmp175, |
50 | tmp275, | 51 | tmp275, |
51 | tmp75, | 52 | tmp75, |
@@ -220,6 +221,7 @@ static const struct i2c_device_id lm75_ids[] = { | |||
220 | { "tcn75", tcn75, }, | 221 | { "tcn75", tcn75, }, |
221 | { "tmp100", tmp100, }, | 222 | { "tmp100", tmp100, }, |
222 | { "tmp101", tmp101, }, | 223 | { "tmp101", tmp101, }, |
224 | { "tmp105", tmp105, }, | ||
223 | { "tmp175", tmp175, }, | 225 | { "tmp175", tmp175, }, |
224 | { "tmp275", tmp275, }, | 226 | { "tmp275", tmp275, }, |
225 | { "tmp75", tmp75, }, | 227 | { "tmp75", tmp75, }, |
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 7cc2708871ab..760ef72eea56 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c | |||
@@ -982,7 +982,8 @@ static struct lm90_data *lm90_update_device(struct device *dev) | |||
982 | 982 | ||
983 | mutex_lock(&data->update_lock); | 983 | mutex_lock(&data->update_lock); |
984 | 984 | ||
985 | if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { | 985 | if (time_after(jiffies, data->last_updated + HZ / 2 + HZ / 10) |
986 | || !data->valid) { | ||
986 | u8 h, l; | 987 | u8 h, l; |
987 | 988 | ||
988 | dev_dbg(&client->dev, "Updating lm90 data.\n"); | 989 | dev_dbg(&client->dev, "Updating lm90 data.\n"); |
diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index 65c232a9d0c5..21d201befc2c 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c | |||
@@ -45,9 +45,7 @@ enum ltc4245_cmd { | |||
45 | LTC4245_VEEIN = 0x19, | 45 | LTC4245_VEEIN = 0x19, |
46 | LTC4245_VEESENSE = 0x1a, | 46 | LTC4245_VEESENSE = 0x1a, |
47 | LTC4245_VEEOUT = 0x1b, | 47 | LTC4245_VEEOUT = 0x1b, |
48 | LTC4245_GPIOADC1 = 0x1c, | 48 | LTC4245_GPIOADC = 0x1c, |
49 | LTC4245_GPIOADC2 = 0x1d, | ||
50 | LTC4245_GPIOADC3 = 0x1e, | ||
51 | }; | 49 | }; |
52 | 50 | ||
53 | struct ltc4245_data { | 51 | struct ltc4245_data { |
@@ -61,7 +59,7 @@ struct ltc4245_data { | |||
61 | u8 cregs[0x08]; | 59 | u8 cregs[0x08]; |
62 | 60 | ||
63 | /* Voltage registers */ | 61 | /* Voltage registers */ |
64 | u8 vregs[0x0f]; | 62 | u8 vregs[0x0d]; |
65 | }; | 63 | }; |
66 | 64 | ||
67 | static struct ltc4245_data *ltc4245_update_device(struct device *dev) | 65 | static struct ltc4245_data *ltc4245_update_device(struct device *dev) |
@@ -86,7 +84,7 @@ static struct ltc4245_data *ltc4245_update_device(struct device *dev) | |||
86 | data->cregs[i] = val; | 84 | data->cregs[i] = val; |
87 | } | 85 | } |
88 | 86 | ||
89 | /* Read voltage registers -- 0x10 to 0x1f */ | 87 | /* Read voltage registers -- 0x10 to 0x1c */ |
90 | for (i = 0; i < ARRAY_SIZE(data->vregs); i++) { | 88 | for (i = 0; i < ARRAY_SIZE(data->vregs); i++) { |
91 | val = i2c_smbus_read_byte_data(client, i+0x10); | 89 | val = i2c_smbus_read_byte_data(client, i+0x10); |
92 | if (unlikely(val < 0)) | 90 | if (unlikely(val < 0)) |
@@ -128,9 +126,7 @@ static int ltc4245_get_voltage(struct device *dev, u8 reg) | |||
128 | case LTC4245_VEEOUT: | 126 | case LTC4245_VEEOUT: |
129 | voltage = regval * -55; | 127 | voltage = regval * -55; |
130 | break; | 128 | break; |
131 | case LTC4245_GPIOADC1: | 129 | case LTC4245_GPIOADC: |
132 | case LTC4245_GPIOADC2: | ||
133 | case LTC4245_GPIOADC3: | ||
134 | voltage = regval * 10; | 130 | voltage = regval * 10; |
135 | break; | 131 | break; |
136 | default: | 132 | default: |
@@ -297,9 +293,7 @@ LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2); | |||
297 | LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); | 293 | LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); |
298 | 294 | ||
299 | /* GPIO voltages */ | 295 | /* GPIO voltages */ |
300 | LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC1); | 296 | LTC4245_VOLTAGE(in9_input, LTC4245_GPIOADC); |
301 | LTC4245_VOLTAGE(in10_input, LTC4245_GPIOADC2); | ||
302 | LTC4245_VOLTAGE(in11_input, LTC4245_GPIOADC3); | ||
303 | 297 | ||
304 | /* Power Consumption (virtual) */ | 298 | /* Power Consumption (virtual) */ |
305 | LTC4245_POWER(power1_input, LTC4245_12VSENSE); | 299 | LTC4245_POWER(power1_input, LTC4245_12VSENSE); |
@@ -342,8 +336,6 @@ static struct attribute *ltc4245_attributes[] = { | |||
342 | &sensor_dev_attr_in8_min_alarm.dev_attr.attr, | 336 | &sensor_dev_attr_in8_min_alarm.dev_attr.attr, |
343 | 337 | ||
344 | &sensor_dev_attr_in9_input.dev_attr.attr, | 338 | &sensor_dev_attr_in9_input.dev_attr.attr, |
345 | &sensor_dev_attr_in10_input.dev_attr.attr, | ||
346 | &sensor_dev_attr_in11_input.dev_attr.attr, | ||
347 | 339 | ||
348 | &sensor_dev_attr_power1_input.dev_attr.attr, | 340 | &sensor_dev_attr_power1_input.dev_attr.attr, |
349 | &sensor_dev_attr_power2_input.dev_attr.attr, | 341 | &sensor_dev_attr_power2_input.dev_attr.attr, |
diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c new file mode 100644 index 000000000000..8013895a1faf --- /dev/null +++ b/drivers/hwmon/tmp102.c | |||
@@ -0,0 +1,321 @@ | |||
1 | /* Texas Instruments TMP102 SMBus temperature sensor driver | ||
2 | * | ||
3 | * Copyright (C) 2010 Steven King <sfking@fdwdc.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/hwmon.h> | ||
25 | #include <linux/hwmon-sysfs.h> | ||
26 | #include <linux/err.h> | ||
27 | #include <linux/mutex.h> | ||
28 | #include <linux/device.h> | ||
29 | |||
30 | #define DRIVER_NAME "tmp102" | ||
31 | |||
32 | #define TMP102_TEMP_REG 0x00 | ||
33 | #define TMP102_CONF_REG 0x01 | ||
34 | /* note: these bit definitions are byte swapped */ | ||
35 | #define TMP102_CONF_SD 0x0100 | ||
36 | #define TMP102_CONF_TM 0x0200 | ||
37 | #define TMP102_CONF_POL 0x0400 | ||
38 | #define TMP102_CONF_F0 0x0800 | ||
39 | #define TMP102_CONF_F1 0x1000 | ||
40 | #define TMP102_CONF_R0 0x2000 | ||
41 | #define TMP102_CONF_R1 0x4000 | ||
42 | #define TMP102_CONF_OS 0x8000 | ||
43 | #define TMP102_CONF_EM 0x0010 | ||
44 | #define TMP102_CONF_AL 0x0020 | ||
45 | #define TMP102_CONF_CR0 0x0040 | ||
46 | #define TMP102_CONF_CR1 0x0080 | ||
47 | #define TMP102_TLOW_REG 0x02 | ||
48 | #define TMP102_THIGH_REG 0x03 | ||
49 | |||
50 | struct tmp102 { | ||
51 | struct device *hwmon_dev; | ||
52 | struct mutex lock; | ||
53 | u16 config_orig; | ||
54 | unsigned long last_update; | ||
55 | int temp[3]; | ||
56 | }; | ||
57 | |||
58 | /* SMBus specifies low byte first, but the TMP102 returns high byte first, | ||
59 | * so we have to swab16 the values */ | ||
60 | static inline int tmp102_read_reg(struct i2c_client *client, u8 reg) | ||
61 | { | ||
62 | int result = i2c_smbus_read_word_data(client, reg); | ||
63 | return result < 0 ? result : swab16(result); | ||
64 | } | ||
65 | |||
66 | static inline int tmp102_write_reg(struct i2c_client *client, u8 reg, u16 val) | ||
67 | { | ||
68 | return i2c_smbus_write_word_data(client, reg, swab16(val)); | ||
69 | } | ||
70 | |||
71 | /* convert left adjusted 13-bit TMP102 register value to milliCelsius */ | ||
72 | static inline int tmp102_reg_to_mC(s16 val) | ||
73 | { | ||
74 | return ((val & ~0x01) * 1000) / 128; | ||
75 | } | ||
76 | |||
77 | /* convert milliCelsius to left adjusted 13-bit TMP102 register value */ | ||
78 | static inline u16 tmp102_mC_to_reg(int val) | ||
79 | { | ||
80 | return (val * 128) / 1000; | ||
81 | } | ||
82 | |||
83 | static const u8 tmp102_reg[] = { | ||
84 | TMP102_TEMP_REG, | ||
85 | TMP102_TLOW_REG, | ||
86 | TMP102_THIGH_REG, | ||
87 | }; | ||
88 | |||
89 | static struct tmp102 *tmp102_update_device(struct i2c_client *client) | ||
90 | { | ||
91 | struct tmp102 *tmp102 = i2c_get_clientdata(client); | ||
92 | |||
93 | mutex_lock(&tmp102->lock); | ||
94 | if (time_after(jiffies, tmp102->last_update + HZ / 3)) { | ||
95 | int i; | ||
96 | for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { | ||
97 | int status = tmp102_read_reg(client, tmp102_reg[i]); | ||
98 | if (status > -1) | ||
99 | tmp102->temp[i] = tmp102_reg_to_mC(status); | ||
100 | } | ||
101 | tmp102->last_update = jiffies; | ||
102 | } | ||
103 | mutex_unlock(&tmp102->lock); | ||
104 | return tmp102; | ||
105 | } | ||
106 | |||
107 | static ssize_t tmp102_show_temp(struct device *dev, | ||
108 | struct device_attribute *attr, | ||
109 | char *buf) | ||
110 | { | ||
111 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | ||
112 | struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev)); | ||
113 | |||
114 | return sprintf(buf, "%d\n", tmp102->temp[sda->index]); | ||
115 | } | ||
116 | |||
117 | static ssize_t tmp102_set_temp(struct device *dev, | ||
118 | struct device_attribute *attr, | ||
119 | const char *buf, size_t count) | ||
120 | { | ||
121 | struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); | ||
122 | struct i2c_client *client = to_i2c_client(dev); | ||
123 | struct tmp102 *tmp102 = i2c_get_clientdata(client); | ||
124 | long val; | ||
125 | int status; | ||
126 | |||
127 | if (strict_strtol(buf, 10, &val) < 0) | ||
128 | return -EINVAL; | ||
129 | val = SENSORS_LIMIT(val, -256000, 255000); | ||
130 | |||
131 | mutex_lock(&tmp102->lock); | ||
132 | tmp102->temp[sda->index] = val; | ||
133 | status = tmp102_write_reg(client, tmp102_reg[sda->index], | ||
134 | tmp102_mC_to_reg(val)); | ||
135 | mutex_unlock(&tmp102->lock); | ||
136 | return status ? : count; | ||
137 | } | ||
138 | |||
139 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0); | ||
140 | |||
141 | static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, | ||
142 | tmp102_set_temp, 1); | ||
143 | |||
144 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, | ||
145 | tmp102_set_temp, 2); | ||
146 | |||
147 | static struct attribute *tmp102_attributes[] = { | ||
148 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
149 | &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, | ||
150 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
151 | NULL | ||
152 | }; | ||
153 | |||
154 | static const struct attribute_group tmp102_attr_group = { | ||
155 | .attrs = tmp102_attributes, | ||
156 | }; | ||
157 | |||
158 | #define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) | ||
159 | #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) | ||
160 | |||
161 | static int __devinit tmp102_probe(struct i2c_client *client, | ||
162 | const struct i2c_device_id *id) | ||
163 | { | ||
164 | struct tmp102 *tmp102; | ||
165 | int status; | ||
166 | |||
167 | if (!i2c_check_functionality(client->adapter, | ||
168 | I2C_FUNC_SMBUS_WORD_DATA)) { | ||
169 | dev_err(&client->dev, "adapter doesnt support SMBus word " | ||
170 | "transactions\n"); | ||
171 | return -ENODEV; | ||
172 | } | ||
173 | |||
174 | tmp102 = kzalloc(sizeof(*tmp102), GFP_KERNEL); | ||
175 | if (!tmp102) { | ||
176 | dev_dbg(&client->dev, "kzalloc failed\n"); | ||
177 | return -ENOMEM; | ||
178 | } | ||
179 | i2c_set_clientdata(client, tmp102); | ||
180 | |||
181 | status = tmp102_read_reg(client, TMP102_CONF_REG); | ||
182 | if (status < 0) { | ||
183 | dev_err(&client->dev, "error reading config register\n"); | ||
184 | goto fail_free; | ||
185 | } | ||
186 | tmp102->config_orig = status; | ||
187 | status = tmp102_write_reg(client, TMP102_CONF_REG, TMP102_CONFIG); | ||
188 | if (status < 0) { | ||
189 | dev_err(&client->dev, "error writing config register\n"); | ||
190 | goto fail_restore_config; | ||
191 | } | ||
192 | status = tmp102_read_reg(client, TMP102_CONF_REG); | ||
193 | if (status < 0) { | ||
194 | dev_err(&client->dev, "error reading config register\n"); | ||
195 | goto fail_restore_config; | ||
196 | } | ||
197 | status &= ~TMP102_CONFIG_RD_ONLY; | ||
198 | if (status != TMP102_CONFIG) { | ||
199 | dev_err(&client->dev, "config settings did not stick\n"); | ||
200 | status = -ENODEV; | ||
201 | goto fail_restore_config; | ||
202 | } | ||
203 | tmp102->last_update = jiffies - HZ; | ||
204 | mutex_init(&tmp102->lock); | ||
205 | |||
206 | status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group); | ||
207 | if (status) { | ||
208 | dev_dbg(&client->dev, "could not create sysfs files\n"); | ||
209 | goto fail_restore_config; | ||
210 | } | ||
211 | tmp102->hwmon_dev = hwmon_device_register(&client->dev); | ||
212 | if (IS_ERR(tmp102->hwmon_dev)) { | ||
213 | dev_dbg(&client->dev, "unable to register hwmon device\n"); | ||
214 | status = PTR_ERR(tmp102->hwmon_dev); | ||
215 | goto fail_remove_sysfs; | ||
216 | } | ||
217 | |||
218 | dev_info(&client->dev, "initialized\n"); | ||
219 | |||
220 | return 0; | ||
221 | |||
222 | fail_remove_sysfs: | ||
223 | sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group); | ||
224 | fail_restore_config: | ||
225 | tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig); | ||
226 | fail_free: | ||
227 | i2c_set_clientdata(client, NULL); | ||
228 | kfree(tmp102); | ||
229 | |||
230 | return status; | ||
231 | } | ||
232 | |||
233 | static int __devexit tmp102_remove(struct i2c_client *client) | ||
234 | { | ||
235 | struct tmp102 *tmp102 = i2c_get_clientdata(client); | ||
236 | |||
237 | hwmon_device_unregister(tmp102->hwmon_dev); | ||
238 | sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group); | ||
239 | |||
240 | /* Stop monitoring if device was stopped originally */ | ||
241 | if (tmp102->config_orig & TMP102_CONF_SD) { | ||
242 | int config; | ||
243 | |||
244 | config = tmp102_read_reg(client, TMP102_CONF_REG); | ||
245 | if (config >= 0) | ||
246 | tmp102_write_reg(client, TMP102_CONF_REG, | ||
247 | config | TMP102_CONF_SD); | ||
248 | } | ||
249 | |||
250 | i2c_set_clientdata(client, NULL); | ||
251 | kfree(tmp102); | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | #ifdef CONFIG_PM | ||
257 | static int tmp102_suspend(struct device *dev) | ||
258 | { | ||
259 | struct i2c_client *client = to_i2c_client(dev); | ||
260 | int config; | ||
261 | |||
262 | config = tmp102_read_reg(client, TMP102_CONF_REG); | ||
263 | if (config < 0) | ||
264 | return config; | ||
265 | |||
266 | config |= TMP102_CONF_SD; | ||
267 | return tmp102_write_reg(client, TMP102_CONF_REG, config); | ||
268 | } | ||
269 | |||
270 | static int tmp102_resume(struct device *dev) | ||
271 | { | ||
272 | struct i2c_client *client = to_i2c_client(dev); | ||
273 | int config; | ||
274 | |||
275 | config = tmp102_read_reg(client, TMP102_CONF_REG); | ||
276 | if (config < 0) | ||
277 | return config; | ||
278 | |||
279 | config &= ~TMP102_CONF_SD; | ||
280 | return tmp102_write_reg(client, TMP102_CONF_REG, config); | ||
281 | } | ||
282 | |||
283 | static const struct dev_pm_ops tmp102_dev_pm_ops = { | ||
284 | .suspend = tmp102_suspend, | ||
285 | .resume = tmp102_resume, | ||
286 | }; | ||
287 | |||
288 | #define TMP102_DEV_PM_OPS (&tmp102_dev_pm_ops) | ||
289 | #else | ||
290 | #define TMP102_DEV_PM_OPS NULL | ||
291 | #endif /* CONFIG_PM */ | ||
292 | |||
293 | static const struct i2c_device_id tmp102_id[] = { | ||
294 | { "tmp102", 0 }, | ||
295 | { } | ||
296 | }; | ||
297 | MODULE_DEVICE_TABLE(i2c, tmp102_id); | ||
298 | |||
299 | static struct i2c_driver tmp102_driver = { | ||
300 | .driver.name = DRIVER_NAME, | ||
301 | .driver.pm = TMP102_DEV_PM_OPS, | ||
302 | .probe = tmp102_probe, | ||
303 | .remove = __devexit_p(tmp102_remove), | ||
304 | .id_table = tmp102_id, | ||
305 | }; | ||
306 | |||
307 | static int __init tmp102_init(void) | ||
308 | { | ||
309 | return i2c_add_driver(&tmp102_driver); | ||
310 | } | ||
311 | module_init(tmp102_init); | ||
312 | |||
313 | static void __exit tmp102_exit(void) | ||
314 | { | ||
315 | i2c_del_driver(&tmp102_driver); | ||
316 | } | ||
317 | module_exit(tmp102_exit); | ||
318 | |||
319 | MODULE_AUTHOR("Steven King <sfking@fdwdc.com>"); | ||
320 | MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver"); | ||
321 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/hwmon/tmp401.c b/drivers/hwmon/tmp401.c index d14a1af9f550..ad8d535235c5 100644 --- a/drivers/hwmon/tmp401.c +++ b/drivers/hwmon/tmp401.c | |||
@@ -92,17 +92,6 @@ static const u8 TMP411_TEMP_HIGHEST_LSB[2] = { 0x33, 0x37 }; | |||
92 | #define TMP411_DEVICE_ID 0x12 | 92 | #define TMP411_DEVICE_ID 0x12 |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * Functions declarations | ||
96 | */ | ||
97 | |||
98 | static int tmp401_probe(struct i2c_client *client, | ||
99 | const struct i2c_device_id *id); | ||
100 | static int tmp401_detect(struct i2c_client *client, | ||
101 | struct i2c_board_info *info); | ||
102 | static int tmp401_remove(struct i2c_client *client); | ||
103 | static struct tmp401_data *tmp401_update_device(struct device *dev); | ||
104 | |||
105 | /* | ||
106 | * Driver data (common to all clients) | 95 | * Driver data (common to all clients) |
107 | */ | 96 | */ |
108 | 97 | ||
@@ -113,18 +102,6 @@ static const struct i2c_device_id tmp401_id[] = { | |||
113 | }; | 102 | }; |
114 | MODULE_DEVICE_TABLE(i2c, tmp401_id); | 103 | MODULE_DEVICE_TABLE(i2c, tmp401_id); |
115 | 104 | ||
116 | static struct i2c_driver tmp401_driver = { | ||
117 | .class = I2C_CLASS_HWMON, | ||
118 | .driver = { | ||
119 | .name = "tmp401", | ||
120 | }, | ||
121 | .probe = tmp401_probe, | ||
122 | .remove = tmp401_remove, | ||
123 | .id_table = tmp401_id, | ||
124 | .detect = tmp401_detect, | ||
125 | .address_list = normal_i2c, | ||
126 | }; | ||
127 | |||
128 | /* | 105 | /* |
129 | * Client data (each client gets its own) | 106 | * Client data (each client gets its own) |
130 | */ | 107 | */ |
@@ -194,6 +171,71 @@ static u8 tmp401_crit_temp_to_register(long temp, u8 config) | |||
194 | return (temp + 500) / 1000; | 171 | return (temp + 500) / 1000; |
195 | } | 172 | } |
196 | 173 | ||
174 | static struct tmp401_data *tmp401_update_device_reg16( | ||
175 | struct i2c_client *client, struct tmp401_data *data) | ||
176 | { | ||
177 | int i; | ||
178 | |||
179 | for (i = 0; i < 2; i++) { | ||
180 | /* | ||
181 | * High byte must be read first immediately followed | ||
182 | * by the low byte | ||
183 | */ | ||
184 | data->temp[i] = i2c_smbus_read_byte_data(client, | ||
185 | TMP401_TEMP_MSB[i]) << 8; | ||
186 | data->temp[i] |= i2c_smbus_read_byte_data(client, | ||
187 | TMP401_TEMP_LSB[i]); | ||
188 | data->temp_low[i] = i2c_smbus_read_byte_data(client, | ||
189 | TMP401_TEMP_LOW_LIMIT_MSB_READ[i]) << 8; | ||
190 | data->temp_low[i] |= i2c_smbus_read_byte_data(client, | ||
191 | TMP401_TEMP_LOW_LIMIT_LSB[i]); | ||
192 | data->temp_high[i] = i2c_smbus_read_byte_data(client, | ||
193 | TMP401_TEMP_HIGH_LIMIT_MSB_READ[i]) << 8; | ||
194 | data->temp_high[i] |= i2c_smbus_read_byte_data(client, | ||
195 | TMP401_TEMP_HIGH_LIMIT_LSB[i]); | ||
196 | data->temp_crit[i] = i2c_smbus_read_byte_data(client, | ||
197 | TMP401_TEMP_CRIT_LIMIT[i]); | ||
198 | |||
199 | if (data->kind == tmp411) { | ||
200 | data->temp_lowest[i] = i2c_smbus_read_byte_data(client, | ||
201 | TMP411_TEMP_LOWEST_MSB[i]) << 8; | ||
202 | data->temp_lowest[i] |= i2c_smbus_read_byte_data( | ||
203 | client, TMP411_TEMP_LOWEST_LSB[i]); | ||
204 | |||
205 | data->temp_highest[i] = i2c_smbus_read_byte_data( | ||
206 | client, TMP411_TEMP_HIGHEST_MSB[i]) << 8; | ||
207 | data->temp_highest[i] |= i2c_smbus_read_byte_data( | ||
208 | client, TMP411_TEMP_HIGHEST_LSB[i]); | ||
209 | } | ||
210 | } | ||
211 | return data; | ||
212 | } | ||
213 | |||
214 | static struct tmp401_data *tmp401_update_device(struct device *dev) | ||
215 | { | ||
216 | struct i2c_client *client = to_i2c_client(dev); | ||
217 | struct tmp401_data *data = i2c_get_clientdata(client); | ||
218 | |||
219 | mutex_lock(&data->update_lock); | ||
220 | |||
221 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
222 | data->status = i2c_smbus_read_byte_data(client, TMP401_STATUS); | ||
223 | data->config = i2c_smbus_read_byte_data(client, | ||
224 | TMP401_CONFIG_READ); | ||
225 | tmp401_update_device_reg16(client, data); | ||
226 | |||
227 | data->temp_crit_hyst = i2c_smbus_read_byte_data(client, | ||
228 | TMP401_TEMP_CRIT_HYST); | ||
229 | |||
230 | data->last_updated = jiffies; | ||
231 | data->valid = 1; | ||
232 | } | ||
233 | |||
234 | mutex_unlock(&data->update_lock); | ||
235 | |||
236 | return data; | ||
237 | } | ||
238 | |||
197 | static ssize_t show_temp_value(struct device *dev, | 239 | static ssize_t show_temp_value(struct device *dev, |
198 | struct device_attribute *devattr, char *buf) | 240 | struct device_attribute *devattr, char *buf) |
199 | { | 241 | { |
@@ -420,30 +462,36 @@ static ssize_t reset_temp_history(struct device *dev, | |||
420 | } | 462 | } |
421 | 463 | ||
422 | static struct sensor_device_attribute tmp401_attr[] = { | 464 | static struct sensor_device_attribute tmp401_attr[] = { |
423 | SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0), | 465 | SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0), |
424 | SENSOR_ATTR(temp1_min, 0644, show_temp_min, store_temp_min, 0), | 466 | SENSOR_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, |
425 | SENSOR_ATTR(temp1_max, 0644, show_temp_max, store_temp_max, 0), | 467 | store_temp_min, 0), |
426 | SENSOR_ATTR(temp1_crit, 0644, show_temp_crit, store_temp_crit, 0), | 468 | SENSOR_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, |
427 | SENSOR_ATTR(temp1_crit_hyst, 0644, show_temp_crit_hyst, | 469 | store_temp_max, 0), |
470 | SENSOR_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit, | ||
471 | store_temp_crit, 0), | ||
472 | SENSOR_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_crit_hyst, | ||
428 | store_temp_crit_hyst, 0), | 473 | store_temp_crit_hyst, 0), |
429 | SENSOR_ATTR(temp1_min_alarm, 0444, show_status, NULL, | 474 | SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_status, NULL, |
430 | TMP401_STATUS_LOCAL_LOW), | 475 | TMP401_STATUS_LOCAL_LOW), |
431 | SENSOR_ATTR(temp1_max_alarm, 0444, show_status, NULL, | 476 | SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_status, NULL, |
432 | TMP401_STATUS_LOCAL_HIGH), | 477 | TMP401_STATUS_LOCAL_HIGH), |
433 | SENSOR_ATTR(temp1_crit_alarm, 0444, show_status, NULL, | 478 | SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_status, NULL, |
434 | TMP401_STATUS_LOCAL_CRIT), | 479 | TMP401_STATUS_LOCAL_CRIT), |
435 | SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1), | 480 | SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1), |
436 | SENSOR_ATTR(temp2_min, 0644, show_temp_min, store_temp_min, 1), | 481 | SENSOR_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, |
437 | SENSOR_ATTR(temp2_max, 0644, show_temp_max, store_temp_max, 1), | 482 | store_temp_min, 1), |
438 | SENSOR_ATTR(temp2_crit, 0644, show_temp_crit, store_temp_crit, 1), | 483 | SENSOR_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, |
439 | SENSOR_ATTR(temp2_crit_hyst, 0444, show_temp_crit_hyst, NULL, 1), | 484 | store_temp_max, 1), |
440 | SENSOR_ATTR(temp2_fault, 0444, show_status, NULL, | 485 | SENSOR_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit, |
486 | store_temp_crit, 1), | ||
487 | SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1), | ||
488 | SENSOR_ATTR(temp2_fault, S_IRUGO, show_status, NULL, | ||
441 | TMP401_STATUS_REMOTE_OPEN), | 489 | TMP401_STATUS_REMOTE_OPEN), |
442 | SENSOR_ATTR(temp2_min_alarm, 0444, show_status, NULL, | 490 | SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_status, NULL, |
443 | TMP401_STATUS_REMOTE_LOW), | 491 | TMP401_STATUS_REMOTE_LOW), |
444 | SENSOR_ATTR(temp2_max_alarm, 0444, show_status, NULL, | 492 | SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_status, NULL, |
445 | TMP401_STATUS_REMOTE_HIGH), | 493 | TMP401_STATUS_REMOTE_HIGH), |
446 | SENSOR_ATTR(temp2_crit_alarm, 0444, show_status, NULL, | 494 | SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL, |
447 | TMP401_STATUS_REMOTE_CRIT), | 495 | TMP401_STATUS_REMOTE_CRIT), |
448 | }; | 496 | }; |
449 | 497 | ||
@@ -455,11 +503,11 @@ static struct sensor_device_attribute tmp401_attr[] = { | |||
455 | * and remote channels. | 503 | * and remote channels. |
456 | */ | 504 | */ |
457 | static struct sensor_device_attribute tmp411_attr[] = { | 505 | static struct sensor_device_attribute tmp411_attr[] = { |
458 | SENSOR_ATTR(temp1_highest, 0444, show_temp_highest, NULL, 0), | 506 | SENSOR_ATTR(temp1_highest, S_IRUGO, show_temp_highest, NULL, 0), |
459 | SENSOR_ATTR(temp1_lowest, 0444, show_temp_lowest, NULL, 0), | 507 | SENSOR_ATTR(temp1_lowest, S_IRUGO, show_temp_lowest, NULL, 0), |
460 | SENSOR_ATTR(temp2_highest, 0444, show_temp_highest, NULL, 1), | 508 | SENSOR_ATTR(temp2_highest, S_IRUGO, show_temp_highest, NULL, 1), |
461 | SENSOR_ATTR(temp2_lowest, 0444, show_temp_lowest, NULL, 1), | 509 | SENSOR_ATTR(temp2_lowest, S_IRUGO, show_temp_lowest, NULL, 1), |
462 | SENSOR_ATTR(temp_reset_history, 0200, NULL, reset_temp_history, 0), | 510 | SENSOR_ATTR(temp_reset_history, S_IWUSR, NULL, reset_temp_history, 0), |
463 | }; | 511 | }; |
464 | 512 | ||
465 | /* | 513 | /* |
@@ -529,6 +577,27 @@ static int tmp401_detect(struct i2c_client *client, | |||
529 | return 0; | 577 | return 0; |
530 | } | 578 | } |
531 | 579 | ||
580 | static int tmp401_remove(struct i2c_client *client) | ||
581 | { | ||
582 | struct tmp401_data *data = i2c_get_clientdata(client); | ||
583 | int i; | ||
584 | |||
585 | if (data->hwmon_dev) | ||
586 | hwmon_device_unregister(data->hwmon_dev); | ||
587 | |||
588 | for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++) | ||
589 | device_remove_file(&client->dev, &tmp401_attr[i].dev_attr); | ||
590 | |||
591 | if (data->kind == tmp411) { | ||
592 | for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) | ||
593 | device_remove_file(&client->dev, | ||
594 | &tmp411_attr[i].dev_attr); | ||
595 | } | ||
596 | |||
597 | kfree(data); | ||
598 | return 0; | ||
599 | } | ||
600 | |||
532 | static int tmp401_probe(struct i2c_client *client, | 601 | static int tmp401_probe(struct i2c_client *client, |
533 | const struct i2c_device_id *id) | 602 | const struct i2c_device_id *id) |
534 | { | 603 | { |
@@ -581,91 +650,17 @@ exit_remove: | |||
581 | return err; | 650 | return err; |
582 | } | 651 | } |
583 | 652 | ||
584 | static int tmp401_remove(struct i2c_client *client) | 653 | static struct i2c_driver tmp401_driver = { |
585 | { | 654 | .class = I2C_CLASS_HWMON, |
586 | struct tmp401_data *data = i2c_get_clientdata(client); | 655 | .driver = { |
587 | int i; | 656 | .name = "tmp401", |
588 | 657 | }, | |
589 | if (data->hwmon_dev) | 658 | .probe = tmp401_probe, |
590 | hwmon_device_unregister(data->hwmon_dev); | 659 | .remove = tmp401_remove, |
591 | 660 | .id_table = tmp401_id, | |
592 | for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++) | 661 | .detect = tmp401_detect, |
593 | device_remove_file(&client->dev, &tmp401_attr[i].dev_attr); | 662 | .address_list = normal_i2c, |
594 | 663 | }; | |
595 | if (data->kind == tmp411) { | ||
596 | for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) | ||
597 | device_remove_file(&client->dev, | ||
598 | &tmp411_attr[i].dev_attr); | ||
599 | } | ||
600 | |||
601 | kfree(data); | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | static struct tmp401_data *tmp401_update_device_reg16( | ||
606 | struct i2c_client *client, struct tmp401_data *data) | ||
607 | { | ||
608 | int i; | ||
609 | |||
610 | for (i = 0; i < 2; i++) { | ||
611 | /* | ||
612 | * High byte must be read first immediately followed | ||
613 | * by the low byte | ||
614 | */ | ||
615 | data->temp[i] = i2c_smbus_read_byte_data(client, | ||
616 | TMP401_TEMP_MSB[i]) << 8; | ||
617 | data->temp[i] |= i2c_smbus_read_byte_data(client, | ||
618 | TMP401_TEMP_LSB[i]); | ||
619 | data->temp_low[i] = i2c_smbus_read_byte_data(client, | ||
620 | TMP401_TEMP_LOW_LIMIT_MSB_READ[i]) << 8; | ||
621 | data->temp_low[i] |= i2c_smbus_read_byte_data(client, | ||
622 | TMP401_TEMP_LOW_LIMIT_LSB[i]); | ||
623 | data->temp_high[i] = i2c_smbus_read_byte_data(client, | ||
624 | TMP401_TEMP_HIGH_LIMIT_MSB_READ[i]) << 8; | ||
625 | data->temp_high[i] |= i2c_smbus_read_byte_data(client, | ||
626 | TMP401_TEMP_HIGH_LIMIT_LSB[i]); | ||
627 | data->temp_crit[i] = i2c_smbus_read_byte_data(client, | ||
628 | TMP401_TEMP_CRIT_LIMIT[i]); | ||
629 | |||
630 | if (data->kind == tmp411) { | ||
631 | data->temp_lowest[i] = i2c_smbus_read_byte_data(client, | ||
632 | TMP411_TEMP_LOWEST_MSB[i]) << 8; | ||
633 | data->temp_lowest[i] |= i2c_smbus_read_byte_data( | ||
634 | client, TMP411_TEMP_LOWEST_LSB[i]); | ||
635 | |||
636 | data->temp_highest[i] = i2c_smbus_read_byte_data( | ||
637 | client, TMP411_TEMP_HIGHEST_MSB[i]) << 8; | ||
638 | data->temp_highest[i] |= i2c_smbus_read_byte_data( | ||
639 | client, TMP411_TEMP_HIGHEST_LSB[i]); | ||
640 | } | ||
641 | } | ||
642 | return data; | ||
643 | } | ||
644 | |||
645 | static struct tmp401_data *tmp401_update_device(struct device *dev) | ||
646 | { | ||
647 | struct i2c_client *client = to_i2c_client(dev); | ||
648 | struct tmp401_data *data = i2c_get_clientdata(client); | ||
649 | |||
650 | mutex_lock(&data->update_lock); | ||
651 | |||
652 | if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { | ||
653 | data->status = i2c_smbus_read_byte_data(client, TMP401_STATUS); | ||
654 | data->config = i2c_smbus_read_byte_data(client, | ||
655 | TMP401_CONFIG_READ); | ||
656 | tmp401_update_device_reg16(client, data); | ||
657 | |||
658 | data->temp_crit_hyst = i2c_smbus_read_byte_data(client, | ||
659 | TMP401_TEMP_CRIT_HYST); | ||
660 | |||
661 | data->last_updated = jiffies; | ||
662 | data->valid = 1; | ||
663 | } | ||
664 | |||
665 | mutex_unlock(&data->update_lock); | ||
666 | |||
667 | return data; | ||
668 | } | ||
669 | 664 | ||
670 | static int __init tmp401_init(void) | 665 | static int __init tmp401_init(void) |
671 | { | 666 | { |
diff --git a/drivers/ide/gayle.c b/drivers/ide/gayle.c index b9e517de6a82..3feaa26410be 100644 --- a/drivers/ide/gayle.c +++ b/drivers/ide/gayle.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/zorro.h> | 17 | #include <linux/zorro.h> |
18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> | ||
19 | 20 | ||
20 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
21 | #include <asm/amigahw.h> | 22 | #include <asm/amigahw.h> |
@@ -24,15 +25,6 @@ | |||
24 | 25 | ||
25 | 26 | ||
26 | /* | 27 | /* |
27 | * Bases of the IDE interfaces | ||
28 | */ | ||
29 | |||
30 | #define GAYLE_BASE_4000 0xdd2020 /* A4000/A4000T */ | ||
31 | #define GAYLE_BASE_1200 0xda0000 /* A1200/A600 and E-Matrix 530 */ | ||
32 | |||
33 | #define GAYLE_IDEREG_SIZE 0x2000 | ||
34 | |||
35 | /* | ||
36 | * Offsets from one of the above bases | 28 | * Offsets from one of the above bases |
37 | */ | 29 | */ |
38 | 30 | ||
@@ -68,20 +60,20 @@ MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); | |||
68 | 60 | ||
69 | static int gayle_test_irq(ide_hwif_t *hwif) | 61 | static int gayle_test_irq(ide_hwif_t *hwif) |
70 | { | 62 | { |
71 | unsigned char ch; | 63 | unsigned char ch; |
72 | 64 | ||
73 | ch = z_readb(hwif->io_ports.irq_addr); | 65 | ch = z_readb(hwif->io_ports.irq_addr); |
74 | if (!(ch & GAYLE_IRQ_IDE)) | 66 | if (!(ch & GAYLE_IRQ_IDE)) |
75 | return 0; | 67 | return 0; |
76 | return 1; | 68 | return 1; |
77 | } | 69 | } |
78 | 70 | ||
79 | static void gayle_a1200_clear_irq(ide_drive_t *drive) | 71 | static void gayle_a1200_clear_irq(ide_drive_t *drive) |
80 | { | 72 | { |
81 | ide_hwif_t *hwif = drive->hwif; | 73 | ide_hwif_t *hwif = drive->hwif; |
82 | 74 | ||
83 | (void)z_readb(hwif->io_ports.status_addr); | 75 | (void)z_readb(hwif->io_ports.status_addr); |
84 | z_writeb(0x7c, hwif->io_ports.irq_addr); | 76 | z_writeb(0x7c, hwif->io_ports.irq_addr); |
85 | } | 77 | } |
86 | 78 | ||
87 | static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, | 79 | static void __init gayle_setup_ports(struct ide_hw *hw, unsigned long base, |
@@ -122,64 +114,89 @@ static const struct ide_port_info gayle_port_info = { | |||
122 | * Probe for a Gayle IDE interface (and optionally for an IDE doubler) | 114 | * Probe for a Gayle IDE interface (and optionally for an IDE doubler) |
123 | */ | 115 | */ |
124 | 116 | ||
125 | static int __init gayle_init(void) | 117 | static int __init amiga_gayle_ide_probe(struct platform_device *pdev) |
126 | { | 118 | { |
127 | unsigned long phys_base, res_start, res_n; | 119 | struct resource *res; |
128 | unsigned long base, ctrlport, irqport; | 120 | struct gayle_ide_platform_data *pdata; |
129 | int a4000, i, rc; | 121 | unsigned long base, ctrlport, irqport; |
130 | struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; | 122 | unsigned int i; |
131 | struct ide_port_info d = gayle_port_info; | 123 | int error; |
132 | 124 | struct ide_hw hw[GAYLE_NUM_HWIFS], *hws[GAYLE_NUM_HWIFS]; | |
133 | if (!MACH_IS_AMIGA) | 125 | struct ide_port_info d = gayle_port_info; |
134 | return -ENODEV; | 126 | struct ide_host *host; |
135 | 127 | ||
136 | if ((a4000 = AMIGAHW_PRESENT(A4000_IDE)) || AMIGAHW_PRESENT(A1200_IDE)) | 128 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
137 | goto found; | 129 | if (!res) |
138 | 130 | return -ENODEV; | |
139 | #ifdef CONFIG_ZORRO | 131 | |
140 | if (zorro_find_device(ZORRO_PROD_MTEC_VIPER_MK_V_E_MATRIX_530_SCSI_IDE, | 132 | if (!request_mem_region(res->start, resource_size(res), "IDE")) |
141 | NULL)) | 133 | return -EBUSY; |
142 | goto found; | 134 | |
143 | #endif | 135 | pdata = pdev->dev.platform_data; |
144 | return -ENODEV; | 136 | pr_info("ide: Gayle IDE controller (A%u style%s)\n", |
145 | 137 | pdata->explicit_ack ? 1200 : 4000, | |
146 | found: | 138 | ide_doubler ? ", IDE doubler" : ""); |
147 | printk(KERN_INFO "ide: Gayle IDE controller (A%d style%s)\n", | 139 | |
148 | a4000 ? 4000 : 1200, | 140 | base = (unsigned long)ZTWO_VADDR(pdata->base); |
149 | ide_doubler ? ", IDE doubler" : ""); | 141 | ctrlport = 0; |
150 | 142 | irqport = (unsigned long)ZTWO_VADDR(pdata->irqport); | |
151 | if (a4000) { | 143 | if (pdata->explicit_ack) |
152 | phys_base = GAYLE_BASE_4000; | 144 | d.port_ops = &gayle_a1200_port_ops; |
153 | irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_4000); | 145 | else |
154 | d.port_ops = &gayle_a4000_port_ops; | 146 | d.port_ops = &gayle_a4000_port_ops; |
155 | } else { | 147 | |
156 | phys_base = GAYLE_BASE_1200; | 148 | for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++, base += GAYLE_NEXT_PORT) { |
157 | irqport = (unsigned long)ZTWO_VADDR(GAYLE_IRQ_1200); | 149 | if (GAYLE_HAS_CONTROL_REG) |
158 | d.port_ops = &gayle_a1200_port_ops; | 150 | ctrlport = base + GAYLE_CONTROL; |
151 | |||
152 | gayle_setup_ports(&hw[i], base, ctrlport, irqport); | ||
153 | hws[i] = &hw[i]; | ||
159 | } | 154 | } |
160 | 155 | ||
161 | res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1); | 156 | error = ide_host_add(&d, hws, i, &host); |
162 | res_n = GAYLE_IDEREG_SIZE; | 157 | if (error) |
158 | goto out; | ||
163 | 159 | ||
164 | if (!request_mem_region(res_start, res_n, "IDE")) | 160 | platform_set_drvdata(pdev, host); |
165 | return -EBUSY; | 161 | return 0; |
166 | 162 | ||
167 | for (i = 0; i < GAYLE_NUM_PROBE_HWIFS; i++) { | 163 | out: |
168 | base = (unsigned long)ZTWO_VADDR(phys_base + i * GAYLE_NEXT_PORT); | 164 | release_mem_region(res->start, resource_size(res)); |
169 | ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0; | 165 | return error; |
166 | } | ||
167 | |||
168 | static int __exit amiga_gayle_ide_remove(struct platform_device *pdev) | ||
169 | { | ||
170 | struct ide_host *host = platform_get_drvdata(pdev); | ||
171 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
172 | |||
173 | ide_host_remove(host); | ||
174 | release_mem_region(res->start, resource_size(res)); | ||
175 | return 0; | ||
176 | } | ||
170 | 177 | ||
171 | gayle_setup_ports(&hw[i], base, ctrlport, irqport); | 178 | static struct platform_driver amiga_gayle_ide_driver = { |
179 | .remove = __exit_p(amiga_gayle_ide_remove), | ||
180 | .driver = { | ||
181 | .name = "amiga-gayle-ide", | ||
182 | .owner = THIS_MODULE, | ||
183 | }, | ||
184 | }; | ||
172 | 185 | ||
173 | hws[i] = &hw[i]; | 186 | static int __init amiga_gayle_ide_init(void) |
174 | } | 187 | { |
188 | return platform_driver_probe(&amiga_gayle_ide_driver, | ||
189 | amiga_gayle_ide_probe); | ||
190 | } | ||
175 | 191 | ||
176 | rc = ide_host_add(&d, hws, i, NULL); | 192 | module_init(amiga_gayle_ide_init); |
177 | if (rc) | ||
178 | release_mem_region(res_start, res_n); | ||
179 | 193 | ||
180 | return rc; | 194 | static void __exit amiga_gayle_ide_exit(void) |
195 | { | ||
196 | platform_driver_unregister(&amiga_gayle_ide_driver); | ||
181 | } | 197 | } |
182 | 198 | ||
183 | module_init(gayle_init); | 199 | module_exit(amiga_gayle_ide_exit); |
184 | 200 | ||
185 | MODULE_LICENSE("GPL"); | 201 | MODULE_LICENSE("GPL"); |
202 | MODULE_ALIAS("platform:amiga-gayle-ide"); | ||
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 9fd4a0d3206e..adaefabc40e9 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c | |||
@@ -1824,7 +1824,7 @@ static int dv1394_open(struct inode *inode, struct file *file) | |||
1824 | "and will not be available in the new firewire driver stack. " | 1824 | "and will not be available in the new firewire driver stack. " |
1825 | "Try libraw1394 based programs instead.\n", current->comm); | 1825 | "Try libraw1394 based programs instead.\n", current->comm); |
1826 | 1826 | ||
1827 | return 0; | 1827 | return nonseekable_open(inode, file); |
1828 | } | 1828 | } |
1829 | 1829 | ||
1830 | 1830 | ||
@@ -2153,17 +2153,18 @@ static struct cdev dv1394_cdev; | |||
2153 | static const struct file_operations dv1394_fops= | 2153 | static const struct file_operations dv1394_fops= |
2154 | { | 2154 | { |
2155 | .owner = THIS_MODULE, | 2155 | .owner = THIS_MODULE, |
2156 | .poll = dv1394_poll, | 2156 | .poll = dv1394_poll, |
2157 | .unlocked_ioctl = dv1394_ioctl, | 2157 | .unlocked_ioctl = dv1394_ioctl, |
2158 | #ifdef CONFIG_COMPAT | 2158 | #ifdef CONFIG_COMPAT |
2159 | .compat_ioctl = dv1394_compat_ioctl, | 2159 | .compat_ioctl = dv1394_compat_ioctl, |
2160 | #endif | 2160 | #endif |
2161 | .mmap = dv1394_mmap, | 2161 | .mmap = dv1394_mmap, |
2162 | .open = dv1394_open, | 2162 | .open = dv1394_open, |
2163 | .write = dv1394_write, | 2163 | .write = dv1394_write, |
2164 | .read = dv1394_read, | 2164 | .read = dv1394_read, |
2165 | .release = dv1394_release, | 2165 | .release = dv1394_release, |
2166 | .fasync = dv1394_fasync, | 2166 | .fasync = dv1394_fasync, |
2167 | .llseek = no_llseek, | ||
2167 | }; | 2168 | }; |
2168 | 2169 | ||
2169 | 2170 | ||
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 8aa56ac07e29..b563d5e9fa2e 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
@@ -2834,7 +2834,7 @@ static int raw1394_open(struct inode *inode, struct file *file) | |||
2834 | 2834 | ||
2835 | file->private_data = fi; | 2835 | file->private_data = fi; |
2836 | 2836 | ||
2837 | return 0; | 2837 | return nonseekable_open(inode, file); |
2838 | } | 2838 | } |
2839 | 2839 | ||
2840 | static int raw1394_release(struct inode *inode, struct file *file) | 2840 | static int raw1394_release(struct inode *inode, struct file *file) |
@@ -3035,6 +3035,7 @@ static const struct file_operations raw1394_fops = { | |||
3035 | .poll = raw1394_poll, | 3035 | .poll = raw1394_poll, |
3036 | .open = raw1394_open, | 3036 | .open = raw1394_open, |
3037 | .release = raw1394_release, | 3037 | .release = raw1394_release, |
3038 | .llseek = no_llseek, | ||
3038 | }; | 3039 | }; |
3039 | 3040 | ||
3040 | static int __init init_raw1394(void) | 3041 | static int __init init_raw1394(void) |
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index 949064a05675..a42bd6893bcf 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c | |||
@@ -1239,7 +1239,7 @@ static int video1394_open(struct inode *inode, struct file *file) | |||
1239 | ctx->current_ctx = NULL; | 1239 | ctx->current_ctx = NULL; |
1240 | file->private_data = ctx; | 1240 | file->private_data = ctx; |
1241 | 1241 | ||
1242 | return 0; | 1242 | return nonseekable_open(inode, file); |
1243 | } | 1243 | } |
1244 | 1244 | ||
1245 | static int video1394_release(struct inode *inode, struct file *file) | 1245 | static int video1394_release(struct inode *inode, struct file *file) |
@@ -1287,7 +1287,8 @@ static const struct file_operations video1394_fops= | |||
1287 | .poll = video1394_poll, | 1287 | .poll = video1394_poll, |
1288 | .mmap = video1394_mmap, | 1288 | .mmap = video1394_mmap, |
1289 | .open = video1394_open, | 1289 | .open = video1394_open, |
1290 | .release = video1394_release | 1290 | .release = video1394_release, |
1291 | .llseek = no_llseek, | ||
1291 | }; | 1292 | }; |
1292 | 1293 | ||
1293 | /*** HOTPLUG STUFF **********************************************************/ | 1294 | /*** HOTPLUG STUFF **********************************************************/ |
diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 07cae552cafb..e571e60ecb88 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c | |||
@@ -847,7 +847,7 @@ static int __cpuinit comp_pool_callback(struct notifier_block *nfb, | |||
847 | ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu); | 847 | ehca_gen_dbg("CPU: %x (CPU_PREPARE)", cpu); |
848 | if (!create_comp_task(pool, cpu)) { | 848 | if (!create_comp_task(pool, cpu)) { |
849 | ehca_gen_err("Can't create comp_task for cpu: %x", cpu); | 849 | ehca_gen_err("Can't create comp_task for cpu: %x", cpu); |
850 | return NOTIFY_BAD; | 850 | return notifier_from_errno(-ENOMEM); |
851 | } | 851 | } |
852 | break; | 852 | break; |
853 | case CPU_UP_CANCELED: | 853 | case CPU_UP_CANCELED: |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 423e0e6031ab..34157bb97ed6 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -47,15 +47,15 @@ struct joydev { | |||
47 | struct mutex mutex; | 47 | struct mutex mutex; |
48 | struct device dev; | 48 | struct device dev; |
49 | 49 | ||
50 | struct js_corr corr[ABS_MAX + 1]; | 50 | struct js_corr corr[ABS_CNT]; |
51 | struct JS_DATA_SAVE_TYPE glue; | 51 | struct JS_DATA_SAVE_TYPE glue; |
52 | int nabs; | 52 | int nabs; |
53 | int nkey; | 53 | int nkey; |
54 | __u16 keymap[KEY_MAX - BTN_MISC + 1]; | 54 | __u16 keymap[KEY_MAX - BTN_MISC + 1]; |
55 | __u16 keypam[KEY_MAX - BTN_MISC + 1]; | 55 | __u16 keypam[KEY_MAX - BTN_MISC + 1]; |
56 | __u8 absmap[ABS_MAX + 1]; | 56 | __u8 absmap[ABS_CNT]; |
57 | __u8 abspam[ABS_MAX + 1]; | 57 | __u8 abspam[ABS_CNT]; |
58 | __s16 abs[ABS_MAX + 1]; | 58 | __s16 abs[ABS_CNT]; |
59 | }; | 59 | }; |
60 | 60 | ||
61 | struct joydev_client { | 61 | struct joydev_client { |
@@ -826,7 +826,7 @@ static int joydev_connect(struct input_handler *handler, struct input_dev *dev, | |||
826 | joydev->handle.handler = handler; | 826 | joydev->handle.handler = handler; |
827 | joydev->handle.private = joydev; | 827 | joydev->handle.private = joydev; |
828 | 828 | ||
829 | for (i = 0; i < ABS_MAX + 1; i++) | 829 | for (i = 0; i < ABS_CNT; i++) |
830 | if (test_bit(i, dev->absbit)) { | 830 | if (test_bit(i, dev->absbit)) { |
831 | joydev->absmap[i] = joydev->nabs; | 831 | joydev->absmap[i] = joydev->nabs; |
832 | joydev->abspam[joydev->nabs] = i; | 832 | joydev->abspam[joydev->nabs] = i; |
diff --git a/drivers/input/keyboard/amikbd.c b/drivers/input/keyboard/amikbd.c index 35149ec455a9..79172af164f2 100644 --- a/drivers/input/keyboard/amikbd.c +++ b/drivers/input/keyboard/amikbd.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/keyboard.h> | 37 | #include <linux/keyboard.h> |
38 | #include <linux/platform_device.h> | ||
38 | 39 | ||
39 | #include <asm/amigaints.h> | 40 | #include <asm/amigaints.h> |
40 | #include <asm/amigahw.h> | 41 | #include <asm/amigahw.h> |
@@ -154,10 +155,9 @@ static const char *amikbd_messages[8] = { | |||
154 | [7] = KERN_WARNING "amikbd: keyboard interrupt\n" | 155 | [7] = KERN_WARNING "amikbd: keyboard interrupt\n" |
155 | }; | 156 | }; |
156 | 157 | ||
157 | static struct input_dev *amikbd_dev; | 158 | static irqreturn_t amikbd_interrupt(int irq, void *data) |
158 | |||
159 | static irqreturn_t amikbd_interrupt(int irq, void *dummy) | ||
160 | { | 159 | { |
160 | struct input_dev *dev = data; | ||
161 | unsigned char scancode, down; | 161 | unsigned char scancode, down; |
162 | 162 | ||
163 | scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */ | 163 | scancode = ~ciaa.sdr; /* get and invert scancode (keyboard is active low) */ |
@@ -170,47 +170,42 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy) | |||
170 | 170 | ||
171 | if (scancode < 0x78) { /* scancodes < 0x78 are keys */ | 171 | if (scancode < 0x78) { /* scancodes < 0x78 are keys */ |
172 | if (scancode == 98) { /* CapsLock is a toggle switch key on Amiga */ | 172 | if (scancode == 98) { /* CapsLock is a toggle switch key on Amiga */ |
173 | input_report_key(amikbd_dev, scancode, 1); | 173 | input_report_key(dev, scancode, 1); |
174 | input_report_key(amikbd_dev, scancode, 0); | 174 | input_report_key(dev, scancode, 0); |
175 | } else { | 175 | } else { |
176 | input_report_key(amikbd_dev, scancode, down); | 176 | input_report_key(dev, scancode, down); |
177 | } | 177 | } |
178 | 178 | ||
179 | input_sync(amikbd_dev); | 179 | input_sync(dev); |
180 | } else /* scancodes >= 0x78 are error codes */ | 180 | } else /* scancodes >= 0x78 are error codes */ |
181 | printk(amikbd_messages[scancode - 0x78]); | 181 | printk(amikbd_messages[scancode - 0x78]); |
182 | 182 | ||
183 | return IRQ_HANDLED; | 183 | return IRQ_HANDLED; |
184 | } | 184 | } |
185 | 185 | ||
186 | static int __init amikbd_init(void) | 186 | static int __init amikbd_probe(struct platform_device *pdev) |
187 | { | 187 | { |
188 | struct input_dev *dev; | ||
188 | int i, j, err; | 189 | int i, j, err; |
189 | 190 | ||
190 | if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) | 191 | dev = input_allocate_device(); |
191 | return -ENODEV; | 192 | if (!dev) { |
192 | 193 | dev_err(&pdev->dev, "Not enough memory for input device\n"); | |
193 | if (!request_mem_region(CIAA_PHYSADDR-1+0xb00, 0x100, "amikeyb")) | 194 | return -ENOMEM; |
194 | return -EBUSY; | ||
195 | |||
196 | amikbd_dev = input_allocate_device(); | ||
197 | if (!amikbd_dev) { | ||
198 | printk(KERN_ERR "amikbd: not enough memory for input device\n"); | ||
199 | err = -ENOMEM; | ||
200 | goto fail1; | ||
201 | } | 195 | } |
202 | 196 | ||
203 | amikbd_dev->name = "Amiga Keyboard"; | 197 | dev->name = pdev->name; |
204 | amikbd_dev->phys = "amikbd/input0"; | 198 | dev->phys = "amikbd/input0"; |
205 | amikbd_dev->id.bustype = BUS_AMIGA; | 199 | dev->id.bustype = BUS_AMIGA; |
206 | amikbd_dev->id.vendor = 0x0001; | 200 | dev->id.vendor = 0x0001; |
207 | amikbd_dev->id.product = 0x0001; | 201 | dev->id.product = 0x0001; |
208 | amikbd_dev->id.version = 0x0100; | 202 | dev->id.version = 0x0100; |
203 | dev->dev.parent = &pdev->dev; | ||
209 | 204 | ||
210 | amikbd_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); | 205 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); |
211 | 206 | ||
212 | for (i = 0; i < 0x78; i++) | 207 | for (i = 0; i < 0x78; i++) |
213 | set_bit(i, amikbd_dev->keybit); | 208 | set_bit(i, dev->keybit); |
214 | 209 | ||
215 | for (i = 0; i < MAX_NR_KEYMAPS; i++) { | 210 | for (i = 0; i < MAX_NR_KEYMAPS; i++) { |
216 | static u_short temp_map[NR_KEYS] __initdata; | 211 | static u_short temp_map[NR_KEYS] __initdata; |
@@ -229,30 +224,54 @@ static int __init amikbd_init(void) | |||
229 | memcpy(key_maps[i], temp_map, sizeof(temp_map)); | 224 | memcpy(key_maps[i], temp_map, sizeof(temp_map)); |
230 | } | 225 | } |
231 | ciaa.cra &= ~0x41; /* serial data in, turn off TA */ | 226 | ciaa.cra &= ~0x41; /* serial data in, turn off TA */ |
232 | if (request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", | 227 | err = request_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt, 0, "amikbd", |
233 | amikbd_interrupt)) { | 228 | dev); |
234 | err = -EBUSY; | 229 | if (err) |
235 | goto fail2; | 230 | goto fail2; |
236 | } | ||
237 | 231 | ||
238 | err = input_register_device(amikbd_dev); | 232 | err = input_register_device(dev); |
239 | if (err) | 233 | if (err) |
240 | goto fail3; | 234 | goto fail3; |
241 | 235 | ||
236 | platform_set_drvdata(pdev, dev); | ||
237 | |||
242 | return 0; | 238 | return 0; |
243 | 239 | ||
244 | fail3: free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); | 240 | fail3: free_irq(IRQ_AMIGA_CIAA_SP, dev); |
245 | fail2: input_free_device(amikbd_dev); | 241 | fail2: input_free_device(dev); |
246 | fail1: release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); | ||
247 | return err; | 242 | return err; |
248 | } | 243 | } |
249 | 244 | ||
250 | static void __exit amikbd_exit(void) | 245 | static int __exit amikbd_remove(struct platform_device *pdev) |
246 | { | ||
247 | struct input_dev *dev = platform_get_drvdata(pdev); | ||
248 | |||
249 | platform_set_drvdata(pdev, NULL); | ||
250 | free_irq(IRQ_AMIGA_CIAA_SP, dev); | ||
251 | input_unregister_device(dev); | ||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static struct platform_driver amikbd_driver = { | ||
256 | .remove = __exit_p(amikbd_remove), | ||
257 | .driver = { | ||
258 | .name = "amiga-keyboard", | ||
259 | .owner = THIS_MODULE, | ||
260 | }, | ||
261 | }; | ||
262 | |||
263 | static int __init amikbd_init(void) | ||
251 | { | 264 | { |
252 | free_irq(IRQ_AMIGA_CIAA_SP, amikbd_interrupt); | 265 | return platform_driver_probe(&amikbd_driver, amikbd_probe); |
253 | input_unregister_device(amikbd_dev); | ||
254 | release_mem_region(CIAA_PHYSADDR - 1 + 0xb00, 0x100); | ||
255 | } | 266 | } |
256 | 267 | ||
257 | module_init(amikbd_init); | 268 | module_init(amikbd_init); |
269 | |||
270 | static void __exit amikbd_exit(void) | ||
271 | { | ||
272 | platform_driver_unregister(&amikbd_driver); | ||
273 | } | ||
274 | |||
258 | module_exit(amikbd_exit); | 275 | module_exit(amikbd_exit); |
276 | |||
277 | MODULE_ALIAS("platform:amiga-keyboard"); | ||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 48cdabec372a..c44b9eafc556 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig | |||
@@ -80,6 +80,16 @@ config INPUT_M68K_BEEP | |||
80 | tristate "M68k Beeper support" | 80 | tristate "M68k Beeper support" |
81 | depends on M68K | 81 | depends on M68K |
82 | 82 | ||
83 | config INPUT_MAX8925_ONKEY | ||
84 | tristate "MAX8925 ONKEY support" | ||
85 | depends on MFD_MAX8925 | ||
86 | help | ||
87 | Support the ONKEY of MAX8925 PMICs as an input device | ||
88 | reporting power button status. | ||
89 | |||
90 | To compile this driver as a module, choose M here: the module | ||
91 | will be called max8925_onkey. | ||
92 | |||
83 | config INPUT_APANEL | 93 | config INPUT_APANEL |
84 | tristate "Fujitsu Lifebook Application Panel buttons" | 94 | tristate "Fujitsu Lifebook Application Panel buttons" |
85 | depends on X86 && I2C && LEDS_CLASS | 95 | depends on X86 && I2C && LEDS_CLASS |
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index f9f577031e06..71fe57d8023f 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o | |||
20 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o | 20 | obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o |
21 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o | 21 | obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o |
22 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o | 22 | obj-$(CONFIG_INPUT_M68K_BEEP) += m68kspkr.o |
23 | obj-$(CONFIG_INPUT_MAX8925_ONKEY) += max8925_onkey.o | ||
23 | obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o | 24 | obj-$(CONFIG_INPUT_PCAP) += pcap_keys.o |
24 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o | 25 | obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o |
25 | obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o | 26 | obj-$(CONFIG_INPUT_PCF8574) += pcf8574_keypad.o |
diff --git a/drivers/input/misc/max8925_onkey.c b/drivers/input/misc/max8925_onkey.c new file mode 100644 index 000000000000..80af44608018 --- /dev/null +++ b/drivers/input/misc/max8925_onkey.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /** | ||
2 | * max8925_onkey.c - MAX8925 ONKEY driver | ||
3 | * | ||
4 | * Copyright (C) 2009 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * | ||
7 | * This file is subject to the terms and conditions of the GNU General | ||
8 | * Public License. See the file "COPYING" in the main directory of this | ||
9 | * archive for more details. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/input.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/mfd/max8925.h> | ||
28 | #include <linux/slab.h> | ||
29 | |||
30 | #define HARDRESET_EN (1 << 7) | ||
31 | #define PWREN_EN (1 << 7) | ||
32 | |||
33 | struct max8925_onkey_info { | ||
34 | struct input_dev *idev; | ||
35 | struct i2c_client *i2c; | ||
36 | int irq; | ||
37 | }; | ||
38 | |||
39 | /* | ||
40 | * MAX8925 gives us an interrupt when ONKEY is held for 3 seconds. | ||
41 | * max8925_set_bits() operates I2C bus and may sleep. So implement | ||
42 | * it in thread IRQ handler. | ||
43 | */ | ||
44 | static irqreturn_t max8925_onkey_handler(int irq, void *data) | ||
45 | { | ||
46 | struct max8925_onkey_info *info = data; | ||
47 | |||
48 | input_report_key(info->idev, KEY_POWER, 1); | ||
49 | input_sync(info->idev); | ||
50 | |||
51 | /* Enable hardreset to halt if system isn't shutdown on time */ | ||
52 | max8925_set_bits(info->i2c, MAX8925_SYSENSEL, | ||
53 | HARDRESET_EN, HARDRESET_EN); | ||
54 | |||
55 | return IRQ_HANDLED; | ||
56 | } | ||
57 | |||
58 | static int __devinit max8925_onkey_probe(struct platform_device *pdev) | ||
59 | { | ||
60 | struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent); | ||
61 | struct max8925_onkey_info *info; | ||
62 | int error; | ||
63 | |||
64 | info = kzalloc(sizeof(struct max8925_onkey_info), GFP_KERNEL); | ||
65 | if (!info) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | info->i2c = chip->i2c; | ||
69 | info->irq = chip->irq_base + MAX8925_IRQ_GPM_SW_3SEC; | ||
70 | |||
71 | info->idev = input_allocate_device(); | ||
72 | if (!info->idev) { | ||
73 | dev_err(chip->dev, "Failed to allocate input dev\n"); | ||
74 | error = -ENOMEM; | ||
75 | goto out_input; | ||
76 | } | ||
77 | |||
78 | info->idev->name = "max8925_on"; | ||
79 | info->idev->phys = "max8925_on/input0"; | ||
80 | info->idev->id.bustype = BUS_I2C; | ||
81 | info->idev->dev.parent = &pdev->dev; | ||
82 | info->idev->evbit[0] = BIT_MASK(EV_KEY); | ||
83 | info->idev->keybit[BIT_WORD(KEY_POWER)] = BIT_MASK(KEY_POWER); | ||
84 | |||
85 | error = request_threaded_irq(info->irq, NULL, max8925_onkey_handler, | ||
86 | IRQF_ONESHOT, "onkey", info); | ||
87 | if (error < 0) { | ||
88 | dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n", | ||
89 | info->irq, error); | ||
90 | goto out_irq; | ||
91 | } | ||
92 | |||
93 | error = input_register_device(info->idev); | ||
94 | if (error) { | ||
95 | dev_err(chip->dev, "Can't register input device: %d\n", error); | ||
96 | goto out; | ||
97 | } | ||
98 | |||
99 | platform_set_drvdata(pdev, info); | ||
100 | |||
101 | return 0; | ||
102 | |||
103 | out: | ||
104 | free_irq(info->irq, info); | ||
105 | out_irq: | ||
106 | input_free_device(info->idev); | ||
107 | out_input: | ||
108 | kfree(info); | ||
109 | return error; | ||
110 | } | ||
111 | |||
112 | static int __devexit max8925_onkey_remove(struct platform_device *pdev) | ||
113 | { | ||
114 | struct max8925_onkey_info *info = platform_get_drvdata(pdev); | ||
115 | |||
116 | free_irq(info->irq, info); | ||
117 | input_unregister_device(info->idev); | ||
118 | kfree(info); | ||
119 | |||
120 | platform_set_drvdata(pdev, NULL); | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static struct platform_driver max8925_onkey_driver = { | ||
126 | .driver = { | ||
127 | .name = "max8925-onkey", | ||
128 | .owner = THIS_MODULE, | ||
129 | }, | ||
130 | .probe = max8925_onkey_probe, | ||
131 | .remove = __devexit_p(max8925_onkey_remove), | ||
132 | }; | ||
133 | |||
134 | static int __init max8925_onkey_init(void) | ||
135 | { | ||
136 | return platform_driver_register(&max8925_onkey_driver); | ||
137 | } | ||
138 | module_init(max8925_onkey_init); | ||
139 | |||
140 | static void __exit max8925_onkey_exit(void) | ||
141 | { | ||
142 | platform_driver_unregister(&max8925_onkey_driver); | ||
143 | } | ||
144 | module_exit(max8925_onkey_exit); | ||
145 | |||
146 | MODULE_DESCRIPTION("Maxim MAX8925 ONKEY driver"); | ||
147 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | ||
148 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c index fee9eac8e04a..4f9b2afc24e8 100644 --- a/drivers/input/misc/twl4030-vibra.c +++ b/drivers/input/misc/twl4030-vibra.c | |||
@@ -90,8 +90,8 @@ static void vibra_disable(struct vibra_info *info) | |||
90 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, | 90 | twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, |
91 | (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); | 91 | (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); |
92 | 92 | ||
93 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); | ||
94 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); | 93 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); |
94 | twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); | ||
95 | 95 | ||
96 | info->enabled = false; | 96 | info->enabled = false; |
97 | } | 97 | } |
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 1477466076ad..b71eb55f2dbc 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -300,7 +300,7 @@ static int uinput_validate_absbits(struct input_dev *dev) | |||
300 | unsigned int cnt; | 300 | unsigned int cnt; |
301 | int retval = 0; | 301 | int retval = 0; |
302 | 302 | ||
303 | for (cnt = 0; cnt < ABS_MAX + 1; cnt++) { | 303 | for (cnt = 0; cnt < ABS_CNT; cnt++) { |
304 | if (!test_bit(cnt, dev->absbit)) | 304 | if (!test_bit(cnt, dev->absbit)) |
305 | continue; | 305 | continue; |
306 | 306 | ||
@@ -387,7 +387,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
387 | dev->id.product = user_dev->id.product; | 387 | dev->id.product = user_dev->id.product; |
388 | dev->id.version = user_dev->id.version; | 388 | dev->id.version = user_dev->id.version; |
389 | 389 | ||
390 | size = sizeof(int) * (ABS_MAX + 1); | 390 | size = sizeof(int) * ABS_CNT; |
391 | memcpy(dev->absmax, user_dev->absmax, size); | 391 | memcpy(dev->absmax, user_dev->absmax, size); |
392 | memcpy(dev->absmin, user_dev->absmin, size); | 392 | memcpy(dev->absmin, user_dev->absmin, size); |
393 | memcpy(dev->absfuzz, user_dev->absfuzz, size); | 393 | memcpy(dev->absfuzz, user_dev->absfuzz, size); |
diff --git a/drivers/input/mouse/amimouse.c b/drivers/input/mouse/amimouse.c index a185ac78a42c..ff5f61a0fd3a 100644 --- a/drivers/input/mouse/amimouse.c +++ b/drivers/input/mouse/amimouse.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/input.h> | 22 | #include <linux/input.h> |
23 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
24 | #include <linux/platform_device.h> | ||
24 | 25 | ||
25 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
26 | #include <asm/setup.h> | 27 | #include <asm/setup.h> |
@@ -34,10 +35,10 @@ MODULE_DESCRIPTION("Amiga mouse driver"); | |||
34 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
35 | 36 | ||
36 | static int amimouse_lastx, amimouse_lasty; | 37 | static int amimouse_lastx, amimouse_lasty; |
37 | static struct input_dev *amimouse_dev; | ||
38 | 38 | ||
39 | static irqreturn_t amimouse_interrupt(int irq, void *dummy) | 39 | static irqreturn_t amimouse_interrupt(int irq, void *data) |
40 | { | 40 | { |
41 | struct input_dev *dev = data; | ||
41 | unsigned short joy0dat, potgor; | 42 | unsigned short joy0dat, potgor; |
42 | int nx, ny, dx, dy; | 43 | int nx, ny, dx, dy; |
43 | 44 | ||
@@ -59,14 +60,14 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy) | |||
59 | 60 | ||
60 | potgor = amiga_custom.potgor; | 61 | potgor = amiga_custom.potgor; |
61 | 62 | ||
62 | input_report_rel(amimouse_dev, REL_X, dx); | 63 | input_report_rel(dev, REL_X, dx); |
63 | input_report_rel(amimouse_dev, REL_Y, dy); | 64 | input_report_rel(dev, REL_Y, dy); |
64 | 65 | ||
65 | input_report_key(amimouse_dev, BTN_LEFT, ciaa.pra & 0x40); | 66 | input_report_key(dev, BTN_LEFT, ciaa.pra & 0x40); |
66 | input_report_key(amimouse_dev, BTN_MIDDLE, potgor & 0x0100); | 67 | input_report_key(dev, BTN_MIDDLE, potgor & 0x0100); |
67 | input_report_key(amimouse_dev, BTN_RIGHT, potgor & 0x0400); | 68 | input_report_key(dev, BTN_RIGHT, potgor & 0x0400); |
68 | 69 | ||
69 | input_sync(amimouse_dev); | 70 | input_sync(dev); |
70 | 71 | ||
71 | return IRQ_HANDLED; | 72 | return IRQ_HANDLED; |
72 | } | 73 | } |
@@ -74,63 +75,90 @@ static irqreturn_t amimouse_interrupt(int irq, void *dummy) | |||
74 | static int amimouse_open(struct input_dev *dev) | 75 | static int amimouse_open(struct input_dev *dev) |
75 | { | 76 | { |
76 | unsigned short joy0dat; | 77 | unsigned short joy0dat; |
78 | int error; | ||
77 | 79 | ||
78 | joy0dat = amiga_custom.joy0dat; | 80 | joy0dat = amiga_custom.joy0dat; |
79 | 81 | ||
80 | amimouse_lastx = joy0dat & 0xff; | 82 | amimouse_lastx = joy0dat & 0xff; |
81 | amimouse_lasty = joy0dat >> 8; | 83 | amimouse_lasty = joy0dat >> 8; |
82 | 84 | ||
83 | if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", amimouse_interrupt)) { | 85 | error = request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", |
84 | printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", IRQ_AMIGA_VERTB); | 86 | dev); |
85 | return -EBUSY; | 87 | if (error) |
86 | } | 88 | dev_err(&dev->dev, "Can't allocate irq %d\n", IRQ_AMIGA_VERTB); |
87 | 89 | ||
88 | return 0; | 90 | return error; |
89 | } | 91 | } |
90 | 92 | ||
91 | static void amimouse_close(struct input_dev *dev) | 93 | static void amimouse_close(struct input_dev *dev) |
92 | { | 94 | { |
93 | free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt); | 95 | free_irq(IRQ_AMIGA_VERTB, dev); |
94 | } | 96 | } |
95 | 97 | ||
96 | static int __init amimouse_init(void) | 98 | static int __init amimouse_probe(struct platform_device *pdev) |
97 | { | 99 | { |
98 | int err; | 100 | int err; |
101 | struct input_dev *dev; | ||
99 | 102 | ||
100 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE)) | 103 | dev = input_allocate_device(); |
101 | return -ENODEV; | 104 | if (!dev) |
102 | |||
103 | amimouse_dev = input_allocate_device(); | ||
104 | if (!amimouse_dev) | ||
105 | return -ENOMEM; | 105 | return -ENOMEM; |
106 | 106 | ||
107 | amimouse_dev->name = "Amiga mouse"; | 107 | dev->name = pdev->name; |
108 | amimouse_dev->phys = "amimouse/input0"; | 108 | dev->phys = "amimouse/input0"; |
109 | amimouse_dev->id.bustype = BUS_AMIGA; | 109 | dev->id.bustype = BUS_AMIGA; |
110 | amimouse_dev->id.vendor = 0x0001; | 110 | dev->id.vendor = 0x0001; |
111 | amimouse_dev->id.product = 0x0002; | 111 | dev->id.product = 0x0002; |
112 | amimouse_dev->id.version = 0x0100; | 112 | dev->id.version = 0x0100; |
113 | 113 | ||
114 | amimouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); | 114 | dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL); |
115 | amimouse_dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); | 115 | dev->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y); |
116 | amimouse_dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | | 116 | dev->keybit[BIT_WORD(BTN_LEFT)] = BIT_MASK(BTN_LEFT) | |
117 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); | 117 | BIT_MASK(BTN_MIDDLE) | BIT_MASK(BTN_RIGHT); |
118 | amimouse_dev->open = amimouse_open; | 118 | dev->open = amimouse_open; |
119 | amimouse_dev->close = amimouse_close; | 119 | dev->close = amimouse_close; |
120 | dev->dev.parent = &pdev->dev; | ||
120 | 121 | ||
121 | err = input_register_device(amimouse_dev); | 122 | err = input_register_device(dev); |
122 | if (err) { | 123 | if (err) { |
123 | input_free_device(amimouse_dev); | 124 | input_free_device(dev); |
124 | return err; | 125 | return err; |
125 | } | 126 | } |
126 | 127 | ||
128 | platform_set_drvdata(pdev, dev); | ||
129 | |||
127 | return 0; | 130 | return 0; |
128 | } | 131 | } |
129 | 132 | ||
130 | static void __exit amimouse_exit(void) | 133 | static int __exit amimouse_remove(struct platform_device *pdev) |
131 | { | 134 | { |
132 | input_unregister_device(amimouse_dev); | 135 | struct input_dev *dev = platform_get_drvdata(pdev); |
136 | |||
137 | platform_set_drvdata(pdev, NULL); | ||
138 | input_unregister_device(dev); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static struct platform_driver amimouse_driver = { | ||
143 | .remove = __exit_p(amimouse_remove), | ||
144 | .driver = { | ||
145 | .name = "amiga-mouse", | ||
146 | .owner = THIS_MODULE, | ||
147 | }, | ||
148 | }; | ||
149 | |||
150 | static int __init amimouse_init(void) | ||
151 | { | ||
152 | return platform_driver_probe(&amimouse_driver, amimouse_probe); | ||
133 | } | 153 | } |
134 | 154 | ||
135 | module_init(amimouse_init); | 155 | module_init(amimouse_init); |
156 | |||
157 | static void __exit amimouse_exit(void) | ||
158 | { | ||
159 | platform_driver_unregister(&amimouse_driver); | ||
160 | } | ||
161 | |||
136 | module_exit(amimouse_exit); | 162 | module_exit(amimouse_exit); |
163 | |||
164 | MODULE_ALIAS("platform:amiga-mouse"); | ||
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 532279cda0e4..634f6f6b9b13 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -1163,8 +1163,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) | |||
1163 | 1163 | ||
1164 | ts->reg = regulator_get(&spi->dev, "vcc"); | 1164 | ts->reg = regulator_get(&spi->dev, "vcc"); |
1165 | if (IS_ERR(ts->reg)) { | 1165 | if (IS_ERR(ts->reg)) { |
1166 | dev_err(&spi->dev, "unable to get regulator: %ld\n", | 1166 | err = PTR_ERR(ts->reg); |
1167 | PTR_ERR(ts->reg)); | 1167 | dev_err(&spi->dev, "unable to get regulator: %ld\n", err); |
1168 | goto err_free_gpio; | 1168 | goto err_free_gpio; |
1169 | } | 1169 | } |
1170 | 1170 | ||
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c index e0b7c834111d..ac5d0f9b0cb1 100644 --- a/drivers/input/touchscreen/s3c2410_ts.c +++ b/drivers/input/touchscreen/s3c2410_ts.c | |||
@@ -413,6 +413,8 @@ static struct dev_pm_ops s3c_ts_pmops = { | |||
413 | #endif | 413 | #endif |
414 | 414 | ||
415 | static struct platform_device_id s3cts_driver_ids[] = { | 415 | static struct platform_device_id s3cts_driver_ids[] = { |
416 | { "s3c2410-ts", 0 }, | ||
417 | { "s3c2440-ts", 0 }, | ||
416 | { "s3c64xx-ts", FEAT_PEN_IRQ }, | 418 | { "s3c64xx-ts", FEAT_PEN_IRQ }, |
417 | { } | 419 | { } |
418 | }; | 420 | }; |
diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 29a8bbf3f086..567d57215c28 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c | |||
@@ -857,6 +857,11 @@ static int nexio_read_data(struct usbtouch_usb *usbtouch, unsigned char *pkt) | |||
857 | if ((pkt[0] & 0xe0) != 0xe0) | 857 | if ((pkt[0] & 0xe0) != 0xe0) |
858 | return 0; | 858 | return 0; |
859 | 859 | ||
860 | if (be16_to_cpu(packet->data_len) > 0xff) | ||
861 | packet->data_len = cpu_to_be16(be16_to_cpu(packet->data_len) - 0x100); | ||
862 | if (be16_to_cpu(packet->x_len) > 0xff) | ||
863 | packet->x_len = cpu_to_be16(be16_to_cpu(packet->x_len) - 0x80); | ||
864 | |||
860 | /* send ACK */ | 865 | /* send ACK */ |
861 | ret = usb_submit_urb(priv->ack, GFP_ATOMIC); | 866 | ret = usb_submit_urb(priv->ack, GFP_ATOMIC); |
862 | 867 | ||
@@ -1112,7 +1117,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = { | |||
1112 | 1117 | ||
1113 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO | 1118 | #ifdef CONFIG_TOUCHSCREEN_USB_NEXIO |
1114 | [DEVTYPE_NEXIO] = { | 1119 | [DEVTYPE_NEXIO] = { |
1115 | .rept_size = 128, | 1120 | .rept_size = 1024, |
1116 | .irq_always = true, | 1121 | .irq_always = true, |
1117 | .read_data = nexio_read_data, | 1122 | .read_data = nexio_read_data, |
1118 | .init = nexio_init, | 1123 | .init = nexio_init, |
diff --git a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c index bd00dceacaf0..bde3c88b8b27 100644 --- a/drivers/isdn/capi/kcapi.c +++ b/drivers/isdn/capi/kcapi.c | |||
@@ -1147,6 +1147,12 @@ load_unlock_out: | |||
1147 | if (ctr->state == CAPI_CTR_DETECTED) | 1147 | if (ctr->state == CAPI_CTR_DETECTED) |
1148 | goto reset_unlock_out; | 1148 | goto reset_unlock_out; |
1149 | 1149 | ||
1150 | if (ctr->reset_ctr == NULL) { | ||
1151 | printk(KERN_DEBUG "kcapi: reset: no reset function\n"); | ||
1152 | retval = -ESRCH; | ||
1153 | goto reset_unlock_out; | ||
1154 | } | ||
1155 | |||
1150 | ctr->reset_ctr(ctr); | 1156 | ctr->reset_ctr(ctr); |
1151 | 1157 | ||
1152 | retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); | 1158 | retval = wait_on_ctr_state(ctr, CAPI_CTR_DETECTED); |
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index ac4cfeed3946..8f78f15c8ef7 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c | |||
@@ -922,30 +922,6 @@ void gigaset_isdn_stop(struct cardstate *cs) | |||
922 | */ | 922 | */ |
923 | 923 | ||
924 | /* | 924 | /* |
925 | * load firmware | ||
926 | */ | ||
927 | static int gigaset_load_firmware(struct capi_ctr *ctr, capiloaddata *data) | ||
928 | { | ||
929 | struct cardstate *cs = ctr->driverdata; | ||
930 | |||
931 | /* AVM specific operation, not needed for Gigaset -- ignore */ | ||
932 | dev_notice(cs->dev, "load_firmware ignored\n"); | ||
933 | |||
934 | return 0; | ||
935 | } | ||
936 | |||
937 | /* | ||
938 | * reset (deactivate) controller | ||
939 | */ | ||
940 | static void gigaset_reset_ctr(struct capi_ctr *ctr) | ||
941 | { | ||
942 | struct cardstate *cs = ctr->driverdata; | ||
943 | |||
944 | /* AVM specific operation, not needed for Gigaset -- ignore */ | ||
945 | dev_notice(cs->dev, "reset_ctr ignored\n"); | ||
946 | } | ||
947 | |||
948 | /* | ||
949 | * register CAPI application | 925 | * register CAPI application |
950 | */ | 926 | */ |
951 | static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, | 927 | static void gigaset_register_appl(struct capi_ctr *ctr, u16 appl, |
@@ -2202,8 +2178,8 @@ int gigaset_isdn_regdev(struct cardstate *cs, const char *isdnid) | |||
2202 | iif->ctr.driverdata = cs; | 2178 | iif->ctr.driverdata = cs; |
2203 | strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name)); | 2179 | strncpy(iif->ctr.name, isdnid, sizeof(iif->ctr.name)); |
2204 | iif->ctr.driver_name = "gigaset"; | 2180 | iif->ctr.driver_name = "gigaset"; |
2205 | iif->ctr.load_firmware = gigaset_load_firmware; | 2181 | iif->ctr.load_firmware = NULL; |
2206 | iif->ctr.reset_ctr = gigaset_reset_ctr; | 2182 | iif->ctr.reset_ctr = NULL; |
2207 | iif->ctr.register_appl = gigaset_register_appl; | 2183 | iif->ctr.register_appl = gigaset_register_appl; |
2208 | iif->ctr.release_appl = gigaset_release_appl; | 2184 | iif->ctr.release_appl = gigaset_release_appl; |
2209 | iif->ctr.send_message = gigaset_send_message; | 2185 | iif->ctr.send_message = gigaset_send_message; |
diff --git a/drivers/isdn/mISDN/timerdev.c b/drivers/isdn/mISDN/timerdev.c index c3243c913ec0..81048b8ed8ad 100644 --- a/drivers/isdn/mISDN/timerdev.c +++ b/drivers/isdn/mISDN/timerdev.c | |||
@@ -98,8 +98,6 @@ mISDN_read(struct file *filep, char __user *buf, size_t count, loff_t *off) | |||
98 | if (*debug & DEBUG_TIMER) | 98 | if (*debug & DEBUG_TIMER) |
99 | printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__, | 99 | printk(KERN_DEBUG "%s(%p, %p, %d, %p)\n", __func__, |
100 | filep, buf, (int)count, off); | 100 | filep, buf, (int)count, off); |
101 | if (*off != filep->f_pos) | ||
102 | return -ESPIPE; | ||
103 | 101 | ||
104 | if (list_empty(&dev->expired) && (dev->work == 0)) { | 102 | if (list_empty(&dev->expired) && (dev->work == 0)) { |
105 | if (filep->f_flags & O_NONBLOCK) | 103 | if (filep->f_flags & O_NONBLOCK) |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 505eb64c329c..f98d17a7108b 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -67,6 +67,16 @@ config LEDS_NET48XX | |||
67 | This option enables support for the Soekris net4801 and net4826 error | 67 | This option enables support for the Soekris net4801 and net4826 error |
68 | LED. | 68 | LED. |
69 | 69 | ||
70 | config LEDS_NET5501 | ||
71 | tristate "LED Support for Soekris net5501 series Error LED" | ||
72 | depends on LEDS_CLASS && LEDS_TRIGGERS | ||
73 | depends on LEDS_GPIO_PLATFORM && GPIO_CS5535 | ||
74 | select LEDS_TRIGGER_DEFAULT_ON | ||
75 | default n | ||
76 | help | ||
77 | Add support for the Soekris net5501 board (detection, error led | ||
78 | and GPIO). | ||
79 | |||
70 | config LEDS_FSG | 80 | config LEDS_FSG |
71 | tristate "LED Support for the Freecom FSG-3" | 81 | tristate "LED Support for the Freecom FSG-3" |
72 | depends on MACH_FSG | 82 | depends on MACH_FSG |
@@ -285,6 +295,13 @@ config LEDS_DELL_NETBOOKS | |||
285 | This adds support for the Latitude 2100 and similar | 295 | This adds support for the Latitude 2100 and similar |
286 | notebooks that have an external LED. | 296 | notebooks that have an external LED. |
287 | 297 | ||
298 | config LEDS_MC13783 | ||
299 | tristate "LED Support for MC13783 PMIC" | ||
300 | depends on MFD_MC13783 | ||
301 | help | ||
302 | This option enable support for on-chip LED drivers found | ||
303 | on Freescale Semiconductor MC13783 PMIC. | ||
304 | |||
288 | config LEDS_TRIGGERS | 305 | config LEDS_TRIGGERS |
289 | bool "LED Trigger support" | 306 | bool "LED Trigger support" |
290 | help | 307 | help |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 0cd8b9957380..2493de499374 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -13,6 +13,7 @@ obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o | |||
13 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o | 13 | obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o |
14 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o | 14 | obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o |
15 | obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o | 15 | obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o |
16 | obj-$(CONFIG_LEDS_NET5501) += leds-net5501.o | ||
16 | obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o | 17 | obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o |
17 | obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o | 18 | obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o |
18 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o | 19 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o |
@@ -35,6 +36,7 @@ obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o | |||
35 | obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o | 36 | obj-$(CONFIG_LEDS_LT3593) += leds-lt3593.o |
36 | obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o | 37 | obj-$(CONFIG_LEDS_ADP5520) += leds-adp5520.o |
37 | obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o | 38 | obj-$(CONFIG_LEDS_DELL_NETBOOKS) += dell-led.o |
39 | obj-$(CONFIG_LEDS_MC13783) += leds-mc13783.o | ||
38 | 40 | ||
39 | # LED SPI Drivers | 41 | # LED SPI Drivers |
40 | obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o | 42 | obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o |
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 69e7d86a5143..260660076507 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c | |||
@@ -74,7 +74,7 @@ static ssize_t led_max_brightness_show(struct device *dev, | |||
74 | 74 | ||
75 | static struct device_attribute led_class_attrs[] = { | 75 | static struct device_attribute led_class_attrs[] = { |
76 | __ATTR(brightness, 0644, led_brightness_show, led_brightness_store), | 76 | __ATTR(brightness, 0644, led_brightness_show, led_brightness_store), |
77 | __ATTR(max_brightness, 0644, led_max_brightness_show, NULL), | 77 | __ATTR(max_brightness, 0444, led_max_brightness_show, NULL), |
78 | #ifdef CONFIG_LEDS_TRIGGERS | 78 | #ifdef CONFIG_LEDS_TRIGGERS |
79 | __ATTR(trigger, 0644, led_trigger_show, led_trigger_store), | 79 | __ATTR(trigger, 0644, led_trigger_show, led_trigger_store), |
80 | #endif | 80 | #endif |
diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 16a60c06c96c..b7677106cff8 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c | |||
@@ -256,8 +256,10 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
256 | if (pdev->dev.parent->platform_data) { | 256 | if (pdev->dev.parent->platform_data) { |
257 | pm860x_pdata = pdev->dev.parent->platform_data; | 257 | pm860x_pdata = pdev->dev.parent->platform_data; |
258 | pdata = pm860x_pdata->led; | 258 | pdata = pm860x_pdata->led; |
259 | } else | 259 | } else { |
260 | pdata = NULL; | 260 | dev_err(&pdev->dev, "missing platform data\n"); |
261 | return -EINVAL; | ||
262 | } | ||
261 | 263 | ||
262 | data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); | 264 | data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL); |
263 | if (data == NULL) | 265 | if (data == NULL) |
@@ -268,8 +270,11 @@ static int pm860x_led_probe(struct platform_device *pdev) | |||
268 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; | 270 | data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion; |
269 | data->iset = pdata->iset; | 271 | data->iset = pdata->iset; |
270 | data->port = __check_device(pdata, data->name); | 272 | data->port = __check_device(pdata, data->name); |
271 | if (data->port < 0) | 273 | if (data->port < 0) { |
274 | dev_err(&pdev->dev, "check device failed\n"); | ||
275 | kfree(data); | ||
272 | return -EINVAL; | 276 | return -EINVAL; |
277 | } | ||
273 | 278 | ||
274 | data->current_brightness = 0; | 279 | data->current_brightness = 0; |
275 | data->cdev.name = data->name; | 280 | data->cdev.name = data->name; |
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 6d94b0b9979c..26843dd6b859 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c | |||
@@ -26,7 +26,8 @@ struct gpio_led_data { | |||
26 | u8 new_level; | 26 | u8 new_level; |
27 | u8 can_sleep; | 27 | u8 can_sleep; |
28 | u8 active_low; | 28 | u8 active_low; |
29 | int (*platform_gpio_blink_set)(unsigned gpio, | 29 | u8 blinking; |
30 | int (*platform_gpio_blink_set)(unsigned gpio, int state, | ||
30 | unsigned long *delay_on, unsigned long *delay_off); | 31 | unsigned long *delay_on, unsigned long *delay_off); |
31 | }; | 32 | }; |
32 | 33 | ||
@@ -35,7 +36,13 @@ static void gpio_led_work(struct work_struct *work) | |||
35 | struct gpio_led_data *led_dat = | 36 | struct gpio_led_data *led_dat = |
36 | container_of(work, struct gpio_led_data, work); | 37 | container_of(work, struct gpio_led_data, work); |
37 | 38 | ||
38 | gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); | 39 | if (led_dat->blinking) { |
40 | led_dat->platform_gpio_blink_set(led_dat->gpio, | ||
41 | led_dat->new_level, | ||
42 | NULL, NULL); | ||
43 | led_dat->blinking = 0; | ||
44 | } else | ||
45 | gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level); | ||
39 | } | 46 | } |
40 | 47 | ||
41 | static void gpio_led_set(struct led_classdev *led_cdev, | 48 | static void gpio_led_set(struct led_classdev *led_cdev, |
@@ -60,8 +67,14 @@ static void gpio_led_set(struct led_classdev *led_cdev, | |||
60 | if (led_dat->can_sleep) { | 67 | if (led_dat->can_sleep) { |
61 | led_dat->new_level = level; | 68 | led_dat->new_level = level; |
62 | schedule_work(&led_dat->work); | 69 | schedule_work(&led_dat->work); |
63 | } else | 70 | } else { |
64 | gpio_set_value(led_dat->gpio, level); | 71 | if (led_dat->blinking) { |
72 | led_dat->platform_gpio_blink_set(led_dat->gpio, level, | ||
73 | NULL, NULL); | ||
74 | led_dat->blinking = 0; | ||
75 | } else | ||
76 | gpio_set_value(led_dat->gpio, level); | ||
77 | } | ||
65 | } | 78 | } |
66 | 79 | ||
67 | static int gpio_blink_set(struct led_classdev *led_cdev, | 80 | static int gpio_blink_set(struct led_classdev *led_cdev, |
@@ -70,12 +83,14 @@ static int gpio_blink_set(struct led_classdev *led_cdev, | |||
70 | struct gpio_led_data *led_dat = | 83 | struct gpio_led_data *led_dat = |
71 | container_of(led_cdev, struct gpio_led_data, cdev); | 84 | container_of(led_cdev, struct gpio_led_data, cdev); |
72 | 85 | ||
73 | return led_dat->platform_gpio_blink_set(led_dat->gpio, delay_on, delay_off); | 86 | led_dat->blinking = 1; |
87 | return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK, | ||
88 | delay_on, delay_off); | ||
74 | } | 89 | } |
75 | 90 | ||
76 | static int __devinit create_gpio_led(const struct gpio_led *template, | 91 | static int __devinit create_gpio_led(const struct gpio_led *template, |
77 | struct gpio_led_data *led_dat, struct device *parent, | 92 | struct gpio_led_data *led_dat, struct device *parent, |
78 | int (*blink_set)(unsigned, unsigned long *, unsigned long *)) | 93 | int (*blink_set)(unsigned, int, unsigned long *, unsigned long *)) |
79 | { | 94 | { |
80 | int ret, state; | 95 | int ret, state; |
81 | 96 | ||
@@ -97,6 +112,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
97 | led_dat->gpio = template->gpio; | 112 | led_dat->gpio = template->gpio; |
98 | led_dat->can_sleep = gpio_cansleep(template->gpio); | 113 | led_dat->can_sleep = gpio_cansleep(template->gpio); |
99 | led_dat->active_low = template->active_low; | 114 | led_dat->active_low = template->active_low; |
115 | led_dat->blinking = 0; | ||
100 | if (blink_set) { | 116 | if (blink_set) { |
101 | led_dat->platform_gpio_blink_set = blink_set; | 117 | led_dat->platform_gpio_blink_set = blink_set; |
102 | led_dat->cdev.blink_set = gpio_blink_set; | 118 | led_dat->cdev.blink_set = gpio_blink_set; |
@@ -113,7 +129,7 @@ static int __devinit create_gpio_led(const struct gpio_led *template, | |||
113 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); | 129 | ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state); |
114 | if (ret < 0) | 130 | if (ret < 0) |
115 | goto err; | 131 | goto err; |
116 | 132 | ||
117 | INIT_WORK(&led_dat->work, gpio_led_work); | 133 | INIT_WORK(&led_dat->work, gpio_led_work); |
118 | 134 | ||
119 | ret = led_classdev_register(parent, &led_dat->cdev); | 135 | ret = led_classdev_register(parent, &led_dat->cdev); |
@@ -234,6 +250,7 @@ static int __devinit of_gpio_leds_probe(struct of_device *ofdev, | |||
234 | led.gpio = of_get_gpio_flags(child, 0, &flags); | 250 | led.gpio = of_get_gpio_flags(child, 0, &flags); |
235 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; | 251 | led.active_low = flags & OF_GPIO_ACTIVE_LOW; |
236 | led.name = of_get_property(child, "label", NULL) ? : child->name; | 252 | led.name = of_get_property(child, "label", NULL) ? : child->name; |
253 | led.blinking = 0; | ||
237 | led.default_trigger = | 254 | led.default_trigger = |
238 | of_get_property(child, "linux,default-trigger", NULL); | 255 | of_get_property(child, "linux,default-trigger", NULL); |
239 | state = of_get_property(child, "default-state", NULL); | 256 | state = of_get_property(child, "default-state", NULL); |
diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c index 8d5ecceba181..932a58da76c4 100644 --- a/drivers/leds/leds-lp3944.c +++ b/drivers/leds/leds-lp3944.c | |||
@@ -379,6 +379,7 @@ static int __devinit lp3944_probe(struct i2c_client *client, | |||
379 | { | 379 | { |
380 | struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; | 380 | struct lp3944_platform_data *lp3944_pdata = client->dev.platform_data; |
381 | struct lp3944_data *data; | 381 | struct lp3944_data *data; |
382 | int err; | ||
382 | 383 | ||
383 | if (lp3944_pdata == NULL) { | 384 | if (lp3944_pdata == NULL) { |
384 | dev_err(&client->dev, "no platform data\n"); | 385 | dev_err(&client->dev, "no platform data\n"); |
@@ -401,9 +402,13 @@ static int __devinit lp3944_probe(struct i2c_client *client, | |||
401 | 402 | ||
402 | mutex_init(&data->lock); | 403 | mutex_init(&data->lock); |
403 | 404 | ||
404 | dev_info(&client->dev, "lp3944 enabled\n"); | 405 | err = lp3944_configure(client, data, lp3944_pdata); |
406 | if (err < 0) { | ||
407 | kfree(data); | ||
408 | return err; | ||
409 | } | ||
405 | 410 | ||
406 | lp3944_configure(client, data, lp3944_pdata); | 411 | dev_info(&client->dev, "lp3944 enabled\n"); |
407 | return 0; | 412 | return 0; |
408 | } | 413 | } |
409 | 414 | ||
diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c new file mode 100644 index 000000000000..f05bb08d0f09 --- /dev/null +++ b/drivers/leds/leds-mc13783.c | |||
@@ -0,0 +1,403 @@ | |||
1 | /* | ||
2 | * LEDs driver for Freescale MC13783 | ||
3 | * | ||
4 | * Copyright (C) 2010 Philippe Rétornaz | ||
5 | * | ||
6 | * Based on leds-da903x: | ||
7 | * Copyright (C) 2008 Compulab, Ltd. | ||
8 | * Mike Rapoport <mike@compulab.co.il> | ||
9 | * | ||
10 | * Copyright (C) 2006-2008 Marvell International Ltd. | ||
11 | * Eric Miao <eric.miao@marvell.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2 as | ||
15 | * published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/leds.h> | ||
23 | #include <linux/workqueue.h> | ||
24 | #include <linux/mfd/mc13783.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | struct mc13783_led { | ||
28 | struct led_classdev cdev; | ||
29 | struct work_struct work; | ||
30 | struct mc13783 *master; | ||
31 | enum led_brightness new_brightness; | ||
32 | int id; | ||
33 | }; | ||
34 | |||
35 | #define MC13783_REG_LED_CONTROL_0 51 | ||
36 | #define MC13783_LED_C0_ENABLE_BIT (1 << 0) | ||
37 | #define MC13783_LED_C0_TRIODE_MD_BIT (1 << 7) | ||
38 | #define MC13783_LED_C0_TRIODE_AD_BIT (1 << 8) | ||
39 | #define MC13783_LED_C0_TRIODE_KP_BIT (1 << 9) | ||
40 | #define MC13783_LED_C0_BOOST_BIT (1 << 10) | ||
41 | #define MC13783_LED_C0_ABMODE_MASK 0x7 | ||
42 | #define MC13783_LED_C0_ABMODE 11 | ||
43 | #define MC13783_LED_C0_ABREF_MASK 0x3 | ||
44 | #define MC13783_LED_C0_ABREF 14 | ||
45 | |||
46 | #define MC13783_REG_LED_CONTROL_1 52 | ||
47 | #define MC13783_LED_C1_TC1HALF_BIT (1 << 18) | ||
48 | |||
49 | #define MC13783_REG_LED_CONTROL_2 53 | ||
50 | #define MC13783_LED_C2_BL_P_MASK 0xf | ||
51 | #define MC13783_LED_C2_MD_P 9 | ||
52 | #define MC13783_LED_C2_AD_P 13 | ||
53 | #define MC13783_LED_C2_KP_P 17 | ||
54 | #define MC13783_LED_C2_BL_C_MASK 0x7 | ||
55 | #define MC13783_LED_C2_MD_C 0 | ||
56 | #define MC13783_LED_C2_AD_C 3 | ||
57 | #define MC13783_LED_C2_KP_C 6 | ||
58 | |||
59 | #define MC13783_REG_LED_CONTROL_3 54 | ||
60 | #define MC13783_LED_C3_TC_P 6 | ||
61 | #define MC13783_LED_C3_TC_P_MASK 0x1f | ||
62 | |||
63 | #define MC13783_REG_LED_CONTROL_4 55 | ||
64 | #define MC13783_REG_LED_CONTROL_5 56 | ||
65 | |||
66 | #define MC13783_LED_Cx_PERIOD 21 | ||
67 | #define MC13783_LED_Cx_PERIOD_MASK 0x3 | ||
68 | #define MC13783_LED_Cx_SLEWLIM_BIT (1 << 23) | ||
69 | #define MC13783_LED_Cx_TRIODE_TC_BIT (1 << 23) | ||
70 | #define MC13783_LED_Cx_TC_C_MASK 0x3 | ||
71 | |||
72 | static void mc13783_led_work(struct work_struct *work) | ||
73 | { | ||
74 | struct mc13783_led *led = container_of(work, struct mc13783_led, work); | ||
75 | int reg = 0; | ||
76 | int mask = 0; | ||
77 | int value = 0; | ||
78 | int bank, off, shift; | ||
79 | |||
80 | switch (led->id) { | ||
81 | case MC13783_LED_MD: | ||
82 | reg = MC13783_REG_LED_CONTROL_2; | ||
83 | mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_MD_P; | ||
84 | value = (led->new_brightness >> 4) << MC13783_LED_C2_MD_P; | ||
85 | break; | ||
86 | case MC13783_LED_AD: | ||
87 | reg = MC13783_REG_LED_CONTROL_2; | ||
88 | mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_AD_P; | ||
89 | value = (led->new_brightness >> 4) << MC13783_LED_C2_AD_P; | ||
90 | break; | ||
91 | case MC13783_LED_KP: | ||
92 | reg = MC13783_REG_LED_CONTROL_2; | ||
93 | mask = MC13783_LED_C2_BL_P_MASK << MC13783_LED_C2_KP_P; | ||
94 | value = (led->new_brightness >> 4) << MC13783_LED_C2_KP_P; | ||
95 | break; | ||
96 | case MC13783_LED_R1: | ||
97 | case MC13783_LED_G1: | ||
98 | case MC13783_LED_B1: | ||
99 | case MC13783_LED_R2: | ||
100 | case MC13783_LED_G2: | ||
101 | case MC13783_LED_B2: | ||
102 | case MC13783_LED_R3: | ||
103 | case MC13783_LED_G3: | ||
104 | case MC13783_LED_B3: | ||
105 | off = led->id - MC13783_LED_R1; | ||
106 | bank = off/3; | ||
107 | reg = MC13783_REG_LED_CONTROL_3 + off/3; | ||
108 | shift = (off - bank * 3) * 5 + MC13783_LED_C3_TC_P; | ||
109 | value = (led->new_brightness >> 3) << shift; | ||
110 | mask = MC13783_LED_C3_TC_P_MASK << shift; | ||
111 | break; | ||
112 | } | ||
113 | |||
114 | mc13783_lock(led->master); | ||
115 | |||
116 | mc13783_reg_rmw(led->master, reg, mask, value); | ||
117 | |||
118 | mc13783_unlock(led->master); | ||
119 | } | ||
120 | |||
121 | static void mc13783_led_set(struct led_classdev *led_cdev, | ||
122 | enum led_brightness value) | ||
123 | { | ||
124 | struct mc13783_led *led; | ||
125 | |||
126 | led = container_of(led_cdev, struct mc13783_led, cdev); | ||
127 | led->new_brightness = value; | ||
128 | schedule_work(&led->work); | ||
129 | } | ||
130 | |||
131 | static int __devinit mc13783_led_setup(struct mc13783_led *led, int max_current) | ||
132 | { | ||
133 | int shift = 0; | ||
134 | int mask = 0; | ||
135 | int value = 0; | ||
136 | int reg = 0; | ||
137 | int ret, bank; | ||
138 | |||
139 | switch (led->id) { | ||
140 | case MC13783_LED_MD: | ||
141 | shift = MC13783_LED_C2_MD_C; | ||
142 | mask = MC13783_LED_C2_BL_C_MASK; | ||
143 | value = max_current & MC13783_LED_C2_BL_C_MASK; | ||
144 | reg = MC13783_REG_LED_CONTROL_2; | ||
145 | break; | ||
146 | case MC13783_LED_AD: | ||
147 | shift = MC13783_LED_C2_AD_C; | ||
148 | mask = MC13783_LED_C2_BL_C_MASK; | ||
149 | value = max_current & MC13783_LED_C2_BL_C_MASK; | ||
150 | reg = MC13783_REG_LED_CONTROL_2; | ||
151 | break; | ||
152 | case MC13783_LED_KP: | ||
153 | shift = MC13783_LED_C2_KP_C; | ||
154 | mask = MC13783_LED_C2_BL_C_MASK; | ||
155 | value = max_current & MC13783_LED_C2_BL_C_MASK; | ||
156 | reg = MC13783_REG_LED_CONTROL_2; | ||
157 | break; | ||
158 | case MC13783_LED_R1: | ||
159 | case MC13783_LED_G1: | ||
160 | case MC13783_LED_B1: | ||
161 | case MC13783_LED_R2: | ||
162 | case MC13783_LED_G2: | ||
163 | case MC13783_LED_B2: | ||
164 | case MC13783_LED_R3: | ||
165 | case MC13783_LED_G3: | ||
166 | case MC13783_LED_B3: | ||
167 | bank = (led->id - MC13783_LED_R1)/3; | ||
168 | reg = MC13783_REG_LED_CONTROL_3 + bank; | ||
169 | shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2; | ||
170 | mask = MC13783_LED_Cx_TC_C_MASK; | ||
171 | value = max_current & MC13783_LED_Cx_TC_C_MASK; | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | mc13783_lock(led->master); | ||
176 | |||
177 | ret = mc13783_reg_rmw(led->master, reg, mask << shift, | ||
178 | value << shift); | ||
179 | |||
180 | mc13783_unlock(led->master); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static int __devinit mc13783_leds_prepare(struct platform_device *pdev) | ||
185 | { | ||
186 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
187 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | ||
188 | int ret = 0; | ||
189 | int reg = 0; | ||
190 | |||
191 | mc13783_lock(dev); | ||
192 | |||
193 | if (pdata->flags & MC13783_LED_TC1HALF) | ||
194 | reg |= MC13783_LED_C1_TC1HALF_BIT; | ||
195 | |||
196 | if (pdata->flags & MC13783_LED_SLEWLIMTC) | ||
197 | reg |= MC13783_LED_Cx_SLEWLIM_BIT; | ||
198 | |||
199 | ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, reg); | ||
200 | if (ret) | ||
201 | goto out; | ||
202 | |||
203 | reg = (pdata->bl_period & MC13783_LED_Cx_PERIOD_MASK) << | ||
204 | MC13783_LED_Cx_PERIOD; | ||
205 | |||
206 | if (pdata->flags & MC13783_LED_SLEWLIMBL) | ||
207 | reg |= MC13783_LED_Cx_SLEWLIM_BIT; | ||
208 | |||
209 | ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, reg); | ||
210 | if (ret) | ||
211 | goto out; | ||
212 | |||
213 | reg = (pdata->tc1_period & MC13783_LED_Cx_PERIOD_MASK) << | ||
214 | MC13783_LED_Cx_PERIOD; | ||
215 | |||
216 | if (pdata->flags & MC13783_LED_TRIODE_TC1) | ||
217 | reg |= MC13783_LED_Cx_TRIODE_TC_BIT; | ||
218 | |||
219 | ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, reg); | ||
220 | if (ret) | ||
221 | goto out; | ||
222 | |||
223 | reg = (pdata->tc2_period & MC13783_LED_Cx_PERIOD_MASK) << | ||
224 | MC13783_LED_Cx_PERIOD; | ||
225 | |||
226 | if (pdata->flags & MC13783_LED_TRIODE_TC2) | ||
227 | reg |= MC13783_LED_Cx_TRIODE_TC_BIT; | ||
228 | |||
229 | ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, reg); | ||
230 | if (ret) | ||
231 | goto out; | ||
232 | |||
233 | reg = (pdata->tc3_period & MC13783_LED_Cx_PERIOD_MASK) << | ||
234 | MC13783_LED_Cx_PERIOD; | ||
235 | |||
236 | if (pdata->flags & MC13783_LED_TRIODE_TC3) | ||
237 | reg |= MC13783_LED_Cx_TRIODE_TC_BIT;; | ||
238 | |||
239 | ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, reg); | ||
240 | if (ret) | ||
241 | goto out; | ||
242 | |||
243 | reg = MC13783_LED_C0_ENABLE_BIT; | ||
244 | if (pdata->flags & MC13783_LED_TRIODE_MD) | ||
245 | reg |= MC13783_LED_C0_TRIODE_MD_BIT; | ||
246 | if (pdata->flags & MC13783_LED_TRIODE_AD) | ||
247 | reg |= MC13783_LED_C0_TRIODE_AD_BIT; | ||
248 | if (pdata->flags & MC13783_LED_TRIODE_KP) | ||
249 | reg |= MC13783_LED_C0_TRIODE_KP_BIT; | ||
250 | if (pdata->flags & MC13783_LED_BOOST_EN) | ||
251 | reg |= MC13783_LED_C0_BOOST_BIT; | ||
252 | |||
253 | reg |= (pdata->abmode & MC13783_LED_C0_ABMODE_MASK) << | ||
254 | MC13783_LED_C0_ABMODE; | ||
255 | reg |= (pdata->abref & MC13783_LED_C0_ABREF_MASK) << | ||
256 | MC13783_LED_C0_ABREF; | ||
257 | |||
258 | ret = mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, reg); | ||
259 | |||
260 | out: | ||
261 | mc13783_unlock(dev); | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | static int __devinit mc13783_led_probe(struct platform_device *pdev) | ||
266 | { | ||
267 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
268 | struct mc13783_led_platform_data *led_cur; | ||
269 | struct mc13783_led *led, *led_dat; | ||
270 | int ret, i; | ||
271 | int init_led = 0; | ||
272 | |||
273 | if (pdata == NULL) { | ||
274 | dev_err(&pdev->dev, "missing platform data\n"); | ||
275 | return -ENODEV; | ||
276 | } | ||
277 | |||
278 | if (pdata->num_leds < 1 || pdata->num_leds > MC13783_LED_MAX) { | ||
279 | dev_err(&pdev->dev, "Invalid led count %d\n", pdata->num_leds); | ||
280 | return -EINVAL; | ||
281 | } | ||
282 | |||
283 | led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL); | ||
284 | if (led == NULL) { | ||
285 | dev_err(&pdev->dev, "failed to alloc memory\n"); | ||
286 | return -ENOMEM; | ||
287 | } | ||
288 | |||
289 | ret = mc13783_leds_prepare(pdev); | ||
290 | if (ret) { | ||
291 | dev_err(&pdev->dev, "unable to init led driver\n"); | ||
292 | goto err_free; | ||
293 | } | ||
294 | |||
295 | for (i = 0; i < pdata->num_leds; i++) { | ||
296 | led_dat = &led[i]; | ||
297 | led_cur = &pdata->led[i]; | ||
298 | |||
299 | if (led_cur->id > MC13783_LED_MAX || led_cur->id < 0) { | ||
300 | dev_err(&pdev->dev, "invalid id %d\n", led_cur->id); | ||
301 | ret = -EINVAL; | ||
302 | goto err_register; | ||
303 | } | ||
304 | |||
305 | if (init_led & (1 << led_cur->id)) { | ||
306 | dev_err(&pdev->dev, "led %d already initialized\n", | ||
307 | led_cur->id); | ||
308 | ret = -EINVAL; | ||
309 | goto err_register; | ||
310 | } | ||
311 | |||
312 | init_led |= 1 << led_cur->id; | ||
313 | led_dat->cdev.name = led_cur->name; | ||
314 | led_dat->cdev.default_trigger = led_cur->default_trigger; | ||
315 | led_dat->cdev.brightness_set = mc13783_led_set; | ||
316 | led_dat->cdev.brightness = LED_OFF; | ||
317 | led_dat->id = led_cur->id; | ||
318 | led_dat->master = dev_get_drvdata(pdev->dev.parent); | ||
319 | |||
320 | INIT_WORK(&led_dat->work, mc13783_led_work); | ||
321 | |||
322 | ret = led_classdev_register(pdev->dev.parent, &led_dat->cdev); | ||
323 | if (ret) { | ||
324 | dev_err(&pdev->dev, "failed to register led %d\n", | ||
325 | led_dat->id); | ||
326 | goto err_register; | ||
327 | } | ||
328 | |||
329 | ret = mc13783_led_setup(led_dat, led_cur->max_current); | ||
330 | if (ret) { | ||
331 | dev_err(&pdev->dev, "unable to init led %d\n", | ||
332 | led_dat->id); | ||
333 | i++; | ||
334 | goto err_register; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | platform_set_drvdata(pdev, led); | ||
339 | return 0; | ||
340 | |||
341 | err_register: | ||
342 | for (i = i - 1; i >= 0; i--) { | ||
343 | led_classdev_unregister(&led[i].cdev); | ||
344 | cancel_work_sync(&led[i].work); | ||
345 | } | ||
346 | |||
347 | err_free: | ||
348 | kfree(led); | ||
349 | return ret; | ||
350 | } | ||
351 | |||
352 | static int __devexit mc13783_led_remove(struct platform_device *pdev) | ||
353 | { | ||
354 | struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); | ||
355 | struct mc13783_led *led = platform_get_drvdata(pdev); | ||
356 | struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent); | ||
357 | int i; | ||
358 | |||
359 | for (i = 0; i < pdata->num_leds; i++) { | ||
360 | led_classdev_unregister(&led[i].cdev); | ||
361 | cancel_work_sync(&led[i].work); | ||
362 | } | ||
363 | |||
364 | mc13783_lock(dev); | ||
365 | |||
366 | mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_0, 0); | ||
367 | mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_1, 0); | ||
368 | mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_2, 0); | ||
369 | mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_3, 0); | ||
370 | mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_4, 0); | ||
371 | mc13783_reg_write(dev, MC13783_REG_LED_CONTROL_5, 0); | ||
372 | |||
373 | mc13783_unlock(dev); | ||
374 | |||
375 | kfree(led); | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | static struct platform_driver mc13783_led_driver = { | ||
380 | .driver = { | ||
381 | .name = "mc13783-led", | ||
382 | .owner = THIS_MODULE, | ||
383 | }, | ||
384 | .probe = mc13783_led_probe, | ||
385 | .remove = __devexit_p(mc13783_led_remove), | ||
386 | }; | ||
387 | |||
388 | static int __init mc13783_led_init(void) | ||
389 | { | ||
390 | return platform_driver_register(&mc13783_led_driver); | ||
391 | } | ||
392 | module_init(mc13783_led_init); | ||
393 | |||
394 | static void __exit mc13783_led_exit(void) | ||
395 | { | ||
396 | platform_driver_unregister(&mc13783_led_driver); | ||
397 | } | ||
398 | module_exit(mc13783_led_exit); | ||
399 | |||
400 | MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC"); | ||
401 | MODULE_AUTHOR("Philippe Retornaz <philippe.retornaz@epfl.ch>"); | ||
402 | MODULE_LICENSE("GPL"); | ||
403 | MODULE_ALIAS("platform:mc13783-led"); | ||
diff --git a/drivers/leds/leds-net5501.c b/drivers/leds/leds-net5501.c new file mode 100644 index 000000000000..3063f591f0dc --- /dev/null +++ b/drivers/leds/leds-net5501.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Soekris board support code | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Tower Technologies | ||
5 | * Written by Alessandro Zummo <a.zummo@towertech.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 | ||
9 | * as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <linux/leds.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/gpio.h> | ||
19 | |||
20 | #include <asm/geode.h> | ||
21 | |||
22 | static struct gpio_led net5501_leds[] = { | ||
23 | { | ||
24 | .name = "error", | ||
25 | .gpio = 6, | ||
26 | .default_trigger = "default-on", | ||
27 | }, | ||
28 | }; | ||
29 | |||
30 | static struct gpio_led_platform_data net5501_leds_data = { | ||
31 | .num_leds = ARRAY_SIZE(net5501_leds), | ||
32 | .leds = net5501_leds, | ||
33 | }; | ||
34 | |||
35 | static struct platform_device net5501_leds_dev = { | ||
36 | .name = "leds-gpio", | ||
37 | .id = -1, | ||
38 | .dev.platform_data = &net5501_leds_data, | ||
39 | }; | ||
40 | |||
41 | static void __init init_net5501(void) | ||
42 | { | ||
43 | platform_device_register(&net5501_leds_dev); | ||
44 | } | ||
45 | |||
46 | struct soekris_board { | ||
47 | u16 offset; | ||
48 | char *sig; | ||
49 | u8 len; | ||
50 | void (*init)(void); | ||
51 | }; | ||
52 | |||
53 | static struct soekris_board __initdata boards[] = { | ||
54 | { 0xb7b, "net5501", 7, init_net5501 }, /* net5501 v1.33/1.33c */ | ||
55 | { 0xb1f, "net5501", 7, init_net5501 }, /* net5501 v1.32i */ | ||
56 | }; | ||
57 | |||
58 | static int __init soekris_init(void) | ||
59 | { | ||
60 | int i; | ||
61 | unsigned char *rombase, *bios; | ||
62 | |||
63 | if (!is_geode()) | ||
64 | return 0; | ||
65 | |||
66 | rombase = ioremap(0xffff0000, 0xffff); | ||
67 | if (!rombase) { | ||
68 | printk(KERN_INFO "Soekris net5501 LED driver failed to get rombase"); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | bios = rombase + 0x20; /* null terminated */ | ||
73 | |||
74 | if (strncmp(bios, "comBIOS", 7)) | ||
75 | goto unmap; | ||
76 | |||
77 | for (i = 0; i < ARRAY_SIZE(boards); i++) { | ||
78 | unsigned char *model = rombase + boards[i].offset; | ||
79 | |||
80 | if (strncmp(model, boards[i].sig, boards[i].len) == 0) { | ||
81 | printk(KERN_INFO "Soekris %s: %s\n", model, bios); | ||
82 | |||
83 | if (boards[i].init) | ||
84 | boards[i].init(); | ||
85 | break; | ||
86 | } | ||
87 | } | ||
88 | |||
89 | unmap: | ||
90 | iounmap(rombase); | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | arch_initcall(soekris_init); | ||
diff --git a/drivers/leds/leds-ss4200.c b/drivers/leds/leds-ss4200.c index 51477ec71391..a688293abd0b 100644 --- a/drivers/leds/leds-ss4200.c +++ b/drivers/leds/leds-ss4200.c | |||
@@ -534,7 +534,7 @@ static int __init nas_gpio_init(void) | |||
534 | set_power_light_amber_noblink(); | 534 | set_power_light_amber_noblink(); |
535 | return 0; | 535 | return 0; |
536 | out_err: | 536 | out_err: |
537 | for (; i >= 0; i--) | 537 | for (i--; i >= 0; i--) |
538 | unregister_nasgpio_led(i); | 538 | unregister_nasgpio_led(i); |
539 | pci_unregister_driver(&nas_gpio_pci_driver); | 539 | pci_unregister_driver(&nas_gpio_pci_driver); |
540 | return ret; | 540 | return ret; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 9ea17d6c799b..d2c0f94fa37d 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -4645,7 +4645,7 @@ static int raid456_cpu_notify(struct notifier_block *nfb, unsigned long action, | |||
4645 | kfree(percpu->scribble); | 4645 | kfree(percpu->scribble); |
4646 | pr_err("%s: failed memory allocation for cpu%ld\n", | 4646 | pr_err("%s: failed memory allocation for cpu%ld\n", |
4647 | __func__, cpu); | 4647 | __func__, cpu); |
4648 | return NOTIFY_BAD; | 4648 | return notifier_from_errno(-ENOMEM); |
4649 | } | 4649 | } |
4650 | break; | 4650 | break; |
4651 | case CPU_DEAD: | 4651 | case CPU_DEAD: |
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index d33693c13368..c4b117f5fb70 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
@@ -186,14 +186,9 @@ static int i2o_cfg_parms(unsigned long arg, unsigned int type) | |||
186 | if (!dev) | 186 | if (!dev) |
187 | return -ENXIO; | 187 | return -ENXIO; |
188 | 188 | ||
189 | ops = kmalloc(kcmd.oplen, GFP_KERNEL); | 189 | ops = memdup_user(kcmd.opbuf, kcmd.oplen); |
190 | if (!ops) | 190 | if (IS_ERR(ops)) |
191 | return -ENOMEM; | 191 | return PTR_ERR(ops); |
192 | |||
193 | if (copy_from_user(ops, kcmd.opbuf, kcmd.oplen)) { | ||
194 | kfree(ops); | ||
195 | return -EFAULT; | ||
196 | } | ||
197 | 192 | ||
198 | /* | 193 | /* |
199 | * It's possible to have a _very_ large table | 194 | * It's possible to have a _very_ large table |
diff --git a/drivers/mfd/mc13783-core.c b/drivers/mfd/mc13783-core.c index 1f68ecadddc2..fecf38a4f025 100644 --- a/drivers/mfd/mc13783-core.c +++ b/drivers/mfd/mc13783-core.c | |||
@@ -679,6 +679,10 @@ err_revision: | |||
679 | if (pdata->flags & MC13783_USE_TOUCHSCREEN) | 679 | if (pdata->flags & MC13783_USE_TOUCHSCREEN) |
680 | mc13783_add_subdevice(mc13783, "mc13783-ts"); | 680 | mc13783_add_subdevice(mc13783, "mc13783-ts"); |
681 | 681 | ||
682 | if (pdata->flags & MC13783_USE_LED) | ||
683 | mc13783_add_subdevice_pdata(mc13783, "mc13783-led", | ||
684 | pdata->leds, sizeof(*pdata->leds)); | ||
685 | |||
682 | return 0; | 686 | return 0; |
683 | } | 687 | } |
684 | 688 | ||
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 63a614d696c1..dc95ddb708f1 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -620,6 +620,9 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
620 | &pcf->mbc_pdev); | 620 | &pcf->mbc_pdev); |
621 | pcf50633_client_dev_register(pcf, "pcf50633-adc", | 621 | pcf50633_client_dev_register(pcf, "pcf50633-adc", |
622 | &pcf->adc_pdev); | 622 | &pcf->adc_pdev); |
623 | pcf50633_client_dev_register(pcf, "pcf50633-backlight", | ||
624 | &pcf->bl_pdev); | ||
625 | |||
623 | 626 | ||
624 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { | 627 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { |
625 | struct platform_device *pdev; | 628 | struct platform_device *pdev; |
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c index 31a991161f0a..5bfb2a2041b8 100644 --- a/drivers/misc/lkdtm.c +++ b/drivers/misc/lkdtm.c | |||
@@ -75,6 +75,9 @@ enum ctype { | |||
75 | UNALIGNED_LOAD_STORE_WRITE, | 75 | UNALIGNED_LOAD_STORE_WRITE, |
76 | OVERWRITE_ALLOCATION, | 76 | OVERWRITE_ALLOCATION, |
77 | WRITE_AFTER_FREE, | 77 | WRITE_AFTER_FREE, |
78 | SOFTLOCKUP, | ||
79 | HARDLOCKUP, | ||
80 | HUNG_TASK, | ||
78 | }; | 81 | }; |
79 | 82 | ||
80 | static char* cp_name[] = { | 83 | static char* cp_name[] = { |
@@ -99,6 +102,9 @@ static char* cp_type[] = { | |||
99 | "UNALIGNED_LOAD_STORE_WRITE", | 102 | "UNALIGNED_LOAD_STORE_WRITE", |
100 | "OVERWRITE_ALLOCATION", | 103 | "OVERWRITE_ALLOCATION", |
101 | "WRITE_AFTER_FREE", | 104 | "WRITE_AFTER_FREE", |
105 | "SOFTLOCKUP", | ||
106 | "HARDLOCKUP", | ||
107 | "HUNG_TASK", | ||
102 | }; | 108 | }; |
103 | 109 | ||
104 | static struct jprobe lkdtm; | 110 | static struct jprobe lkdtm; |
@@ -320,6 +326,20 @@ static void lkdtm_do_action(enum ctype which) | |||
320 | memset(data, 0x78, len); | 326 | memset(data, 0x78, len); |
321 | break; | 327 | break; |
322 | } | 328 | } |
329 | case SOFTLOCKUP: | ||
330 | preempt_disable(); | ||
331 | for (;;) | ||
332 | cpu_relax(); | ||
333 | break; | ||
334 | case HARDLOCKUP: | ||
335 | local_irq_disable(); | ||
336 | for (;;) | ||
337 | cpu_relax(); | ||
338 | break; | ||
339 | case HUNG_TASK: | ||
340 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
341 | schedule(); | ||
342 | break; | ||
323 | case NONE: | 343 | case NONE: |
324 | default: | 344 | default: |
325 | break; | 345 | break; |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 3168ebd616b2..569e94da844c 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
@@ -1252,9 +1252,8 @@ EXPORT_SYMBOL(mmc_card_can_sleep); | |||
1252 | /** | 1252 | /** |
1253 | * mmc_suspend_host - suspend a host | 1253 | * mmc_suspend_host - suspend a host |
1254 | * @host: mmc host | 1254 | * @host: mmc host |
1255 | * @state: suspend mode (PM_SUSPEND_xxx) | ||
1256 | */ | 1255 | */ |
1257 | int mmc_suspend_host(struct mmc_host *host, pm_message_t state) | 1256 | int mmc_suspend_host(struct mmc_host *host) |
1258 | { | 1257 | { |
1259 | int err = 0; | 1258 | int err = 0; |
1260 | 1259 | ||
diff --git a/drivers/mmc/core/sd_ops.c b/drivers/mmc/core/sd_ops.c index 0d96080d44b0..63772e7e7608 100644 --- a/drivers/mmc/core/sd_ops.c +++ b/drivers/mmc/core/sd_ops.c | |||
@@ -79,8 +79,6 @@ int mmc_wait_for_app_cmd(struct mmc_host *host, struct mmc_card *card, | |||
79 | * we cannot use the retries field in mmc_command. | 79 | * we cannot use the retries field in mmc_command. |
80 | */ | 80 | */ |
81 | for (i = 0;i <= retries;i++) { | 81 | for (i = 0;i <= retries;i++) { |
82 | memset(&mrq, 0, sizeof(struct mmc_request)); | ||
83 | |||
84 | err = mmc_app_cmd(host, card); | 82 | err = mmc_app_cmd(host, card); |
85 | if (err) { | 83 | if (err) { |
86 | /* no point in retrying; no APP commands allowed */ | 84 | /* no point in retrying; no APP commands allowed */ |
diff --git a/drivers/mmc/core/sdio_io.c b/drivers/mmc/core/sdio_io.c index ff27c8c71355..0f687cdeb064 100644 --- a/drivers/mmc/core/sdio_io.c +++ b/drivers/mmc/core/sdio_io.c | |||
@@ -406,6 +406,36 @@ void sdio_writeb(struct sdio_func *func, u8 b, unsigned int addr, int *err_ret) | |||
406 | EXPORT_SYMBOL_GPL(sdio_writeb); | 406 | EXPORT_SYMBOL_GPL(sdio_writeb); |
407 | 407 | ||
408 | /** | 408 | /** |
409 | * sdio_writeb_readb - write and read a byte from SDIO function | ||
410 | * @func: SDIO function to access | ||
411 | * @write_byte: byte to write | ||
412 | * @addr: address to write to | ||
413 | * @err_ret: optional status value from transfer | ||
414 | * | ||
415 | * Performs a RAW (Read after Write) operation as defined by SDIO spec - | ||
416 | * single byte is written to address space of a given SDIO function and | ||
417 | * response is read back from the same address, both using single request. | ||
418 | * If there is a problem with the operation, 0xff is returned and | ||
419 | * @err_ret will contain the error code. | ||
420 | */ | ||
421 | u8 sdio_writeb_readb(struct sdio_func *func, u8 write_byte, | ||
422 | unsigned int addr, int *err_ret) | ||
423 | { | ||
424 | int ret; | ||
425 | u8 val; | ||
426 | |||
427 | ret = mmc_io_rw_direct(func->card, 1, func->num, addr, | ||
428 | write_byte, &val); | ||
429 | if (err_ret) | ||
430 | *err_ret = ret; | ||
431 | if (ret) | ||
432 | val = 0xff; | ||
433 | |||
434 | return val; | ||
435 | } | ||
436 | EXPORT_SYMBOL_GPL(sdio_writeb_readb); | ||
437 | |||
438 | /** | ||
409 | * sdio_memcpy_fromio - read a chunk of memory from a SDIO function | 439 | * sdio_memcpy_fromio - read a chunk of memory from a SDIO function |
410 | * @func: SDIO function to access | 440 | * @func: SDIO function to access |
411 | * @dst: buffer to store the data | 441 | * @dst: buffer to store the data |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 2e13b94769fd..e171e77f6129 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -136,6 +136,18 @@ config MMC_SDHCI_S3C | |||
136 | 136 | ||
137 | If unsure, say N. | 137 | If unsure, say N. |
138 | 138 | ||
139 | config MMC_SDHCI_SPEAR | ||
140 | tristate "SDHCI support on ST SPEAr platform" | ||
141 | depends on MMC_SDHCI && PLAT_SPEAR | ||
142 | help | ||
143 | This selects the Secure Digital Host Controller Interface (SDHCI) | ||
144 | often referrered to as the HSMMC block in some of the ST SPEAR range | ||
145 | of SoC | ||
146 | |||
147 | If you have a controller with this interface, say Y or M here. | ||
148 | |||
149 | If unsure, say N. | ||
150 | |||
139 | config MMC_SDHCI_S3C_DMA | 151 | config MMC_SDHCI_S3C_DMA |
140 | bool "DMA support on S3C SDHCI" | 152 | bool "DMA support on S3C SDHCI" |
141 | depends on MMC_SDHCI_S3C && EXPERIMENTAL | 153 | depends on MMC_SDHCI_S3C && EXPERIMENTAL |
@@ -412,3 +424,11 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | |||
412 | depends on SDH_BFIN | 424 | depends on SDH_BFIN |
413 | help | 425 | help |
414 | If you say yes here SD-Cards may work on the EZkit. | 426 | If you say yes here SD-Cards may work on the EZkit. |
427 | |||
428 | config MMC_SH_MMCIF | ||
429 | tristate "SuperH Internal MMCIF support" | ||
430 | depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) | ||
431 | help | ||
432 | This selects the MMC Host Interface controler (MMCIF). | ||
433 | |||
434 | This driver supports MMCIF in sh7724/sh7757/sh7372. | ||
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index f4803977dfce..e30c2ee48894 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_MMC_SDHCI) += sdhci.o | |||
14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | 14 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o |
15 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o | 15 | obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o |
16 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o | 16 | obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o |
17 | obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o | ||
17 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 18 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
18 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 19 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
19 | obj-$(CONFIG_MMC_OMAP) += omap.o | 20 | obj-$(CONFIG_MMC_OMAP) += omap.o |
@@ -34,6 +35,7 @@ obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o | |||
34 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o | 35 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o |
35 | obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o | 36 | obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o |
36 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | 37 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o |
38 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | ||
37 | 39 | ||
38 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o | 40 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o |
39 | sdhci-of-y := sdhci-of-core.o | 41 | sdhci-of-y := sdhci-of-core.o |
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index 336d9f553f3e..5f3a599ead07 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
@@ -1157,7 +1157,7 @@ static int at91_mci_suspend(struct platform_device *pdev, pm_message_t state) | |||
1157 | enable_irq_wake(host->board->det_pin); | 1157 | enable_irq_wake(host->board->det_pin); |
1158 | 1158 | ||
1159 | if (mmc) | 1159 | if (mmc) |
1160 | ret = mmc_suspend_host(mmc, state); | 1160 | ret = mmc_suspend_host(mmc); |
1161 | 1161 | ||
1162 | return ret; | 1162 | return ret; |
1163 | } | 1163 | } |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index df0e8a88d85f..95ef864ad8f9 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -173,6 +173,7 @@ struct atmel_mci { | |||
173 | * @mmc: The mmc_host representing this slot. | 173 | * @mmc: The mmc_host representing this slot. |
174 | * @host: The MMC controller this slot is using. | 174 | * @host: The MMC controller this slot is using. |
175 | * @sdc_reg: Value of SDCR to be written before using this slot. | 175 | * @sdc_reg: Value of SDCR to be written before using this slot. |
176 | * @sdio_irq: SDIO irq mask for this slot. | ||
176 | * @mrq: mmc_request currently being processed or waiting to be | 177 | * @mrq: mmc_request currently being processed or waiting to be |
177 | * processed, or NULL when the slot is idle. | 178 | * processed, or NULL when the slot is idle. |
178 | * @queue_node: List node for placing this node in the @queue list of | 179 | * @queue_node: List node for placing this node in the @queue list of |
@@ -191,6 +192,7 @@ struct atmel_mci_slot { | |||
191 | struct atmel_mci *host; | 192 | struct atmel_mci *host; |
192 | 193 | ||
193 | u32 sdc_reg; | 194 | u32 sdc_reg; |
195 | u32 sdio_irq; | ||
194 | 196 | ||
195 | struct mmc_request *mrq; | 197 | struct mmc_request *mrq; |
196 | struct list_head queue_node; | 198 | struct list_head queue_node; |
@@ -792,7 +794,7 @@ static void atmci_start_request(struct atmel_mci *host, | |||
792 | mci_writel(host, SDCR, slot->sdc_reg); | 794 | mci_writel(host, SDCR, slot->sdc_reg); |
793 | 795 | ||
794 | iflags = mci_readl(host, IMR); | 796 | iflags = mci_readl(host, IMR); |
795 | if (iflags) | 797 | if (iflags & ~(MCI_SDIOIRQA | MCI_SDIOIRQB)) |
796 | dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", | 798 | dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", |
797 | iflags); | 799 | iflags); |
798 | 800 | ||
@@ -952,10 +954,21 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
952 | if (mci_has_rwproof()) | 954 | if (mci_has_rwproof()) |
953 | host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF); | 955 | host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF); |
954 | 956 | ||
955 | if (list_empty(&host->queue)) | 957 | if (atmci_is_mci2()) { |
958 | /* setup High Speed mode in relation with card capacity */ | ||
959 | if (ios->timing == MMC_TIMING_SD_HS) | ||
960 | host->cfg_reg |= MCI_CFG_HSMODE; | ||
961 | else | ||
962 | host->cfg_reg &= ~MCI_CFG_HSMODE; | ||
963 | } | ||
964 | |||
965 | if (list_empty(&host->queue)) { | ||
956 | mci_writel(host, MR, host->mode_reg); | 966 | mci_writel(host, MR, host->mode_reg); |
957 | else | 967 | if (atmci_is_mci2()) |
968 | mci_writel(host, CFG, host->cfg_reg); | ||
969 | } else { | ||
958 | host->need_clock_update = true; | 970 | host->need_clock_update = true; |
971 | } | ||
959 | 972 | ||
960 | spin_unlock_bh(&host->lock); | 973 | spin_unlock_bh(&host->lock); |
961 | } else { | 974 | } else { |
@@ -1030,11 +1043,23 @@ static int atmci_get_cd(struct mmc_host *mmc) | |||
1030 | return present; | 1043 | return present; |
1031 | } | 1044 | } |
1032 | 1045 | ||
1046 | static void atmci_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
1047 | { | ||
1048 | struct atmel_mci_slot *slot = mmc_priv(mmc); | ||
1049 | struct atmel_mci *host = slot->host; | ||
1050 | |||
1051 | if (enable) | ||
1052 | mci_writel(host, IER, slot->sdio_irq); | ||
1053 | else | ||
1054 | mci_writel(host, IDR, slot->sdio_irq); | ||
1055 | } | ||
1056 | |||
1033 | static const struct mmc_host_ops atmci_ops = { | 1057 | static const struct mmc_host_ops atmci_ops = { |
1034 | .request = atmci_request, | 1058 | .request = atmci_request, |
1035 | .set_ios = atmci_set_ios, | 1059 | .set_ios = atmci_set_ios, |
1036 | .get_ro = atmci_get_ro, | 1060 | .get_ro = atmci_get_ro, |
1037 | .get_cd = atmci_get_cd, | 1061 | .get_cd = atmci_get_cd, |
1062 | .enable_sdio_irq = atmci_enable_sdio_irq, | ||
1038 | }; | 1063 | }; |
1039 | 1064 | ||
1040 | /* Called with host->lock held */ | 1065 | /* Called with host->lock held */ |
@@ -1052,8 +1077,11 @@ static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) | |||
1052 | * necessary if set_ios() is called when a different slot is | 1077 | * necessary if set_ios() is called when a different slot is |
1053 | * busy transfering data. | 1078 | * busy transfering data. |
1054 | */ | 1079 | */ |
1055 | if (host->need_clock_update) | 1080 | if (host->need_clock_update) { |
1056 | mci_writel(host, MR, host->mode_reg); | 1081 | mci_writel(host, MR, host->mode_reg); |
1082 | if (atmci_is_mci2()) | ||
1083 | mci_writel(host, CFG, host->cfg_reg); | ||
1084 | } | ||
1057 | 1085 | ||
1058 | host->cur_slot->mrq = NULL; | 1086 | host->cur_slot->mrq = NULL; |
1059 | host->mrq = NULL; | 1087 | host->mrq = NULL; |
@@ -1483,6 +1511,19 @@ static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status) | |||
1483 | tasklet_schedule(&host->tasklet); | 1511 | tasklet_schedule(&host->tasklet); |
1484 | } | 1512 | } |
1485 | 1513 | ||
1514 | static void atmci_sdio_interrupt(struct atmel_mci *host, u32 status) | ||
1515 | { | ||
1516 | int i; | ||
1517 | |||
1518 | for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { | ||
1519 | struct atmel_mci_slot *slot = host->slot[i]; | ||
1520 | if (slot && (status & slot->sdio_irq)) { | ||
1521 | mmc_signal_sdio_irq(slot->mmc); | ||
1522 | } | ||
1523 | } | ||
1524 | } | ||
1525 | |||
1526 | |||
1486 | static irqreturn_t atmci_interrupt(int irq, void *dev_id) | 1527 | static irqreturn_t atmci_interrupt(int irq, void *dev_id) |
1487 | { | 1528 | { |
1488 | struct atmel_mci *host = dev_id; | 1529 | struct atmel_mci *host = dev_id; |
@@ -1522,6 +1563,10 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
1522 | 1563 | ||
1523 | if (pending & MCI_CMDRDY) | 1564 | if (pending & MCI_CMDRDY) |
1524 | atmci_cmd_interrupt(host, status); | 1565 | atmci_cmd_interrupt(host, status); |
1566 | |||
1567 | if (pending & (MCI_SDIOIRQA | MCI_SDIOIRQB)) | ||
1568 | atmci_sdio_interrupt(host, status); | ||
1569 | |||
1525 | } while (pass_count++ < 5); | 1570 | } while (pass_count++ < 5); |
1526 | 1571 | ||
1527 | return pass_count ? IRQ_HANDLED : IRQ_NONE; | 1572 | return pass_count ? IRQ_HANDLED : IRQ_NONE; |
@@ -1544,7 +1589,7 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id) | |||
1544 | 1589 | ||
1545 | static int __init atmci_init_slot(struct atmel_mci *host, | 1590 | static int __init atmci_init_slot(struct atmel_mci *host, |
1546 | struct mci_slot_pdata *slot_data, unsigned int id, | 1591 | struct mci_slot_pdata *slot_data, unsigned int id, |
1547 | u32 sdc_reg) | 1592 | u32 sdc_reg, u32 sdio_irq) |
1548 | { | 1593 | { |
1549 | struct mmc_host *mmc; | 1594 | struct mmc_host *mmc; |
1550 | struct atmel_mci_slot *slot; | 1595 | struct atmel_mci_slot *slot; |
@@ -1560,11 +1605,16 @@ static int __init atmci_init_slot(struct atmel_mci *host, | |||
1560 | slot->wp_pin = slot_data->wp_pin; | 1605 | slot->wp_pin = slot_data->wp_pin; |
1561 | slot->detect_is_active_high = slot_data->detect_is_active_high; | 1606 | slot->detect_is_active_high = slot_data->detect_is_active_high; |
1562 | slot->sdc_reg = sdc_reg; | 1607 | slot->sdc_reg = sdc_reg; |
1608 | slot->sdio_irq = sdio_irq; | ||
1563 | 1609 | ||
1564 | mmc->ops = &atmci_ops; | 1610 | mmc->ops = &atmci_ops; |
1565 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); | 1611 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); |
1566 | mmc->f_max = host->bus_hz / 2; | 1612 | mmc->f_max = host->bus_hz / 2; |
1567 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | 1613 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; |
1614 | if (sdio_irq) | ||
1615 | mmc->caps |= MMC_CAP_SDIO_IRQ; | ||
1616 | if (atmci_is_mci2()) | ||
1617 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | ||
1568 | if (slot_data->bus_width >= 4) | 1618 | if (slot_data->bus_width >= 4) |
1569 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 1619 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
1570 | 1620 | ||
@@ -1753,13 +1803,13 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1753 | ret = -ENODEV; | 1803 | ret = -ENODEV; |
1754 | if (pdata->slot[0].bus_width) { | 1804 | if (pdata->slot[0].bus_width) { |
1755 | ret = atmci_init_slot(host, &pdata->slot[0], | 1805 | ret = atmci_init_slot(host, &pdata->slot[0], |
1756 | 0, MCI_SDCSEL_SLOT_A); | 1806 | 0, MCI_SDCSEL_SLOT_A, MCI_SDIOIRQA); |
1757 | if (!ret) | 1807 | if (!ret) |
1758 | nr_slots++; | 1808 | nr_slots++; |
1759 | } | 1809 | } |
1760 | if (pdata->slot[1].bus_width) { | 1810 | if (pdata->slot[1].bus_width) { |
1761 | ret = atmci_init_slot(host, &pdata->slot[1], | 1811 | ret = atmci_init_slot(host, &pdata->slot[1], |
1762 | 1, MCI_SDCSEL_SLOT_B); | 1812 | 1, MCI_SDCSEL_SLOT_B, MCI_SDIOIRQB); |
1763 | if (!ret) | 1813 | if (!ret) |
1764 | nr_slots++; | 1814 | nr_slots++; |
1765 | } | 1815 | } |
diff --git a/drivers/mmc/host/au1xmmc.c b/drivers/mmc/host/au1xmmc.c index f5834449400e..c8da5d30a861 100644 --- a/drivers/mmc/host/au1xmmc.c +++ b/drivers/mmc/host/au1xmmc.c | |||
@@ -1142,7 +1142,7 @@ static int au1xmmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
1142 | struct au1xmmc_host *host = platform_get_drvdata(pdev); | 1142 | struct au1xmmc_host *host = platform_get_drvdata(pdev); |
1143 | int ret; | 1143 | int ret; |
1144 | 1144 | ||
1145 | ret = mmc_suspend_host(host->mmc, state); | 1145 | ret = mmc_suspend_host(host->mmc); |
1146 | if (ret) | 1146 | if (ret) |
1147 | return ret; | 1147 | return ret; |
1148 | 1148 | ||
diff --git a/drivers/mmc/host/bfin_sdh.c b/drivers/mmc/host/bfin_sdh.c index 6919e844072c..4b0e677d7295 100644 --- a/drivers/mmc/host/bfin_sdh.c +++ b/drivers/mmc/host/bfin_sdh.c | |||
@@ -576,7 +576,7 @@ static int sdh_suspend(struct platform_device *dev, pm_message_t state) | |||
576 | int ret = 0; | 576 | int ret = 0; |
577 | 577 | ||
578 | if (mmc) | 578 | if (mmc) |
579 | ret = mmc_suspend_host(mmc, state); | 579 | ret = mmc_suspend_host(mmc); |
580 | 580 | ||
581 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON); | 581 | bfin_write_SDH_PWR_CTL(bfin_read_SDH_PWR_CTL() & ~PWR_ON); |
582 | peripheral_free_list(drv_data->pin_req); | 582 | peripheral_free_list(drv_data->pin_req); |
diff --git a/drivers/mmc/host/cb710-mmc.c b/drivers/mmc/host/cb710-mmc.c index 92a324f7417c..ca3bdc831900 100644 --- a/drivers/mmc/host/cb710-mmc.c +++ b/drivers/mmc/host/cb710-mmc.c | |||
@@ -675,7 +675,7 @@ static int cb710_mmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
675 | struct mmc_host *mmc = cb710_slot_to_mmc(slot); | 675 | struct mmc_host *mmc = cb710_slot_to_mmc(slot); |
676 | int err; | 676 | int err; |
677 | 677 | ||
678 | err = mmc_suspend_host(mmc, state); | 678 | err = mmc_suspend_host(mmc); |
679 | if (err) | 679 | if (err) |
680 | return err; | 680 | return err; |
681 | 681 | ||
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index 3bd0ba294e9d..33d9f1b00862 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
@@ -137,15 +137,15 @@ | |||
137 | 137 | ||
138 | /* | 138 | /* |
139 | * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, | 139 | * One scatterlist dma "segment" is at most MAX_CCNT rw_threshold units, |
140 | * and we handle up to NR_SG segments. MMC_BLOCK_BOUNCE kicks in only | 140 | * and we handle up to MAX_NR_SG segments. MMC_BLOCK_BOUNCE kicks in only |
141 | * for drivers with max_hw_segs == 1, making the segments bigger (64KB) | 141 | * for drivers with max_hw_segs == 1, making the segments bigger (64KB) |
142 | * than the page or two that's otherwise typical. NR_SG == 16 gives at | 142 | * than the page or two that's otherwise typical. nr_sg (passed from |
143 | * least the same throughput boost, using EDMA transfer linkage instead | 143 | * platform data) == 16 gives at least the same throughput boost, using |
144 | * of spending CPU time copying pages. | 144 | * EDMA transfer linkage instead of spending CPU time copying pages. |
145 | */ | 145 | */ |
146 | #define MAX_CCNT ((1 << 16) - 1) | 146 | #define MAX_CCNT ((1 << 16) - 1) |
147 | 147 | ||
148 | #define NR_SG 16 | 148 | #define MAX_NR_SG 16 |
149 | 149 | ||
150 | static unsigned rw_threshold = 32; | 150 | static unsigned rw_threshold = 32; |
151 | module_param(rw_threshold, uint, S_IRUGO); | 151 | module_param(rw_threshold, uint, S_IRUGO); |
@@ -171,6 +171,7 @@ struct mmc_davinci_host { | |||
171 | #define DAVINCI_MMC_DATADIR_READ 1 | 171 | #define DAVINCI_MMC_DATADIR_READ 1 |
172 | #define DAVINCI_MMC_DATADIR_WRITE 2 | 172 | #define DAVINCI_MMC_DATADIR_WRITE 2 |
173 | unsigned char data_dir; | 173 | unsigned char data_dir; |
174 | unsigned char suspended; | ||
174 | 175 | ||
175 | /* buffer is used during PIO of one scatterlist segment, and | 176 | /* buffer is used during PIO of one scatterlist segment, and |
176 | * is updated along with buffer_bytes_left. bytes_left applies | 177 | * is updated along with buffer_bytes_left. bytes_left applies |
@@ -192,7 +193,7 @@ struct mmc_davinci_host { | |||
192 | struct edmacc_param tx_template; | 193 | struct edmacc_param tx_template; |
193 | struct edmacc_param rx_template; | 194 | struct edmacc_param rx_template; |
194 | unsigned n_link; | 195 | unsigned n_link; |
195 | u32 links[NR_SG - 1]; | 196 | u32 links[MAX_NR_SG - 1]; |
196 | 197 | ||
197 | /* For PIO we walk scatterlists one segment at a time. */ | 198 | /* For PIO we walk scatterlists one segment at a time. */ |
198 | unsigned int sg_len; | 199 | unsigned int sg_len; |
@@ -202,6 +203,8 @@ struct mmc_davinci_host { | |||
202 | u8 version; | 203 | u8 version; |
203 | /* for ns in one cycle calculation */ | 204 | /* for ns in one cycle calculation */ |
204 | unsigned ns_in_one_cycle; | 205 | unsigned ns_in_one_cycle; |
206 | /* Number of sg segments */ | ||
207 | u8 nr_sg; | ||
205 | #ifdef CONFIG_CPU_FREQ | 208 | #ifdef CONFIG_CPU_FREQ |
206 | struct notifier_block freq_transition; | 209 | struct notifier_block freq_transition; |
207 | #endif | 210 | #endif |
@@ -568,6 +571,7 @@ davinci_release_dma_channels(struct mmc_davinci_host *host) | |||
568 | 571 | ||
569 | static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) | 572 | static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) |
570 | { | 573 | { |
574 | u32 link_size; | ||
571 | int r, i; | 575 | int r, i; |
572 | 576 | ||
573 | /* Acquire master DMA write channel */ | 577 | /* Acquire master DMA write channel */ |
@@ -593,7 +597,8 @@ static int __init davinci_acquire_dma_channels(struct mmc_davinci_host *host) | |||
593 | /* Allocate parameter RAM slots, which will later be bound to a | 597 | /* Allocate parameter RAM slots, which will later be bound to a |
594 | * channel as needed to handle a scatterlist. | 598 | * channel as needed to handle a scatterlist. |
595 | */ | 599 | */ |
596 | for (i = 0; i < ARRAY_SIZE(host->links); i++) { | 600 | link_size = min_t(unsigned, host->nr_sg, ARRAY_SIZE(host->links)); |
601 | for (i = 0; i < link_size; i++) { | ||
597 | r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); | 602 | r = edma_alloc_slot(EDMA_CTLR(host->txdma), EDMA_SLOT_ANY); |
598 | if (r < 0) { | 603 | if (r < 0) { |
599 | dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n", | 604 | dev_dbg(mmc_dev(host->mmc), "dma PaRAM alloc --> %d\n", |
@@ -905,19 +910,26 @@ static void mmc_davinci_cmd_done(struct mmc_davinci_host *host, | |||
905 | } | 910 | } |
906 | } | 911 | } |
907 | 912 | ||
908 | static void | 913 | static inline void mmc_davinci_reset_ctrl(struct mmc_davinci_host *host, |
909 | davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data) | 914 | int val) |
910 | { | 915 | { |
911 | u32 temp; | 916 | u32 temp; |
912 | 917 | ||
913 | /* reset command and data state machines */ | ||
914 | temp = readl(host->base + DAVINCI_MMCCTL); | 918 | temp = readl(host->base + DAVINCI_MMCCTL); |
915 | writel(temp | MMCCTL_CMDRST | MMCCTL_DATRST, | 919 | if (val) /* reset */ |
916 | host->base + DAVINCI_MMCCTL); | 920 | temp |= MMCCTL_CMDRST | MMCCTL_DATRST; |
921 | else /* enable */ | ||
922 | temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST); | ||
917 | 923 | ||
918 | temp &= ~(MMCCTL_CMDRST | MMCCTL_DATRST); | ||
919 | udelay(10); | ||
920 | writel(temp, host->base + DAVINCI_MMCCTL); | 924 | writel(temp, host->base + DAVINCI_MMCCTL); |
925 | udelay(10); | ||
926 | } | ||
927 | |||
928 | static void | ||
929 | davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data) | ||
930 | { | ||
931 | mmc_davinci_reset_ctrl(host, 1); | ||
932 | mmc_davinci_reset_ctrl(host, 0); | ||
921 | } | 933 | } |
922 | 934 | ||
923 | static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) | 935 | static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) |
@@ -1121,15 +1133,8 @@ static inline void mmc_davinci_cpufreq_deregister(struct mmc_davinci_host *host) | |||
1121 | #endif | 1133 | #endif |
1122 | static void __init init_mmcsd_host(struct mmc_davinci_host *host) | 1134 | static void __init init_mmcsd_host(struct mmc_davinci_host *host) |
1123 | { | 1135 | { |
1124 | /* DAT line portion is diabled and in reset state */ | ||
1125 | writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_DATRST, | ||
1126 | host->base + DAVINCI_MMCCTL); | ||
1127 | |||
1128 | /* CMD line portion is diabled and in reset state */ | ||
1129 | writel(readl(host->base + DAVINCI_MMCCTL) | MMCCTL_CMDRST, | ||
1130 | host->base + DAVINCI_MMCCTL); | ||
1131 | 1136 | ||
1132 | udelay(10); | 1137 | mmc_davinci_reset_ctrl(host, 1); |
1133 | 1138 | ||
1134 | writel(0, host->base + DAVINCI_MMCCLK); | 1139 | writel(0, host->base + DAVINCI_MMCCLK); |
1135 | writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK); | 1140 | writel(MMCCLK_CLKEN, host->base + DAVINCI_MMCCLK); |
@@ -1137,12 +1142,7 @@ static void __init init_mmcsd_host(struct mmc_davinci_host *host) | |||
1137 | writel(0x1FFF, host->base + DAVINCI_MMCTOR); | 1142 | writel(0x1FFF, host->base + DAVINCI_MMCTOR); |
1138 | writel(0xFFFF, host->base + DAVINCI_MMCTOD); | 1143 | writel(0xFFFF, host->base + DAVINCI_MMCTOD); |
1139 | 1144 | ||
1140 | writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_DATRST, | 1145 | mmc_davinci_reset_ctrl(host, 0); |
1141 | host->base + DAVINCI_MMCCTL); | ||
1142 | writel(readl(host->base + DAVINCI_MMCCTL) & ~MMCCTL_CMDRST, | ||
1143 | host->base + DAVINCI_MMCCTL); | ||
1144 | |||
1145 | udelay(10); | ||
1146 | } | 1146 | } |
1147 | 1147 | ||
1148 | static int __init davinci_mmcsd_probe(struct platform_device *pdev) | 1148 | static int __init davinci_mmcsd_probe(struct platform_device *pdev) |
@@ -1202,6 +1202,12 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
1202 | 1202 | ||
1203 | init_mmcsd_host(host); | 1203 | init_mmcsd_host(host); |
1204 | 1204 | ||
1205 | if (pdata->nr_sg) | ||
1206 | host->nr_sg = pdata->nr_sg - 1; | ||
1207 | |||
1208 | if (host->nr_sg > MAX_NR_SG || !host->nr_sg) | ||
1209 | host->nr_sg = MAX_NR_SG; | ||
1210 | |||
1205 | host->use_dma = use_dma; | 1211 | host->use_dma = use_dma; |
1206 | host->irq = irq; | 1212 | host->irq = irq; |
1207 | 1213 | ||
@@ -1327,32 +1333,65 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) | |||
1327 | } | 1333 | } |
1328 | 1334 | ||
1329 | #ifdef CONFIG_PM | 1335 | #ifdef CONFIG_PM |
1330 | static int davinci_mmcsd_suspend(struct platform_device *pdev, pm_message_t msg) | 1336 | static int davinci_mmcsd_suspend(struct device *dev) |
1331 | { | 1337 | { |
1338 | struct platform_device *pdev = to_platform_device(dev); | ||
1332 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | 1339 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); |
1340 | int ret; | ||
1333 | 1341 | ||
1334 | return mmc_suspend_host(host->mmc, msg); | 1342 | mmc_host_enable(host->mmc); |
1343 | ret = mmc_suspend_host(host->mmc); | ||
1344 | if (!ret) { | ||
1345 | writel(0, host->base + DAVINCI_MMCIM); | ||
1346 | mmc_davinci_reset_ctrl(host, 1); | ||
1347 | mmc_host_disable(host->mmc); | ||
1348 | clk_disable(host->clk); | ||
1349 | host->suspended = 1; | ||
1350 | } else { | ||
1351 | host->suspended = 0; | ||
1352 | mmc_host_disable(host->mmc); | ||
1353 | } | ||
1354 | |||
1355 | return ret; | ||
1335 | } | 1356 | } |
1336 | 1357 | ||
1337 | static int davinci_mmcsd_resume(struct platform_device *pdev) | 1358 | static int davinci_mmcsd_resume(struct device *dev) |
1338 | { | 1359 | { |
1360 | struct platform_device *pdev = to_platform_device(dev); | ||
1339 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); | 1361 | struct mmc_davinci_host *host = platform_get_drvdata(pdev); |
1362 | int ret; | ||
1363 | |||
1364 | if (!host->suspended) | ||
1365 | return 0; | ||
1340 | 1366 | ||
1341 | return mmc_resume_host(host->mmc); | 1367 | clk_enable(host->clk); |
1368 | mmc_host_enable(host->mmc); | ||
1369 | |||
1370 | mmc_davinci_reset_ctrl(host, 0); | ||
1371 | ret = mmc_resume_host(host->mmc); | ||
1372 | if (!ret) | ||
1373 | host->suspended = 0; | ||
1374 | |||
1375 | return ret; | ||
1342 | } | 1376 | } |
1377 | |||
1378 | static const struct dev_pm_ops davinci_mmcsd_pm = { | ||
1379 | .suspend = davinci_mmcsd_suspend, | ||
1380 | .resume = davinci_mmcsd_resume, | ||
1381 | }; | ||
1382 | |||
1383 | #define davinci_mmcsd_pm_ops (&davinci_mmcsd_pm) | ||
1343 | #else | 1384 | #else |
1344 | #define davinci_mmcsd_suspend NULL | 1385 | #define davinci_mmcsd_pm_ops NULL |
1345 | #define davinci_mmcsd_resume NULL | ||
1346 | #endif | 1386 | #endif |
1347 | 1387 | ||
1348 | static struct platform_driver davinci_mmcsd_driver = { | 1388 | static struct platform_driver davinci_mmcsd_driver = { |
1349 | .driver = { | 1389 | .driver = { |
1350 | .name = "davinci_mmc", | 1390 | .name = "davinci_mmc", |
1351 | .owner = THIS_MODULE, | 1391 | .owner = THIS_MODULE, |
1392 | .pm = davinci_mmcsd_pm_ops, | ||
1352 | }, | 1393 | }, |
1353 | .remove = __exit_p(davinci_mmcsd_remove), | 1394 | .remove = __exit_p(davinci_mmcsd_remove), |
1354 | .suspend = davinci_mmcsd_suspend, | ||
1355 | .resume = davinci_mmcsd_resume, | ||
1356 | }; | 1395 | }; |
1357 | 1396 | ||
1358 | static int __init davinci_mmcsd_init(void) | 1397 | static int __init davinci_mmcsd_init(void) |
diff --git a/drivers/mmc/host/imxmmc.c b/drivers/mmc/host/imxmmc.c index bf98d7cc928a..9a68ff4353a2 100644 --- a/drivers/mmc/host/imxmmc.c +++ b/drivers/mmc/host/imxmmc.c | |||
@@ -1115,7 +1115,7 @@ static int imxmci_suspend(struct platform_device *dev, pm_message_t state) | |||
1115 | int ret = 0; | 1115 | int ret = 0; |
1116 | 1116 | ||
1117 | if (mmc) | 1117 | if (mmc) |
1118 | ret = mmc_suspend_host(mmc, state); | 1118 | ret = mmc_suspend_host(mmc); |
1119 | 1119 | ||
1120 | return ret; | 1120 | return ret; |
1121 | } | 1121 | } |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index ff115d920888..4917af96bae1 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
@@ -824,7 +824,7 @@ static int mmci_suspend(struct amba_device *dev, pm_message_t state) | |||
824 | if (mmc) { | 824 | if (mmc) { |
825 | struct mmci_host *host = mmc_priv(mmc); | 825 | struct mmci_host *host = mmc_priv(mmc); |
826 | 826 | ||
827 | ret = mmc_suspend_host(mmc, state); | 827 | ret = mmc_suspend_host(mmc); |
828 | if (ret == 0) | 828 | if (ret == 0) |
829 | writel(0, host->base + MMCIMASK0); | 829 | writel(0, host->base + MMCIMASK0); |
830 | } | 830 | } |
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 61f1d27fed3f..24e09454e522 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -1327,7 +1327,7 @@ msmsdcc_suspend(struct platform_device *dev, pm_message_t state) | |||
1327 | disable_irq(host->stat_irq); | 1327 | disable_irq(host->stat_irq); |
1328 | 1328 | ||
1329 | if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) | 1329 | if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) |
1330 | rc = mmc_suspend_host(mmc, state); | 1330 | rc = mmc_suspend_host(mmc); |
1331 | if (!rc) | 1331 | if (!rc) |
1332 | msmsdcc_writel(host, 0, MMCIMASK0); | 1332 | msmsdcc_writel(host, 0, MMCIMASK0); |
1333 | if (host->clks_on) | 1333 | if (host->clks_on) |
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index 34e23489811a..366eefa77c5a 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -865,7 +865,7 @@ static int mvsd_suspend(struct platform_device *dev, pm_message_t state) | |||
865 | int ret = 0; | 865 | int ret = 0; |
866 | 866 | ||
867 | if (mmc) | 867 | if (mmc) |
868 | ret = mmc_suspend_host(mmc, state); | 868 | ret = mmc_suspend_host(mmc); |
869 | 869 | ||
870 | return ret; | 870 | return ret; |
871 | } | 871 | } |
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index ec18e3b60342..d9d4a72e0ec7 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -932,7 +932,7 @@ static int mxcmci_suspend(struct platform_device *dev, pm_message_t state) | |||
932 | int ret = 0; | 932 | int ret = 0; |
933 | 933 | ||
934 | if (mmc) | 934 | if (mmc) |
935 | ret = mmc_suspend_host(mmc, state); | 935 | ret = mmc_suspend_host(mmc); |
936 | 936 | ||
937 | return ret; | 937 | return ret; |
938 | } | 938 | } |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index 84d280406341..2b281680e320 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
@@ -39,30 +39,30 @@ | |||
39 | #include <plat/fpga.h> | 39 | #include <plat/fpga.h> |
40 | 40 | ||
41 | #define OMAP_MMC_REG_CMD 0x00 | 41 | #define OMAP_MMC_REG_CMD 0x00 |
42 | #define OMAP_MMC_REG_ARGL 0x04 | 42 | #define OMAP_MMC_REG_ARGL 0x01 |
43 | #define OMAP_MMC_REG_ARGH 0x08 | 43 | #define OMAP_MMC_REG_ARGH 0x02 |
44 | #define OMAP_MMC_REG_CON 0x0c | 44 | #define OMAP_MMC_REG_CON 0x03 |
45 | #define OMAP_MMC_REG_STAT 0x10 | 45 | #define OMAP_MMC_REG_STAT 0x04 |
46 | #define OMAP_MMC_REG_IE 0x14 | 46 | #define OMAP_MMC_REG_IE 0x05 |
47 | #define OMAP_MMC_REG_CTO 0x18 | 47 | #define OMAP_MMC_REG_CTO 0x06 |
48 | #define OMAP_MMC_REG_DTO 0x1c | 48 | #define OMAP_MMC_REG_DTO 0x07 |
49 | #define OMAP_MMC_REG_DATA 0x20 | 49 | #define OMAP_MMC_REG_DATA 0x08 |
50 | #define OMAP_MMC_REG_BLEN 0x24 | 50 | #define OMAP_MMC_REG_BLEN 0x09 |
51 | #define OMAP_MMC_REG_NBLK 0x28 | 51 | #define OMAP_MMC_REG_NBLK 0x0a |
52 | #define OMAP_MMC_REG_BUF 0x2c | 52 | #define OMAP_MMC_REG_BUF 0x0b |
53 | #define OMAP_MMC_REG_SDIO 0x34 | 53 | #define OMAP_MMC_REG_SDIO 0x0d |
54 | #define OMAP_MMC_REG_REV 0x3c | 54 | #define OMAP_MMC_REG_REV 0x0f |
55 | #define OMAP_MMC_REG_RSP0 0x40 | 55 | #define OMAP_MMC_REG_RSP0 0x10 |
56 | #define OMAP_MMC_REG_RSP1 0x44 | 56 | #define OMAP_MMC_REG_RSP1 0x11 |
57 | #define OMAP_MMC_REG_RSP2 0x48 | 57 | #define OMAP_MMC_REG_RSP2 0x12 |
58 | #define OMAP_MMC_REG_RSP3 0x4c | 58 | #define OMAP_MMC_REG_RSP3 0x13 |
59 | #define OMAP_MMC_REG_RSP4 0x50 | 59 | #define OMAP_MMC_REG_RSP4 0x14 |
60 | #define OMAP_MMC_REG_RSP5 0x54 | 60 | #define OMAP_MMC_REG_RSP5 0x15 |
61 | #define OMAP_MMC_REG_RSP6 0x58 | 61 | #define OMAP_MMC_REG_RSP6 0x16 |
62 | #define OMAP_MMC_REG_RSP7 0x5c | 62 | #define OMAP_MMC_REG_RSP7 0x17 |
63 | #define OMAP_MMC_REG_IOSR 0x60 | 63 | #define OMAP_MMC_REG_IOSR 0x18 |
64 | #define OMAP_MMC_REG_SYSC 0x64 | 64 | #define OMAP_MMC_REG_SYSC 0x19 |
65 | #define OMAP_MMC_REG_SYSS 0x68 | 65 | #define OMAP_MMC_REG_SYSS 0x1a |
66 | 66 | ||
67 | #define OMAP_MMC_STAT_CARD_ERR (1 << 14) | 67 | #define OMAP_MMC_STAT_CARD_ERR (1 << 14) |
68 | #define OMAP_MMC_STAT_CARD_IRQ (1 << 13) | 68 | #define OMAP_MMC_STAT_CARD_IRQ (1 << 13) |
@@ -78,8 +78,9 @@ | |||
78 | #define OMAP_MMC_STAT_CARD_BUSY (1 << 2) | 78 | #define OMAP_MMC_STAT_CARD_BUSY (1 << 2) |
79 | #define OMAP_MMC_STAT_END_OF_CMD (1 << 0) | 79 | #define OMAP_MMC_STAT_END_OF_CMD (1 << 0) |
80 | 80 | ||
81 | #define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG_##reg) | 81 | #define OMAP_MMC_REG(host, reg) (OMAP_MMC_REG_##reg << (host)->reg_shift) |
82 | #define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG_##reg) | 82 | #define OMAP_MMC_READ(host, reg) __raw_readw((host)->virt_base + OMAP_MMC_REG(host, reg)) |
83 | #define OMAP_MMC_WRITE(host, reg, val) __raw_writew((val), (host)->virt_base + OMAP_MMC_REG(host, reg)) | ||
83 | 84 | ||
84 | /* | 85 | /* |
85 | * Command types | 86 | * Command types |
@@ -133,6 +134,7 @@ struct mmc_omap_host { | |||
133 | int irq; | 134 | int irq; |
134 | unsigned char bus_mode; | 135 | unsigned char bus_mode; |
135 | unsigned char hw_bus_mode; | 136 | unsigned char hw_bus_mode; |
137 | unsigned int reg_shift; | ||
136 | 138 | ||
137 | struct work_struct cmd_abort_work; | 139 | struct work_struct cmd_abort_work; |
138 | unsigned abort:1; | 140 | unsigned abort:1; |
@@ -680,9 +682,9 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write) | |||
680 | host->data->bytes_xfered += n; | 682 | host->data->bytes_xfered += n; |
681 | 683 | ||
682 | if (write) { | 684 | if (write) { |
683 | __raw_writesw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); | 685 | __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); |
684 | } else { | 686 | } else { |
685 | __raw_readsw(host->virt_base + OMAP_MMC_REG_DATA, host->buffer, n); | 687 | __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n); |
686 | } | 688 | } |
687 | } | 689 | } |
688 | 690 | ||
@@ -900,7 +902,7 @@ mmc_omap_prepare_dma(struct mmc_omap_host *host, struct mmc_data *data) | |||
900 | int dst_port = 0; | 902 | int dst_port = 0; |
901 | int sync_dev = 0; | 903 | int sync_dev = 0; |
902 | 904 | ||
903 | data_addr = host->phys_base + OMAP_MMC_REG_DATA; | 905 | data_addr = host->phys_base + OMAP_MMC_REG(host, DATA); |
904 | frame = data->blksz; | 906 | frame = data->blksz; |
905 | count = sg_dma_len(sg); | 907 | count = sg_dma_len(sg); |
906 | 908 | ||
@@ -1493,6 +1495,8 @@ static int __init mmc_omap_probe(struct platform_device *pdev) | |||
1493 | } | 1495 | } |
1494 | } | 1496 | } |
1495 | 1497 | ||
1498 | host->reg_shift = (cpu_is_omap7xx() ? 1 : 2); | ||
1499 | |||
1496 | return 0; | 1500 | return 0; |
1497 | 1501 | ||
1498 | err_plat_cleanup: | 1502 | err_plat_cleanup: |
@@ -1557,7 +1561,7 @@ static int mmc_omap_suspend(struct platform_device *pdev, pm_message_t mesg) | |||
1557 | struct mmc_omap_slot *slot; | 1561 | struct mmc_omap_slot *slot; |
1558 | 1562 | ||
1559 | slot = host->slots[i]; | 1563 | slot = host->slots[i]; |
1560 | ret = mmc_suspend_host(slot->mmc, mesg); | 1564 | ret = mmc_suspend_host(slot->mmc); |
1561 | if (ret < 0) { | 1565 | if (ret < 0) { |
1562 | while (--i >= 0) { | 1566 | while (--i >= 0) { |
1563 | slot = host->slots[i]; | 1567 | slot = host->slots[i]; |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index e9caf694c59e..b032828c6126 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
@@ -157,12 +157,10 @@ struct omap_hsmmc_host { | |||
157 | */ | 157 | */ |
158 | struct regulator *vcc; | 158 | struct regulator *vcc; |
159 | struct regulator *vcc_aux; | 159 | struct regulator *vcc_aux; |
160 | struct semaphore sem; | ||
161 | struct work_struct mmc_carddetect_work; | 160 | struct work_struct mmc_carddetect_work; |
162 | void __iomem *base; | 161 | void __iomem *base; |
163 | resource_size_t mapbase; | 162 | resource_size_t mapbase; |
164 | spinlock_t irq_lock; /* Prevent races with irq handler */ | 163 | spinlock_t irq_lock; /* Prevent races with irq handler */ |
165 | unsigned long flags; | ||
166 | unsigned int id; | 164 | unsigned int id; |
167 | unsigned int dma_len; | 165 | unsigned int dma_len; |
168 | unsigned int dma_sg_idx; | 166 | unsigned int dma_sg_idx; |
@@ -183,6 +181,7 @@ struct omap_hsmmc_host { | |||
183 | int protect_card; | 181 | int protect_card; |
184 | int reqs_blocked; | 182 | int reqs_blocked; |
185 | int use_reg; | 183 | int use_reg; |
184 | int req_in_progress; | ||
186 | 185 | ||
187 | struct omap_mmc_platform_data *pdata; | 186 | struct omap_mmc_platform_data *pdata; |
188 | }; | 187 | }; |
@@ -524,6 +523,27 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) | |||
524 | dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); | 523 | dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); |
525 | } | 524 | } |
526 | 525 | ||
526 | static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host) | ||
527 | { | ||
528 | unsigned int irq_mask; | ||
529 | |||
530 | if (host->use_dma) | ||
531 | irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE); | ||
532 | else | ||
533 | irq_mask = INT_EN_MASK; | ||
534 | |||
535 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
536 | OMAP_HSMMC_WRITE(host->base, ISE, irq_mask); | ||
537 | OMAP_HSMMC_WRITE(host->base, IE, irq_mask); | ||
538 | } | ||
539 | |||
540 | static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host) | ||
541 | { | ||
542 | OMAP_HSMMC_WRITE(host->base, ISE, 0); | ||
543 | OMAP_HSMMC_WRITE(host->base, IE, 0); | ||
544 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
545 | } | ||
546 | |||
527 | #ifdef CONFIG_PM | 547 | #ifdef CONFIG_PM |
528 | 548 | ||
529 | /* | 549 | /* |
@@ -592,9 +612,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) | |||
592 | && time_before(jiffies, timeout)) | 612 | && time_before(jiffies, timeout)) |
593 | ; | 613 | ; |
594 | 614 | ||
595 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | 615 | omap_hsmmc_disable_irq(host); |
596 | OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
597 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
598 | 616 | ||
599 | /* Do not initialize card-specific things if the power is off */ | 617 | /* Do not initialize card-specific things if the power is off */ |
600 | if (host->power_mode == MMC_POWER_OFF) | 618 | if (host->power_mode == MMC_POWER_OFF) |
@@ -697,6 +715,8 @@ static void send_init_stream(struct omap_hsmmc_host *host) | |||
697 | return; | 715 | return; |
698 | 716 | ||
699 | disable_irq(host->irq); | 717 | disable_irq(host->irq); |
718 | |||
719 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
700 | OMAP_HSMMC_WRITE(host->base, CON, | 720 | OMAP_HSMMC_WRITE(host->base, CON, |
701 | OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM); | 721 | OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM); |
702 | OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD); | 722 | OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD); |
@@ -762,17 +782,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
762 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); | 782 | mmc_hostname(host->mmc), cmd->opcode, cmd->arg); |
763 | host->cmd = cmd; | 783 | host->cmd = cmd; |
764 | 784 | ||
765 | /* | 785 | omap_hsmmc_enable_irq(host); |
766 | * Clear status bits and enable interrupts | ||
767 | */ | ||
768 | OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); | ||
769 | OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | ||
770 | |||
771 | if (host->use_dma) | ||
772 | OMAP_HSMMC_WRITE(host->base, IE, | ||
773 | INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE)); | ||
774 | else | ||
775 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
776 | 786 | ||
777 | host->response_busy = 0; | 787 | host->response_busy = 0; |
778 | if (cmd->flags & MMC_RSP_PRESENT) { | 788 | if (cmd->flags & MMC_RSP_PRESENT) { |
@@ -806,13 +816,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, | |||
806 | if (host->use_dma) | 816 | if (host->use_dma) |
807 | cmdreg |= DMA_EN; | 817 | cmdreg |= DMA_EN; |
808 | 818 | ||
809 | /* | 819 | host->req_in_progress = 1; |
810 | * In an interrupt context (i.e. STOP command), the spinlock is unlocked | ||
811 | * by the interrupt handler, otherwise (i.e. for a new request) it is | ||
812 | * unlocked here. | ||
813 | */ | ||
814 | if (!in_interrupt()) | ||
815 | spin_unlock_irqrestore(&host->irq_lock, host->flags); | ||
816 | 820 | ||
817 | OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); | 821 | OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); |
818 | OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); | 822 | OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); |
@@ -827,6 +831,23 @@ omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data) | |||
827 | return DMA_FROM_DEVICE; | 831 | return DMA_FROM_DEVICE; |
828 | } | 832 | } |
829 | 833 | ||
834 | static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq) | ||
835 | { | ||
836 | int dma_ch; | ||
837 | |||
838 | spin_lock(&host->irq_lock); | ||
839 | host->req_in_progress = 0; | ||
840 | dma_ch = host->dma_ch; | ||
841 | spin_unlock(&host->irq_lock); | ||
842 | |||
843 | omap_hsmmc_disable_irq(host); | ||
844 | /* Do not complete the request if DMA is still in progress */ | ||
845 | if (mrq->data && host->use_dma && dma_ch != -1) | ||
846 | return; | ||
847 | host->mrq = NULL; | ||
848 | mmc_request_done(host->mmc, mrq); | ||
849 | } | ||
850 | |||
830 | /* | 851 | /* |
831 | * Notify the transfer complete to MMC core | 852 | * Notify the transfer complete to MMC core |
832 | */ | 853 | */ |
@@ -843,25 +864,19 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) | |||
843 | return; | 864 | return; |
844 | } | 865 | } |
845 | 866 | ||
846 | host->mrq = NULL; | 867 | omap_hsmmc_request_done(host, mrq); |
847 | mmc_request_done(host->mmc, mrq); | ||
848 | return; | 868 | return; |
849 | } | 869 | } |
850 | 870 | ||
851 | host->data = NULL; | 871 | host->data = NULL; |
852 | 872 | ||
853 | if (host->use_dma && host->dma_ch != -1) | ||
854 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, | ||
855 | omap_hsmmc_get_dma_dir(host, data)); | ||
856 | |||
857 | if (!data->error) | 873 | if (!data->error) |
858 | data->bytes_xfered += data->blocks * (data->blksz); | 874 | data->bytes_xfered += data->blocks * (data->blksz); |
859 | else | 875 | else |
860 | data->bytes_xfered = 0; | 876 | data->bytes_xfered = 0; |
861 | 877 | ||
862 | if (!data->stop) { | 878 | if (!data->stop) { |
863 | host->mrq = NULL; | 879 | omap_hsmmc_request_done(host, data->mrq); |
864 | mmc_request_done(host->mmc, data->mrq); | ||
865 | return; | 880 | return; |
866 | } | 881 | } |
867 | omap_hsmmc_start_command(host, data->stop, NULL); | 882 | omap_hsmmc_start_command(host, data->stop, NULL); |
@@ -887,10 +902,8 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) | |||
887 | cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); | 902 | cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10); |
888 | } | 903 | } |
889 | } | 904 | } |
890 | if ((host->data == NULL && !host->response_busy) || cmd->error) { | 905 | if ((host->data == NULL && !host->response_busy) || cmd->error) |
891 | host->mrq = NULL; | 906 | omap_hsmmc_request_done(host, cmd->mrq); |
892 | mmc_request_done(host->mmc, cmd->mrq); | ||
893 | } | ||
894 | } | 907 | } |
895 | 908 | ||
896 | /* | 909 | /* |
@@ -898,14 +911,19 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) | |||
898 | */ | 911 | */ |
899 | static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) | 912 | static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) |
900 | { | 913 | { |
914 | int dma_ch; | ||
915 | |||
901 | host->data->error = errno; | 916 | host->data->error = errno; |
902 | 917 | ||
903 | if (host->use_dma && host->dma_ch != -1) { | 918 | spin_lock(&host->irq_lock); |
919 | dma_ch = host->dma_ch; | ||
920 | host->dma_ch = -1; | ||
921 | spin_unlock(&host->irq_lock); | ||
922 | |||
923 | if (host->use_dma && dma_ch != -1) { | ||
904 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, | 924 | dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, |
905 | omap_hsmmc_get_dma_dir(host, host->data)); | 925 | omap_hsmmc_get_dma_dir(host, host->data)); |
906 | omap_free_dma(host->dma_ch); | 926 | omap_free_dma(dma_ch); |
907 | host->dma_ch = -1; | ||
908 | up(&host->sem); | ||
909 | } | 927 | } |
910 | host->data = NULL; | 928 | host->data = NULL; |
911 | } | 929 | } |
@@ -967,28 +985,21 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, | |||
967 | __func__); | 985 | __func__); |
968 | } | 986 | } |
969 | 987 | ||
970 | /* | 988 | static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) |
971 | * MMC controller IRQ handler | ||
972 | */ | ||
973 | static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | ||
974 | { | 989 | { |
975 | struct omap_hsmmc_host *host = dev_id; | ||
976 | struct mmc_data *data; | 990 | struct mmc_data *data; |
977 | int end_cmd = 0, end_trans = 0, status; | 991 | int end_cmd = 0, end_trans = 0; |
978 | 992 | ||
979 | spin_lock(&host->irq_lock); | 993 | if (!host->req_in_progress) { |
980 | 994 | do { | |
981 | if (host->mrq == NULL) { | 995 | OMAP_HSMMC_WRITE(host->base, STAT, status); |
982 | OMAP_HSMMC_WRITE(host->base, STAT, | 996 | /* Flush posted write */ |
983 | OMAP_HSMMC_READ(host->base, STAT)); | 997 | status = OMAP_HSMMC_READ(host->base, STAT); |
984 | /* Flush posted write */ | 998 | } while (status & INT_EN_MASK); |
985 | OMAP_HSMMC_READ(host->base, STAT); | 999 | return; |
986 | spin_unlock(&host->irq_lock); | ||
987 | return IRQ_HANDLED; | ||
988 | } | 1000 | } |
989 | 1001 | ||
990 | data = host->data; | 1002 | data = host->data; |
991 | status = OMAP_HSMMC_READ(host->base, STAT); | ||
992 | dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); | 1003 | dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status); |
993 | 1004 | ||
994 | if (status & ERR) { | 1005 | if (status & ERR) { |
@@ -1041,15 +1052,27 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | |||
1041 | } | 1052 | } |
1042 | 1053 | ||
1043 | OMAP_HSMMC_WRITE(host->base, STAT, status); | 1054 | OMAP_HSMMC_WRITE(host->base, STAT, status); |
1044 | /* Flush posted write */ | ||
1045 | OMAP_HSMMC_READ(host->base, STAT); | ||
1046 | 1055 | ||
1047 | if (end_cmd || ((status & CC) && host->cmd)) | 1056 | if (end_cmd || ((status & CC) && host->cmd)) |
1048 | omap_hsmmc_cmd_done(host, host->cmd); | 1057 | omap_hsmmc_cmd_done(host, host->cmd); |
1049 | if ((end_trans || (status & TC)) && host->mrq) | 1058 | if ((end_trans || (status & TC)) && host->mrq) |
1050 | omap_hsmmc_xfer_done(host, data); | 1059 | omap_hsmmc_xfer_done(host, data); |
1060 | } | ||
1051 | 1061 | ||
1052 | spin_unlock(&host->irq_lock); | 1062 | /* |
1063 | * MMC controller IRQ handler | ||
1064 | */ | ||
1065 | static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) | ||
1066 | { | ||
1067 | struct omap_hsmmc_host *host = dev_id; | ||
1068 | int status; | ||
1069 | |||
1070 | status = OMAP_HSMMC_READ(host->base, STAT); | ||
1071 | do { | ||
1072 | omap_hsmmc_do_irq(host, status); | ||
1073 | /* Flush posted write */ | ||
1074 | status = OMAP_HSMMC_READ(host->base, STAT); | ||
1075 | } while (status & INT_EN_MASK); | ||
1053 | 1076 | ||
1054 | return IRQ_HANDLED; | 1077 | return IRQ_HANDLED; |
1055 | } | 1078 | } |
@@ -1244,31 +1267,47 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, | |||
1244 | /* | 1267 | /* |
1245 | * DMA call back function | 1268 | * DMA call back function |
1246 | */ | 1269 | */ |
1247 | static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data) | 1270 | static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data) |
1248 | { | 1271 | { |
1249 | struct omap_hsmmc_host *host = data; | 1272 | struct omap_hsmmc_host *host = cb_data; |
1273 | struct mmc_data *data = host->mrq->data; | ||
1274 | int dma_ch, req_in_progress; | ||
1250 | 1275 | ||
1251 | if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ) | 1276 | if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ) |
1252 | dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n"); | 1277 | dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n"); |
1253 | 1278 | ||
1254 | if (host->dma_ch < 0) | 1279 | spin_lock(&host->irq_lock); |
1280 | if (host->dma_ch < 0) { | ||
1281 | spin_unlock(&host->irq_lock); | ||
1255 | return; | 1282 | return; |
1283 | } | ||
1256 | 1284 | ||
1257 | host->dma_sg_idx++; | 1285 | host->dma_sg_idx++; |
1258 | if (host->dma_sg_idx < host->dma_len) { | 1286 | if (host->dma_sg_idx < host->dma_len) { |
1259 | /* Fire up the next transfer. */ | 1287 | /* Fire up the next transfer. */ |
1260 | omap_hsmmc_config_dma_params(host, host->data, | 1288 | omap_hsmmc_config_dma_params(host, data, |
1261 | host->data->sg + host->dma_sg_idx); | 1289 | data->sg + host->dma_sg_idx); |
1290 | spin_unlock(&host->irq_lock); | ||
1262 | return; | 1291 | return; |
1263 | } | 1292 | } |
1264 | 1293 | ||
1265 | omap_free_dma(host->dma_ch); | 1294 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, |
1295 | omap_hsmmc_get_dma_dir(host, data)); | ||
1296 | |||
1297 | req_in_progress = host->req_in_progress; | ||
1298 | dma_ch = host->dma_ch; | ||
1266 | host->dma_ch = -1; | 1299 | host->dma_ch = -1; |
1267 | /* | 1300 | spin_unlock(&host->irq_lock); |
1268 | * DMA Callback: run in interrupt context. | 1301 | |
1269 | * mutex_unlock will throw a kernel warning if used. | 1302 | omap_free_dma(dma_ch); |
1270 | */ | 1303 | |
1271 | up(&host->sem); | 1304 | /* If DMA has finished after TC, complete the request */ |
1305 | if (!req_in_progress) { | ||
1306 | struct mmc_request *mrq = host->mrq; | ||
1307 | |||
1308 | host->mrq = NULL; | ||
1309 | mmc_request_done(host->mmc, mrq); | ||
1310 | } | ||
1272 | } | 1311 | } |
1273 | 1312 | ||
1274 | /* | 1313 | /* |
@@ -1277,7 +1316,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data) | |||
1277 | static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, | 1316 | static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, |
1278 | struct mmc_request *req) | 1317 | struct mmc_request *req) |
1279 | { | 1318 | { |
1280 | int dma_ch = 0, ret = 0, err = 1, i; | 1319 | int dma_ch = 0, ret = 0, i; |
1281 | struct mmc_data *data = req->data; | 1320 | struct mmc_data *data = req->data; |
1282 | 1321 | ||
1283 | /* Sanity check: all the SG entries must be aligned by block size. */ | 1322 | /* Sanity check: all the SG entries must be aligned by block size. */ |
@@ -1294,23 +1333,7 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, | |||
1294 | */ | 1333 | */ |
1295 | return -EINVAL; | 1334 | return -EINVAL; |
1296 | 1335 | ||
1297 | /* | 1336 | BUG_ON(host->dma_ch != -1); |
1298 | * If for some reason the DMA transfer is still active, | ||
1299 | * we wait for timeout period and free the dma | ||
1300 | */ | ||
1301 | if (host->dma_ch != -1) { | ||
1302 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
1303 | schedule_timeout(100); | ||
1304 | if (down_trylock(&host->sem)) { | ||
1305 | omap_free_dma(host->dma_ch); | ||
1306 | host->dma_ch = -1; | ||
1307 | up(&host->sem); | ||
1308 | return err; | ||
1309 | } | ||
1310 | } else { | ||
1311 | if (down_trylock(&host->sem)) | ||
1312 | return err; | ||
1313 | } | ||
1314 | 1337 | ||
1315 | ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), | 1338 | ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), |
1316 | "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); | 1339 | "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); |
@@ -1410,37 +1433,27 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
1410 | struct omap_hsmmc_host *host = mmc_priv(mmc); | 1433 | struct omap_hsmmc_host *host = mmc_priv(mmc); |
1411 | int err; | 1434 | int err; |
1412 | 1435 | ||
1413 | /* | 1436 | BUG_ON(host->req_in_progress); |
1414 | * Prevent races with the interrupt handler because of unexpected | 1437 | BUG_ON(host->dma_ch != -1); |
1415 | * interrupts, but not if we are already in interrupt context i.e. | 1438 | if (host->protect_card) { |
1416 | * retries. | 1439 | if (host->reqs_blocked < 3) { |
1417 | */ | 1440 | /* |
1418 | if (!in_interrupt()) { | 1441 | * Ensure the controller is left in a consistent |
1419 | spin_lock_irqsave(&host->irq_lock, host->flags); | 1442 | * state by resetting the command and data state |
1420 | /* | 1443 | * machines. |
1421 | * Protect the card from I/O if there is a possibility | 1444 | */ |
1422 | * it can be removed. | 1445 | omap_hsmmc_reset_controller_fsm(host, SRD); |
1423 | */ | 1446 | omap_hsmmc_reset_controller_fsm(host, SRC); |
1424 | if (host->protect_card) { | 1447 | host->reqs_blocked += 1; |
1425 | if (host->reqs_blocked < 3) { | 1448 | } |
1426 | /* | 1449 | req->cmd->error = -EBADF; |
1427 | * Ensure the controller is left in a consistent | 1450 | if (req->data) |
1428 | * state by resetting the command and data state | 1451 | req->data->error = -EBADF; |
1429 | * machines. | 1452 | req->cmd->retries = 0; |
1430 | */ | 1453 | mmc_request_done(mmc, req); |
1431 | omap_hsmmc_reset_controller_fsm(host, SRD); | 1454 | return; |
1432 | omap_hsmmc_reset_controller_fsm(host, SRC); | 1455 | } else if (host->reqs_blocked) |
1433 | host->reqs_blocked += 1; | 1456 | host->reqs_blocked = 0; |
1434 | } | ||
1435 | req->cmd->error = -EBADF; | ||
1436 | if (req->data) | ||
1437 | req->data->error = -EBADF; | ||
1438 | spin_unlock_irqrestore(&host->irq_lock, host->flags); | ||
1439 | mmc_request_done(mmc, req); | ||
1440 | return; | ||
1441 | } else if (host->reqs_blocked) | ||
1442 | host->reqs_blocked = 0; | ||
1443 | } | ||
1444 | WARN_ON(host->mrq != NULL); | 1457 | WARN_ON(host->mrq != NULL); |
1445 | host->mrq = req; | 1458 | host->mrq = req; |
1446 | err = omap_hsmmc_prepare_data(host, req); | 1459 | err = omap_hsmmc_prepare_data(host, req); |
@@ -1449,8 +1462,6 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) | |||
1449 | if (req->data) | 1462 | if (req->data) |
1450 | req->data->error = err; | 1463 | req->data->error = err; |
1451 | host->mrq = NULL; | 1464 | host->mrq = NULL; |
1452 | if (!in_interrupt()) | ||
1453 | spin_unlock_irqrestore(&host->irq_lock, host->flags); | ||
1454 | mmc_request_done(mmc, req); | 1465 | mmc_request_done(mmc, req); |
1455 | return; | 1466 | return; |
1456 | } | 1467 | } |
@@ -2019,7 +2030,6 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2019 | mmc->f_min = 400000; | 2030 | mmc->f_min = 400000; |
2020 | mmc->f_max = 52000000; | 2031 | mmc->f_max = 52000000; |
2021 | 2032 | ||
2022 | sema_init(&host->sem, 1); | ||
2023 | spin_lock_init(&host->irq_lock); | 2033 | spin_lock_init(&host->irq_lock); |
2024 | 2034 | ||
2025 | host->iclk = clk_get(&pdev->dev, "ick"); | 2035 | host->iclk = clk_get(&pdev->dev, "ick"); |
@@ -2162,8 +2172,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) | |||
2162 | } | 2172 | } |
2163 | } | 2173 | } |
2164 | 2174 | ||
2165 | OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); | 2175 | omap_hsmmc_disable_irq(host); |
2166 | OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); | ||
2167 | 2176 | ||
2168 | mmc_host_lazy_disable(host->mmc); | 2177 | mmc_host_lazy_disable(host->mmc); |
2169 | 2178 | ||
@@ -2258,10 +2267,12 @@ static int omap_hsmmc_remove(struct platform_device *pdev) | |||
2258 | } | 2267 | } |
2259 | 2268 | ||
2260 | #ifdef CONFIG_PM | 2269 | #ifdef CONFIG_PM |
2261 | static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state) | 2270 | static int omap_hsmmc_suspend(struct device *dev) |
2262 | { | 2271 | { |
2263 | int ret = 0; | 2272 | int ret = 0; |
2273 | struct platform_device *pdev = to_platform_device(dev); | ||
2264 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); | 2274 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); |
2275 | pm_message_t state = PMSG_SUSPEND; /* unused by MMC core */ | ||
2265 | 2276 | ||
2266 | if (host && host->suspended) | 2277 | if (host && host->suspended) |
2267 | return 0; | 2278 | return 0; |
@@ -2281,12 +2292,9 @@ static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
2281 | } | 2292 | } |
2282 | cancel_work_sync(&host->mmc_carddetect_work); | 2293 | cancel_work_sync(&host->mmc_carddetect_work); |
2283 | mmc_host_enable(host->mmc); | 2294 | mmc_host_enable(host->mmc); |
2284 | ret = mmc_suspend_host(host->mmc, state); | 2295 | ret = mmc_suspend_host(host->mmc); |
2285 | if (ret == 0) { | 2296 | if (ret == 0) { |
2286 | OMAP_HSMMC_WRITE(host->base, ISE, 0); | 2297 | omap_hsmmc_disable_irq(host); |
2287 | OMAP_HSMMC_WRITE(host->base, IE, 0); | ||
2288 | |||
2289 | |||
2290 | OMAP_HSMMC_WRITE(host->base, HCTL, | 2298 | OMAP_HSMMC_WRITE(host->base, HCTL, |
2291 | OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); | 2299 | OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); |
2292 | mmc_host_disable(host->mmc); | 2300 | mmc_host_disable(host->mmc); |
@@ -2310,9 +2318,10 @@ static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state) | |||
2310 | } | 2318 | } |
2311 | 2319 | ||
2312 | /* Routine to resume the MMC device */ | 2320 | /* Routine to resume the MMC device */ |
2313 | static int omap_hsmmc_resume(struct platform_device *pdev) | 2321 | static int omap_hsmmc_resume(struct device *dev) |
2314 | { | 2322 | { |
2315 | int ret = 0; | 2323 | int ret = 0; |
2324 | struct platform_device *pdev = to_platform_device(dev); | ||
2316 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); | 2325 | struct omap_hsmmc_host *host = platform_get_drvdata(pdev); |
2317 | 2326 | ||
2318 | if (host && !host->suspended) | 2327 | if (host && !host->suspended) |
@@ -2363,13 +2372,17 @@ clk_en_err: | |||
2363 | #define omap_hsmmc_resume NULL | 2372 | #define omap_hsmmc_resume NULL |
2364 | #endif | 2373 | #endif |
2365 | 2374 | ||
2366 | static struct platform_driver omap_hsmmc_driver = { | 2375 | static struct dev_pm_ops omap_hsmmc_dev_pm_ops = { |
2367 | .remove = omap_hsmmc_remove, | ||
2368 | .suspend = omap_hsmmc_suspend, | 2376 | .suspend = omap_hsmmc_suspend, |
2369 | .resume = omap_hsmmc_resume, | 2377 | .resume = omap_hsmmc_resume, |
2378 | }; | ||
2379 | |||
2380 | static struct platform_driver omap_hsmmc_driver = { | ||
2381 | .remove = omap_hsmmc_remove, | ||
2370 | .driver = { | 2382 | .driver = { |
2371 | .name = DRIVER_NAME, | 2383 | .name = DRIVER_NAME, |
2372 | .owner = THIS_MODULE, | 2384 | .owner = THIS_MODULE, |
2385 | .pm = &omap_hsmmc_dev_pm_ops, | ||
2373 | }, | 2386 | }, |
2374 | }; | 2387 | }; |
2375 | 2388 | ||
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index e4f00e70a749..0a4e43f37140 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
@@ -813,7 +813,7 @@ static int pxamci_suspend(struct device *dev) | |||
813 | int ret = 0; | 813 | int ret = 0; |
814 | 814 | ||
815 | if (mmc) | 815 | if (mmc) |
816 | ret = mmc_suspend_host(mmc, PMSG_SUSPEND); | 816 | ret = mmc_suspend_host(mmc); |
817 | 817 | ||
818 | return ret; | 818 | return ret; |
819 | } | 819 | } |
diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index 2fdf7689ae6c..2e16e0a90a5e 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c | |||
@@ -1881,9 +1881,8 @@ MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids); | |||
1881 | static int s3cmci_suspend(struct device *dev) | 1881 | static int s3cmci_suspend(struct device *dev) |
1882 | { | 1882 | { |
1883 | struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev)); | 1883 | struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev)); |
1884 | struct pm_message event = { PM_EVENT_SUSPEND }; | ||
1885 | 1884 | ||
1886 | return mmc_suspend_host(mmc, event); | 1885 | return mmc_suspend_host(mmc); |
1887 | } | 1886 | } |
1888 | 1887 | ||
1889 | static int s3cmci_resume(struct device *dev) | 1888 | static int s3cmci_resume(struct device *dev) |
diff --git a/drivers/mmc/host/sdhci-of-core.c b/drivers/mmc/host/sdhci-of-core.c index 7802a543d8fc..a2e9820cd42f 100644 --- a/drivers/mmc/host/sdhci-of-core.c +++ b/drivers/mmc/host/sdhci-of-core.c | |||
@@ -89,7 +89,7 @@ static int sdhci_of_suspend(struct of_device *ofdev, pm_message_t state) | |||
89 | { | 89 | { |
90 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); | 90 | struct sdhci_host *host = dev_get_drvdata(&ofdev->dev); |
91 | 91 | ||
92 | return mmc_suspend_host(host->mmc, state); | 92 | return mmc_suspend_host(host->mmc); |
93 | } | 93 | } |
94 | 94 | ||
95 | static int sdhci_of_resume(struct of_device *ofdev) | 95 | static int sdhci_of_resume(struct of_device *ofdev) |
diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index d5b11a17e648..c8623de13af3 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c | |||
@@ -129,12 +129,12 @@ struct sdhci_of_data sdhci_esdhc = { | |||
129 | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | | 129 | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | |
130 | SDHCI_QUIRK_NO_CARD_NO_RESET, | 130 | SDHCI_QUIRK_NO_CARD_NO_RESET, |
131 | .ops = { | 131 | .ops = { |
132 | .readl = sdhci_be32bs_readl, | 132 | .read_l = sdhci_be32bs_readl, |
133 | .readw = esdhc_readw, | 133 | .read_w = esdhc_readw, |
134 | .readb = sdhci_be32bs_readb, | 134 | .read_b = sdhci_be32bs_readb, |
135 | .writel = sdhci_be32bs_writel, | 135 | .write_l = sdhci_be32bs_writel, |
136 | .writew = esdhc_writew, | 136 | .write_w = esdhc_writew, |
137 | .writeb = esdhc_writeb, | 137 | .write_b = esdhc_writeb, |
138 | .set_clock = esdhc_set_clock, | 138 | .set_clock = esdhc_set_clock, |
139 | .enable_dma = esdhc_enable_dma, | 139 | .enable_dma = esdhc_enable_dma, |
140 | .get_max_clock = esdhc_get_max_clock, | 140 | .get_max_clock = esdhc_get_max_clock, |
diff --git a/drivers/mmc/host/sdhci-of-hlwd.c b/drivers/mmc/host/sdhci-of-hlwd.c index 35117f3ed757..68ddb7546ae2 100644 --- a/drivers/mmc/host/sdhci-of-hlwd.c +++ b/drivers/mmc/host/sdhci-of-hlwd.c | |||
@@ -55,11 +55,11 @@ struct sdhci_of_data sdhci_hlwd = { | |||
55 | .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | | 55 | .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR | |
56 | SDHCI_QUIRK_32BIT_DMA_SIZE, | 56 | SDHCI_QUIRK_32BIT_DMA_SIZE, |
57 | .ops = { | 57 | .ops = { |
58 | .readl = sdhci_be32bs_readl, | 58 | .read_l = sdhci_be32bs_readl, |
59 | .readw = sdhci_be32bs_readw, | 59 | .read_w = sdhci_be32bs_readw, |
60 | .readb = sdhci_be32bs_readb, | 60 | .read_b = sdhci_be32bs_readb, |
61 | .writel = sdhci_hlwd_writel, | 61 | .write_l = sdhci_hlwd_writel, |
62 | .writew = sdhci_hlwd_writew, | 62 | .write_w = sdhci_hlwd_writew, |
63 | .writeb = sdhci_hlwd_writeb, | 63 | .write_b = sdhci_hlwd_writeb, |
64 | }, | 64 | }, |
65 | }; | 65 | }; |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 6701af629c30..65483fdea45b 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -628,7 +628,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | |||
628 | host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot)); | 628 | host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot)); |
629 | if (IS_ERR(host)) { | 629 | if (IS_ERR(host)) { |
630 | dev_err(&pdev->dev, "cannot allocate host\n"); | 630 | dev_err(&pdev->dev, "cannot allocate host\n"); |
631 | return ERR_PTR(PTR_ERR(host)); | 631 | return ERR_CAST(host); |
632 | } | 632 | } |
633 | 633 | ||
634 | slot = sdhci_priv(host); | 634 | slot = sdhci_priv(host); |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 297f40ae6ad5..b6ee0d719698 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/mmc/host.h> | 29 | #include <linux/mmc/host.h> |
30 | 30 | ||
31 | #include <linux/io.h> | 31 | #include <linux/io.h> |
32 | #include <linux/sdhci-pltfm.h> | ||
32 | 33 | ||
33 | #include "sdhci.h" | 34 | #include "sdhci.h" |
34 | 35 | ||
@@ -49,19 +50,18 @@ static struct sdhci_ops sdhci_pltfm_ops = { | |||
49 | 50 | ||
50 | static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | 51 | static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) |
51 | { | 52 | { |
53 | struct sdhci_pltfm_data *pdata = pdev->dev.platform_data; | ||
52 | struct sdhci_host *host; | 54 | struct sdhci_host *host; |
53 | struct resource *iomem; | 55 | struct resource *iomem; |
54 | int ret; | 56 | int ret; |
55 | 57 | ||
56 | BUG_ON(pdev == NULL); | ||
57 | |||
58 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 58 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
59 | if (!iomem) { | 59 | if (!iomem) { |
60 | ret = -ENOMEM; | 60 | ret = -ENOMEM; |
61 | goto err; | 61 | goto err; |
62 | } | 62 | } |
63 | 63 | ||
64 | if (resource_size(iomem) != 0x100) | 64 | if (resource_size(iomem) < 0x100) |
65 | dev_err(&pdev->dev, "Invalid iomem size. You may " | 65 | dev_err(&pdev->dev, "Invalid iomem size. You may " |
66 | "experience problems.\n"); | 66 | "experience problems.\n"); |
67 | 67 | ||
@@ -76,7 +76,12 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | |||
76 | } | 76 | } |
77 | 77 | ||
78 | host->hw_name = "platform"; | 78 | host->hw_name = "platform"; |
79 | host->ops = &sdhci_pltfm_ops; | 79 | if (pdata && pdata->ops) |
80 | host->ops = pdata->ops; | ||
81 | else | ||
82 | host->ops = &sdhci_pltfm_ops; | ||
83 | if (pdata) | ||
84 | host->quirks = pdata->quirks; | ||
80 | host->irq = platform_get_irq(pdev, 0); | 85 | host->irq = platform_get_irq(pdev, 0); |
81 | 86 | ||
82 | if (!request_mem_region(iomem->start, resource_size(iomem), | 87 | if (!request_mem_region(iomem->start, resource_size(iomem), |
@@ -93,6 +98,12 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | |||
93 | goto err_remap; | 98 | goto err_remap; |
94 | } | 99 | } |
95 | 100 | ||
101 | if (pdata && pdata->init) { | ||
102 | ret = pdata->init(host); | ||
103 | if (ret) | ||
104 | goto err_plat_init; | ||
105 | } | ||
106 | |||
96 | ret = sdhci_add_host(host); | 107 | ret = sdhci_add_host(host); |
97 | if (ret) | 108 | if (ret) |
98 | goto err_add_host; | 109 | goto err_add_host; |
@@ -102,6 +113,9 @@ static int __devinit sdhci_pltfm_probe(struct platform_device *pdev) | |||
102 | return 0; | 113 | return 0; |
103 | 114 | ||
104 | err_add_host: | 115 | err_add_host: |
116 | if (pdata && pdata->exit) | ||
117 | pdata->exit(host); | ||
118 | err_plat_init: | ||
105 | iounmap(host->ioaddr); | 119 | iounmap(host->ioaddr); |
106 | err_remap: | 120 | err_remap: |
107 | release_mem_region(iomem->start, resource_size(iomem)); | 121 | release_mem_region(iomem->start, resource_size(iomem)); |
@@ -114,6 +128,7 @@ err: | |||
114 | 128 | ||
115 | static int __devexit sdhci_pltfm_remove(struct platform_device *pdev) | 129 | static int __devexit sdhci_pltfm_remove(struct platform_device *pdev) |
116 | { | 130 | { |
131 | struct sdhci_pltfm_data *pdata = pdev->dev.platform_data; | ||
117 | struct sdhci_host *host = platform_get_drvdata(pdev); | 132 | struct sdhci_host *host = platform_get_drvdata(pdev); |
118 | struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 133 | struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
119 | int dead; | 134 | int dead; |
@@ -125,6 +140,8 @@ static int __devexit sdhci_pltfm_remove(struct platform_device *pdev) | |||
125 | dead = 1; | 140 | dead = 1; |
126 | 141 | ||
127 | sdhci_remove_host(host, dead); | 142 | sdhci_remove_host(host, dead); |
143 | if (pdata && pdata->exit) | ||
144 | pdata->exit(host); | ||
128 | iounmap(host->ioaddr); | 145 | iounmap(host->ioaddr); |
129 | release_mem_region(iomem->start, resource_size(iomem)); | 146 | release_mem_region(iomem->start, resource_size(iomem)); |
130 | sdhci_free_host(host); | 147 | sdhci_free_host(host); |
@@ -165,4 +182,3 @@ MODULE_DESCRIPTION("Secure Digital Host Controller Interface platform driver"); | |||
165 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); | 182 | MODULE_AUTHOR("Mocean Laboratories <info@mocean-labs.com>"); |
166 | MODULE_LICENSE("GPL v2"); | 183 | MODULE_LICENSE("GPL v2"); |
167 | MODULE_ALIAS("platform:sdhci"); | 184 | MODULE_ALIAS("platform:sdhci"); |
168 | |||
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 2136794c0cfa..af217924a76e 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
@@ -317,12 +317,7 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
317 | host->irq = irq; | 317 | host->irq = irq; |
318 | 318 | ||
319 | /* Setup quirks for the controller */ | 319 | /* Setup quirks for the controller */ |
320 | 320 | host->quirks |= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC; | |
321 | /* Currently with ADMA enabled we are getting some length | ||
322 | * interrupts that are not being dealt with, do disable | ||
323 | * ADMA until this is sorted out. */ | ||
324 | host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; | ||
325 | host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE; | ||
326 | 321 | ||
327 | #ifndef CONFIG_MMC_SDHCI_S3C_DMA | 322 | #ifndef CONFIG_MMC_SDHCI_S3C_DMA |
328 | 323 | ||
@@ -330,9 +325,6 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
330 | * support as well. */ | 325 | * support as well. */ |
331 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; | 326 | host->quirks |= SDHCI_QUIRK_BROKEN_DMA; |
332 | 327 | ||
333 | /* PIO currently has problems with multi-block IO */ | ||
334 | host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK; | ||
335 | |||
336 | #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ | 328 | #endif /* CONFIG_MMC_SDHCI_S3C_DMA */ |
337 | 329 | ||
338 | /* It seems we do not get an DATA transfer complete on non-busy | 330 | /* It seems we do not get an DATA transfer complete on non-busy |
diff --git a/drivers/mmc/host/sdhci-spear.c b/drivers/mmc/host/sdhci-spear.c new file mode 100644 index 000000000000..d70c54c7b70a --- /dev/null +++ b/drivers/mmc/host/sdhci-spear.c | |||
@@ -0,0 +1,298 @@ | |||
1 | /* | ||
2 | * drivers/mmc/host/sdhci-spear.c | ||
3 | * | ||
4 | * Support of SDHCI platform devices for spear soc family | ||
5 | * | ||
6 | * Copyright (C) 2010 ST Microelectronics | ||
7 | * Viresh Kumar<viresh.kumar@st.com> | ||
8 | * | ||
9 | * Inspired by sdhci-pltfm.c | ||
10 | * | ||
11 | * This file is licensed under the terms of the GNU General Public | ||
12 | * License version 2. This program is licensed "as is" without any | ||
13 | * warranty of any kind, whether express or implied. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <linux/highmem.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/mmc/host.h> | ||
25 | #include <linux/mmc/sdhci-spear.h> | ||
26 | #include <linux/io.h> | ||
27 | #include "sdhci.h" | ||
28 | |||
29 | struct spear_sdhci { | ||
30 | struct clk *clk; | ||
31 | struct sdhci_plat_data *data; | ||
32 | }; | ||
33 | |||
34 | /* sdhci ops */ | ||
35 | static struct sdhci_ops sdhci_pltfm_ops = { | ||
36 | /* Nothing to do for now. */ | ||
37 | }; | ||
38 | |||
39 | /* gpio card detection interrupt handler */ | ||
40 | static irqreturn_t sdhci_gpio_irq(int irq, void *dev_id) | ||
41 | { | ||
42 | struct platform_device *pdev = dev_id; | ||
43 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
44 | struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); | ||
45 | unsigned long gpio_irq_type; | ||
46 | int val; | ||
47 | |||
48 | val = gpio_get_value(sdhci->data->card_int_gpio); | ||
49 | |||
50 | /* val == 1 -> card removed, val == 0 -> card inserted */ | ||
51 | /* if card removed - set irq for low level, else vice versa */ | ||
52 | gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH; | ||
53 | set_irq_type(irq, gpio_irq_type); | ||
54 | |||
55 | if (sdhci->data->card_power_gpio >= 0) { | ||
56 | if (!sdhci->data->power_always_enb) { | ||
57 | /* if card inserted, give power, otherwise remove it */ | ||
58 | val = sdhci->data->power_active_high ? !val : val ; | ||
59 | gpio_set_value(sdhci->data->card_power_gpio, val); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | /* inform sdhci driver about card insertion/removal */ | ||
64 | tasklet_schedule(&host->card_tasklet); | ||
65 | |||
66 | return IRQ_HANDLED; | ||
67 | } | ||
68 | |||
69 | static int __devinit sdhci_probe(struct platform_device *pdev) | ||
70 | { | ||
71 | struct sdhci_host *host; | ||
72 | struct resource *iomem; | ||
73 | struct spear_sdhci *sdhci; | ||
74 | int ret; | ||
75 | |||
76 | BUG_ON(pdev == NULL); | ||
77 | |||
78 | iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
79 | if (!iomem) { | ||
80 | ret = -ENOMEM; | ||
81 | dev_dbg(&pdev->dev, "memory resource not defined\n"); | ||
82 | goto err; | ||
83 | } | ||
84 | |||
85 | if (!request_mem_region(iomem->start, resource_size(iomem), | ||
86 | "spear-sdhci")) { | ||
87 | ret = -EBUSY; | ||
88 | dev_dbg(&pdev->dev, "cannot request region\n"); | ||
89 | goto err; | ||
90 | } | ||
91 | |||
92 | sdhci = kzalloc(sizeof(*sdhci), GFP_KERNEL); | ||
93 | if (!sdhci) { | ||
94 | ret = -ENOMEM; | ||
95 | dev_dbg(&pdev->dev, "cannot allocate memory for sdhci\n"); | ||
96 | goto err_kzalloc; | ||
97 | } | ||
98 | |||
99 | /* clk enable */ | ||
100 | sdhci->clk = clk_get(&pdev->dev, NULL); | ||
101 | if (IS_ERR(sdhci->clk)) { | ||
102 | ret = PTR_ERR(sdhci->clk); | ||
103 | dev_dbg(&pdev->dev, "Error getting clock\n"); | ||
104 | goto err_clk_get; | ||
105 | } | ||
106 | |||
107 | ret = clk_enable(sdhci->clk); | ||
108 | if (ret) { | ||
109 | dev_dbg(&pdev->dev, "Error enabling clock\n"); | ||
110 | goto err_clk_enb; | ||
111 | } | ||
112 | |||
113 | /* overwrite platform_data */ | ||
114 | sdhci->data = dev_get_platdata(&pdev->dev); | ||
115 | pdev->dev.platform_data = sdhci; | ||
116 | |||
117 | if (pdev->dev.parent) | ||
118 | host = sdhci_alloc_host(pdev->dev.parent, 0); | ||
119 | else | ||
120 | host = sdhci_alloc_host(&pdev->dev, 0); | ||
121 | |||
122 | if (IS_ERR(host)) { | ||
123 | ret = PTR_ERR(host); | ||
124 | dev_dbg(&pdev->dev, "error allocating host\n"); | ||
125 | goto err_alloc_host; | ||
126 | } | ||
127 | |||
128 | host->hw_name = "sdhci"; | ||
129 | host->ops = &sdhci_pltfm_ops; | ||
130 | host->irq = platform_get_irq(pdev, 0); | ||
131 | host->quirks = SDHCI_QUIRK_BROKEN_ADMA; | ||
132 | |||
133 | host->ioaddr = ioremap(iomem->start, resource_size(iomem)); | ||
134 | if (!host->ioaddr) { | ||
135 | ret = -ENOMEM; | ||
136 | dev_dbg(&pdev->dev, "failed to remap registers\n"); | ||
137 | goto err_ioremap; | ||
138 | } | ||
139 | |||
140 | ret = sdhci_add_host(host); | ||
141 | if (ret) { | ||
142 | dev_dbg(&pdev->dev, "error adding host\n"); | ||
143 | goto err_add_host; | ||
144 | } | ||
145 | |||
146 | platform_set_drvdata(pdev, host); | ||
147 | |||
148 | /* | ||
149 | * It is optional to use GPIOs for sdhci Power control & sdhci card | ||
150 | * interrupt detection. If sdhci->data is NULL, then use original sdhci | ||
151 | * lines otherwise GPIO lines. | ||
152 | * If GPIO is selected for power control, then power should be disabled | ||
153 | * after card removal and should be enabled when card insertion | ||
154 | * interrupt occurs | ||
155 | */ | ||
156 | if (!sdhci->data) | ||
157 | return 0; | ||
158 | |||
159 | if (sdhci->data->card_power_gpio >= 0) { | ||
160 | int val = 0; | ||
161 | |||
162 | ret = gpio_request(sdhci->data->card_power_gpio, "sdhci"); | ||
163 | if (ret < 0) { | ||
164 | dev_dbg(&pdev->dev, "gpio request fail: %d\n", | ||
165 | sdhci->data->card_power_gpio); | ||
166 | goto err_pgpio_request; | ||
167 | } | ||
168 | |||
169 | if (sdhci->data->power_always_enb) | ||
170 | val = sdhci->data->power_active_high; | ||
171 | else | ||
172 | val = !sdhci->data->power_active_high; | ||
173 | |||
174 | ret = gpio_direction_output(sdhci->data->card_power_gpio, val); | ||
175 | if (ret) { | ||
176 | dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", | ||
177 | sdhci->data->card_power_gpio); | ||
178 | goto err_pgpio_direction; | ||
179 | } | ||
180 | |||
181 | gpio_set_value(sdhci->data->card_power_gpio, 1); | ||
182 | } | ||
183 | |||
184 | if (sdhci->data->card_int_gpio >= 0) { | ||
185 | ret = gpio_request(sdhci->data->card_int_gpio, "sdhci"); | ||
186 | if (ret < 0) { | ||
187 | dev_dbg(&pdev->dev, "gpio request fail: %d\n", | ||
188 | sdhci->data->card_int_gpio); | ||
189 | goto err_igpio_request; | ||
190 | } | ||
191 | |||
192 | ret = gpio_direction_input(sdhci->data->card_int_gpio); | ||
193 | if (ret) { | ||
194 | dev_dbg(&pdev->dev, "gpio set direction fail: %d\n", | ||
195 | sdhci->data->card_int_gpio); | ||
196 | goto err_igpio_direction; | ||
197 | } | ||
198 | ret = request_irq(gpio_to_irq(sdhci->data->card_int_gpio), | ||
199 | sdhci_gpio_irq, IRQF_TRIGGER_LOW, | ||
200 | mmc_hostname(host->mmc), pdev); | ||
201 | if (ret) { | ||
202 | dev_dbg(&pdev->dev, "gpio request irq fail: %d\n", | ||
203 | sdhci->data->card_int_gpio); | ||
204 | goto err_igpio_request_irq; | ||
205 | } | ||
206 | |||
207 | } | ||
208 | |||
209 | return 0; | ||
210 | |||
211 | err_igpio_request_irq: | ||
212 | err_igpio_direction: | ||
213 | if (sdhci->data->card_int_gpio >= 0) | ||
214 | gpio_free(sdhci->data->card_int_gpio); | ||
215 | err_igpio_request: | ||
216 | err_pgpio_direction: | ||
217 | if (sdhci->data->card_power_gpio >= 0) | ||
218 | gpio_free(sdhci->data->card_power_gpio); | ||
219 | err_pgpio_request: | ||
220 | platform_set_drvdata(pdev, NULL); | ||
221 | sdhci_remove_host(host, 1); | ||
222 | err_add_host: | ||
223 | iounmap(host->ioaddr); | ||
224 | err_ioremap: | ||
225 | sdhci_free_host(host); | ||
226 | err_alloc_host: | ||
227 | clk_disable(sdhci->clk); | ||
228 | err_clk_enb: | ||
229 | clk_put(sdhci->clk); | ||
230 | err_clk_get: | ||
231 | kfree(sdhci); | ||
232 | err_kzalloc: | ||
233 | release_mem_region(iomem->start, resource_size(iomem)); | ||
234 | err: | ||
235 | dev_err(&pdev->dev, "spear-sdhci probe failed: %d\n", ret); | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | static int __devexit sdhci_remove(struct platform_device *pdev) | ||
240 | { | ||
241 | struct sdhci_host *host = platform_get_drvdata(pdev); | ||
242 | struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
243 | struct spear_sdhci *sdhci = dev_get_platdata(&pdev->dev); | ||
244 | int dead; | ||
245 | u32 scratch; | ||
246 | |||
247 | if (sdhci->data) { | ||
248 | if (sdhci->data->card_int_gpio >= 0) { | ||
249 | free_irq(gpio_to_irq(sdhci->data->card_int_gpio), pdev); | ||
250 | gpio_free(sdhci->data->card_int_gpio); | ||
251 | } | ||
252 | |||
253 | if (sdhci->data->card_power_gpio >= 0) | ||
254 | gpio_free(sdhci->data->card_power_gpio); | ||
255 | } | ||
256 | |||
257 | platform_set_drvdata(pdev, NULL); | ||
258 | dead = 0; | ||
259 | scratch = readl(host->ioaddr + SDHCI_INT_STATUS); | ||
260 | if (scratch == (u32)-1) | ||
261 | dead = 1; | ||
262 | |||
263 | sdhci_remove_host(host, dead); | ||
264 | iounmap(host->ioaddr); | ||
265 | sdhci_free_host(host); | ||
266 | clk_disable(sdhci->clk); | ||
267 | clk_put(sdhci->clk); | ||
268 | kfree(sdhci); | ||
269 | if (iomem) | ||
270 | release_mem_region(iomem->start, resource_size(iomem)); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static struct platform_driver sdhci_driver = { | ||
276 | .driver = { | ||
277 | .name = "sdhci", | ||
278 | .owner = THIS_MODULE, | ||
279 | }, | ||
280 | .probe = sdhci_probe, | ||
281 | .remove = __devexit_p(sdhci_remove), | ||
282 | }; | ||
283 | |||
284 | static int __init sdhci_init(void) | ||
285 | { | ||
286 | return platform_driver_register(&sdhci_driver); | ||
287 | } | ||
288 | module_init(sdhci_init); | ||
289 | |||
290 | static void __exit sdhci_exit(void) | ||
291 | { | ||
292 | platform_driver_unregister(&sdhci_driver); | ||
293 | } | ||
294 | module_exit(sdhci_exit); | ||
295 | |||
296 | MODULE_DESCRIPTION("SPEAr Secure Digital Host Controller Interface driver"); | ||
297 | MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>"); | ||
298 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9d4fdfa685e5..c6d1bd8d4ac4 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -496,12 +496,22 @@ static int sdhci_adma_table_pre(struct sdhci_host *host, | |||
496 | WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); | 496 | WARN_ON((desc - host->adma_desc) > (128 * 2 + 1) * 4); |
497 | } | 497 | } |
498 | 498 | ||
499 | /* | 499 | if (host->quirks & SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC) { |
500 | * Add a terminating entry. | 500 | /* |
501 | */ | 501 | * Mark the last descriptor as the terminating descriptor |
502 | */ | ||
503 | if (desc != host->adma_desc) { | ||
504 | desc -= 8; | ||
505 | desc[0] |= 0x2; /* end */ | ||
506 | } | ||
507 | } else { | ||
508 | /* | ||
509 | * Add a terminating entry. | ||
510 | */ | ||
502 | 511 | ||
503 | /* nop, end, valid */ | 512 | /* nop, end, valid */ |
504 | sdhci_set_adma_desc(desc, 0, 0, 0x3); | 513 | sdhci_set_adma_desc(desc, 0, 0, 0x3); |
514 | } | ||
505 | 515 | ||
506 | /* | 516 | /* |
507 | * Resync align buffer as we might have changed it. | 517 | * Resync align buffer as we might have changed it. |
@@ -1587,7 +1597,7 @@ int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) | |||
1587 | 1597 | ||
1588 | sdhci_disable_card_detection(host); | 1598 | sdhci_disable_card_detection(host); |
1589 | 1599 | ||
1590 | ret = mmc_suspend_host(host->mmc, state); | 1600 | ret = mmc_suspend_host(host->mmc); |
1591 | if (ret) | 1601 | if (ret) |
1592 | return ret; | 1602 | return ret; |
1593 | 1603 | ||
@@ -1744,7 +1754,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1744 | host->max_clk = | 1754 | host->max_clk = |
1745 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; | 1755 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; |
1746 | host->max_clk *= 1000000; | 1756 | host->max_clk *= 1000000; |
1747 | if (host->max_clk == 0) { | 1757 | if (host->max_clk == 0 || host->quirks & |
1758 | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN) { | ||
1748 | if (!host->ops->get_max_clock) { | 1759 | if (!host->ops->get_max_clock) { |
1749 | printk(KERN_ERR | 1760 | printk(KERN_ERR |
1750 | "%s: Hardware doesn't specify base clock " | 1761 | "%s: Hardware doesn't specify base clock " |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 842f46f94284..c8468134adc9 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -127,7 +127,7 @@ | |||
127 | #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ | 127 | #define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \ |
128 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ | 128 | SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \ |
129 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ | 129 | SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \ |
130 | SDHCI_INT_DATA_END_BIT | SDHCI_ADMA_ERROR) | 130 | SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR) |
131 | #define SDHCI_INT_ALL_MASK ((unsigned int)-1) | 131 | #define SDHCI_INT_ALL_MASK ((unsigned int)-1) |
132 | 132 | ||
133 | #define SDHCI_ACMD12_ERR 0x3C | 133 | #define SDHCI_ACMD12_ERR 0x3C |
@@ -236,6 +236,10 @@ struct sdhci_host { | |||
236 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) | 236 | #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) |
237 | /* Controller uses SDCLK instead of TMCLK for data timeouts */ | 237 | /* Controller uses SDCLK instead of TMCLK for data timeouts */ |
238 | #define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) | 238 | #define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) |
239 | /* Controller reports wrong base clock capability */ | ||
240 | #define SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN (1<<25) | ||
241 | /* Controller cannot support End Attribute in NOP ADMA descriptor */ | ||
242 | #define SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC (1<<26) | ||
239 | 243 | ||
240 | int irq; /* Device IRQ */ | 244 | int irq; /* Device IRQ */ |
241 | void __iomem * ioaddr; /* Mapped address */ | 245 | void __iomem * ioaddr; /* Mapped address */ |
@@ -294,12 +298,12 @@ struct sdhci_host { | |||
294 | 298 | ||
295 | struct sdhci_ops { | 299 | struct sdhci_ops { |
296 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS | 300 | #ifdef CONFIG_MMC_SDHCI_IO_ACCESSORS |
297 | u32 (*readl)(struct sdhci_host *host, int reg); | 301 | u32 (*read_l)(struct sdhci_host *host, int reg); |
298 | u16 (*readw)(struct sdhci_host *host, int reg); | 302 | u16 (*read_w)(struct sdhci_host *host, int reg); |
299 | u8 (*readb)(struct sdhci_host *host, int reg); | 303 | u8 (*read_b)(struct sdhci_host *host, int reg); |
300 | void (*writel)(struct sdhci_host *host, u32 val, int reg); | 304 | void (*write_l)(struct sdhci_host *host, u32 val, int reg); |
301 | void (*writew)(struct sdhci_host *host, u16 val, int reg); | 305 | void (*write_w)(struct sdhci_host *host, u16 val, int reg); |
302 | void (*writeb)(struct sdhci_host *host, u8 val, int reg); | 306 | void (*write_b)(struct sdhci_host *host, u8 val, int reg); |
303 | #endif | 307 | #endif |
304 | 308 | ||
305 | void (*set_clock)(struct sdhci_host *host, unsigned int clock); | 309 | void (*set_clock)(struct sdhci_host *host, unsigned int clock); |
@@ -314,48 +318,48 @@ struct sdhci_ops { | |||
314 | 318 | ||
315 | static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) | 319 | static inline void sdhci_writel(struct sdhci_host *host, u32 val, int reg) |
316 | { | 320 | { |
317 | if (unlikely(host->ops->writel)) | 321 | if (unlikely(host->ops->write_l)) |
318 | host->ops->writel(host, val, reg); | 322 | host->ops->write_l(host, val, reg); |
319 | else | 323 | else |
320 | writel(val, host->ioaddr + reg); | 324 | writel(val, host->ioaddr + reg); |
321 | } | 325 | } |
322 | 326 | ||
323 | static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg) | 327 | static inline void sdhci_writew(struct sdhci_host *host, u16 val, int reg) |
324 | { | 328 | { |
325 | if (unlikely(host->ops->writew)) | 329 | if (unlikely(host->ops->write_w)) |
326 | host->ops->writew(host, val, reg); | 330 | host->ops->write_w(host, val, reg); |
327 | else | 331 | else |
328 | writew(val, host->ioaddr + reg); | 332 | writew(val, host->ioaddr + reg); |
329 | } | 333 | } |
330 | 334 | ||
331 | static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg) | 335 | static inline void sdhci_writeb(struct sdhci_host *host, u8 val, int reg) |
332 | { | 336 | { |
333 | if (unlikely(host->ops->writeb)) | 337 | if (unlikely(host->ops->write_b)) |
334 | host->ops->writeb(host, val, reg); | 338 | host->ops->write_b(host, val, reg); |
335 | else | 339 | else |
336 | writeb(val, host->ioaddr + reg); | 340 | writeb(val, host->ioaddr + reg); |
337 | } | 341 | } |
338 | 342 | ||
339 | static inline u32 sdhci_readl(struct sdhci_host *host, int reg) | 343 | static inline u32 sdhci_readl(struct sdhci_host *host, int reg) |
340 | { | 344 | { |
341 | if (unlikely(host->ops->readl)) | 345 | if (unlikely(host->ops->read_l)) |
342 | return host->ops->readl(host, reg); | 346 | return host->ops->read_l(host, reg); |
343 | else | 347 | else |
344 | return readl(host->ioaddr + reg); | 348 | return readl(host->ioaddr + reg); |
345 | } | 349 | } |
346 | 350 | ||
347 | static inline u16 sdhci_readw(struct sdhci_host *host, int reg) | 351 | static inline u16 sdhci_readw(struct sdhci_host *host, int reg) |
348 | { | 352 | { |
349 | if (unlikely(host->ops->readw)) | 353 | if (unlikely(host->ops->read_w)) |
350 | return host->ops->readw(host, reg); | 354 | return host->ops->read_w(host, reg); |
351 | else | 355 | else |
352 | return readw(host->ioaddr + reg); | 356 | return readw(host->ioaddr + reg); |
353 | } | 357 | } |
354 | 358 | ||
355 | static inline u8 sdhci_readb(struct sdhci_host *host, int reg) | 359 | static inline u8 sdhci_readb(struct sdhci_host *host, int reg) |
356 | { | 360 | { |
357 | if (unlikely(host->ops->readb)) | 361 | if (unlikely(host->ops->read_b)) |
358 | return host->ops->readb(host, reg); | 362 | return host->ops->read_b(host, reg); |
359 | else | 363 | else |
360 | return readb(host->ioaddr + reg); | 364 | return readb(host->ioaddr + reg); |
361 | } | 365 | } |
diff --git a/drivers/mmc/host/sdricoh_cs.c b/drivers/mmc/host/sdricoh_cs.c index cb41e9c3ac07..e7507af3856e 100644 --- a/drivers/mmc/host/sdricoh_cs.c +++ b/drivers/mmc/host/sdricoh_cs.c | |||
@@ -519,7 +519,7 @@ static int sdricoh_pcmcia_suspend(struct pcmcia_device *link) | |||
519 | { | 519 | { |
520 | struct mmc_host *mmc = link->priv; | 520 | struct mmc_host *mmc = link->priv; |
521 | dev_dbg(&link->dev, "suspend\n"); | 521 | dev_dbg(&link->dev, "suspend\n"); |
522 | mmc_suspend_host(mmc, PMSG_SUSPEND); | 522 | mmc_suspend_host(mmc); |
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
525 | 525 | ||
diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c new file mode 100644 index 000000000000..eb97830c0344 --- /dev/null +++ b/drivers/mmc/host/sh_mmcif.c | |||
@@ -0,0 +1,965 @@ | |||
1 | /* | ||
2 | * MMCIF eMMC driver. | ||
3 | * | ||
4 | * Copyright (C) 2010 Renesas Solutions Corp. | ||
5 | * Yusuke Goda <yusuke.goda.sx@renesas.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License. | ||
10 | * | ||
11 | * | ||
12 | * TODO | ||
13 | * 1. DMA | ||
14 | * 2. Power management | ||
15 | * 3. Handle MMC errors better | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/mmc/host.h> | ||
21 | #include <linux/mmc/card.h> | ||
22 | #include <linux/mmc/core.h> | ||
23 | #include <linux/mmc/mmc.h> | ||
24 | #include <linux/mmc/sdio.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/mmc/sh_mmcif.h> | ||
29 | |||
30 | #define DRIVER_NAME "sh_mmcif" | ||
31 | #define DRIVER_VERSION "2010-04-28" | ||
32 | |||
33 | #define MMCIF_CE_CMD_SET 0x00000000 | ||
34 | #define MMCIF_CE_ARG 0x00000008 | ||
35 | #define MMCIF_CE_ARG_CMD12 0x0000000C | ||
36 | #define MMCIF_CE_CMD_CTRL 0x00000010 | ||
37 | #define MMCIF_CE_BLOCK_SET 0x00000014 | ||
38 | #define MMCIF_CE_CLK_CTRL 0x00000018 | ||
39 | #define MMCIF_CE_BUF_ACC 0x0000001C | ||
40 | #define MMCIF_CE_RESP3 0x00000020 | ||
41 | #define MMCIF_CE_RESP2 0x00000024 | ||
42 | #define MMCIF_CE_RESP1 0x00000028 | ||
43 | #define MMCIF_CE_RESP0 0x0000002C | ||
44 | #define MMCIF_CE_RESP_CMD12 0x00000030 | ||
45 | #define MMCIF_CE_DATA 0x00000034 | ||
46 | #define MMCIF_CE_INT 0x00000040 | ||
47 | #define MMCIF_CE_INT_MASK 0x00000044 | ||
48 | #define MMCIF_CE_HOST_STS1 0x00000048 | ||
49 | #define MMCIF_CE_HOST_STS2 0x0000004C | ||
50 | #define MMCIF_CE_VERSION 0x0000007C | ||
51 | |||
52 | /* CE_CMD_SET */ | ||
53 | #define CMD_MASK 0x3f000000 | ||
54 | #define CMD_SET_RTYP_NO ((0 << 23) | (0 << 22)) | ||
55 | #define CMD_SET_RTYP_6B ((0 << 23) | (1 << 22)) /* R1/R1b/R3/R4/R5 */ | ||
56 | #define CMD_SET_RTYP_17B ((1 << 23) | (0 << 22)) /* R2 */ | ||
57 | #define CMD_SET_RBSY (1 << 21) /* R1b */ | ||
58 | #define CMD_SET_CCSEN (1 << 20) | ||
59 | #define CMD_SET_WDAT (1 << 19) /* 1: on data, 0: no data */ | ||
60 | #define CMD_SET_DWEN (1 << 18) /* 1: write, 0: read */ | ||
61 | #define CMD_SET_CMLTE (1 << 17) /* 1: multi block trans, 0: single */ | ||
62 | #define CMD_SET_CMD12EN (1 << 16) /* 1: CMD12 auto issue */ | ||
63 | #define CMD_SET_RIDXC_INDEX ((0 << 15) | (0 << 14)) /* index check */ | ||
64 | #define CMD_SET_RIDXC_BITS ((0 << 15) | (1 << 14)) /* check bits check */ | ||
65 | #define CMD_SET_RIDXC_NO ((1 << 15) | (0 << 14)) /* no check */ | ||
66 | #define CMD_SET_CRC7C ((0 << 13) | (0 << 12)) /* CRC7 check*/ | ||
67 | #define CMD_SET_CRC7C_BITS ((0 << 13) | (1 << 12)) /* check bits check*/ | ||
68 | #define CMD_SET_CRC7C_INTERNAL ((1 << 13) | (0 << 12)) /* internal CRC7 check*/ | ||
69 | #define CMD_SET_CRC16C (1 << 10) /* 0: CRC16 check*/ | ||
70 | #define CMD_SET_CRCSTE (1 << 8) /* 1: not receive CRC status */ | ||
71 | #define CMD_SET_TBIT (1 << 7) /* 1: tran mission bit "Low" */ | ||
72 | #define CMD_SET_OPDM (1 << 6) /* 1: open/drain */ | ||
73 | #define CMD_SET_CCSH (1 << 5) | ||
74 | #define CMD_SET_DATW_1 ((0 << 1) | (0 << 0)) /* 1bit */ | ||
75 | #define CMD_SET_DATW_4 ((0 << 1) | (1 << 0)) /* 4bit */ | ||
76 | #define CMD_SET_DATW_8 ((1 << 1) | (0 << 0)) /* 8bit */ | ||
77 | |||
78 | /* CE_CMD_CTRL */ | ||
79 | #define CMD_CTRL_BREAK (1 << 0) | ||
80 | |||
81 | /* CE_BLOCK_SET */ | ||
82 | #define BLOCK_SIZE_MASK 0x0000ffff | ||
83 | |||
84 | /* CE_CLK_CTRL */ | ||
85 | #define CLK_ENABLE (1 << 24) /* 1: output mmc clock */ | ||
86 | #define CLK_CLEAR ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16)) | ||
87 | #define CLK_SUP_PCLK ((1 << 19) | (1 << 18) | (1 << 17) | (1 << 16)) | ||
88 | #define SRSPTO_256 ((1 << 13) | (0 << 12)) /* resp timeout */ | ||
89 | #define SRBSYTO_29 ((1 << 11) | (1 << 10) | \ | ||
90 | (1 << 9) | (1 << 8)) /* resp busy timeout */ | ||
91 | #define SRWDTO_29 ((1 << 7) | (1 << 6) | \ | ||
92 | (1 << 5) | (1 << 4)) /* read/write timeout */ | ||
93 | #define SCCSTO_29 ((1 << 3) | (1 << 2) | \ | ||
94 | (1 << 1) | (1 << 0)) /* ccs timeout */ | ||
95 | |||
96 | /* CE_BUF_ACC */ | ||
97 | #define BUF_ACC_DMAWEN (1 << 25) | ||
98 | #define BUF_ACC_DMAREN (1 << 24) | ||
99 | #define BUF_ACC_BUSW_32 (0 << 17) | ||
100 | #define BUF_ACC_BUSW_16 (1 << 17) | ||
101 | #define BUF_ACC_ATYP (1 << 16) | ||
102 | |||
103 | /* CE_INT */ | ||
104 | #define INT_CCSDE (1 << 29) | ||
105 | #define INT_CMD12DRE (1 << 26) | ||
106 | #define INT_CMD12RBE (1 << 25) | ||
107 | #define INT_CMD12CRE (1 << 24) | ||
108 | #define INT_DTRANE (1 << 23) | ||
109 | #define INT_BUFRE (1 << 22) | ||
110 | #define INT_BUFWEN (1 << 21) | ||
111 | #define INT_BUFREN (1 << 20) | ||
112 | #define INT_CCSRCV (1 << 19) | ||
113 | #define INT_RBSYE (1 << 17) | ||
114 | #define INT_CRSPE (1 << 16) | ||
115 | #define INT_CMDVIO (1 << 15) | ||
116 | #define INT_BUFVIO (1 << 14) | ||
117 | #define INT_WDATERR (1 << 11) | ||
118 | #define INT_RDATERR (1 << 10) | ||
119 | #define INT_RIDXERR (1 << 9) | ||
120 | #define INT_RSPERR (1 << 8) | ||
121 | #define INT_CCSTO (1 << 5) | ||
122 | #define INT_CRCSTO (1 << 4) | ||
123 | #define INT_WDATTO (1 << 3) | ||
124 | #define INT_RDATTO (1 << 2) | ||
125 | #define INT_RBSYTO (1 << 1) | ||
126 | #define INT_RSPTO (1 << 0) | ||
127 | #define INT_ERR_STS (INT_CMDVIO | INT_BUFVIO | INT_WDATERR | \ | ||
128 | INT_RDATERR | INT_RIDXERR | INT_RSPERR | \ | ||
129 | INT_CCSTO | INT_CRCSTO | INT_WDATTO | \ | ||
130 | INT_RDATTO | INT_RBSYTO | INT_RSPTO) | ||
131 | |||
132 | /* CE_INT_MASK */ | ||
133 | #define MASK_ALL 0x00000000 | ||
134 | #define MASK_MCCSDE (1 << 29) | ||
135 | #define MASK_MCMD12DRE (1 << 26) | ||
136 | #define MASK_MCMD12RBE (1 << 25) | ||
137 | #define MASK_MCMD12CRE (1 << 24) | ||
138 | #define MASK_MDTRANE (1 << 23) | ||
139 | #define MASK_MBUFRE (1 << 22) | ||
140 | #define MASK_MBUFWEN (1 << 21) | ||
141 | #define MASK_MBUFREN (1 << 20) | ||
142 | #define MASK_MCCSRCV (1 << 19) | ||
143 | #define MASK_MRBSYE (1 << 17) | ||
144 | #define MASK_MCRSPE (1 << 16) | ||
145 | #define MASK_MCMDVIO (1 << 15) | ||
146 | #define MASK_MBUFVIO (1 << 14) | ||
147 | #define MASK_MWDATERR (1 << 11) | ||
148 | #define MASK_MRDATERR (1 << 10) | ||
149 | #define MASK_MRIDXERR (1 << 9) | ||
150 | #define MASK_MRSPERR (1 << 8) | ||
151 | #define MASK_MCCSTO (1 << 5) | ||
152 | #define MASK_MCRCSTO (1 << 4) | ||
153 | #define MASK_MWDATTO (1 << 3) | ||
154 | #define MASK_MRDATTO (1 << 2) | ||
155 | #define MASK_MRBSYTO (1 << 1) | ||
156 | #define MASK_MRSPTO (1 << 0) | ||
157 | |||
158 | /* CE_HOST_STS1 */ | ||
159 | #define STS1_CMDSEQ (1 << 31) | ||
160 | |||
161 | /* CE_HOST_STS2 */ | ||
162 | #define STS2_CRCSTE (1 << 31) | ||
163 | #define STS2_CRC16E (1 << 30) | ||
164 | #define STS2_AC12CRCE (1 << 29) | ||
165 | #define STS2_RSPCRC7E (1 << 28) | ||
166 | #define STS2_CRCSTEBE (1 << 27) | ||
167 | #define STS2_RDATEBE (1 << 26) | ||
168 | #define STS2_AC12REBE (1 << 25) | ||
169 | #define STS2_RSPEBE (1 << 24) | ||
170 | #define STS2_AC12IDXE (1 << 23) | ||
171 | #define STS2_RSPIDXE (1 << 22) | ||
172 | #define STS2_CCSTO (1 << 15) | ||
173 | #define STS2_RDATTO (1 << 14) | ||
174 | #define STS2_DATBSYTO (1 << 13) | ||
175 | #define STS2_CRCSTTO (1 << 12) | ||
176 | #define STS2_AC12BSYTO (1 << 11) | ||
177 | #define STS2_RSPBSYTO (1 << 10) | ||
178 | #define STS2_AC12RSPTO (1 << 9) | ||
179 | #define STS2_RSPTO (1 << 8) | ||
180 | #define STS2_CRC_ERR (STS2_CRCSTE | STS2_CRC16E | \ | ||
181 | STS2_AC12CRCE | STS2_RSPCRC7E | STS2_CRCSTEBE) | ||
182 | #define STS2_TIMEOUT_ERR (STS2_CCSTO | STS2_RDATTO | \ | ||
183 | STS2_DATBSYTO | STS2_CRCSTTO | \ | ||
184 | STS2_AC12BSYTO | STS2_RSPBSYTO | \ | ||
185 | STS2_AC12RSPTO | STS2_RSPTO) | ||
186 | |||
187 | /* CE_VERSION */ | ||
188 | #define SOFT_RST_ON (1 << 31) | ||
189 | #define SOFT_RST_OFF (0 << 31) | ||
190 | |||
191 | #define CLKDEV_EMMC_DATA 52000000 /* 52MHz */ | ||
192 | #define CLKDEV_MMC_DATA 20000000 /* 20MHz */ | ||
193 | #define CLKDEV_INIT 400000 /* 400 KHz */ | ||
194 | |||
195 | struct sh_mmcif_host { | ||
196 | struct mmc_host *mmc; | ||
197 | struct mmc_data *data; | ||
198 | struct mmc_command *cmd; | ||
199 | struct platform_device *pd; | ||
200 | struct clk *hclk; | ||
201 | unsigned int clk; | ||
202 | int bus_width; | ||
203 | u16 wait_int; | ||
204 | u16 sd_error; | ||
205 | long timeout; | ||
206 | void __iomem *addr; | ||
207 | wait_queue_head_t intr_wait; | ||
208 | }; | ||
209 | |||
210 | static inline u32 sh_mmcif_readl(struct sh_mmcif_host *host, unsigned int reg) | ||
211 | { | ||
212 | return readl(host->addr + reg); | ||
213 | } | ||
214 | |||
215 | static inline void sh_mmcif_writel(struct sh_mmcif_host *host, | ||
216 | unsigned int reg, u32 val) | ||
217 | { | ||
218 | writel(val, host->addr + reg); | ||
219 | } | ||
220 | |||
221 | static inline void sh_mmcif_bitset(struct sh_mmcif_host *host, | ||
222 | unsigned int reg, u32 val) | ||
223 | { | ||
224 | writel(val | sh_mmcif_readl(host, reg), host->addr + reg); | ||
225 | } | ||
226 | |||
227 | static inline void sh_mmcif_bitclr(struct sh_mmcif_host *host, | ||
228 | unsigned int reg, u32 val) | ||
229 | { | ||
230 | writel(~val & sh_mmcif_readl(host, reg), host->addr + reg); | ||
231 | } | ||
232 | |||
233 | |||
234 | static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk) | ||
235 | { | ||
236 | struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; | ||
237 | |||
238 | sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); | ||
239 | sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR); | ||
240 | |||
241 | if (!clk) | ||
242 | return; | ||
243 | if (p->sup_pclk && clk == host->clk) | ||
244 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK); | ||
245 | else | ||
246 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR & | ||
247 | (ilog2(__rounddown_pow_of_two(host->clk / clk)) << 16)); | ||
248 | |||
249 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE); | ||
250 | } | ||
251 | |||
252 | static void sh_mmcif_sync_reset(struct sh_mmcif_host *host) | ||
253 | { | ||
254 | u32 tmp; | ||
255 | |||
256 | tmp = 0x010f0000 & sh_mmcif_readl(host, MMCIF_CE_CLK_CTRL); | ||
257 | |||
258 | sh_mmcif_writel(host, MMCIF_CE_VERSION, SOFT_RST_ON); | ||
259 | sh_mmcif_writel(host, MMCIF_CE_VERSION, SOFT_RST_OFF); | ||
260 | sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, tmp | | ||
261 | SRSPTO_256 | SRBSYTO_29 | SRWDTO_29 | SCCSTO_29); | ||
262 | /* byte swap on */ | ||
263 | sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_ATYP); | ||
264 | } | ||
265 | |||
266 | static int sh_mmcif_error_manage(struct sh_mmcif_host *host) | ||
267 | { | ||
268 | u32 state1, state2; | ||
269 | int ret, timeout = 10000000; | ||
270 | |||
271 | host->sd_error = 0; | ||
272 | host->wait_int = 0; | ||
273 | |||
274 | state1 = sh_mmcif_readl(host, MMCIF_CE_HOST_STS1); | ||
275 | state2 = sh_mmcif_readl(host, MMCIF_CE_HOST_STS2); | ||
276 | pr_debug("%s: ERR HOST_STS1 = %08x\n", \ | ||
277 | DRIVER_NAME, sh_mmcif_readl(host, MMCIF_CE_HOST_STS1)); | ||
278 | pr_debug("%s: ERR HOST_STS2 = %08x\n", \ | ||
279 | DRIVER_NAME, sh_mmcif_readl(host, MMCIF_CE_HOST_STS2)); | ||
280 | |||
281 | if (state1 & STS1_CMDSEQ) { | ||
282 | sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, CMD_CTRL_BREAK); | ||
283 | sh_mmcif_bitset(host, MMCIF_CE_CMD_CTRL, ~CMD_CTRL_BREAK); | ||
284 | while (1) { | ||
285 | timeout--; | ||
286 | if (timeout < 0) { | ||
287 | pr_err(DRIVER_NAME": Forceed end of " \ | ||
288 | "command sequence timeout err\n"); | ||
289 | return -EIO; | ||
290 | } | ||
291 | if (!(sh_mmcif_readl(host, MMCIF_CE_HOST_STS1) | ||
292 | & STS1_CMDSEQ)) | ||
293 | break; | ||
294 | mdelay(1); | ||
295 | } | ||
296 | sh_mmcif_sync_reset(host); | ||
297 | pr_debug(DRIVER_NAME": Forced end of command sequence\n"); | ||
298 | return -EIO; | ||
299 | } | ||
300 | |||
301 | if (state2 & STS2_CRC_ERR) { | ||
302 | pr_debug(DRIVER_NAME": Happened CRC error\n"); | ||
303 | ret = -EIO; | ||
304 | } else if (state2 & STS2_TIMEOUT_ERR) { | ||
305 | pr_debug(DRIVER_NAME": Happened Timeout error\n"); | ||
306 | ret = -ETIMEDOUT; | ||
307 | } else { | ||
308 | pr_debug(DRIVER_NAME": Happened End/Index error\n"); | ||
309 | ret = -EIO; | ||
310 | } | ||
311 | return ret; | ||
312 | } | ||
313 | |||
314 | static int sh_mmcif_single_read(struct sh_mmcif_host *host, | ||
315 | struct mmc_request *mrq) | ||
316 | { | ||
317 | struct mmc_data *data = mrq->data; | ||
318 | long time; | ||
319 | u32 blocksize, i, *p = sg_virt(data->sg); | ||
320 | |||
321 | host->wait_int = 0; | ||
322 | |||
323 | /* buf read enable */ | ||
324 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | ||
325 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
326 | host->wait_int == 1 || | ||
327 | host->sd_error == 1, host->timeout); | ||
328 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
329 | return sh_mmcif_error_manage(host); | ||
330 | |||
331 | host->wait_int = 0; | ||
332 | blocksize = (BLOCK_SIZE_MASK & | ||
333 | sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET)) + 3; | ||
334 | for (i = 0; i < blocksize / 4; i++) | ||
335 | *p++ = sh_mmcif_readl(host, MMCIF_CE_DATA); | ||
336 | |||
337 | /* buffer read end */ | ||
338 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); | ||
339 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
340 | host->wait_int == 1 || | ||
341 | host->sd_error == 1, host->timeout); | ||
342 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
343 | return sh_mmcif_error_manage(host); | ||
344 | |||
345 | host->wait_int = 0; | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int sh_mmcif_multi_read(struct sh_mmcif_host *host, | ||
350 | struct mmc_request *mrq) | ||
351 | { | ||
352 | struct mmc_data *data = mrq->data; | ||
353 | long time; | ||
354 | u32 blocksize, i, j, sec, *p; | ||
355 | |||
356 | blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET); | ||
357 | for (j = 0; j < data->sg_len; j++) { | ||
358 | p = sg_virt(data->sg); | ||
359 | host->wait_int = 0; | ||
360 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { | ||
361 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | ||
362 | /* buf read enable */ | ||
363 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
364 | host->wait_int == 1 || | ||
365 | host->sd_error == 1, host->timeout); | ||
366 | |||
367 | if (host->wait_int != 1 && | ||
368 | (time == 0 || host->sd_error != 0)) | ||
369 | return sh_mmcif_error_manage(host); | ||
370 | |||
371 | host->wait_int = 0; | ||
372 | for (i = 0; i < blocksize / 4; i++) | ||
373 | *p++ = sh_mmcif_readl(host, MMCIF_CE_DATA); | ||
374 | } | ||
375 | if (j < data->sg_len - 1) | ||
376 | data->sg++; | ||
377 | } | ||
378 | return 0; | ||
379 | } | ||
380 | |||
381 | static int sh_mmcif_single_write(struct sh_mmcif_host *host, | ||
382 | struct mmc_request *mrq) | ||
383 | { | ||
384 | struct mmc_data *data = mrq->data; | ||
385 | long time; | ||
386 | u32 blocksize, i, *p = sg_virt(data->sg); | ||
387 | |||
388 | host->wait_int = 0; | ||
389 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | ||
390 | |||
391 | /* buf write enable */ | ||
392 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
393 | host->wait_int == 1 || | ||
394 | host->sd_error == 1, host->timeout); | ||
395 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
396 | return sh_mmcif_error_manage(host); | ||
397 | |||
398 | host->wait_int = 0; | ||
399 | blocksize = (BLOCK_SIZE_MASK & | ||
400 | sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET)) + 3; | ||
401 | for (i = 0; i < blocksize / 4; i++) | ||
402 | sh_mmcif_writel(host, MMCIF_CE_DATA, *p++); | ||
403 | |||
404 | /* buffer write end */ | ||
405 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); | ||
406 | |||
407 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
408 | host->wait_int == 1 || | ||
409 | host->sd_error == 1, host->timeout); | ||
410 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) | ||
411 | return sh_mmcif_error_manage(host); | ||
412 | |||
413 | host->wait_int = 0; | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static int sh_mmcif_multi_write(struct sh_mmcif_host *host, | ||
418 | struct mmc_request *mrq) | ||
419 | { | ||
420 | struct mmc_data *data = mrq->data; | ||
421 | long time; | ||
422 | u32 i, sec, j, blocksize, *p; | ||
423 | |||
424 | blocksize = BLOCK_SIZE_MASK & sh_mmcif_readl(host, MMCIF_CE_BLOCK_SET); | ||
425 | |||
426 | for (j = 0; j < data->sg_len; j++) { | ||
427 | p = sg_virt(data->sg); | ||
428 | host->wait_int = 0; | ||
429 | for (sec = 0; sec < data->sg->length / blocksize; sec++) { | ||
430 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | ||
431 | /* buf write enable*/ | ||
432 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
433 | host->wait_int == 1 || | ||
434 | host->sd_error == 1, host->timeout); | ||
435 | |||
436 | if (host->wait_int != 1 && | ||
437 | (time == 0 || host->sd_error != 0)) | ||
438 | return sh_mmcif_error_manage(host); | ||
439 | |||
440 | host->wait_int = 0; | ||
441 | for (i = 0; i < blocksize / 4; i++) | ||
442 | sh_mmcif_writel(host, MMCIF_CE_DATA, *p++); | ||
443 | } | ||
444 | if (j < data->sg_len - 1) | ||
445 | data->sg++; | ||
446 | } | ||
447 | return 0; | ||
448 | } | ||
449 | |||
450 | static void sh_mmcif_get_response(struct sh_mmcif_host *host, | ||
451 | struct mmc_command *cmd) | ||
452 | { | ||
453 | if (cmd->flags & MMC_RSP_136) { | ||
454 | cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP3); | ||
455 | cmd->resp[1] = sh_mmcif_readl(host, MMCIF_CE_RESP2); | ||
456 | cmd->resp[2] = sh_mmcif_readl(host, MMCIF_CE_RESP1); | ||
457 | cmd->resp[3] = sh_mmcif_readl(host, MMCIF_CE_RESP0); | ||
458 | } else | ||
459 | cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP0); | ||
460 | } | ||
461 | |||
462 | static void sh_mmcif_get_cmd12response(struct sh_mmcif_host *host, | ||
463 | struct mmc_command *cmd) | ||
464 | { | ||
465 | cmd->resp[0] = sh_mmcif_readl(host, MMCIF_CE_RESP_CMD12); | ||
466 | } | ||
467 | |||
468 | static u32 sh_mmcif_set_cmd(struct sh_mmcif_host *host, | ||
469 | struct mmc_request *mrq, struct mmc_command *cmd, u32 opc) | ||
470 | { | ||
471 | u32 tmp = 0; | ||
472 | |||
473 | /* Response Type check */ | ||
474 | switch (mmc_resp_type(cmd)) { | ||
475 | case MMC_RSP_NONE: | ||
476 | tmp |= CMD_SET_RTYP_NO; | ||
477 | break; | ||
478 | case MMC_RSP_R1: | ||
479 | case MMC_RSP_R1B: | ||
480 | case MMC_RSP_R3: | ||
481 | tmp |= CMD_SET_RTYP_6B; | ||
482 | break; | ||
483 | case MMC_RSP_R2: | ||
484 | tmp |= CMD_SET_RTYP_17B; | ||
485 | break; | ||
486 | default: | ||
487 | pr_err(DRIVER_NAME": Not support type response.\n"); | ||
488 | break; | ||
489 | } | ||
490 | switch (opc) { | ||
491 | /* RBSY */ | ||
492 | case MMC_SWITCH: | ||
493 | case MMC_STOP_TRANSMISSION: | ||
494 | case MMC_SET_WRITE_PROT: | ||
495 | case MMC_CLR_WRITE_PROT: | ||
496 | case MMC_ERASE: | ||
497 | case MMC_GEN_CMD: | ||
498 | tmp |= CMD_SET_RBSY; | ||
499 | break; | ||
500 | } | ||
501 | /* WDAT / DATW */ | ||
502 | if (host->data) { | ||
503 | tmp |= CMD_SET_WDAT; | ||
504 | switch (host->bus_width) { | ||
505 | case MMC_BUS_WIDTH_1: | ||
506 | tmp |= CMD_SET_DATW_1; | ||
507 | break; | ||
508 | case MMC_BUS_WIDTH_4: | ||
509 | tmp |= CMD_SET_DATW_4; | ||
510 | break; | ||
511 | case MMC_BUS_WIDTH_8: | ||
512 | tmp |= CMD_SET_DATW_8; | ||
513 | break; | ||
514 | default: | ||
515 | pr_err(DRIVER_NAME": Not support bus width.\n"); | ||
516 | break; | ||
517 | } | ||
518 | } | ||
519 | /* DWEN */ | ||
520 | if (opc == MMC_WRITE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) | ||
521 | tmp |= CMD_SET_DWEN; | ||
522 | /* CMLTE/CMD12EN */ | ||
523 | if (opc == MMC_READ_MULTIPLE_BLOCK || opc == MMC_WRITE_MULTIPLE_BLOCK) { | ||
524 | tmp |= CMD_SET_CMLTE | CMD_SET_CMD12EN; | ||
525 | sh_mmcif_bitset(host, MMCIF_CE_BLOCK_SET, | ||
526 | mrq->data->blocks << 16); | ||
527 | } | ||
528 | /* RIDXC[1:0] check bits */ | ||
529 | if (opc == MMC_SEND_OP_COND || opc == MMC_ALL_SEND_CID || | ||
530 | opc == MMC_SEND_CSD || opc == MMC_SEND_CID) | ||
531 | tmp |= CMD_SET_RIDXC_BITS; | ||
532 | /* RCRC7C[1:0] check bits */ | ||
533 | if (opc == MMC_SEND_OP_COND) | ||
534 | tmp |= CMD_SET_CRC7C_BITS; | ||
535 | /* RCRC7C[1:0] internal CRC7 */ | ||
536 | if (opc == MMC_ALL_SEND_CID || | ||
537 | opc == MMC_SEND_CSD || opc == MMC_SEND_CID) | ||
538 | tmp |= CMD_SET_CRC7C_INTERNAL; | ||
539 | |||
540 | return opc = ((opc << 24) | tmp); | ||
541 | } | ||
542 | |||
543 | static u32 sh_mmcif_data_trans(struct sh_mmcif_host *host, | ||
544 | struct mmc_request *mrq, u32 opc) | ||
545 | { | ||
546 | u32 ret; | ||
547 | |||
548 | switch (opc) { | ||
549 | case MMC_READ_MULTIPLE_BLOCK: | ||
550 | ret = sh_mmcif_multi_read(host, mrq); | ||
551 | break; | ||
552 | case MMC_WRITE_MULTIPLE_BLOCK: | ||
553 | ret = sh_mmcif_multi_write(host, mrq); | ||
554 | break; | ||
555 | case MMC_WRITE_BLOCK: | ||
556 | ret = sh_mmcif_single_write(host, mrq); | ||
557 | break; | ||
558 | case MMC_READ_SINGLE_BLOCK: | ||
559 | case MMC_SEND_EXT_CSD: | ||
560 | ret = sh_mmcif_single_read(host, mrq); | ||
561 | break; | ||
562 | default: | ||
563 | pr_err(DRIVER_NAME": NOT SUPPORT CMD = d'%08d\n", opc); | ||
564 | ret = -EINVAL; | ||
565 | break; | ||
566 | } | ||
567 | return ret; | ||
568 | } | ||
569 | |||
570 | static void sh_mmcif_start_cmd(struct sh_mmcif_host *host, | ||
571 | struct mmc_request *mrq, struct mmc_command *cmd) | ||
572 | { | ||
573 | long time; | ||
574 | int ret = 0, mask = 0; | ||
575 | u32 opc = cmd->opcode; | ||
576 | |||
577 | host->cmd = cmd; | ||
578 | |||
579 | switch (opc) { | ||
580 | /* respons busy check */ | ||
581 | case MMC_SWITCH: | ||
582 | case MMC_STOP_TRANSMISSION: | ||
583 | case MMC_SET_WRITE_PROT: | ||
584 | case MMC_CLR_WRITE_PROT: | ||
585 | case MMC_ERASE: | ||
586 | case MMC_GEN_CMD: | ||
587 | mask = MASK_MRBSYE; | ||
588 | break; | ||
589 | default: | ||
590 | mask = MASK_MCRSPE; | ||
591 | break; | ||
592 | } | ||
593 | mask |= MASK_MCMDVIO | MASK_MBUFVIO | MASK_MWDATERR | | ||
594 | MASK_MRDATERR | MASK_MRIDXERR | MASK_MRSPERR | | ||
595 | MASK_MCCSTO | MASK_MCRCSTO | MASK_MWDATTO | | ||
596 | MASK_MRDATTO | MASK_MRBSYTO | MASK_MRSPTO; | ||
597 | |||
598 | if (host->data) { | ||
599 | sh_mmcif_writel(host, MMCIF_CE_BLOCK_SET, 0); | ||
600 | sh_mmcif_writel(host, MMCIF_CE_BLOCK_SET, mrq->data->blksz); | ||
601 | } | ||
602 | opc = sh_mmcif_set_cmd(host, mrq, cmd, opc); | ||
603 | |||
604 | sh_mmcif_writel(host, MMCIF_CE_INT, 0xD80430C0); | ||
605 | sh_mmcif_writel(host, MMCIF_CE_INT_MASK, mask); | ||
606 | /* set arg */ | ||
607 | sh_mmcif_writel(host, MMCIF_CE_ARG, cmd->arg); | ||
608 | host->wait_int = 0; | ||
609 | /* set cmd */ | ||
610 | sh_mmcif_writel(host, MMCIF_CE_CMD_SET, opc); | ||
611 | |||
612 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
613 | host->wait_int == 1 || host->sd_error == 1, host->timeout); | ||
614 | if (host->wait_int != 1 && time == 0) { | ||
615 | cmd->error = sh_mmcif_error_manage(host); | ||
616 | return; | ||
617 | } | ||
618 | if (host->sd_error) { | ||
619 | switch (cmd->opcode) { | ||
620 | case MMC_ALL_SEND_CID: | ||
621 | case MMC_SELECT_CARD: | ||
622 | case MMC_APP_CMD: | ||
623 | cmd->error = -ETIMEDOUT; | ||
624 | break; | ||
625 | default: | ||
626 | pr_debug("%s: Cmd(d'%d) err\n", | ||
627 | DRIVER_NAME, cmd->opcode); | ||
628 | cmd->error = sh_mmcif_error_manage(host); | ||
629 | break; | ||
630 | } | ||
631 | host->sd_error = 0; | ||
632 | host->wait_int = 0; | ||
633 | return; | ||
634 | } | ||
635 | if (!(cmd->flags & MMC_RSP_PRESENT)) { | ||
636 | cmd->error = ret; | ||
637 | host->wait_int = 0; | ||
638 | return; | ||
639 | } | ||
640 | if (host->wait_int == 1) { | ||
641 | sh_mmcif_get_response(host, cmd); | ||
642 | host->wait_int = 0; | ||
643 | } | ||
644 | if (host->data) { | ||
645 | ret = sh_mmcif_data_trans(host, mrq, cmd->opcode); | ||
646 | if (ret < 0) | ||
647 | mrq->data->bytes_xfered = 0; | ||
648 | else | ||
649 | mrq->data->bytes_xfered = | ||
650 | mrq->data->blocks * mrq->data->blksz; | ||
651 | } | ||
652 | cmd->error = ret; | ||
653 | } | ||
654 | |||
655 | static void sh_mmcif_stop_cmd(struct sh_mmcif_host *host, | ||
656 | struct mmc_request *mrq, struct mmc_command *cmd) | ||
657 | { | ||
658 | long time; | ||
659 | |||
660 | if (mrq->cmd->opcode == MMC_READ_MULTIPLE_BLOCK) | ||
661 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); | ||
662 | else if (mrq->cmd->opcode == MMC_WRITE_MULTIPLE_BLOCK) | ||
663 | sh_mmcif_bitset(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); | ||
664 | else { | ||
665 | pr_err(DRIVER_NAME": not support stop cmd\n"); | ||
666 | cmd->error = sh_mmcif_error_manage(host); | ||
667 | return; | ||
668 | } | ||
669 | |||
670 | time = wait_event_interruptible_timeout(host->intr_wait, | ||
671 | host->wait_int == 1 || | ||
672 | host->sd_error == 1, host->timeout); | ||
673 | if (host->wait_int != 1 && (time == 0 || host->sd_error != 0)) { | ||
674 | cmd->error = sh_mmcif_error_manage(host); | ||
675 | return; | ||
676 | } | ||
677 | sh_mmcif_get_cmd12response(host, cmd); | ||
678 | host->wait_int = 0; | ||
679 | cmd->error = 0; | ||
680 | } | ||
681 | |||
682 | static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
683 | { | ||
684 | struct sh_mmcif_host *host = mmc_priv(mmc); | ||
685 | |||
686 | switch (mrq->cmd->opcode) { | ||
687 | /* MMCIF does not support SD/SDIO command */ | ||
688 | case SD_IO_SEND_OP_COND: | ||
689 | case MMC_APP_CMD: | ||
690 | mrq->cmd->error = -ETIMEDOUT; | ||
691 | mmc_request_done(mmc, mrq); | ||
692 | return; | ||
693 | case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */ | ||
694 | if (!mrq->data) { | ||
695 | /* send_if_cond cmd (not support) */ | ||
696 | mrq->cmd->error = -ETIMEDOUT; | ||
697 | mmc_request_done(mmc, mrq); | ||
698 | return; | ||
699 | } | ||
700 | break; | ||
701 | default: | ||
702 | break; | ||
703 | } | ||
704 | host->data = mrq->data; | ||
705 | sh_mmcif_start_cmd(host, mrq, mrq->cmd); | ||
706 | host->data = NULL; | ||
707 | |||
708 | if (mrq->cmd->error != 0) { | ||
709 | mmc_request_done(mmc, mrq); | ||
710 | return; | ||
711 | } | ||
712 | if (mrq->stop) | ||
713 | sh_mmcif_stop_cmd(host, mrq, mrq->stop); | ||
714 | mmc_request_done(mmc, mrq); | ||
715 | } | ||
716 | |||
717 | static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
718 | { | ||
719 | struct sh_mmcif_host *host = mmc_priv(mmc); | ||
720 | struct sh_mmcif_plat_data *p = host->pd->dev.platform_data; | ||
721 | |||
722 | if (ios->power_mode == MMC_POWER_OFF) { | ||
723 | /* clock stop */ | ||
724 | sh_mmcif_clock_control(host, 0); | ||
725 | if (p->down_pwr) | ||
726 | p->down_pwr(host->pd); | ||
727 | return; | ||
728 | } else if (ios->power_mode == MMC_POWER_UP) { | ||
729 | if (p->set_pwr) | ||
730 | p->set_pwr(host->pd, ios->power_mode); | ||
731 | } | ||
732 | |||
733 | if (ios->clock) | ||
734 | sh_mmcif_clock_control(host, ios->clock); | ||
735 | |||
736 | host->bus_width = ios->bus_width; | ||
737 | } | ||
738 | |||
739 | static struct mmc_host_ops sh_mmcif_ops = { | ||
740 | .request = sh_mmcif_request, | ||
741 | .set_ios = sh_mmcif_set_ios, | ||
742 | }; | ||
743 | |||
744 | static void sh_mmcif_detect(struct mmc_host *mmc) | ||
745 | { | ||
746 | mmc_detect_change(mmc, 0); | ||
747 | } | ||
748 | |||
749 | static irqreturn_t sh_mmcif_intr(int irq, void *dev_id) | ||
750 | { | ||
751 | struct sh_mmcif_host *host = dev_id; | ||
752 | u32 state = 0; | ||
753 | int err = 0; | ||
754 | |||
755 | state = sh_mmcif_readl(host, MMCIF_CE_INT); | ||
756 | |||
757 | if (state & INT_RBSYE) { | ||
758 | sh_mmcif_writel(host, MMCIF_CE_INT, ~(INT_RBSYE | INT_CRSPE)); | ||
759 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MRBSYE); | ||
760 | } else if (state & INT_CRSPE) { | ||
761 | sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_CRSPE); | ||
762 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCRSPE); | ||
763 | } else if (state & INT_BUFREN) { | ||
764 | sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFREN); | ||
765 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFREN); | ||
766 | } else if (state & INT_BUFWEN) { | ||
767 | sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFWEN); | ||
768 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFWEN); | ||
769 | } else if (state & INT_CMD12DRE) { | ||
770 | sh_mmcif_writel(host, MMCIF_CE_INT, | ||
771 | ~(INT_CMD12DRE | INT_CMD12RBE | | ||
772 | INT_CMD12CRE | INT_BUFRE)); | ||
773 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12DRE); | ||
774 | } else if (state & INT_BUFRE) { | ||
775 | sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_BUFRE); | ||
776 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MBUFRE); | ||
777 | } else if (state & INT_DTRANE) { | ||
778 | sh_mmcif_writel(host, MMCIF_CE_INT, ~INT_DTRANE); | ||
779 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MDTRANE); | ||
780 | } else if (state & INT_CMD12RBE) { | ||
781 | sh_mmcif_writel(host, MMCIF_CE_INT, | ||
782 | ~(INT_CMD12RBE | INT_CMD12CRE)); | ||
783 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, MASK_MCMD12RBE); | ||
784 | } else if (state & INT_ERR_STS) { | ||
785 | /* err interrupts */ | ||
786 | sh_mmcif_writel(host, MMCIF_CE_INT, ~state); | ||
787 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); | ||
788 | err = 1; | ||
789 | } else { | ||
790 | pr_debug("%s: Not support int\n", DRIVER_NAME); | ||
791 | sh_mmcif_writel(host, MMCIF_CE_INT, ~state); | ||
792 | sh_mmcif_bitclr(host, MMCIF_CE_INT_MASK, state); | ||
793 | err = 1; | ||
794 | } | ||
795 | if (err) { | ||
796 | host->sd_error = 1; | ||
797 | pr_debug("%s: int err state = %08x\n", DRIVER_NAME, state); | ||
798 | } | ||
799 | host->wait_int = 1; | ||
800 | wake_up(&host->intr_wait); | ||
801 | |||
802 | return IRQ_HANDLED; | ||
803 | } | ||
804 | |||
805 | static int __devinit sh_mmcif_probe(struct platform_device *pdev) | ||
806 | { | ||
807 | int ret = 0, irq[2]; | ||
808 | struct mmc_host *mmc; | ||
809 | struct sh_mmcif_host *host = NULL; | ||
810 | struct sh_mmcif_plat_data *pd = NULL; | ||
811 | struct resource *res; | ||
812 | void __iomem *reg; | ||
813 | char clk_name[8]; | ||
814 | |||
815 | irq[0] = platform_get_irq(pdev, 0); | ||
816 | irq[1] = platform_get_irq(pdev, 1); | ||
817 | if (irq[0] < 0 || irq[1] < 0) { | ||
818 | pr_err(DRIVER_NAME": Get irq error\n"); | ||
819 | return -ENXIO; | ||
820 | } | ||
821 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
822 | if (!res) { | ||
823 | dev_err(&pdev->dev, "platform_get_resource error.\n"); | ||
824 | return -ENXIO; | ||
825 | } | ||
826 | reg = ioremap(res->start, resource_size(res)); | ||
827 | if (!reg) { | ||
828 | dev_err(&pdev->dev, "ioremap error.\n"); | ||
829 | return -ENOMEM; | ||
830 | } | ||
831 | pd = (struct sh_mmcif_plat_data *)(pdev->dev.platform_data); | ||
832 | if (!pd) { | ||
833 | dev_err(&pdev->dev, "sh_mmcif plat data error.\n"); | ||
834 | ret = -ENXIO; | ||
835 | goto clean_up; | ||
836 | } | ||
837 | mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev); | ||
838 | if (!mmc) { | ||
839 | ret = -ENOMEM; | ||
840 | goto clean_up; | ||
841 | } | ||
842 | host = mmc_priv(mmc); | ||
843 | host->mmc = mmc; | ||
844 | host->addr = reg; | ||
845 | host->timeout = 1000; | ||
846 | |||
847 | snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id); | ||
848 | host->hclk = clk_get(&pdev->dev, clk_name); | ||
849 | if (IS_ERR(host->hclk)) { | ||
850 | dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); | ||
851 | ret = PTR_ERR(host->hclk); | ||
852 | goto clean_up1; | ||
853 | } | ||
854 | clk_enable(host->hclk); | ||
855 | host->clk = clk_get_rate(host->hclk); | ||
856 | host->pd = pdev; | ||
857 | |||
858 | init_waitqueue_head(&host->intr_wait); | ||
859 | |||
860 | mmc->ops = &sh_mmcif_ops; | ||
861 | mmc->f_max = host->clk; | ||
862 | /* close to 400KHz */ | ||
863 | if (mmc->f_max < 51200000) | ||
864 | mmc->f_min = mmc->f_max / 128; | ||
865 | else if (mmc->f_max < 102400000) | ||
866 | mmc->f_min = mmc->f_max / 256; | ||
867 | else | ||
868 | mmc->f_min = mmc->f_max / 512; | ||
869 | if (pd->ocr) | ||
870 | mmc->ocr_avail = pd->ocr; | ||
871 | mmc->caps = MMC_CAP_MMC_HIGHSPEED; | ||
872 | if (pd->caps) | ||
873 | mmc->caps |= pd->caps; | ||
874 | mmc->max_phys_segs = 128; | ||
875 | mmc->max_hw_segs = 128; | ||
876 | mmc->max_blk_size = 512; | ||
877 | mmc->max_blk_count = 65535; | ||
878 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
879 | mmc->max_seg_size = mmc->max_req_size; | ||
880 | |||
881 | sh_mmcif_sync_reset(host); | ||
882 | platform_set_drvdata(pdev, host); | ||
883 | mmc_add_host(mmc); | ||
884 | |||
885 | ret = request_irq(irq[0], sh_mmcif_intr, 0, "sh_mmc:error", host); | ||
886 | if (ret) { | ||
887 | pr_err(DRIVER_NAME": request_irq error (sh_mmc:error)\n"); | ||
888 | goto clean_up2; | ||
889 | } | ||
890 | ret = request_irq(irq[1], sh_mmcif_intr, 0, "sh_mmc:int", host); | ||
891 | if (ret) { | ||
892 | free_irq(irq[0], host); | ||
893 | pr_err(DRIVER_NAME": request_irq error (sh_mmc:int)\n"); | ||
894 | goto clean_up2; | ||
895 | } | ||
896 | |||
897 | sh_mmcif_writel(host, MMCIF_CE_INT_MASK, MASK_ALL); | ||
898 | sh_mmcif_detect(host->mmc); | ||
899 | |||
900 | pr_info("%s: driver version %s\n", DRIVER_NAME, DRIVER_VERSION); | ||
901 | pr_debug("%s: chip ver H'%04x\n", DRIVER_NAME, | ||
902 | sh_mmcif_readl(host, MMCIF_CE_VERSION) & 0x0000ffff); | ||
903 | return ret; | ||
904 | |||
905 | clean_up2: | ||
906 | clk_disable(host->hclk); | ||
907 | clean_up1: | ||
908 | mmc_free_host(mmc); | ||
909 | clean_up: | ||
910 | if (reg) | ||
911 | iounmap(reg); | ||
912 | return ret; | ||
913 | } | ||
914 | |||
915 | static int __devexit sh_mmcif_remove(struct platform_device *pdev) | ||
916 | { | ||
917 | struct sh_mmcif_host *host = platform_get_drvdata(pdev); | ||
918 | int irq[2]; | ||
919 | |||
920 | sh_mmcif_writel(host, MMCIF_CE_INT_MASK, MASK_ALL); | ||
921 | |||
922 | irq[0] = platform_get_irq(pdev, 0); | ||
923 | irq[1] = platform_get_irq(pdev, 1); | ||
924 | |||
925 | if (host->addr) | ||
926 | iounmap(host->addr); | ||
927 | |||
928 | platform_set_drvdata(pdev, NULL); | ||
929 | mmc_remove_host(host->mmc); | ||
930 | |||
931 | free_irq(irq[0], host); | ||
932 | free_irq(irq[1], host); | ||
933 | |||
934 | clk_disable(host->hclk); | ||
935 | mmc_free_host(host->mmc); | ||
936 | |||
937 | return 0; | ||
938 | } | ||
939 | |||
940 | static struct platform_driver sh_mmcif_driver = { | ||
941 | .probe = sh_mmcif_probe, | ||
942 | .remove = sh_mmcif_remove, | ||
943 | .driver = { | ||
944 | .name = DRIVER_NAME, | ||
945 | }, | ||
946 | }; | ||
947 | |||
948 | static int __init sh_mmcif_init(void) | ||
949 | { | ||
950 | return platform_driver_register(&sh_mmcif_driver); | ||
951 | } | ||
952 | |||
953 | static void __exit sh_mmcif_exit(void) | ||
954 | { | ||
955 | platform_driver_unregister(&sh_mmcif_driver); | ||
956 | } | ||
957 | |||
958 | module_init(sh_mmcif_init); | ||
959 | module_exit(sh_mmcif_exit); | ||
960 | |||
961 | |||
962 | MODULE_DESCRIPTION("SuperH on-chip MMC/eMMC interface driver"); | ||
963 | MODULE_LICENSE("GPL"); | ||
964 | MODULE_ALIAS(DRIVER_NAME); | ||
965 | MODULE_AUTHOR("Yusuke Goda <yusuke.goda.sx@renesas.com>"); | ||
diff --git a/drivers/mmc/host/tifm_sd.c b/drivers/mmc/host/tifm_sd.c index 82554ddec6b3..cec99958b652 100644 --- a/drivers/mmc/host/tifm_sd.c +++ b/drivers/mmc/host/tifm_sd.c | |||
@@ -1032,7 +1032,7 @@ static void tifm_sd_remove(struct tifm_dev *sock) | |||
1032 | 1032 | ||
1033 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) | 1033 | static int tifm_sd_suspend(struct tifm_dev *sock, pm_message_t state) |
1034 | { | 1034 | { |
1035 | return mmc_suspend_host(tifm_get_drvdata(sock), state); | 1035 | return mmc_suspend_host(tifm_get_drvdata(sock)); |
1036 | } | 1036 | } |
1037 | 1037 | ||
1038 | static int tifm_sd_resume(struct tifm_dev *sock) | 1038 | static int tifm_sd_resume(struct tifm_dev *sock) |
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index 883fcac21004..ee7d0a5a51c4 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
@@ -768,7 +768,7 @@ static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state) | |||
768 | struct mmc_host *mmc = platform_get_drvdata(dev); | 768 | struct mmc_host *mmc = platform_get_drvdata(dev); |
769 | int ret; | 769 | int ret; |
770 | 770 | ||
771 | ret = mmc_suspend_host(mmc, state); | 771 | ret = mmc_suspend_host(mmc); |
772 | 772 | ||
773 | /* Tell MFD core it can disable us now.*/ | 773 | /* Tell MFD core it can disable us now.*/ |
774 | if (!ret && cell->disable) | 774 | if (!ret && cell->disable) |
diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 632858a94376..19f2d72dbca5 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c | |||
@@ -1280,7 +1280,7 @@ static int via_sd_suspend(struct pci_dev *pcidev, pm_message_t state) | |||
1280 | via_save_pcictrlreg(host); | 1280 | via_save_pcictrlreg(host); |
1281 | via_save_sdcreg(host); | 1281 | via_save_sdcreg(host); |
1282 | 1282 | ||
1283 | ret = mmc_suspend_host(host->mmc, state); | 1283 | ret = mmc_suspend_host(host->mmc); |
1284 | 1284 | ||
1285 | pci_save_state(pcidev); | 1285 | pci_save_state(pcidev); |
1286 | pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); | 1286 | pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); |
diff --git a/drivers/mmc/host/wbsd.c b/drivers/mmc/host/wbsd.c index 69efe01eece8..0012f5d13d28 100644 --- a/drivers/mmc/host/wbsd.c +++ b/drivers/mmc/host/wbsd.c | |||
@@ -1819,7 +1819,7 @@ static int wbsd_suspend(struct wbsd_host *host, pm_message_t state) | |||
1819 | { | 1819 | { |
1820 | BUG_ON(host == NULL); | 1820 | BUG_ON(host == NULL); |
1821 | 1821 | ||
1822 | return mmc_suspend_host(host->mmc, state); | 1822 | return mmc_suspend_host(host->mmc); |
1823 | } | 1823 | } |
1824 | 1824 | ||
1825 | static int wbsd_resume(struct wbsd_host *host) | 1825 | static int wbsd_resume(struct wbsd_host *host) |
diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 373c1a563474..b46be490cd2a 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h | |||
@@ -283,6 +283,8 @@ struct be_adapter { | |||
283 | u8 port_type; | 283 | u8 port_type; |
284 | u8 transceiver; | 284 | u8 transceiver; |
285 | u8 generation; /* BladeEngine ASIC generation */ | 285 | u8 generation; /* BladeEngine ASIC generation */ |
286 | u32 flash_status; | ||
287 | struct completion flash_compl; | ||
286 | 288 | ||
287 | bool sriov_enabled; | 289 | bool sriov_enabled; |
288 | u32 vf_if_handle[BE_MAX_VF]; | 290 | u32 vf_if_handle[BE_MAX_VF]; |
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index e79bf8b9af3b..c911bfb55b19 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
@@ -59,6 +59,13 @@ static int be_mcc_compl_process(struct be_adapter *adapter, | |||
59 | 59 | ||
60 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & | 60 | compl_status = (compl->status >> CQE_STATUS_COMPL_SHIFT) & |
61 | CQE_STATUS_COMPL_MASK; | 61 | CQE_STATUS_COMPL_MASK; |
62 | |||
63 | if ((compl->tag0 == OPCODE_COMMON_WRITE_FLASHROM) && | ||
64 | (compl->tag1 == CMD_SUBSYSTEM_COMMON)) { | ||
65 | adapter->flash_status = compl_status; | ||
66 | complete(&adapter->flash_compl); | ||
67 | } | ||
68 | |||
62 | if (compl_status == MCC_STATUS_SUCCESS) { | 69 | if (compl_status == MCC_STATUS_SUCCESS) { |
63 | if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) { | 70 | if (compl->tag0 == OPCODE_ETH_GET_STATISTICS) { |
64 | struct be_cmd_resp_get_stats *resp = | 71 | struct be_cmd_resp_get_stats *resp = |
@@ -1417,6 +1424,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, | |||
1417 | int status; | 1424 | int status; |
1418 | 1425 | ||
1419 | spin_lock_bh(&adapter->mcc_lock); | 1426 | spin_lock_bh(&adapter->mcc_lock); |
1427 | adapter->flash_status = 0; | ||
1420 | 1428 | ||
1421 | wrb = wrb_from_mccq(adapter); | 1429 | wrb = wrb_from_mccq(adapter); |
1422 | if (!wrb) { | 1430 | if (!wrb) { |
@@ -1428,6 +1436,7 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, | |||
1428 | 1436 | ||
1429 | be_wrb_hdr_prepare(wrb, cmd->size, false, 1, | 1437 | be_wrb_hdr_prepare(wrb, cmd->size, false, 1, |
1430 | OPCODE_COMMON_WRITE_FLASHROM); | 1438 | OPCODE_COMMON_WRITE_FLASHROM); |
1439 | wrb->tag1 = CMD_SUBSYSTEM_COMMON; | ||
1431 | 1440 | ||
1432 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, | 1441 | be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, |
1433 | OPCODE_COMMON_WRITE_FLASHROM, cmd->size); | 1442 | OPCODE_COMMON_WRITE_FLASHROM, cmd->size); |
@@ -1439,10 +1448,16 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, | |||
1439 | req->params.op_code = cpu_to_le32(flash_opcode); | 1448 | req->params.op_code = cpu_to_le32(flash_opcode); |
1440 | req->params.data_buf_size = cpu_to_le32(buf_size); | 1449 | req->params.data_buf_size = cpu_to_le32(buf_size); |
1441 | 1450 | ||
1442 | status = be_mcc_notify_wait(adapter); | 1451 | be_mcc_notify(adapter); |
1452 | spin_unlock_bh(&adapter->mcc_lock); | ||
1453 | |||
1454 | if (!wait_for_completion_timeout(&adapter->flash_compl, | ||
1455 | msecs_to_jiffies(12000))) | ||
1456 | status = -1; | ||
1457 | else | ||
1458 | status = adapter->flash_status; | ||
1443 | 1459 | ||
1444 | err: | 1460 | err: |
1445 | spin_unlock_bh(&adapter->mcc_lock); | ||
1446 | return status; | 1461 | return status; |
1447 | } | 1462 | } |
1448 | 1463 | ||
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 058d7f95f5ae..aa065c71ddd8 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -2319,6 +2319,7 @@ static int be_ctrl_init(struct be_adapter *adapter) | |||
2319 | spin_lock_init(&adapter->mcc_lock); | 2319 | spin_lock_init(&adapter->mcc_lock); |
2320 | spin_lock_init(&adapter->mcc_cq_lock); | 2320 | spin_lock_init(&adapter->mcc_cq_lock); |
2321 | 2321 | ||
2322 | init_completion(&adapter->flash_compl); | ||
2322 | pci_save_state(adapter->pdev); | 2323 | pci_save_state(adapter->pdev); |
2323 | return 0; | 2324 | return 0; |
2324 | 2325 | ||
@@ -2487,10 +2488,6 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
2487 | status = be_cmd_POST(adapter); | 2488 | status = be_cmd_POST(adapter); |
2488 | if (status) | 2489 | if (status) |
2489 | goto ctrl_clean; | 2490 | goto ctrl_clean; |
2490 | |||
2491 | status = be_cmd_reset_function(adapter); | ||
2492 | if (status) | ||
2493 | goto ctrl_clean; | ||
2494 | } | 2491 | } |
2495 | 2492 | ||
2496 | /* tell fw we're ready to fire cmds */ | 2493 | /* tell fw we're ready to fire cmds */ |
@@ -2498,6 +2495,12 @@ static int __devinit be_probe(struct pci_dev *pdev, | |||
2498 | if (status) | 2495 | if (status) |
2499 | goto ctrl_clean; | 2496 | goto ctrl_clean; |
2500 | 2497 | ||
2498 | if (be_physfn(adapter)) { | ||
2499 | status = be_cmd_reset_function(adapter); | ||
2500 | if (status) | ||
2501 | goto ctrl_clean; | ||
2502 | } | ||
2503 | |||
2501 | status = be_stats_init(adapter); | 2504 | status = be_stats_init(adapter); |
2502 | if (status) | 2505 | if (status) |
2503 | goto ctrl_clean; | 2506 | goto ctrl_clean; |
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 39a54bad397f..368f33313fb6 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
@@ -1626,6 +1626,7 @@ static int __devinit bfin_mii_bus_probe(struct platform_device *pdev) | |||
1626 | return 0; | 1626 | return 0; |
1627 | 1627 | ||
1628 | out_err_mdiobus_register: | 1628 | out_err_mdiobus_register: |
1629 | kfree(miibus->irq); | ||
1629 | mdiobus_free(miibus); | 1630 | mdiobus_free(miibus); |
1630 | out_err_alloc: | 1631 | out_err_alloc: |
1631 | peripheral_free_list(pin_req); | 1632 | peripheral_free_list(pin_req); |
@@ -1638,6 +1639,7 @@ static int __devexit bfin_mii_bus_remove(struct platform_device *pdev) | |||
1638 | struct mii_bus *miibus = platform_get_drvdata(pdev); | 1639 | struct mii_bus *miibus = platform_get_drvdata(pdev); |
1639 | platform_set_drvdata(pdev, NULL); | 1640 | platform_set_drvdata(pdev, NULL); |
1640 | mdiobus_unregister(miibus); | 1641 | mdiobus_unregister(miibus); |
1642 | kfree(miibus->irq); | ||
1641 | mdiobus_free(miibus); | 1643 | mdiobus_free(miibus); |
1642 | peripheral_free_list(pin_req); | 1644 | peripheral_free_list(pin_req); |
1643 | return 0; | 1645 | return 0; |
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 85f7cbfe8e5f..0a8de01d52f7 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c | |||
@@ -599,6 +599,8 @@ struct net_device *alloc_sja1000dev(int sizeof_priv) | |||
599 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | | 599 | priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | |
600 | CAN_CTRLMODE_BERR_REPORTING; | 600 | CAN_CTRLMODE_BERR_REPORTING; |
601 | 601 | ||
602 | spin_lock_init(&priv->cmdreg_lock); | ||
603 | |||
602 | if (sizeof_priv) | 604 | if (sizeof_priv) |
603 | priv->priv = (void *)priv + sizeof(struct sja1000_priv); | 605 | priv->priv = (void *)priv + sizeof(struct sja1000_priv); |
604 | 606 | ||
diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index e125113759a5..6586b5c7e4b6 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c | |||
@@ -1034,9 +1034,10 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, | |||
1034 | { | 1034 | { |
1035 | struct vic_provinfo *vp; | 1035 | struct vic_provinfo *vp; |
1036 | u8 oui[3] = VIC_PROVINFO_CISCO_OUI; | 1036 | u8 oui[3] = VIC_PROVINFO_CISCO_OUI; |
1037 | unsigned short *uuid; | 1037 | u8 *uuid; |
1038 | char uuid_str[38]; | 1038 | char uuid_str[38]; |
1039 | static char *uuid_fmt = "%04X%04X-%04X-%04X-%04X-%04X%04X%04X"; | 1039 | static char *uuid_fmt = "%02X%02X%02X%02X-%02X%02X-%02X%02X-" |
1040 | "%02X%02X-%02X%02X%02X%02X%0X%02X"; | ||
1040 | int err; | 1041 | int err; |
1041 | 1042 | ||
1042 | if (!name) | 1043 | if (!name) |
@@ -1058,20 +1059,24 @@ static int enic_set_port_profile(struct enic *enic, u8 request, u8 *mac, | |||
1058 | ETH_ALEN, mac); | 1059 | ETH_ALEN, mac); |
1059 | 1060 | ||
1060 | if (instance_uuid) { | 1061 | if (instance_uuid) { |
1061 | uuid = (unsigned short *)instance_uuid; | 1062 | uuid = instance_uuid; |
1062 | sprintf(uuid_str, uuid_fmt, | 1063 | sprintf(uuid_str, uuid_fmt, |
1063 | uuid[0], uuid[1], uuid[2], uuid[3], | 1064 | uuid[0], uuid[1], uuid[2], uuid[3], |
1064 | uuid[4], uuid[5], uuid[6], uuid[7]); | 1065 | uuid[4], uuid[5], uuid[6], uuid[7], |
1066 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
1067 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
1065 | vic_provinfo_add_tlv(vp, | 1068 | vic_provinfo_add_tlv(vp, |
1066 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR, | 1069 | VIC_LINUX_PROV_TLV_CLIENT_UUID_STR, |
1067 | sizeof(uuid_str), uuid_str); | 1070 | sizeof(uuid_str), uuid_str); |
1068 | } | 1071 | } |
1069 | 1072 | ||
1070 | if (host_uuid) { | 1073 | if (host_uuid) { |
1071 | uuid = (unsigned short *)host_uuid; | 1074 | uuid = host_uuid; |
1072 | sprintf(uuid_str, uuid_fmt, | 1075 | sprintf(uuid_str, uuid_fmt, |
1073 | uuid[0], uuid[1], uuid[2], uuid[3], | 1076 | uuid[0], uuid[1], uuid[2], uuid[3], |
1074 | uuid[4], uuid[5], uuid[6], uuid[7]); | 1077 | uuid[4], uuid[5], uuid[6], uuid[7], |
1078 | uuid[8], uuid[9], uuid[10], uuid[11], | ||
1079 | uuid[12], uuid[13], uuid[14], uuid[15]); | ||
1075 | vic_provinfo_add_tlv(vp, | 1080 | vic_provinfo_add_tlv(vp, |
1076 | VIC_LINUX_PROV_TLV_HOST_UUID_STR, | 1081 | VIC_LINUX_PROV_TLV_HOST_UUID_STR, |
1077 | sizeof(uuid_str), uuid_str); | 1082 | sizeof(uuid_str), uuid_str); |
@@ -1127,6 +1132,14 @@ static int enic_set_vf_port(struct net_device *netdev, int vf, | |||
1127 | switch (request) { | 1132 | switch (request) { |
1128 | case PORT_REQUEST_ASSOCIATE: | 1133 | case PORT_REQUEST_ASSOCIATE: |
1129 | 1134 | ||
1135 | /* If the interface mac addr hasn't been assigned, | ||
1136 | * assign a random mac addr before setting port- | ||
1137 | * profile. | ||
1138 | */ | ||
1139 | |||
1140 | if (is_zero_ether_addr(netdev->dev_addr)) | ||
1141 | random_ether_addr(netdev->dev_addr); | ||
1142 | |||
1130 | if (port[IFLA_PORT_PROFILE]) | 1143 | if (port[IFLA_PORT_PROFILE]) |
1131 | name = nla_data(port[IFLA_PORT_PROFILE]); | 1144 | name = nla_data(port[IFLA_PORT_PROFILE]); |
1132 | 1145 | ||
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index 14cbde5cf68e..6ed2df14ec84 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c | |||
@@ -174,6 +174,7 @@ MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size"); | |||
174 | * @iobase: pointer to I/O memory region | 174 | * @iobase: pointer to I/O memory region |
175 | * @membase: pointer to buffer memory region | 175 | * @membase: pointer to buffer memory region |
176 | * @dma_alloc: dma allocated buffer size | 176 | * @dma_alloc: dma allocated buffer size |
177 | * @io_region_size: I/O memory region size | ||
177 | * @num_tx: number of send buffers | 178 | * @num_tx: number of send buffers |
178 | * @cur_tx: last send buffer written | 179 | * @cur_tx: last send buffer written |
179 | * @dty_tx: last buffer actually sent | 180 | * @dty_tx: last buffer actually sent |
@@ -193,6 +194,7 @@ struct ethoc { | |||
193 | void __iomem *iobase; | 194 | void __iomem *iobase; |
194 | void __iomem *membase; | 195 | void __iomem *membase; |
195 | int dma_alloc; | 196 | int dma_alloc; |
197 | resource_size_t io_region_size; | ||
196 | 198 | ||
197 | unsigned int num_tx; | 199 | unsigned int num_tx; |
198 | unsigned int cur_tx; | 200 | unsigned int cur_tx; |
@@ -943,6 +945,7 @@ static int ethoc_probe(struct platform_device *pdev) | |||
943 | priv = netdev_priv(netdev); | 945 | priv = netdev_priv(netdev); |
944 | priv->netdev = netdev; | 946 | priv->netdev = netdev; |
945 | priv->dma_alloc = 0; | 947 | priv->dma_alloc = 0; |
948 | priv->io_region_size = mmio->end - mmio->start + 1; | ||
946 | 949 | ||
947 | priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, | 950 | priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, |
948 | resource_size(mmio)); | 951 | resource_size(mmio)); |
@@ -1047,20 +1050,34 @@ static int ethoc_probe(struct platform_device *pdev) | |||
1047 | ret = register_netdev(netdev); | 1050 | ret = register_netdev(netdev); |
1048 | if (ret < 0) { | 1051 | if (ret < 0) { |
1049 | dev_err(&netdev->dev, "failed to register interface\n"); | 1052 | dev_err(&netdev->dev, "failed to register interface\n"); |
1050 | goto error; | 1053 | goto error2; |
1051 | } | 1054 | } |
1052 | 1055 | ||
1053 | goto out; | 1056 | goto out; |
1054 | 1057 | ||
1058 | error2: | ||
1059 | netif_napi_del(&priv->napi); | ||
1055 | error: | 1060 | error: |
1056 | mdiobus_unregister(priv->mdio); | 1061 | mdiobus_unregister(priv->mdio); |
1057 | free_mdio: | 1062 | free_mdio: |
1058 | kfree(priv->mdio->irq); | 1063 | kfree(priv->mdio->irq); |
1059 | mdiobus_free(priv->mdio); | 1064 | mdiobus_free(priv->mdio); |
1060 | free: | 1065 | free: |
1061 | if (priv->dma_alloc) | 1066 | if (priv) { |
1062 | dma_free_coherent(NULL, priv->dma_alloc, priv->membase, | 1067 | if (priv->dma_alloc) |
1063 | netdev->mem_start); | 1068 | dma_free_coherent(NULL, priv->dma_alloc, priv->membase, |
1069 | netdev->mem_start); | ||
1070 | else if (priv->membase) | ||
1071 | devm_iounmap(&pdev->dev, priv->membase); | ||
1072 | if (priv->iobase) | ||
1073 | devm_iounmap(&pdev->dev, priv->iobase); | ||
1074 | } | ||
1075 | if (mem) | ||
1076 | devm_release_mem_region(&pdev->dev, mem->start, | ||
1077 | mem->end - mem->start + 1); | ||
1078 | if (mmio) | ||
1079 | devm_release_mem_region(&pdev->dev, mmio->start, | ||
1080 | mmio->end - mmio->start + 1); | ||
1064 | free_netdev(netdev); | 1081 | free_netdev(netdev); |
1065 | out: | 1082 | out: |
1066 | return ret; | 1083 | return ret; |
@@ -1078,6 +1095,7 @@ static int ethoc_remove(struct platform_device *pdev) | |||
1078 | platform_set_drvdata(pdev, NULL); | 1095 | platform_set_drvdata(pdev, NULL); |
1079 | 1096 | ||
1080 | if (netdev) { | 1097 | if (netdev) { |
1098 | netif_napi_del(&priv->napi); | ||
1081 | phy_disconnect(priv->phy); | 1099 | phy_disconnect(priv->phy); |
1082 | priv->phy = NULL; | 1100 | priv->phy = NULL; |
1083 | 1101 | ||
@@ -1089,6 +1107,14 @@ static int ethoc_remove(struct platform_device *pdev) | |||
1089 | if (priv->dma_alloc) | 1107 | if (priv->dma_alloc) |
1090 | dma_free_coherent(NULL, priv->dma_alloc, priv->membase, | 1108 | dma_free_coherent(NULL, priv->dma_alloc, priv->membase, |
1091 | netdev->mem_start); | 1109 | netdev->mem_start); |
1110 | else { | ||
1111 | devm_iounmap(&pdev->dev, priv->membase); | ||
1112 | devm_release_mem_region(&pdev->dev, netdev->mem_start, | ||
1113 | netdev->mem_end - netdev->mem_start + 1); | ||
1114 | } | ||
1115 | devm_iounmap(&pdev->dev, priv->iobase); | ||
1116 | devm_release_mem_region(&pdev->dev, netdev->base_addr, | ||
1117 | priv->io_region_size); | ||
1092 | unregister_netdev(netdev); | 1118 | unregister_netdev(netdev); |
1093 | free_netdev(netdev); | 1119 | free_netdev(netdev); |
1094 | } | 1120 | } |
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 42d9ac9ba395..326465ffbb23 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/clk.h> | 41 | #include <linux/clk.h> |
42 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> |
43 | #include <linux/phy.h> | 43 | #include <linux/phy.h> |
44 | #include <linux/fec.h> | ||
44 | 45 | ||
45 | #include <asm/cacheflush.h> | 46 | #include <asm/cacheflush.h> |
46 | 47 | ||
@@ -182,6 +183,7 @@ struct fec_enet_private { | |||
182 | struct phy_device *phy_dev; | 183 | struct phy_device *phy_dev; |
183 | int mii_timeout; | 184 | int mii_timeout; |
184 | uint phy_speed; | 185 | uint phy_speed; |
186 | phy_interface_t phy_interface; | ||
185 | int index; | 187 | int index; |
186 | int link; | 188 | int link; |
187 | int full_duplex; | 189 | int full_duplex; |
@@ -1191,6 +1193,21 @@ fec_restart(struct net_device *dev, int duplex) | |||
1191 | /* Set MII speed */ | 1193 | /* Set MII speed */ |
1192 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); | 1194 | writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED); |
1193 | 1195 | ||
1196 | #ifdef FEC_MIIGSK_ENR | ||
1197 | if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) { | ||
1198 | /* disable the gasket and wait */ | ||
1199 | writel(0, fep->hwp + FEC_MIIGSK_ENR); | ||
1200 | while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4) | ||
1201 | udelay(1); | ||
1202 | |||
1203 | /* configure the gasket: RMII, 50 MHz, no loopback, no echo */ | ||
1204 | writel(1, fep->hwp + FEC_MIIGSK_CFGR); | ||
1205 | |||
1206 | /* re-enable the gasket */ | ||
1207 | writel(2, fep->hwp + FEC_MIIGSK_ENR); | ||
1208 | } | ||
1209 | #endif | ||
1210 | |||
1194 | /* And last, enable the transmit and receive processing */ | 1211 | /* And last, enable the transmit and receive processing */ |
1195 | writel(2, fep->hwp + FEC_ECNTRL); | 1212 | writel(2, fep->hwp + FEC_ECNTRL); |
1196 | writel(0, fep->hwp + FEC_R_DES_ACTIVE); | 1213 | writel(0, fep->hwp + FEC_R_DES_ACTIVE); |
@@ -1226,6 +1243,7 @@ static int __devinit | |||
1226 | fec_probe(struct platform_device *pdev) | 1243 | fec_probe(struct platform_device *pdev) |
1227 | { | 1244 | { |
1228 | struct fec_enet_private *fep; | 1245 | struct fec_enet_private *fep; |
1246 | struct fec_platform_data *pdata; | ||
1229 | struct net_device *ndev; | 1247 | struct net_device *ndev; |
1230 | int i, irq, ret = 0; | 1248 | int i, irq, ret = 0; |
1231 | struct resource *r; | 1249 | struct resource *r; |
@@ -1259,6 +1277,10 @@ fec_probe(struct platform_device *pdev) | |||
1259 | 1277 | ||
1260 | platform_set_drvdata(pdev, ndev); | 1278 | platform_set_drvdata(pdev, ndev); |
1261 | 1279 | ||
1280 | pdata = pdev->dev.platform_data; | ||
1281 | if (pdata) | ||
1282 | fep->phy_interface = pdata->phy; | ||
1283 | |||
1262 | /* This device has up to three irqs on some platforms */ | 1284 | /* This device has up to three irqs on some platforms */ |
1263 | for (i = 0; i < 3; i++) { | 1285 | for (i = 0; i < 3; i++) { |
1264 | irq = platform_get_irq(pdev, i); | 1286 | irq = platform_get_irq(pdev, i); |
diff --git a/drivers/net/fec.h b/drivers/net/fec.h index cc47f3f057c7..2c48b25668d5 100644 --- a/drivers/net/fec.h +++ b/drivers/net/fec.h | |||
@@ -43,6 +43,8 @@ | |||
43 | #define FEC_R_DES_START 0x180 /* Receive descriptor ring */ | 43 | #define FEC_R_DES_START 0x180 /* Receive descriptor ring */ |
44 | #define FEC_X_DES_START 0x184 /* Transmit descriptor ring */ | 44 | #define FEC_X_DES_START 0x184 /* Transmit descriptor ring */ |
45 | #define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */ | 45 | #define FEC_R_BUFF_SIZE 0x188 /* Maximum receive buff size */ |
46 | #define FEC_MIIGSK_CFGR 0x300 /* MIIGSK Configuration reg */ | ||
47 | #define FEC_MIIGSK_ENR 0x308 /* MIIGSK Enable reg */ | ||
46 | 48 | ||
47 | #else | 49 | #else |
48 | 50 | ||
diff --git a/drivers/net/irda/bfin_sir.c b/drivers/net/irda/bfin_sir.c index 911c082cee5a..f940dfa1f7f8 100644 --- a/drivers/net/irda/bfin_sir.c +++ b/drivers/net/irda/bfin_sir.c | |||
@@ -107,8 +107,12 @@ static int bfin_sir_set_speed(struct bfin_sir_port *port, int speed) | |||
107 | case 57600: | 107 | case 57600: |
108 | case 115200: | 108 | case 115200: |
109 | 109 | ||
110 | quot = (port->clk + (8 * speed)) / (16 * speed)\ | 110 | /* |
111 | - ANOMALY_05000230; | 111 | * IRDA is not affected by anomaly 05000230, so there is no |
112 | * need to tweak the divisor like he UART driver (which will | ||
113 | * slightly speed up the baud rate on us). | ||
114 | */ | ||
115 | quot = (port->clk + (8 * speed)) / (16 * speed); | ||
112 | 116 | ||
113 | do { | 117 | do { |
114 | udelay(utime); | 118 | udelay(utime); |
diff --git a/drivers/net/ixgbe/ixgbe.h b/drivers/net/ixgbe/ixgbe.h index d0ea3d6dea95..ffae480587ae 100644 --- a/drivers/net/ixgbe/ixgbe.h +++ b/drivers/net/ixgbe/ixgbe.h | |||
@@ -360,6 +360,7 @@ struct ixgbe_adapter { | |||
360 | u32 flags2; | 360 | u32 flags2; |
361 | #define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) | 361 | #define IXGBE_FLAG2_RSC_CAPABLE (u32)(1) |
362 | #define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) | 362 | #define IXGBE_FLAG2_RSC_ENABLED (u32)(1 << 1) |
363 | #define IXGBE_FLAG2_TEMP_SENSOR_CAPABLE (u32)(1 << 2) | ||
363 | /* default to trying for four seconds */ | 364 | /* default to trying for four seconds */ |
364 | #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) | 365 | #define IXGBE_TRY_LINK_TIMEOUT (4 * HZ) |
365 | 366 | ||
@@ -407,6 +408,8 @@ struct ixgbe_adapter { | |||
407 | u16 eeprom_version; | 408 | u16 eeprom_version; |
408 | 409 | ||
409 | int node; | 410 | int node; |
411 | struct work_struct check_overtemp_task; | ||
412 | u32 interrupt_event; | ||
410 | 413 | ||
411 | /* SR-IOV */ | 414 | /* SR-IOV */ |
412 | DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); | 415 | DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS); |
diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index f2b7ff44215b..9c02d6014cc4 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c | |||
@@ -1236,6 +1236,7 @@ static struct ixgbe_phy_operations phy_ops_82598 = { | |||
1236 | .setup_link = &ixgbe_setup_phy_link_generic, | 1236 | .setup_link = &ixgbe_setup_phy_link_generic, |
1237 | .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, | 1237 | .setup_link_speed = &ixgbe_setup_phy_link_speed_generic, |
1238 | .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598, | 1238 | .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_82598, |
1239 | .check_overtemp = &ixgbe_tn_check_overtemp, | ||
1239 | }; | 1240 | }; |
1240 | 1241 | ||
1241 | struct ixgbe_info ixgbe_82598_info = { | 1242 | struct ixgbe_info ixgbe_82598_info = { |
diff --git a/drivers/net/ixgbe/ixgbe_82599.c b/drivers/net/ixgbe/ixgbe_82599.c index e9706eb8e4ff..a4e2901f2f08 100644 --- a/drivers/net/ixgbe/ixgbe_82599.c +++ b/drivers/net/ixgbe/ixgbe_82599.c | |||
@@ -2395,6 +2395,7 @@ static struct ixgbe_phy_operations phy_ops_82599 = { | |||
2395 | .write_i2c_byte = &ixgbe_write_i2c_byte_generic, | 2395 | .write_i2c_byte = &ixgbe_write_i2c_byte_generic, |
2396 | .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, | 2396 | .read_i2c_eeprom = &ixgbe_read_i2c_eeprom_generic, |
2397 | .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, | 2397 | .write_i2c_eeprom = &ixgbe_write_i2c_eeprom_generic, |
2398 | .check_overtemp = &ixgbe_tn_check_overtemp, | ||
2398 | }; | 2399 | }; |
2399 | 2400 | ||
2400 | struct ixgbe_info ixgbe_82599_info = { | 2401 | struct ixgbe_info ixgbe_82599_info = { |
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 9551cbb7bf01..d571d101de08 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
@@ -108,6 +108,8 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { | |||
108 | board_82599 }, | 108 | board_82599 }, |
109 | {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4), | 109 | {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4), |
110 | board_82599 }, | 110 | board_82599 }, |
111 | {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_T3_LOM), | ||
112 | board_82599 }, | ||
111 | {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE), | 113 | {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE), |
112 | board_82599 }, | 114 | board_82599 }, |
113 | 115 | ||
@@ -1618,6 +1620,48 @@ static void ixgbe_set_itr_msix(struct ixgbe_q_vector *q_vector) | |||
1618 | } | 1620 | } |
1619 | } | 1621 | } |
1620 | 1622 | ||
1623 | /** | ||
1624 | * ixgbe_check_overtemp_task - worker thread to check over tempurature | ||
1625 | * @work: pointer to work_struct containing our data | ||
1626 | **/ | ||
1627 | static void ixgbe_check_overtemp_task(struct work_struct *work) | ||
1628 | { | ||
1629 | struct ixgbe_adapter *adapter = container_of(work, | ||
1630 | struct ixgbe_adapter, | ||
1631 | check_overtemp_task); | ||
1632 | struct ixgbe_hw *hw = &adapter->hw; | ||
1633 | u32 eicr = adapter->interrupt_event; | ||
1634 | |||
1635 | if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) { | ||
1636 | switch (hw->device_id) { | ||
1637 | case IXGBE_DEV_ID_82599_T3_LOM: { | ||
1638 | u32 autoneg; | ||
1639 | bool link_up = false; | ||
1640 | |||
1641 | if (hw->mac.ops.check_link) | ||
1642 | hw->mac.ops.check_link(hw, &autoneg, &link_up, false); | ||
1643 | |||
1644 | if (((eicr & IXGBE_EICR_GPI_SDP0) && (!link_up)) || | ||
1645 | (eicr & IXGBE_EICR_LSC)) | ||
1646 | /* Check if this is due to overtemp */ | ||
1647 | if (hw->phy.ops.check_overtemp(hw) == IXGBE_ERR_OVERTEMP) | ||
1648 | break; | ||
1649 | } | ||
1650 | return; | ||
1651 | default: | ||
1652 | if (!(eicr & IXGBE_EICR_GPI_SDP0)) | ||
1653 | return; | ||
1654 | break; | ||
1655 | } | ||
1656 | DPRINTK(DRV, ERR, "Network adapter has been stopped because it " | ||
1657 | "has over heated. Restart the computer. If the problem " | ||
1658 | "persists, power off the system and replace the " | ||
1659 | "adapter\n"); | ||
1660 | /* write to clear the interrupt */ | ||
1661 | IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0); | ||
1662 | } | ||
1663 | } | ||
1664 | |||
1621 | static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr) | 1665 | static void ixgbe_check_fan_failure(struct ixgbe_adapter *adapter, u32 eicr) |
1622 | { | 1666 | { |
1623 | struct ixgbe_hw *hw = &adapter->hw; | 1667 | struct ixgbe_hw *hw = &adapter->hw; |
@@ -1689,6 +1733,10 @@ static irqreturn_t ixgbe_msix_lsc(int irq, void *data) | |||
1689 | 1733 | ||
1690 | if (hw->mac.type == ixgbe_mac_82599EB) { | 1734 | if (hw->mac.type == ixgbe_mac_82599EB) { |
1691 | ixgbe_check_sfp_event(adapter, eicr); | 1735 | ixgbe_check_sfp_event(adapter, eicr); |
1736 | adapter->interrupt_event = eicr; | ||
1737 | if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && | ||
1738 | ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) | ||
1739 | schedule_work(&adapter->check_overtemp_task); | ||
1692 | 1740 | ||
1693 | /* Handle Flow Director Full threshold interrupt */ | 1741 | /* Handle Flow Director Full threshold interrupt */ |
1694 | if (eicr & IXGBE_EICR_FLOW_DIR) { | 1742 | if (eicr & IXGBE_EICR_FLOW_DIR) { |
@@ -2190,6 +2238,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter) | |||
2190 | u32 mask; | 2238 | u32 mask; |
2191 | 2239 | ||
2192 | mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); | 2240 | mask = (IXGBE_EIMS_ENABLE_MASK & ~IXGBE_EIMS_RTX_QUEUE); |
2241 | if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) | ||
2242 | mask |= IXGBE_EIMS_GPI_SDP0; | ||
2193 | if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) | 2243 | if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) |
2194 | mask |= IXGBE_EIMS_GPI_SDP1; | 2244 | mask |= IXGBE_EIMS_GPI_SDP1; |
2195 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) { | 2245 | if (adapter->hw.mac.type == ixgbe_mac_82599EB) { |
@@ -2250,6 +2300,9 @@ static irqreturn_t ixgbe_intr(int irq, void *data) | |||
2250 | ixgbe_check_sfp_event(adapter, eicr); | 2300 | ixgbe_check_sfp_event(adapter, eicr); |
2251 | 2301 | ||
2252 | ixgbe_check_fan_failure(adapter, eicr); | 2302 | ixgbe_check_fan_failure(adapter, eicr); |
2303 | if ((adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) && | ||
2304 | ((eicr & IXGBE_EICR_GPI_SDP0) || (eicr & IXGBE_EICR_LSC))) | ||
2305 | schedule_work(&adapter->check_overtemp_task); | ||
2253 | 2306 | ||
2254 | if (napi_schedule_prep(&(q_vector->napi))) { | 2307 | if (napi_schedule_prep(&(q_vector->napi))) { |
2255 | adapter->tx_ring[0]->total_packets = 0; | 2308 | adapter->tx_ring[0]->total_packets = 0; |
@@ -3265,6 +3318,13 @@ static int ixgbe_up_complete(struct ixgbe_adapter *adapter) | |||
3265 | IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); | 3318 | IXGBE_WRITE_REG(hw, IXGBE_EIAM, IXGBE_EICS_RTX_QUEUE); |
3266 | } | 3319 | } |
3267 | 3320 | ||
3321 | /* Enable Thermal over heat sensor interrupt */ | ||
3322 | if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) { | ||
3323 | gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); | ||
3324 | gpie |= IXGBE_SDP0_GPIEN; | ||
3325 | IXGBE_WRITE_REG(hw, IXGBE_GPIE, gpie); | ||
3326 | } | ||
3327 | |||
3268 | /* Enable fan failure interrupt if media type is copper */ | 3328 | /* Enable fan failure interrupt if media type is copper */ |
3269 | if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { | 3329 | if (adapter->flags & IXGBE_FLAG_FAN_FAIL_CAPABLE) { |
3270 | gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); | 3330 | gpie = IXGBE_READ_REG(hw, IXGBE_GPIE); |
@@ -3666,6 +3726,9 @@ void ixgbe_down(struct ixgbe_adapter *adapter) | |||
3666 | adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) | 3726 | adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) |
3667 | cancel_work_sync(&adapter->fdir_reinit_task); | 3727 | cancel_work_sync(&adapter->fdir_reinit_task); |
3668 | 3728 | ||
3729 | if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) | ||
3730 | cancel_work_sync(&adapter->check_overtemp_task); | ||
3731 | |||
3669 | /* disable transmits in the hardware now that interrupts are off */ | 3732 | /* disable transmits in the hardware now that interrupts are off */ |
3670 | for (i = 0; i < adapter->num_tx_queues; i++) { | 3733 | for (i = 0; i < adapter->num_tx_queues; i++) { |
3671 | j = adapter->tx_ring[i]->reg_idx; | 3734 | j = adapter->tx_ring[i]->reg_idx; |
@@ -4645,6 +4708,8 @@ static int __devinit ixgbe_sw_init(struct ixgbe_adapter *adapter) | |||
4645 | adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; | 4708 | adapter->max_msix_q_vectors = MAX_MSIX_Q_VECTORS_82599; |
4646 | adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; | 4709 | adapter->flags2 |= IXGBE_FLAG2_RSC_CAPABLE; |
4647 | adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; | 4710 | adapter->flags2 |= IXGBE_FLAG2_RSC_ENABLED; |
4711 | if (hw->device_id == IXGBE_DEV_ID_82599_T3_LOM) | ||
4712 | adapter->flags2 |= IXGBE_FLAG2_TEMP_SENSOR_CAPABLE; | ||
4648 | if (dev->features & NETIF_F_NTUPLE) { | 4713 | if (dev->features & NETIF_F_NTUPLE) { |
4649 | /* Flow Director perfect filter enabled */ | 4714 | /* Flow Director perfect filter enabled */ |
4650 | adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE; | 4715 | adapter->flags |= IXGBE_FLAG_FDIR_PERFECT_CAPABLE; |
@@ -6561,7 +6626,9 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
6561 | } | 6626 | } |
6562 | 6627 | ||
6563 | /* reset_hw fills in the perm_addr as well */ | 6628 | /* reset_hw fills in the perm_addr as well */ |
6629 | hw->phy.reset_if_overtemp = true; | ||
6564 | err = hw->mac.ops.reset_hw(hw); | 6630 | err = hw->mac.ops.reset_hw(hw); |
6631 | hw->phy.reset_if_overtemp = false; | ||
6565 | if (err == IXGBE_ERR_SFP_NOT_PRESENT && | 6632 | if (err == IXGBE_ERR_SFP_NOT_PRESENT && |
6566 | hw->mac.type == ixgbe_mac_82598EB) { | 6633 | hw->mac.type == ixgbe_mac_82598EB) { |
6567 | /* | 6634 | /* |
@@ -6730,6 +6797,8 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
6730 | adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) | 6797 | adapter->flags & IXGBE_FLAG_FDIR_PERFECT_CAPABLE) |
6731 | INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task); | 6798 | INIT_WORK(&adapter->fdir_reinit_task, ixgbe_fdir_reinit_task); |
6732 | 6799 | ||
6800 | if (adapter->flags2 & IXGBE_FLAG2_TEMP_SENSOR_CAPABLE) | ||
6801 | INIT_WORK(&adapter->check_overtemp_task, ixgbe_check_overtemp_task); | ||
6733 | #ifdef CONFIG_IXGBE_DCA | 6802 | #ifdef CONFIG_IXGBE_DCA |
6734 | if (dca_add_requester(&pdev->dev) == 0) { | 6803 | if (dca_add_requester(&pdev->dev) == 0) { |
6735 | adapter->flags |= IXGBE_FLAG_DCA_ENABLED; | 6804 | adapter->flags |= IXGBE_FLAG_DCA_ENABLED; |
diff --git a/drivers/net/ixgbe/ixgbe_phy.c b/drivers/net/ixgbe/ixgbe_phy.c index 22d21af14783..09e1911ff510 100644 --- a/drivers/net/ixgbe/ixgbe_phy.c +++ b/drivers/net/ixgbe/ixgbe_phy.c | |||
@@ -135,6 +135,11 @@ static enum ixgbe_phy_type ixgbe_get_phy_type_from_id(u32 phy_id) | |||
135 | **/ | 135 | **/ |
136 | s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) | 136 | s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw) |
137 | { | 137 | { |
138 | /* Don't reset PHY if it's shut down due to overtemp. */ | ||
139 | if (!hw->phy.reset_if_overtemp && | ||
140 | (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw))) | ||
141 | return 0; | ||
142 | |||
138 | /* | 143 | /* |
139 | * Perform soft PHY reset to the PHY_XS. | 144 | * Perform soft PHY reset to the PHY_XS. |
140 | * This will cause a soft reset to the PHY | 145 | * This will cause a soft reset to the PHY |
@@ -1345,3 +1350,28 @@ s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, | |||
1345 | return status; | 1350 | return status; |
1346 | } | 1351 | } |
1347 | 1352 | ||
1353 | /** | ||
1354 | * ixgbe_tn_check_overtemp - Checks if an overtemp occured. | ||
1355 | * @hw: pointer to hardware structure | ||
1356 | * | ||
1357 | * Checks if the LASI temp alarm status was triggered due to overtemp | ||
1358 | **/ | ||
1359 | s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw) | ||
1360 | { | ||
1361 | s32 status = 0; | ||
1362 | u16 phy_data = 0; | ||
1363 | |||
1364 | if (hw->device_id != IXGBE_DEV_ID_82599_T3_LOM) | ||
1365 | goto out; | ||
1366 | |||
1367 | /* Check that the LASI temp alarm status was triggered */ | ||
1368 | hw->phy.ops.read_reg(hw, IXGBE_TN_LASI_STATUS_REG, | ||
1369 | MDIO_MMD_PMAPMD, &phy_data); | ||
1370 | |||
1371 | if (!(phy_data & IXGBE_TN_LASI_STATUS_TEMP_ALARM)) | ||
1372 | goto out; | ||
1373 | |||
1374 | status = IXGBE_ERR_OVERTEMP; | ||
1375 | out: | ||
1376 | return status; | ||
1377 | } | ||
diff --git a/drivers/net/ixgbe/ixgbe_phy.h b/drivers/net/ixgbe/ixgbe_phy.h index c9c545941407..ef4ba834c593 100644 --- a/drivers/net/ixgbe/ixgbe_phy.h +++ b/drivers/net/ixgbe/ixgbe_phy.h | |||
@@ -80,6 +80,8 @@ | |||
80 | #define IXGBE_I2C_T_SU_STO 4 | 80 | #define IXGBE_I2C_T_SU_STO 4 |
81 | #define IXGBE_I2C_T_BUF 5 | 81 | #define IXGBE_I2C_T_BUF 5 |
82 | 82 | ||
83 | #define IXGBE_TN_LASI_STATUS_REG 0x9005 | ||
84 | #define IXGBE_TN_LASI_STATUS_TEMP_ALARM 0x0008 | ||
83 | 85 | ||
84 | s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw); | 86 | s32 ixgbe_init_phy_ops_generic(struct ixgbe_hw *hw); |
85 | s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw); | 87 | s32 ixgbe_identify_phy_generic(struct ixgbe_hw *hw); |
@@ -106,6 +108,7 @@ s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw); | |||
106 | s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, | 108 | s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw, |
107 | u16 *list_offset, | 109 | u16 *list_offset, |
108 | u16 *data_offset); | 110 | u16 *data_offset); |
111 | s32 ixgbe_tn_check_overtemp(struct ixgbe_hw *hw); | ||
109 | s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, | 112 | s32 ixgbe_read_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, |
110 | u8 dev_addr, u8 *data); | 113 | u8 dev_addr, u8 *data); |
111 | s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, | 114 | s32 ixgbe_write_i2c_byte_generic(struct ixgbe_hw *hw, u8 byte_offset, |
diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 39b9be897439..2eb6e151016c 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h | |||
@@ -51,6 +51,7 @@ | |||
51 | #define IXGBE_DEV_ID_82599_KX4 0x10F7 | 51 | #define IXGBE_DEV_ID_82599_KX4 0x10F7 |
52 | #define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 | 52 | #define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 |
53 | #define IXGBE_DEV_ID_82599_KR 0x1517 | 53 | #define IXGBE_DEV_ID_82599_KR 0x1517 |
54 | #define IXGBE_DEV_ID_82599_T3_LOM 0x151C | ||
54 | #define IXGBE_DEV_ID_82599_CX4 0x10F9 | 55 | #define IXGBE_DEV_ID_82599_CX4 0x10F9 |
55 | #define IXGBE_DEV_ID_82599_SFP 0x10FB | 56 | #define IXGBE_DEV_ID_82599_SFP 0x10FB |
56 | #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 | 57 | #define IXGBE_DEV_ID_82599_SFP_EM 0x1507 |
@@ -2470,6 +2471,7 @@ struct ixgbe_phy_operations { | |||
2470 | s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8); | 2471 | s32 (*write_i2c_byte)(struct ixgbe_hw *, u8, u8, u8); |
2471 | s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); | 2472 | s32 (*read_i2c_eeprom)(struct ixgbe_hw *, u8 , u8 *); |
2472 | s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); | 2473 | s32 (*write_i2c_eeprom)(struct ixgbe_hw *, u8, u8); |
2474 | s32 (*check_overtemp)(struct ixgbe_hw *); | ||
2473 | }; | 2475 | }; |
2474 | 2476 | ||
2475 | struct ixgbe_eeprom_info { | 2477 | struct ixgbe_eeprom_info { |
@@ -2518,6 +2520,7 @@ struct ixgbe_phy_info { | |||
2518 | enum ixgbe_smart_speed smart_speed; | 2520 | enum ixgbe_smart_speed smart_speed; |
2519 | bool smart_speed_active; | 2521 | bool smart_speed_active; |
2520 | bool multispeed_fiber; | 2522 | bool multispeed_fiber; |
2523 | bool reset_if_overtemp; | ||
2521 | }; | 2524 | }; |
2522 | 2525 | ||
2523 | #include "ixgbe_mbx.h" | 2526 | #include "ixgbe_mbx.h" |
@@ -2605,6 +2608,7 @@ struct ixgbe_info { | |||
2605 | #define IXGBE_ERR_FDIR_REINIT_FAILED -23 | 2608 | #define IXGBE_ERR_FDIR_REINIT_FAILED -23 |
2606 | #define IXGBE_ERR_EEPROM_VERSION -24 | 2609 | #define IXGBE_ERR_EEPROM_VERSION -24 |
2607 | #define IXGBE_ERR_NO_SPACE -25 | 2610 | #define IXGBE_ERR_NO_SPACE -25 |
2611 | #define IXGBE_ERR_OVERTEMP -26 | ||
2608 | #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF | 2612 | #define IXGBE_NOT_IMPLEMENTED 0x7FFFFFFF |
2609 | 2613 | ||
2610 | #endif /* _IXGBE_TYPE_H_ */ | 2614 | #endif /* _IXGBE_TYPE_H_ */ |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 4e238afab4a3..87e8d4cb4057 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -634,11 +634,18 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, | |||
634 | 634 | ||
635 | err = register_netdevice(dev); | 635 | err = register_netdevice(dev); |
636 | if (err < 0) | 636 | if (err < 0) |
637 | return err; | 637 | goto destroy_port; |
638 | 638 | ||
639 | list_add_tail(&vlan->list, &port->vlans); | 639 | list_add_tail(&vlan->list, &port->vlans); |
640 | netif_stacked_transfer_operstate(lowerdev, dev); | 640 | netif_stacked_transfer_operstate(lowerdev, dev); |
641 | |||
641 | return 0; | 642 | return 0; |
643 | |||
644 | destroy_port: | ||
645 | if (list_empty(&port->vlans)) | ||
646 | macvlan_port_destroy(lowerdev); | ||
647 | |||
648 | return err; | ||
642 | } | 649 | } |
643 | EXPORT_SYMBOL_GPL(macvlan_common_newlink); | 650 | EXPORT_SYMBOL_GPL(macvlan_common_newlink); |
644 | 651 | ||
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 5441688daba7..c5f8eb102bf7 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
@@ -2926,5 +2926,5 @@ EXPORT_SYMBOL(ppp_output_wakeup); | |||
2926 | EXPORT_SYMBOL(ppp_register_compressor); | 2926 | EXPORT_SYMBOL(ppp_register_compressor); |
2927 | EXPORT_SYMBOL(ppp_unregister_compressor); | 2927 | EXPORT_SYMBOL(ppp_unregister_compressor); |
2928 | MODULE_LICENSE("GPL"); | 2928 | MODULE_LICENSE("GPL"); |
2929 | MODULE_ALIAS_CHARDEV_MAJOR(PPP_MAJOR); | 2929 | MODULE_ALIAS_CHARDEV(PPP_MAJOR, 0); |
2930 | MODULE_ALIAS("/dev/ppp"); | 2930 | MODULE_ALIAS("devname:ppp"); |
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index b1b93ff2351f..805b64d1e893 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c | |||
@@ -289,6 +289,7 @@ static void pppoe_flush_dev(struct net_device *dev) | |||
289 | struct pppoe_net *pn; | 289 | struct pppoe_net *pn; |
290 | int i; | 290 | int i; |
291 | 291 | ||
292 | pn = pppoe_pernet(dev_net(dev)); | ||
292 | write_lock_bh(&pn->hash_lock); | 293 | write_lock_bh(&pn->hash_lock); |
293 | for (i = 0; i < PPPOE_HASH_SIZE; i++) { | 294 | for (i = 0; i < PPPOE_HASH_SIZE; i++) { |
294 | struct pppox_sock *po = pn->hash_table[i]; | 295 | struct pppox_sock *po = pn->hash_table[i]; |
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 586ed0915a29..501a55ffce57 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c | |||
@@ -1294,6 +1294,9 @@ static int sh_mdio_release(struct net_device *ndev) | |||
1294 | /* remove mdio bus info from net_device */ | 1294 | /* remove mdio bus info from net_device */ |
1295 | dev_set_drvdata(&ndev->dev, NULL); | 1295 | dev_set_drvdata(&ndev->dev, NULL); |
1296 | 1296 | ||
1297 | /* free interrupts memory */ | ||
1298 | kfree(bus->irq); | ||
1299 | |||
1297 | /* free bitbang info */ | 1300 | /* free bitbang info */ |
1298 | free_mdio_bitbang(bus); | 1301 | free_mdio_bitbang(bus); |
1299 | 1302 | ||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 97b25533e5fb..6ad6fe706312 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -526,6 +526,8 @@ static inline struct sk_buff *tun_alloc_skb(struct tun_struct *tun, | |||
526 | struct sk_buff *skb; | 526 | struct sk_buff *skb; |
527 | int err; | 527 | int err; |
528 | 528 | ||
529 | sock_update_classid(sk); | ||
530 | |||
529 | /* Under a page? Don't bother with paged skb. */ | 531 | /* Under a page? Don't bother with paged skb. */ |
530 | if (prepad + len < PAGE_SIZE || !linear) | 532 | if (prepad + len < PAGE_SIZE || !linear) |
531 | linear = len; | 533 | linear = len; |
@@ -1649,3 +1651,4 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); | |||
1649 | MODULE_AUTHOR(DRV_COPYRIGHT); | 1651 | MODULE_AUTHOR(DRV_COPYRIGHT); |
1650 | MODULE_LICENSE("GPL"); | 1652 | MODULE_LICENSE("GPL"); |
1651 | MODULE_ALIAS_MISCDEV(TUN_MINOR); | 1653 | MODULE_ALIAS_MISCDEV(TUN_MINOR); |
1654 | MODULE_ALIAS("devname:net/tun"); | ||
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 31b73310ec77..1f802e90474c 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c | |||
@@ -322,7 +322,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
322 | size = (u16) (header & 0x0000ffff); | 322 | size = (u16) (header & 0x0000ffff); |
323 | 323 | ||
324 | if ((skb->len) - ((size + 1) & 0xfffe) == 0) { | 324 | if ((skb->len) - ((size + 1) & 0xfffe) == 0) { |
325 | u8 alignment = (u32)skb->data & 0x3; | 325 | u8 alignment = (unsigned long)skb->data & 0x3; |
326 | if (alignment != 0x2) { | 326 | if (alignment != 0x2) { |
327 | /* | 327 | /* |
328 | * not 16bit aligned so use the room provided by | 328 | * not 16bit aligned so use the room provided by |
@@ -351,7 +351,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | |||
351 | } | 351 | } |
352 | ax_skb = skb_clone(skb, GFP_ATOMIC); | 352 | ax_skb = skb_clone(skb, GFP_ATOMIC); |
353 | if (ax_skb) { | 353 | if (ax_skb) { |
354 | u8 alignment = (u32)packet & 0x3; | 354 | u8 alignment = (unsigned long)packet & 0x3; |
355 | ax_skb->len = size; | 355 | ax_skb->len = size; |
356 | 356 | ||
357 | if (alignment != 0x2) { | 357 | if (alignment != 0x2) { |
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 9964df199511..0a3c41faea9c 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c | |||
@@ -475,6 +475,9 @@ static const struct usb_device_id hso_ids[] = { | |||
475 | {USB_DEVICE(0x0af0, 0x8302)}, | 475 | {USB_DEVICE(0x0af0, 0x8302)}, |
476 | {USB_DEVICE(0x0af0, 0x8304)}, | 476 | {USB_DEVICE(0x0af0, 0x8304)}, |
477 | {USB_DEVICE(0x0af0, 0x8400)}, | 477 | {USB_DEVICE(0x0af0, 0x8400)}, |
478 | {USB_DEVICE(0x0af0, 0x8600)}, | ||
479 | {USB_DEVICE(0x0af0, 0x8800)}, | ||
480 | {USB_DEVICE(0x0af0, 0x8900)}, | ||
478 | {USB_DEVICE(0x0af0, 0xd035)}, | 481 | {USB_DEVICE(0x0af0, 0xd035)}, |
479 | {USB_DEVICE(0x0af0, 0xd055)}, | 482 | {USB_DEVICE(0x0af0, 0xd055)}, |
480 | {USB_DEVICE(0x0af0, 0xd155)}, | 483 | {USB_DEVICE(0x0af0, 0xd155)}, |
diff --git a/drivers/net/wimax/i2400m/rx.c b/drivers/net/wimax/i2400m/rx.c index 6537593fae66..8cc9e319f435 100644 --- a/drivers/net/wimax/i2400m/rx.c +++ b/drivers/net/wimax/i2400m/rx.c | |||
@@ -1027,12 +1027,12 @@ void i2400m_rx_edata(struct i2400m *i2400m, struct sk_buff *skb_rx, | |||
1027 | ro_sn = (reorder >> I2400M_RO_SN_SHIFT) & I2400M_RO_SN; | 1027 | ro_sn = (reorder >> I2400M_RO_SN_SHIFT) & I2400M_RO_SN; |
1028 | 1028 | ||
1029 | spin_lock_irqsave(&i2400m->rx_lock, flags); | 1029 | spin_lock_irqsave(&i2400m->rx_lock, flags); |
1030 | roq = &i2400m->rx_roq[ro_cin]; | 1030 | if (i2400m->rx_roq == NULL) { |
1031 | if (roq == NULL) { | ||
1032 | kfree_skb(skb); /* rx_roq is already destroyed */ | 1031 | kfree_skb(skb); /* rx_roq is already destroyed */ |
1033 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | 1032 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); |
1034 | goto error; | 1033 | goto error; |
1035 | } | 1034 | } |
1035 | roq = &i2400m->rx_roq[ro_cin]; | ||
1036 | kref_get(&i2400m->rx_roq_refcount); | 1036 | kref_get(&i2400m->rx_roq_refcount); |
1037 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); | 1037 | spin_unlock_irqrestore(&i2400m->rx_lock, flags); |
1038 | 1038 | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 5f04cf38a5bc..cc6d41dec332 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -1214,6 +1214,7 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1214 | struct ath5k_hw *ah = sc->ah; | 1214 | struct ath5k_hw *ah = sc->ah; |
1215 | struct sk_buff *skb = bf->skb; | 1215 | struct sk_buff *skb = bf->skb; |
1216 | struct ath5k_desc *ds; | 1216 | struct ath5k_desc *ds; |
1217 | int ret; | ||
1217 | 1218 | ||
1218 | if (!skb) { | 1219 | if (!skb) { |
1219 | skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); | 1220 | skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); |
@@ -1240,9 +1241,9 @@ ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1240 | ds = bf->desc; | 1241 | ds = bf->desc; |
1241 | ds->ds_link = bf->daddr; /* link to self */ | 1242 | ds->ds_link = bf->daddr; /* link to self */ |
1242 | ds->ds_data = bf->skbaddr; | 1243 | ds->ds_data = bf->skbaddr; |
1243 | ah->ah_setup_rx_desc(ah, ds, | 1244 | ret = ah->ah_setup_rx_desc(ah, ds, ah->common.rx_bufsize, 0); |
1244 | skb_tailroom(skb), /* buffer size */ | 1245 | if (ret) |
1245 | 0); | 1246 | return ret; |
1246 | 1247 | ||
1247 | if (sc->rxlink != NULL) | 1248 | if (sc->rxlink != NULL) |
1248 | *sc->rxlink = bf->daddr; | 1249 | *sc->rxlink = bf->daddr; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index c8a4558f79ba..f43d85a302c4 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -76,22 +76,13 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, | |||
76 | ds = bf->bf_desc; | 76 | ds = bf->bf_desc; |
77 | flags = ATH9K_TXDESC_NOACK; | 77 | flags = ATH9K_TXDESC_NOACK; |
78 | 78 | ||
79 | if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || | 79 | ds->ds_link = 0; |
80 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) && | 80 | /* |
81 | (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { | 81 | * Switch antenna every beacon. |
82 | ds->ds_link = bf->bf_daddr; /* self-linked */ | 82 | * Should only switch every beacon period, not for every SWBA |
83 | flags |= ATH9K_TXDESC_VEOL; | 83 | * XXX assumes two antennae |
84 | /* Let hardware handle antenna switching. */ | 84 | */ |
85 | antenna = 0; | 85 | antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); |
86 | } else { | ||
87 | ds->ds_link = 0; | ||
88 | /* | ||
89 | * Switch antenna every beacon. | ||
90 | * Should only switch every beacon period, not for every SWBA | ||
91 | * XXX assumes two antennae | ||
92 | */ | ||
93 | antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); | ||
94 | } | ||
95 | 86 | ||
96 | sband = &sc->sbands[common->hw->conf.channel->band]; | 87 | sband = &sc->sbands[common->hw->conf.channel->band]; |
97 | rate = sband->bitrates[rateidx].hw_value; | 88 | rate = sband->bitrates[rateidx].hw_value; |
@@ -215,36 +206,6 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, | |||
215 | return bf; | 206 | return bf; |
216 | } | 207 | } |
217 | 208 | ||
218 | /* | ||
219 | * Startup beacon transmission for adhoc mode when they are sent entirely | ||
220 | * by the hardware using the self-linked descriptor + veol trick. | ||
221 | */ | ||
222 | static void ath_beacon_start_adhoc(struct ath_softc *sc, | ||
223 | struct ieee80211_vif *vif) | ||
224 | { | ||
225 | struct ath_hw *ah = sc->sc_ah; | ||
226 | struct ath_common *common = ath9k_hw_common(ah); | ||
227 | struct ath_buf *bf; | ||
228 | struct ath_vif *avp; | ||
229 | struct sk_buff *skb; | ||
230 | |||
231 | avp = (void *)vif->drv_priv; | ||
232 | |||
233 | if (avp->av_bcbuf == NULL) | ||
234 | return; | ||
235 | |||
236 | bf = avp->av_bcbuf; | ||
237 | skb = bf->bf_mpdu; | ||
238 | |||
239 | ath_beacon_setup(sc, avp, bf, 0); | ||
240 | |||
241 | /* NB: caller is known to have already stopped tx dma */ | ||
242 | ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); | ||
243 | ath9k_hw_txstart(ah, sc->beacon.beaconq); | ||
244 | ath_print(common, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", | ||
245 | sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); | ||
246 | } | ||
247 | |||
248 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | 209 | int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) |
249 | { | 210 | { |
250 | struct ath_softc *sc = aphy->sc; | 211 | struct ath_softc *sc = aphy->sc; |
@@ -265,7 +226,8 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
265 | list_del(&avp->av_bcbuf->list); | 226 | list_del(&avp->av_bcbuf->list); |
266 | 227 | ||
267 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || | 228 | if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || |
268 | !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { | 229 | sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC || |
230 | sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) { | ||
269 | int slot; | 231 | int slot; |
270 | /* | 232 | /* |
271 | * Assign the vif to a beacon xmit slot. As | 233 | * Assign the vif to a beacon xmit slot. As |
@@ -274,17 +236,11 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) | |||
274 | avp->av_bslot = 0; | 236 | avp->av_bslot = 0; |
275 | for (slot = 0; slot < ATH_BCBUF; slot++) | 237 | for (slot = 0; slot < ATH_BCBUF; slot++) |
276 | if (sc->beacon.bslot[slot] == NULL) { | 238 | if (sc->beacon.bslot[slot] == NULL) { |
277 | /* | ||
278 | * XXX hack, space out slots to better | ||
279 | * deal with misses | ||
280 | */ | ||
281 | if (slot+1 < ATH_BCBUF && | ||
282 | sc->beacon.bslot[slot+1] == NULL) { | ||
283 | avp->av_bslot = slot+1; | ||
284 | break; | ||
285 | } | ||
286 | avp->av_bslot = slot; | 239 | avp->av_bslot = slot; |
240 | |||
287 | /* NB: keep looking for a double slot */ | 241 | /* NB: keep looking for a double slot */ |
242 | if (slot == 0 || !sc->beacon.bslot[slot-1]) | ||
243 | break; | ||
288 | } | 244 | } |
289 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); | 245 | BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); |
290 | sc->beacon.bslot[avp->av_bslot] = vif; | 246 | sc->beacon.bslot[avp->av_bslot] = vif; |
@@ -721,8 +677,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
721 | * self-linked tx descriptor and let the hardware deal with things. | 677 | * self-linked tx descriptor and let the hardware deal with things. |
722 | */ | 678 | */ |
723 | intval |= ATH9K_BEACON_ENA; | 679 | intval |= ATH9K_BEACON_ENA; |
724 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) | 680 | ah->imask |= ATH9K_INT_SWBA; |
725 | ah->imask |= ATH9K_INT_SWBA; | ||
726 | 681 | ||
727 | ath_beaconq_config(sc); | 682 | ath_beaconq_config(sc); |
728 | 683 | ||
@@ -732,10 +687,6 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
732 | ath9k_beacon_init(sc, nexttbtt, intval); | 687 | ath9k_beacon_init(sc, nexttbtt, intval); |
733 | sc->beacon.bmisscnt = 0; | 688 | sc->beacon.bmisscnt = 0; |
734 | ath9k_hw_set_interrupts(ah, ah->imask); | 689 | ath9k_hw_set_interrupts(ah, ah->imask); |
735 | |||
736 | /* FIXME: Handle properly when vif is NULL */ | ||
737 | if (vif && ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) | ||
738 | ath_beacon_start_adhoc(sc, vif); | ||
739 | } | 690 | } |
740 | 691 | ||
741 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) | 692 | void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 46dc41a16faa..77b359162d6c 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -107,12 +107,14 @@ static inline void ath9k_skb_queue_purge(struct hif_device_usb *hif_dev, | |||
107 | static void hif_usb_tx_cb(struct urb *urb) | 107 | static void hif_usb_tx_cb(struct urb *urb) |
108 | { | 108 | { |
109 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; | 109 | struct tx_buf *tx_buf = (struct tx_buf *) urb->context; |
110 | struct hif_device_usb *hif_dev = tx_buf->hif_dev; | 110 | struct hif_device_usb *hif_dev; |
111 | struct sk_buff *skb; | 111 | struct sk_buff *skb; |
112 | 112 | ||
113 | if (!hif_dev || !tx_buf) | 113 | if (!tx_buf || !tx_buf->hif_dev) |
114 | return; | 114 | return; |
115 | 115 | ||
116 | hif_dev = tx_buf->hif_dev; | ||
117 | |||
116 | switch (urb->status) { | 118 | switch (urb->status) { |
117 | case 0: | 119 | case 0: |
118 | break; | 120 | break; |
@@ -607,6 +609,10 @@ static int ath9k_hif_usb_alloc_tx_urbs(struct hif_device_usb *hif_dev) | |||
607 | 609 | ||
608 | return 0; | 610 | return 0; |
609 | err: | 611 | err: |
612 | if (tx_buf) { | ||
613 | kfree(tx_buf->buf); | ||
614 | kfree(tx_buf); | ||
615 | } | ||
610 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); | 616 | ath9k_hif_usb_dealloc_tx_urbs(hif_dev); |
611 | return -ENOMEM; | 617 | return -ENOMEM; |
612 | } | 618 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index ad556aa8da39..c251603ab032 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | #include <linux/leds.h> | 25 | #include <linux/leds.h> |
26 | #include <linux/slab.h> | ||
26 | #include <net/mac80211.h> | 27 | #include <net/mac80211.h> |
27 | 28 | ||
28 | #include "common.h" | 29 | #include "common.h" |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 257b10ba6f57..1ec836cf1c0d 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -28,7 +28,6 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { | |||
28 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ | 28 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ |
29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ | 29 | { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ |
30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ | 30 | { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ |
31 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ | ||
32 | { 0 } | 31 | { 0 } |
33 | }; | 32 | }; |
34 | 33 | ||
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index ba139132c85f..ca6065b71b46 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -19,6 +19,12 @@ | |||
19 | 19 | ||
20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) | 20 | #define SKB_CB_ATHBUF(__skb) (*((struct ath_buf **)__skb->cb)) |
21 | 21 | ||
22 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | ||
23 | { | ||
24 | return sc->ps_enabled && | ||
25 | (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP); | ||
26 | } | ||
27 | |||
22 | static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, | 28 | static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, |
23 | struct ieee80211_hdr *hdr) | 29 | struct ieee80211_hdr *hdr) |
24 | { | 30 | { |
@@ -616,8 +622,8 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
616 | hdr = (struct ieee80211_hdr *)skb->data; | 622 | hdr = (struct ieee80211_hdr *)skb->data; |
617 | 623 | ||
618 | /* Process Beacon and CAB receive in PS state */ | 624 | /* Process Beacon and CAB receive in PS state */ |
619 | if ((sc->ps_flags & PS_WAIT_FOR_BEACON) && | 625 | if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) |
620 | ieee80211_is_beacon(hdr->frame_control)) | 626 | && ieee80211_is_beacon(hdr->frame_control)) |
621 | ath_rx_ps_beacon(sc, skb); | 627 | ath_rx_ps_beacon(sc, skb); |
622 | else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && | 628 | else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && |
623 | (ieee80211_is_data(hdr->frame_control) || | 629 | (ieee80211_is_data(hdr->frame_control) || |
@@ -932,9 +938,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
932 | sc->rx.rxotherant = 0; | 938 | sc->rx.rxotherant = 0; |
933 | } | 939 | } |
934 | 940 | ||
935 | if (unlikely(sc->ps_flags & (PS_WAIT_FOR_BEACON | | 941 | if (unlikely(ath9k_check_auto_sleep(sc) || |
936 | PS_WAIT_FOR_CAB | | 942 | (sc->ps_flags & (PS_WAIT_FOR_BEACON | |
937 | PS_WAIT_FOR_PSPOLL_DATA))) | 943 | PS_WAIT_FOR_CAB | |
944 | PS_WAIT_FOR_PSPOLL_DATA)))) | ||
938 | ath_rx_ps(sc, skb); | 945 | ath_rx_ps(sc, skb); |
939 | 946 | ||
940 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); | 947 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c index a273e373b7b0..c92b2c0cbd91 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ict.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ict.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/etherdevice.h> | 31 | #include <linux/etherdevice.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/gfp.h> | ||
33 | #include <net/mac80211.h> | 34 | #include <net/mac80211.h> |
34 | 35 | ||
35 | #include "iwl-dev.h" | 36 | #include "iwl-dev.h" |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 107e173112f6..5d3f51ff2f0d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -376,6 +376,11 @@ void iwl_bg_start_internal_scan(struct work_struct *work) | |||
376 | 376 | ||
377 | mutex_lock(&priv->mutex); | 377 | mutex_lock(&priv->mutex); |
378 | 378 | ||
379 | if (priv->is_internal_short_scan == true) { | ||
380 | IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); | ||
381 | goto unlock; | ||
382 | } | ||
383 | |||
379 | if (!iwl_is_ready_rf(priv)) { | 384 | if (!iwl_is_ready_rf(priv)) { |
380 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | 385 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); |
381 | goto unlock; | 386 | goto unlock; |
@@ -497,17 +502,27 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
497 | { | 502 | { |
498 | struct iwl_priv *priv = | 503 | struct iwl_priv *priv = |
499 | container_of(work, struct iwl_priv, scan_completed); | 504 | container_of(work, struct iwl_priv, scan_completed); |
505 | bool internal = false; | ||
500 | 506 | ||
501 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); | 507 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); |
502 | 508 | ||
503 | cancel_delayed_work(&priv->scan_check); | 509 | cancel_delayed_work(&priv->scan_check); |
504 | 510 | ||
505 | if (!priv->is_internal_short_scan) | 511 | mutex_lock(&priv->mutex); |
506 | ieee80211_scan_completed(priv->hw, false); | 512 | if (priv->is_internal_short_scan) { |
507 | else { | ||
508 | priv->is_internal_short_scan = false; | 513 | priv->is_internal_short_scan = false; |
509 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 514 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); |
515 | internal = true; | ||
510 | } | 516 | } |
517 | mutex_unlock(&priv->mutex); | ||
518 | |||
519 | /* | ||
520 | * Do not hold mutex here since this will cause mac80211 to call | ||
521 | * into driver again into functions that will attempt to take | ||
522 | * mutex. | ||
523 | */ | ||
524 | if (!internal) | ||
525 | ieee80211_scan_completed(priv->hw, false); | ||
511 | 526 | ||
512 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | 527 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) |
513 | return; | 528 | return; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 85ed235ac901..83a26361a9b5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -431,7 +431,7 @@ int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, | |||
431 | struct iwl_link_quality_cmd *link_cmd; | 431 | struct iwl_link_quality_cmd *link_cmd; |
432 | unsigned long flags; | 432 | unsigned long flags; |
433 | 433 | ||
434 | if (*sta_id_r) | 434 | if (sta_id_r) |
435 | *sta_id_r = IWL_INVALID_STATION; | 435 | *sta_id_r = IWL_INVALID_STATION; |
436 | 436 | ||
437 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); | 437 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 2d2890878dea..4bd61ee627c0 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -2572,14 +2572,18 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) | |||
2572 | 2572 | ||
2573 | static void rndis_wlan_do_link_down_work(struct usbnet *usbdev) | 2573 | static void rndis_wlan_do_link_down_work(struct usbnet *usbdev) |
2574 | { | 2574 | { |
2575 | union iwreq_data evt; | 2575 | struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); |
2576 | 2576 | ||
2577 | netif_carrier_off(usbdev->net); | 2577 | if (priv->connected) { |
2578 | priv->connected = false; | ||
2579 | memset(priv->bssid, 0, ETH_ALEN); | ||
2580 | |||
2581 | deauthenticate(usbdev); | ||
2578 | 2582 | ||
2579 | evt.data.flags = 0; | 2583 | cfg80211_disconnected(usbdev->net, 0, NULL, 0, GFP_KERNEL); |
2580 | evt.data.length = 0; | 2584 | } |
2581 | memset(evt.ap_addr.sa_data, 0, ETH_ALEN); | 2585 | |
2582 | wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL); | 2586 | netif_carrier_off(usbdev->net); |
2583 | } | 2587 | } |
2584 | 2588 | ||
2585 | static void rndis_wlan_worker(struct work_struct *work) | 2589 | static void rndis_wlan_worker(struct work_struct *work) |
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 4ba7b038928f..ad2c98af7e9d 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -926,7 +926,7 @@ static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
926 | static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, | 926 | static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, |
927 | enum dev_state state) | 927 | enum dev_state state) |
928 | { | 928 | { |
929 | u32 reg; | 929 | u32 reg, reg2; |
930 | unsigned int i; | 930 | unsigned int i; |
931 | char put_to_sleep; | 931 | char put_to_sleep; |
932 | char bbp_state; | 932 | char bbp_state; |
@@ -947,11 +947,12 @@ static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, | |||
947 | * device has entered the correct state. | 947 | * device has entered the correct state. |
948 | */ | 948 | */ |
949 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 949 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
950 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); | 950 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2); |
951 | bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE); | 951 | bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); |
952 | rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE); | 952 | rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); |
953 | if (bbp_state == state && rf_state == state) | 953 | if (bbp_state == state && rf_state == state) |
954 | return 0; | 954 | return 0; |
955 | rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); | ||
955 | msleep(10); | 956 | msleep(10); |
956 | } | 957 | } |
957 | 958 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 89d132d4af12..41da3d218c65 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -1084,7 +1084,7 @@ static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
1084 | static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, | 1084 | static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, |
1085 | enum dev_state state) | 1085 | enum dev_state state) |
1086 | { | 1086 | { |
1087 | u32 reg; | 1087 | u32 reg, reg2; |
1088 | unsigned int i; | 1088 | unsigned int i; |
1089 | char put_to_sleep; | 1089 | char put_to_sleep; |
1090 | char bbp_state; | 1090 | char bbp_state; |
@@ -1105,11 +1105,12 @@ static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, | |||
1105 | * device has entered the correct state. | 1105 | * device has entered the correct state. |
1106 | */ | 1106 | */ |
1107 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 1107 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
1108 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); | 1108 | rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®2); |
1109 | bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE); | 1109 | bbp_state = rt2x00_get_field32(reg2, PWRCSR1_BBP_CURR_STATE); |
1110 | rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE); | 1110 | rf_state = rt2x00_get_field32(reg2, PWRCSR1_RF_CURR_STATE); |
1111 | if (bbp_state == state && rf_state == state) | 1111 | if (bbp_state == state && rf_state == state) |
1112 | return 0; | 1112 | return 0; |
1113 | rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); | ||
1113 | msleep(10); | 1114 | msleep(10); |
1114 | } | 1115 | } |
1115 | 1116 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0f8b84b7224c..699161327d65 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -413,7 +413,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
413 | */ | 413 | */ |
414 | rt2x00_desc_read(txi, 0, &word); | 414 | rt2x00_desc_read(txi, 0, &word); |
415 | rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, | 415 | rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, |
416 | skb->len + TXWI_DESC_SIZE); | 416 | skb->len - TXINFO_DESC_SIZE); |
417 | rt2x00_set_field32(&word, TXINFO_W0_WIV, | 417 | rt2x00_set_field32(&word, TXINFO_W0_WIV, |
418 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); | 418 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); |
419 | rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); | 419 | rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index a016f7ccde29..f71eee67f977 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c | |||
@@ -206,7 +206,7 @@ void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) | |||
206 | /* | 206 | /* |
207 | * Free irq line. | 207 | * Free irq line. |
208 | */ | 208 | */ |
209 | free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev); | 209 | free_irq(rt2x00dev->irq, rt2x00dev); |
210 | 210 | ||
211 | /* | 211 | /* |
212 | * Free DMA | 212 | * Free DMA |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 2e3076f67535..6a74baf4e934 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1689,7 +1689,7 @@ static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
1689 | 1689 | ||
1690 | static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | 1690 | static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) |
1691 | { | 1691 | { |
1692 | u32 reg; | 1692 | u32 reg, reg2; |
1693 | unsigned int i; | 1693 | unsigned int i; |
1694 | char put_to_sleep; | 1694 | char put_to_sleep; |
1695 | 1695 | ||
@@ -1706,10 +1706,11 @@ static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
1706 | * device has entered the correct state. | 1706 | * device has entered the correct state. |
1707 | */ | 1707 | */ |
1708 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 1708 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
1709 | rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®); | 1709 | rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®2); |
1710 | state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); | 1710 | state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE); |
1711 | if (state == !put_to_sleep) | 1711 | if (state == !put_to_sleep) |
1712 | return 0; | 1712 | return 0; |
1713 | rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg); | ||
1713 | msleep(10); | 1714 | msleep(10); |
1714 | } | 1715 | } |
1715 | 1716 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e35bd19c3c5a..6e0d82efe924 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -1366,7 +1366,7 @@ static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) | |||
1366 | 1366 | ||
1367 | static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | 1367 | static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) |
1368 | { | 1368 | { |
1369 | u32 reg; | 1369 | u32 reg, reg2; |
1370 | unsigned int i; | 1370 | unsigned int i; |
1371 | char put_to_sleep; | 1371 | char put_to_sleep; |
1372 | 1372 | ||
@@ -1383,10 +1383,11 @@ static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
1383 | * device has entered the correct state. | 1383 | * device has entered the correct state. |
1384 | */ | 1384 | */ |
1385 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { | 1385 | for (i = 0; i < REGISTER_BUSY_COUNT; i++) { |
1386 | rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®); | 1386 | rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®2); |
1387 | state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); | 1387 | state = rt2x00_get_field32(reg2, MAC_CSR12_BBP_CURRENT_STATE); |
1388 | if (state == !put_to_sleep) | 1388 | if (state == !put_to_sleep) |
1389 | return 0; | 1389 | return 0; |
1390 | rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg); | ||
1390 | msleep(10); | 1391 | msleep(10); |
1391 | } | 1392 | } |
1392 | 1393 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c index 57f4bfd959c8..b98fb643fab0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ b/drivers/net/wireless/wl12xx/wl1271_rx.c | |||
@@ -113,6 +113,8 @@ static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) | |||
113 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, | 113 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, |
114 | beacon ? "beacon" : ""); | 114 | beacon ? "beacon" : ""); |
115 | 115 | ||
116 | skb_trim(skb, skb->len - desc->pad_len); | ||
117 | |||
116 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 118 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
117 | ieee80211_rx_ni(wl->hw, skb); | 119 | ieee80211_rx_ni(wl->hw, skb); |
118 | } | 120 | } |
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c index 1586e1caa2f5..8bef6d60f88b 100644 --- a/drivers/parport/parport_amiga.c +++ b/drivers/parport/parport_amiga.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/parport.h> | 18 | #include <linux/parport.h> |
19 | #include <linux/ioport.h> | 19 | #include <linux/ioport.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/platform_device.h> | ||
22 | |||
21 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
22 | #include <asm/amigahw.h> | 24 | #include <asm/amigahw.h> |
23 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
@@ -31,7 +33,6 @@ | |||
31 | #define DPRINTK(x...) do { } while (0) | 33 | #define DPRINTK(x...) do { } while (0) |
32 | #endif | 34 | #endif |
33 | 35 | ||
34 | static struct parport *this_port = NULL; | ||
35 | 36 | ||
36 | static void amiga_write_data(struct parport *p, unsigned char data) | 37 | static void amiga_write_data(struct parport *p, unsigned char data) |
37 | { | 38 | { |
@@ -227,18 +228,11 @@ static struct parport_operations pp_amiga_ops = { | |||
227 | 228 | ||
228 | /* ----------- Initialisation code --------------------------------- */ | 229 | /* ----------- Initialisation code --------------------------------- */ |
229 | 230 | ||
230 | static int __init parport_amiga_init(void) | 231 | static int __init amiga_parallel_probe(struct platform_device *pdev) |
231 | { | 232 | { |
232 | struct parport *p; | 233 | struct parport *p; |
233 | int err; | 234 | int err; |
234 | 235 | ||
235 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_PARALLEL)) | ||
236 | return -ENODEV; | ||
237 | |||
238 | err = -EBUSY; | ||
239 | if (!request_mem_region(CIAA_PHYSADDR-1+0x100, 0x100, "parallel")) | ||
240 | goto out_mem; | ||
241 | |||
242 | ciaa.ddrb = 0xff; | 236 | ciaa.ddrb = 0xff; |
243 | ciab.ddra &= 0xf8; | 237 | ciab.ddra &= 0xf8; |
244 | mb(); | 238 | mb(); |
@@ -246,41 +240,63 @@ static int __init parport_amiga_init(void) | |||
246 | p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG, | 240 | p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG, |
247 | PARPORT_DMA_NONE, &pp_amiga_ops); | 241 | PARPORT_DMA_NONE, &pp_amiga_ops); |
248 | if (!p) | 242 | if (!p) |
249 | goto out_port; | 243 | return -EBUSY; |
250 | 244 | ||
251 | err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, p); | 245 | err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, |
246 | p); | ||
252 | if (err) | 247 | if (err) |
253 | goto out_irq; | 248 | goto out_irq; |
254 | 249 | ||
255 | this_port = p; | ||
256 | printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); | 250 | printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); |
257 | /* XXX: set operating mode */ | 251 | /* XXX: set operating mode */ |
258 | parport_announce_port(p); | 252 | parport_announce_port(p); |
259 | 253 | ||
254 | platform_set_drvdata(pdev, p); | ||
255 | |||
260 | return 0; | 256 | return 0; |
261 | 257 | ||
262 | out_irq: | 258 | out_irq: |
263 | parport_put_port(p); | 259 | parport_put_port(p); |
264 | out_port: | ||
265 | release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); | ||
266 | out_mem: | ||
267 | return err; | 260 | return err; |
268 | } | 261 | } |
269 | 262 | ||
270 | static void __exit parport_amiga_exit(void) | 263 | static int __exit amiga_parallel_remove(struct platform_device *pdev) |
264 | { | ||
265 | struct parport *port = platform_get_drvdata(pdev); | ||
266 | |||
267 | parport_remove_port(port); | ||
268 | if (port->irq != PARPORT_IRQ_NONE) | ||
269 | free_irq(IRQ_AMIGA_CIAA_FLG, port); | ||
270 | parport_put_port(port); | ||
271 | platform_set_drvdata(pdev, NULL); | ||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | static struct platform_driver amiga_parallel_driver = { | ||
276 | .remove = __exit_p(amiga_parallel_remove), | ||
277 | .driver = { | ||
278 | .name = "amiga-parallel", | ||
279 | .owner = THIS_MODULE, | ||
280 | }, | ||
281 | }; | ||
282 | |||
283 | static int __init amiga_parallel_init(void) | ||
284 | { | ||
285 | return platform_driver_probe(&amiga_parallel_driver, | ||
286 | amiga_parallel_probe); | ||
287 | } | ||
288 | |||
289 | module_init(amiga_parallel_init); | ||
290 | |||
291 | static void __exit amiga_parallel_exit(void) | ||
271 | { | 292 | { |
272 | parport_remove_port(this_port); | 293 | platform_driver_unregister(&amiga_parallel_driver); |
273 | if (this_port->irq != PARPORT_IRQ_NONE) | ||
274 | free_irq(IRQ_AMIGA_CIAA_FLG, this_port); | ||
275 | parport_put_port(this_port); | ||
276 | release_mem_region(CIAA_PHYSADDR-1+0x100, 0x100); | ||
277 | } | 294 | } |
278 | 295 | ||
296 | module_exit(amiga_parallel_exit); | ||
279 | 297 | ||
280 | MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>"); | 298 | MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>"); |
281 | MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); | 299 | MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); |
282 | MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); | 300 | MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); |
283 | MODULE_LICENSE("GPL"); | 301 | MODULE_LICENSE("GPL"); |
284 | 302 | MODULE_ALIAS("platform:amiga-parallel"); | |
285 | module_init(parport_amiga_init) | ||
286 | module_exit(parport_amiga_exit) | ||
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig index c32822ad84a4..070211a5955c 100644 --- a/drivers/rapidio/Kconfig +++ b/drivers/rapidio/Kconfig | |||
@@ -8,3 +8,27 @@ config RAPIDIO_DISC_TIMEOUT | |||
8 | ---help--- | 8 | ---help--- |
9 | Amount of time a discovery node waits for a host to complete | 9 | Amount of time a discovery node waits for a host to complete |
10 | enumeration before giving up. | 10 | enumeration before giving up. |
11 | |||
12 | config RAPIDIO_ENABLE_RX_TX_PORTS | ||
13 | bool "Enable RapidIO Input/Output Ports" | ||
14 | depends on RAPIDIO | ||
15 | ---help--- | ||
16 | The RapidIO specification describes a Output port transmit | ||
17 | enable and a Input port receive enable. The recommended state | ||
18 | for Input ports and Output ports should be disabled. When | ||
19 | this switch is set the RapidIO subsystem will enable all | ||
20 | ports for Input/Output direction to allow other traffic | ||
21 | than Maintenance transfers. | ||
22 | |||
23 | source "drivers/rapidio/switches/Kconfig" | ||
24 | |||
25 | config RAPIDIO_DEBUG | ||
26 | bool "RapidIO subsystem debug messages" | ||
27 | depends on RAPIDIO | ||
28 | help | ||
29 | Say Y here if you want the RapidIO subsystem to produce a bunch of | ||
30 | debug messages to the system log. Select this if you are having a | ||
31 | problem with the RapidIO subsystem and want to see more of what is | ||
32 | going on. | ||
33 | |||
34 | If you are unsure about this, say N here. | ||
diff --git a/drivers/rapidio/Makefile b/drivers/rapidio/Makefile index 7c0e1818de51..b6139fe187bf 100644 --- a/drivers/rapidio/Makefile +++ b/drivers/rapidio/Makefile | |||
@@ -4,3 +4,7 @@ | |||
4 | obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o | 4 | obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o |
5 | 5 | ||
6 | obj-$(CONFIG_RAPIDIO) += switches/ | 6 | obj-$(CONFIG_RAPIDIO) += switches/ |
7 | |||
8 | ifeq ($(CONFIG_RAPIDIO_DEBUG),y) | ||
9 | EXTRA_CFLAGS += -DDEBUG | ||
10 | endif | ||
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 45415096c294..566432106cc5 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c | |||
@@ -4,6 +4,14 @@ | |||
4 | * Copyright 2005 MontaVista Software, Inc. | 4 | * Copyright 2005 MontaVista Software, Inc. |
5 | * Matt Porter <mporter@kernel.crashing.org> | 5 | * Matt Porter <mporter@kernel.crashing.org> |
6 | * | 6 | * |
7 | * Copyright 2009 Integrated Device Technology, Inc. | ||
8 | * Alex Bounine <alexandre.bounine@idt.com> | ||
9 | * - Added Port-Write/Error Management initialization and handling | ||
10 | * | ||
11 | * Copyright 2009 Sysgo AG | ||
12 | * Thomas Moll <thomas.moll@sysgo.com> | ||
13 | * - Added Input- Output- enable functionality, to allow full communication | ||
14 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | 15 | * This program is free software; you can redistribute it and/or modify it |
8 | * under the terms of the GNU General Public License as published by the | 16 | * under the terms of the GNU General Public License as published by the |
9 | * Free Software Foundation; either version 2 of the License, or (at your | 17 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -31,15 +39,16 @@ | |||
31 | LIST_HEAD(rio_devices); | 39 | LIST_HEAD(rio_devices); |
32 | static LIST_HEAD(rio_switches); | 40 | static LIST_HEAD(rio_switches); |
33 | 41 | ||
34 | #define RIO_ENUM_CMPL_MAGIC 0xdeadbeef | ||
35 | |||
36 | static void rio_enum_timeout(unsigned long); | 42 | static void rio_enum_timeout(unsigned long); |
37 | 43 | ||
44 | static void rio_init_em(struct rio_dev *rdev); | ||
45 | |||
38 | DEFINE_SPINLOCK(rio_global_list_lock); | 46 | DEFINE_SPINLOCK(rio_global_list_lock); |
39 | 47 | ||
40 | static int next_destid = 0; | 48 | static int next_destid = 0; |
41 | static int next_switchid = 0; | 49 | static int next_switchid = 0; |
42 | static int next_net = 0; | 50 | static int next_net = 0; |
51 | static int next_comptag; | ||
43 | 52 | ||
44 | static struct timer_list rio_enum_timer = | 53 | static struct timer_list rio_enum_timer = |
45 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); | 54 | TIMER_INITIALIZER(rio_enum_timeout, 0, 0); |
@@ -52,12 +61,6 @@ static int rio_mport_phys_table[] = { | |||
52 | -1, | 61 | -1, |
53 | }; | 62 | }; |
54 | 63 | ||
55 | static int rio_sport_phys_table[] = { | ||
56 | RIO_EFB_PAR_EP_FREE_ID, | ||
57 | RIO_EFB_SER_EP_FREE_ID, | ||
58 | -1, | ||
59 | }; | ||
60 | |||
61 | /** | 64 | /** |
62 | * rio_get_device_id - Get the base/extended device id for a device | 65 | * rio_get_device_id - Get the base/extended device id for a device |
63 | * @port: RIO master port | 66 | * @port: RIO master port |
@@ -118,12 +121,26 @@ static int rio_clear_locks(struct rio_mport *port) | |||
118 | u32 result; | 121 | u32 result; |
119 | int ret = 0; | 122 | int ret = 0; |
120 | 123 | ||
121 | /* Write component tag CSR magic complete value */ | 124 | /* Assign component tag to all devices */ |
122 | rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, | 125 | next_comptag = 1; |
123 | RIO_ENUM_CMPL_MAGIC); | 126 | rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR, next_comptag++); |
124 | list_for_each_entry(rdev, &rio_devices, global_list) | 127 | |
125 | rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, | 128 | list_for_each_entry(rdev, &rio_devices, global_list) { |
126 | RIO_ENUM_CMPL_MAGIC); | 129 | /* Mark device as discovered */ |
130 | rio_read_config_32(rdev, | ||
131 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
132 | &result); | ||
133 | rio_write_config_32(rdev, | ||
134 | rdev->phys_efptr + RIO_PORT_GEN_CTL_CSR, | ||
135 | result | RIO_PORT_GEN_DISCOVERED); | ||
136 | |||
137 | rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR, next_comptag); | ||
138 | rdev->comp_tag = next_comptag++; | ||
139 | if (next_comptag >= 0x10000) { | ||
140 | pr_err("RIO: Component Tag Counter Overflow\n"); | ||
141 | break; | ||
142 | } | ||
143 | } | ||
127 | 144 | ||
128 | /* Release host device id locks */ | 145 | /* Release host device id locks */ |
129 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, | 146 | rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR, |
@@ -229,27 +246,37 @@ static int rio_is_switch(struct rio_dev *rdev) | |||
229 | } | 246 | } |
230 | 247 | ||
231 | /** | 248 | /** |
232 | * rio_route_set_ops- Sets routing operations for a particular vendor switch | 249 | * rio_switch_init - Sets switch operations for a particular vendor switch |
233 | * @rdev: RIO device | 250 | * @rdev: RIO device |
251 | * @do_enum: Enumeration/Discovery mode flag | ||
234 | * | 252 | * |
235 | * Searches the RIO route ops table for known switch types. If the vid | 253 | * Searches the RIO switch ops table for known switch types. If the vid |
236 | * and did match a switch table entry, then set the add_entry() and | 254 | * and did match a switch table entry, then call switch initialization |
237 | * get_entry() ops to the table entry values. | 255 | * routine to setup switch-specific routines. |
238 | */ | 256 | */ |
239 | static void rio_route_set_ops(struct rio_dev *rdev) | 257 | static void rio_switch_init(struct rio_dev *rdev, int do_enum) |
240 | { | 258 | { |
241 | struct rio_route_ops *cur = __start_rio_route_ops; | 259 | struct rio_switch_ops *cur = __start_rio_switch_ops; |
242 | struct rio_route_ops *end = __end_rio_route_ops; | 260 | struct rio_switch_ops *end = __end_rio_switch_ops; |
243 | 261 | ||
244 | while (cur < end) { | 262 | while (cur < end) { |
245 | if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { | 263 | if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) { |
246 | pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev)); | 264 | pr_debug("RIO: calling init routine for %s\n", |
247 | rdev->rswitch->add_entry = cur->add_hook; | 265 | rio_name(rdev)); |
248 | rdev->rswitch->get_entry = cur->get_hook; | 266 | cur->init_hook(rdev, do_enum); |
267 | break; | ||
249 | } | 268 | } |
250 | cur++; | 269 | cur++; |
251 | } | 270 | } |
252 | 271 | ||
272 | if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) { | ||
273 | pr_debug("RIO: adding STD routing ops for %s\n", | ||
274 | rio_name(rdev)); | ||
275 | rdev->rswitch->add_entry = rio_std_route_add_entry; | ||
276 | rdev->rswitch->get_entry = rio_std_route_get_entry; | ||
277 | rdev->rswitch->clr_table = rio_std_route_clr_table; | ||
278 | } | ||
279 | |||
253 | if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) | 280 | if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) |
254 | printk(KERN_ERR "RIO: missing routing ops for %s\n", | 281 | printk(KERN_ERR "RIO: missing routing ops for %s\n", |
255 | rio_name(rdev)); | 282 | rio_name(rdev)); |
@@ -281,6 +308,65 @@ static int __devinit rio_add_device(struct rio_dev *rdev) | |||
281 | } | 308 | } |
282 | 309 | ||
283 | /** | 310 | /** |
311 | * rio_enable_rx_tx_port - enable input reciever and output transmitter of | ||
312 | * given port | ||
313 | * @port: Master port associated with the RIO network | ||
314 | * @local: local=1 select local port otherwise a far device is reached | ||
315 | * @destid: Destination ID of the device to check host bit | ||
316 | * @hopcount: Number of hops to reach the target | ||
317 | * @port_num: Port (-number on switch) to enable on a far end device | ||
318 | * | ||
319 | * Returns 0 or 1 from on General Control Command and Status Register | ||
320 | * (EXT_PTR+0x3C) | ||
321 | */ | ||
322 | inline int rio_enable_rx_tx_port(struct rio_mport *port, | ||
323 | int local, u16 destid, | ||
324 | u8 hopcount, u8 port_num) { | ||
325 | #ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS | ||
326 | u32 regval; | ||
327 | u32 ext_ftr_ptr; | ||
328 | |||
329 | /* | ||
330 | * enable rx input tx output port | ||
331 | */ | ||
332 | pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = " | ||
333 | "%d, port_num = %d)\n", local, destid, hopcount, port_num); | ||
334 | |||
335 | ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount); | ||
336 | |||
337 | if (local) { | ||
338 | rio_local_read_config_32(port, ext_ftr_ptr + | ||
339 | RIO_PORT_N_CTL_CSR(0), | ||
340 | ®val); | ||
341 | } else { | ||
342 | if (rio_mport_read_config_32(port, destid, hopcount, | ||
343 | ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), ®val) < 0) | ||
344 | return -EIO; | ||
345 | } | ||
346 | |||
347 | if (regval & RIO_PORT_N_CTL_P_TYP_SER) { | ||
348 | /* serial */ | ||
349 | regval = regval | RIO_PORT_N_CTL_EN_RX_SER | ||
350 | | RIO_PORT_N_CTL_EN_TX_SER; | ||
351 | } else { | ||
352 | /* parallel */ | ||
353 | regval = regval | RIO_PORT_N_CTL_EN_RX_PAR | ||
354 | | RIO_PORT_N_CTL_EN_TX_PAR; | ||
355 | } | ||
356 | |||
357 | if (local) { | ||
358 | rio_local_write_config_32(port, ext_ftr_ptr + | ||
359 | RIO_PORT_N_CTL_CSR(0), regval); | ||
360 | } else { | ||
361 | if (rio_mport_write_config_32(port, destid, hopcount, | ||
362 | ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0) | ||
363 | return -EIO; | ||
364 | } | ||
365 | #endif | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | /** | ||
284 | * rio_setup_device- Allocates and sets up a RIO device | 370 | * rio_setup_device- Allocates and sets up a RIO device |
285 | * @net: RIO network | 371 | * @net: RIO network |
286 | * @port: Master port to send transactions | 372 | * @port: Master port to send transactions |
@@ -325,8 +411,14 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
325 | rdev->asm_rev = result >> 16; | 411 | rdev->asm_rev = result >> 16; |
326 | rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, | 412 | rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR, |
327 | &rdev->pef); | 413 | &rdev->pef); |
328 | if (rdev->pef & RIO_PEF_EXT_FEATURES) | 414 | if (rdev->pef & RIO_PEF_EXT_FEATURES) { |
329 | rdev->efptr = result & 0xffff; | 415 | rdev->efptr = result & 0xffff; |
416 | rdev->phys_efptr = rio_mport_get_physefb(port, 0, destid, | ||
417 | hopcount); | ||
418 | |||
419 | rdev->em_efptr = rio_mport_get_feature(port, 0, destid, | ||
420 | hopcount, RIO_EFB_ERR_MGMNT); | ||
421 | } | ||
330 | 422 | ||
331 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, | 423 | rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR, |
332 | &rdev->src_ops); | 424 | &rdev->src_ops); |
@@ -349,12 +441,13 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
349 | if (rio_is_switch(rdev)) { | 441 | if (rio_is_switch(rdev)) { |
350 | rio_mport_read_config_32(port, destid, hopcount, | 442 | rio_mport_read_config_32(port, destid, hopcount, |
351 | RIO_SWP_INFO_CAR, &rdev->swpinfo); | 443 | RIO_SWP_INFO_CAR, &rdev->swpinfo); |
352 | rswitch = kmalloc(sizeof(struct rio_switch), GFP_KERNEL); | 444 | rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL); |
353 | if (!rswitch) | 445 | if (!rswitch) |
354 | goto cleanup; | 446 | goto cleanup; |
355 | rswitch->switchid = next_switchid; | 447 | rswitch->switchid = next_switchid; |
356 | rswitch->hopcount = hopcount; | 448 | rswitch->hopcount = hopcount; |
357 | rswitch->destid = destid; | 449 | rswitch->destid = destid; |
450 | rswitch->port_ok = 0; | ||
358 | rswitch->route_table = kzalloc(sizeof(u8)* | 451 | rswitch->route_table = kzalloc(sizeof(u8)* |
359 | RIO_MAX_ROUTE_ENTRIES(port->sys_size), | 452 | RIO_MAX_ROUTE_ENTRIES(port->sys_size), |
360 | GFP_KERNEL); | 453 | GFP_KERNEL); |
@@ -367,13 +460,22 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net, | |||
367 | rdev->rswitch = rswitch; | 460 | rdev->rswitch = rswitch; |
368 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, | 461 | dev_set_name(&rdev->dev, "%02x:s:%04x", rdev->net->id, |
369 | rdev->rswitch->switchid); | 462 | rdev->rswitch->switchid); |
370 | rio_route_set_ops(rdev); | 463 | rio_switch_init(rdev, do_enum); |
464 | |||
465 | if (do_enum && rdev->rswitch->clr_table) | ||
466 | rdev->rswitch->clr_table(port, destid, hopcount, | ||
467 | RIO_GLOBAL_TABLE); | ||
371 | 468 | ||
372 | list_add_tail(&rswitch->node, &rio_switches); | 469 | list_add_tail(&rswitch->node, &rio_switches); |
373 | 470 | ||
374 | } else | 471 | } else { |
472 | if (do_enum) | ||
473 | /*Enable Input Output Port (transmitter reviever)*/ | ||
474 | rio_enable_rx_tx_port(port, 0, destid, hopcount, 0); | ||
475 | |||
375 | dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id, | 476 | dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id, |
376 | rdev->destid); | 477 | rdev->destid); |
478 | } | ||
377 | 479 | ||
378 | rdev->dev.bus = &rio_bus_type; | 480 | rdev->dev.bus = &rio_bus_type; |
379 | 481 | ||
@@ -414,23 +516,29 @@ cleanup: | |||
414 | * | 516 | * |
415 | * Reads the port error status CSR for a particular switch port to | 517 | * Reads the port error status CSR for a particular switch port to |
416 | * determine if the port has an active link. Returns | 518 | * determine if the port has an active link. Returns |
417 | * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is | 519 | * %RIO_PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is |
418 | * inactive. | 520 | * inactive. |
419 | */ | 521 | */ |
420 | static int | 522 | static int |
421 | rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) | 523 | rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) |
422 | { | 524 | { |
423 | u32 result; | 525 | u32 result = 0; |
424 | u32 ext_ftr_ptr; | 526 | u32 ext_ftr_ptr; |
425 | 527 | ||
426 | int *entry = rio_sport_phys_table; | 528 | ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount, 0); |
427 | |||
428 | do { | ||
429 | if ((ext_ftr_ptr = | ||
430 | rio_mport_get_feature(port, 0, destid, hopcount, *entry))) | ||
431 | 529 | ||
530 | while (ext_ftr_ptr) { | ||
531 | rio_mport_read_config_32(port, destid, hopcount, | ||
532 | ext_ftr_ptr, &result); | ||
533 | result = RIO_GET_BLOCK_ID(result); | ||
534 | if ((result == RIO_EFB_SER_EP_FREE_ID) || | ||
535 | (result == RIO_EFB_SER_EP_FREE_ID_V13P) || | ||
536 | (result == RIO_EFB_SER_EP_FREC_ID)) | ||
432 | break; | 537 | break; |
433 | } while (*++entry >= 0); | 538 | |
539 | ext_ftr_ptr = rio_mport_get_efb(port, 0, destid, hopcount, | ||
540 | ext_ftr_ptr); | ||
541 | } | ||
434 | 542 | ||
435 | if (ext_ftr_ptr) | 543 | if (ext_ftr_ptr) |
436 | rio_mport_read_config_32(port, destid, hopcount, | 544 | rio_mport_read_config_32(port, destid, hopcount, |
@@ -438,7 +546,81 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) | |||
438 | RIO_PORT_N_ERR_STS_CSR(sport), | 546 | RIO_PORT_N_ERR_STS_CSR(sport), |
439 | &result); | 547 | &result); |
440 | 548 | ||
441 | return (result & PORT_N_ERR_STS_PORT_OK); | 549 | return result & RIO_PORT_N_ERR_STS_PORT_OK; |
550 | } | ||
551 | |||
552 | /** | ||
553 | * rio_lock_device - Acquires host device lock for specified device | ||
554 | * @port: Master port to send transaction | ||
555 | * @destid: Destination ID for device/switch | ||
556 | * @hopcount: Hopcount to reach switch | ||
557 | * @wait_ms: Max wait time in msec (0 = no timeout) | ||
558 | * | ||
559 | * Attepts to acquire host device lock for specified device | ||
560 | * Returns 0 if device lock acquired or EINVAL if timeout expires. | ||
561 | */ | ||
562 | static int | ||
563 | rio_lock_device(struct rio_mport *port, u16 destid, u8 hopcount, int wait_ms) | ||
564 | { | ||
565 | u32 result; | ||
566 | int tcnt = 0; | ||
567 | |||
568 | /* Attempt to acquire device lock */ | ||
569 | rio_mport_write_config_32(port, destid, hopcount, | ||
570 | RIO_HOST_DID_LOCK_CSR, port->host_deviceid); | ||
571 | rio_mport_read_config_32(port, destid, hopcount, | ||
572 | RIO_HOST_DID_LOCK_CSR, &result); | ||
573 | |||
574 | while (result != port->host_deviceid) { | ||
575 | if (wait_ms != 0 && tcnt == wait_ms) { | ||
576 | pr_debug("RIO: timeout when locking device %x:%x\n", | ||
577 | destid, hopcount); | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | /* Delay a bit */ | ||
582 | mdelay(1); | ||
583 | tcnt++; | ||
584 | /* Try to acquire device lock again */ | ||
585 | rio_mport_write_config_32(port, destid, | ||
586 | hopcount, | ||
587 | RIO_HOST_DID_LOCK_CSR, | ||
588 | port->host_deviceid); | ||
589 | rio_mport_read_config_32(port, destid, | ||
590 | hopcount, | ||
591 | RIO_HOST_DID_LOCK_CSR, &result); | ||
592 | } | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | |||
597 | /** | ||
598 | * rio_unlock_device - Releases host device lock for specified device | ||
599 | * @port: Master port to send transaction | ||
600 | * @destid: Destination ID for device/switch | ||
601 | * @hopcount: Hopcount to reach switch | ||
602 | * | ||
603 | * Returns 0 if device lock released or EINVAL if fails. | ||
604 | */ | ||
605 | static int | ||
606 | rio_unlock_device(struct rio_mport *port, u16 destid, u8 hopcount) | ||
607 | { | ||
608 | u32 result; | ||
609 | |||
610 | /* Release device lock */ | ||
611 | rio_mport_write_config_32(port, destid, | ||
612 | hopcount, | ||
613 | RIO_HOST_DID_LOCK_CSR, | ||
614 | port->host_deviceid); | ||
615 | rio_mport_read_config_32(port, destid, hopcount, | ||
616 | RIO_HOST_DID_LOCK_CSR, &result); | ||
617 | if ((result & 0xffff) != 0xffff) { | ||
618 | pr_debug("RIO: badness when releasing device lock %x:%x\n", | ||
619 | destid, hopcount); | ||
620 | return -EINVAL; | ||
621 | } | ||
622 | |||
623 | return 0; | ||
442 | } | 624 | } |
443 | 625 | ||
444 | /** | 626 | /** |
@@ -448,6 +630,7 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) | |||
448 | * @table: Routing table ID | 630 | * @table: Routing table ID |
449 | * @route_destid: Destination ID to be routed | 631 | * @route_destid: Destination ID to be routed |
450 | * @route_port: Port number to be routed | 632 | * @route_port: Port number to be routed |
633 | * @lock: lock switch device flag | ||
451 | * | 634 | * |
452 | * Calls the switch specific add_entry() method to add a route entry | 635 | * Calls the switch specific add_entry() method to add a route entry |
453 | * on a switch. The route table can be specified using the @table | 636 | * on a switch. The route table can be specified using the @table |
@@ -456,12 +639,26 @@ rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int sport) | |||
456 | * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL | 639 | * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL |
457 | * on failure. | 640 | * on failure. |
458 | */ | 641 | */ |
459 | static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, | 642 | static int |
460 | u16 table, u16 route_destid, u8 route_port) | 643 | rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswitch, |
644 | u16 table, u16 route_destid, u8 route_port, int lock) | ||
461 | { | 645 | { |
462 | return rswitch->add_entry(mport, rswitch->destid, | 646 | int rc; |
647 | |||
648 | if (lock) { | ||
649 | rc = rio_lock_device(mport, rswitch->destid, | ||
650 | rswitch->hopcount, 1000); | ||
651 | if (rc) | ||
652 | return rc; | ||
653 | } | ||
654 | |||
655 | rc = rswitch->add_entry(mport, rswitch->destid, | ||
463 | rswitch->hopcount, table, | 656 | rswitch->hopcount, table, |
464 | route_destid, route_port); | 657 | route_destid, route_port); |
658 | if (lock) | ||
659 | rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); | ||
660 | |||
661 | return rc; | ||
465 | } | 662 | } |
466 | 663 | ||
467 | /** | 664 | /** |
@@ -471,6 +668,7 @@ static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswit | |||
471 | * @table: Routing table ID | 668 | * @table: Routing table ID |
472 | * @route_destid: Destination ID to be routed | 669 | * @route_destid: Destination ID to be routed |
473 | * @route_port: Pointer to read port number into | 670 | * @route_port: Pointer to read port number into |
671 | * @lock: lock switch device flag | ||
474 | * | 672 | * |
475 | * Calls the switch specific get_entry() method to read a route entry | 673 | * Calls the switch specific get_entry() method to read a route entry |
476 | * in a switch. The route table can be specified using the @table | 674 | * in a switch. The route table can be specified using the @table |
@@ -481,11 +679,24 @@ static int rio_route_add_entry(struct rio_mport *mport, struct rio_switch *rswit | |||
481 | */ | 679 | */ |
482 | static int | 680 | static int |
483 | rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, | 681 | rio_route_get_entry(struct rio_mport *mport, struct rio_switch *rswitch, u16 table, |
484 | u16 route_destid, u8 * route_port) | 682 | u16 route_destid, u8 *route_port, int lock) |
485 | { | 683 | { |
486 | return rswitch->get_entry(mport, rswitch->destid, | 684 | int rc; |
685 | |||
686 | if (lock) { | ||
687 | rc = rio_lock_device(mport, rswitch->destid, | ||
688 | rswitch->hopcount, 1000); | ||
689 | if (rc) | ||
690 | return rc; | ||
691 | } | ||
692 | |||
693 | rc = rswitch->get_entry(mport, rswitch->destid, | ||
487 | rswitch->hopcount, table, | 694 | rswitch->hopcount, table, |
488 | route_destid, route_port); | 695 | route_destid, route_port); |
696 | if (lock) | ||
697 | rio_unlock_device(mport, rswitch->destid, rswitch->hopcount); | ||
698 | |||
699 | return rc; | ||
489 | } | 700 | } |
490 | 701 | ||
491 | /** | 702 | /** |
@@ -625,14 +836,14 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
625 | sw_inport = rio_get_swpinfo_inport(port, | 836 | sw_inport = rio_get_swpinfo_inport(port, |
626 | RIO_ANY_DESTID(port->sys_size), hopcount); | 837 | RIO_ANY_DESTID(port->sys_size), hopcount); |
627 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, | 838 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, |
628 | port->host_deviceid, sw_inport); | 839 | port->host_deviceid, sw_inport, 0); |
629 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; | 840 | rdev->rswitch->route_table[port->host_deviceid] = sw_inport; |
630 | 841 | ||
631 | for (destid = 0; destid < next_destid; destid++) { | 842 | for (destid = 0; destid < next_destid; destid++) { |
632 | if (destid == port->host_deviceid) | 843 | if (destid == port->host_deviceid) |
633 | continue; | 844 | continue; |
634 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, | 845 | rio_route_add_entry(port, rdev->rswitch, RIO_GLOBAL_TABLE, |
635 | destid, sw_inport); | 846 | destid, sw_inport, 0); |
636 | rdev->rswitch->route_table[destid] = sw_inport; | 847 | rdev->rswitch->route_table[destid] = sw_inport; |
637 | } | 848 | } |
638 | 849 | ||
@@ -644,8 +855,15 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
644 | rio_name(rdev), rdev->vid, rdev->did, num_ports); | 855 | rio_name(rdev), rdev->vid, rdev->did, num_ports); |
645 | sw_destid = next_destid; | 856 | sw_destid = next_destid; |
646 | for (port_num = 0; port_num < num_ports; port_num++) { | 857 | for (port_num = 0; port_num < num_ports; port_num++) { |
647 | if (sw_inport == port_num) | 858 | /*Enable Input Output Port (transmitter reviever)*/ |
859 | rio_enable_rx_tx_port(port, 0, | ||
860 | RIO_ANY_DESTID(port->sys_size), | ||
861 | hopcount, port_num); | ||
862 | |||
863 | if (sw_inport == port_num) { | ||
864 | rdev->rswitch->port_ok |= (1 << port_num); | ||
648 | continue; | 865 | continue; |
866 | } | ||
649 | 867 | ||
650 | cur_destid = next_destid; | 868 | cur_destid = next_destid; |
651 | 869 | ||
@@ -655,10 +873,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
655 | pr_debug( | 873 | pr_debug( |
656 | "RIO: scanning device on port %d\n", | 874 | "RIO: scanning device on port %d\n", |
657 | port_num); | 875 | port_num); |
876 | rdev->rswitch->port_ok |= (1 << port_num); | ||
658 | rio_route_add_entry(port, rdev->rswitch, | 877 | rio_route_add_entry(port, rdev->rswitch, |
659 | RIO_GLOBAL_TABLE, | 878 | RIO_GLOBAL_TABLE, |
660 | RIO_ANY_DESTID(port->sys_size), | 879 | RIO_ANY_DESTID(port->sys_size), |
661 | port_num); | 880 | port_num, 0); |
662 | 881 | ||
663 | if (rio_enum_peer(net, port, hopcount + 1) < 0) | 882 | if (rio_enum_peer(net, port, hopcount + 1) < 0) |
664 | return -1; | 883 | return -1; |
@@ -672,15 +891,35 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
672 | rio_route_add_entry(port, rdev->rswitch, | 891 | rio_route_add_entry(port, rdev->rswitch, |
673 | RIO_GLOBAL_TABLE, | 892 | RIO_GLOBAL_TABLE, |
674 | destid, | 893 | destid, |
675 | port_num); | 894 | port_num, |
895 | 0); | ||
676 | rdev->rswitch-> | 896 | rdev->rswitch-> |
677 | route_table[destid] = | 897 | route_table[destid] = |
678 | port_num; | 898 | port_num; |
679 | } | 899 | } |
680 | } | 900 | } |
901 | } else { | ||
902 | /* If switch supports Error Management, | ||
903 | * set PORT_LOCKOUT bit for unused port | ||
904 | */ | ||
905 | if (rdev->em_efptr) | ||
906 | rio_set_port_lockout(rdev, port_num, 1); | ||
907 | |||
908 | rdev->rswitch->port_ok &= ~(1 << port_num); | ||
681 | } | 909 | } |
682 | } | 910 | } |
683 | 911 | ||
912 | /* Direct Port-write messages to the enumeratiing host */ | ||
913 | if ((rdev->src_ops & RIO_SRC_OPS_PORT_WRITE) && | ||
914 | (rdev->em_efptr)) { | ||
915 | rio_write_config_32(rdev, | ||
916 | rdev->em_efptr + RIO_EM_PW_TGT_DEVID, | ||
917 | (port->host_deviceid << 16) | | ||
918 | (port->sys_size << 15)); | ||
919 | } | ||
920 | |||
921 | rio_init_em(rdev); | ||
922 | |||
684 | /* Check for empty switch */ | 923 | /* Check for empty switch */ |
685 | if (next_destid == sw_destid) { | 924 | if (next_destid == sw_destid) { |
686 | next_destid++; | 925 | next_destid++; |
@@ -700,21 +939,16 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port, | |||
700 | * rio_enum_complete- Tests if enumeration of a network is complete | 939 | * rio_enum_complete- Tests if enumeration of a network is complete |
701 | * @port: Master port to send transaction | 940 | * @port: Master port to send transaction |
702 | * | 941 | * |
703 | * Tests the Component Tag CSR for presence of the magic enumeration | 942 | * Tests the Component Tag CSR for non-zero value (enumeration |
704 | * complete flag. Return %1 if enumeration is complete or %0 if | 943 | * complete flag). Return %1 if enumeration is complete or %0 if |
705 | * enumeration is incomplete. | 944 | * enumeration is incomplete. |
706 | */ | 945 | */ |
707 | static int rio_enum_complete(struct rio_mport *port) | 946 | static int rio_enum_complete(struct rio_mport *port) |
708 | { | 947 | { |
709 | u32 tag_csr; | 948 | u32 tag_csr; |
710 | int ret = 0; | ||
711 | 949 | ||
712 | rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); | 950 | rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr); |
713 | 951 | return (tag_csr & 0xffff) ? 1 : 0; | |
714 | if (tag_csr == RIO_ENUM_CMPL_MAGIC) | ||
715 | ret = 1; | ||
716 | |||
717 | return ret; | ||
718 | } | 952 | } |
719 | 953 | ||
720 | /** | 954 | /** |
@@ -763,17 +997,21 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
763 | pr_debug( | 997 | pr_debug( |
764 | "RIO: scanning device on port %d\n", | 998 | "RIO: scanning device on port %d\n", |
765 | port_num); | 999 | port_num); |
1000 | |||
1001 | rio_lock_device(port, destid, hopcount, 1000); | ||
1002 | |||
766 | for (ndestid = 0; | 1003 | for (ndestid = 0; |
767 | ndestid < RIO_ANY_DESTID(port->sys_size); | 1004 | ndestid < RIO_ANY_DESTID(port->sys_size); |
768 | ndestid++) { | 1005 | ndestid++) { |
769 | rio_route_get_entry(port, rdev->rswitch, | 1006 | rio_route_get_entry(port, rdev->rswitch, |
770 | RIO_GLOBAL_TABLE, | 1007 | RIO_GLOBAL_TABLE, |
771 | ndestid, | 1008 | ndestid, |
772 | &route_port); | 1009 | &route_port, 0); |
773 | if (route_port == port_num) | 1010 | if (route_port == port_num) |
774 | break; | 1011 | break; |
775 | } | 1012 | } |
776 | 1013 | ||
1014 | rio_unlock_device(port, destid, hopcount); | ||
777 | if (rio_disc_peer | 1015 | if (rio_disc_peer |
778 | (net, port, ndestid, hopcount + 1) < 0) | 1016 | (net, port, ndestid, hopcount + 1) < 0) |
779 | return -1; | 1017 | return -1; |
@@ -792,7 +1030,7 @@ rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid, | |||
792 | * | 1030 | * |
793 | * Reads the port error status CSR for the master port to | 1031 | * Reads the port error status CSR for the master port to |
794 | * determine if the port has an active link. Returns | 1032 | * determine if the port has an active link. Returns |
795 | * %PORT_N_ERR_STS_PORT_OK if the master port is active | 1033 | * %RIO_PORT_N_ERR_STS_PORT_OK if the master port is active |
796 | * or %0 if it is inactive. | 1034 | * or %0 if it is inactive. |
797 | */ | 1035 | */ |
798 | static int rio_mport_is_active(struct rio_mport *port) | 1036 | static int rio_mport_is_active(struct rio_mport *port) |
@@ -813,7 +1051,7 @@ static int rio_mport_is_active(struct rio_mport *port) | |||
813 | RIO_PORT_N_ERR_STS_CSR(port->index), | 1051 | RIO_PORT_N_ERR_STS_CSR(port->index), |
814 | &result); | 1052 | &result); |
815 | 1053 | ||
816 | return (result & PORT_N_ERR_STS_PORT_OK); | 1054 | return result & RIO_PORT_N_ERR_STS_PORT_OK; |
817 | } | 1055 | } |
818 | 1056 | ||
819 | /** | 1057 | /** |
@@ -866,12 +1104,17 @@ static void rio_update_route_tables(struct rio_mport *port) | |||
866 | continue; | 1104 | continue; |
867 | 1105 | ||
868 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { | 1106 | if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { |
1107 | /* Skip if destid ends in empty switch*/ | ||
1108 | if (rswitch->destid == destid) | ||
1109 | continue; | ||
869 | 1110 | ||
870 | sport = rio_get_swpinfo_inport(port, | 1111 | sport = rio_get_swpinfo_inport(port, |
871 | rswitch->destid, rswitch->hopcount); | 1112 | rswitch->destid, rswitch->hopcount); |
872 | 1113 | ||
873 | if (rswitch->add_entry) { | 1114 | if (rswitch->add_entry) { |
874 | rio_route_add_entry(port, rswitch, RIO_GLOBAL_TABLE, destid, sport); | 1115 | rio_route_add_entry(port, rswitch, |
1116 | RIO_GLOBAL_TABLE, destid, | ||
1117 | sport, 0); | ||
875 | rswitch->route_table[destid] = sport; | 1118 | rswitch->route_table[destid] = sport; |
876 | } | 1119 | } |
877 | } | 1120 | } |
@@ -880,6 +1123,32 @@ static void rio_update_route_tables(struct rio_mport *port) | |||
880 | } | 1123 | } |
881 | 1124 | ||
882 | /** | 1125 | /** |
1126 | * rio_init_em - Initializes RIO Error Management (for switches) | ||
1127 | * @port: Master port associated with the RIO network | ||
1128 | * | ||
1129 | * For each enumerated switch, call device-specific error management | ||
1130 | * initialization routine (if supplied by the switch driver). | ||
1131 | */ | ||
1132 | static void rio_init_em(struct rio_dev *rdev) | ||
1133 | { | ||
1134 | if (rio_is_switch(rdev) && (rdev->em_efptr) && | ||
1135 | (rdev->rswitch->em_init)) { | ||
1136 | rdev->rswitch->em_init(rdev); | ||
1137 | } | ||
1138 | } | ||
1139 | |||
1140 | /** | ||
1141 | * rio_pw_enable - Enables/disables port-write handling by a master port | ||
1142 | * @port: Master port associated with port-write handling | ||
1143 | * @enable: 1=enable, 0=disable | ||
1144 | */ | ||
1145 | static void rio_pw_enable(struct rio_mport *port, int enable) | ||
1146 | { | ||
1147 | if (port->ops->pwenable) | ||
1148 | port->ops->pwenable(port, enable); | ||
1149 | } | ||
1150 | |||
1151 | /** | ||
883 | * rio_enum_mport- Start enumeration through a master port | 1152 | * rio_enum_mport- Start enumeration through a master port |
884 | * @mport: Master port to send transactions | 1153 | * @mport: Master port to send transactions |
885 | * | 1154 | * |
@@ -911,6 +1180,10 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
911 | rc = -ENOMEM; | 1180 | rc = -ENOMEM; |
912 | goto out; | 1181 | goto out; |
913 | } | 1182 | } |
1183 | |||
1184 | /* Enable Input Output Port (transmitter reviever) */ | ||
1185 | rio_enable_rx_tx_port(mport, 1, 0, 0, 0); | ||
1186 | |||
914 | if (rio_enum_peer(net, mport, 0) < 0) { | 1187 | if (rio_enum_peer(net, mport, 0) < 0) { |
915 | /* A higher priority host won enumeration, bail. */ | 1188 | /* A higher priority host won enumeration, bail. */ |
916 | printk(KERN_INFO | 1189 | printk(KERN_INFO |
@@ -922,6 +1195,7 @@ int __devinit rio_enum_mport(struct rio_mport *mport) | |||
922 | } | 1195 | } |
923 | rio_update_route_tables(mport); | 1196 | rio_update_route_tables(mport); |
924 | rio_clear_locks(mport); | 1197 | rio_clear_locks(mport); |
1198 | rio_pw_enable(mport, 1); | ||
925 | } else { | 1199 | } else { |
926 | printk(KERN_INFO "RIO: master port %d link inactive\n", | 1200 | printk(KERN_INFO "RIO: master port %d link inactive\n", |
927 | mport->id); | 1201 | mport->id); |
@@ -945,15 +1219,22 @@ static void rio_build_route_tables(void) | |||
945 | u8 sport; | 1219 | u8 sport; |
946 | 1220 | ||
947 | list_for_each_entry(rdev, &rio_devices, global_list) | 1221 | list_for_each_entry(rdev, &rio_devices, global_list) |
948 | if (rio_is_switch(rdev)) | 1222 | if (rio_is_switch(rdev)) { |
949 | for (i = 0; | 1223 | rio_lock_device(rdev->net->hport, rdev->rswitch->destid, |
950 | i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); | 1224 | rdev->rswitch->hopcount, 1000); |
951 | i++) { | 1225 | for (i = 0; |
952 | if (rio_route_get_entry | 1226 | i < RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size); |
953 | (rdev->net->hport, rdev->rswitch, RIO_GLOBAL_TABLE, | 1227 | i++) { |
954 | i, &sport) < 0) | 1228 | if (rio_route_get_entry |
955 | continue; | 1229 | (rdev->net->hport, rdev->rswitch, |
956 | rdev->rswitch->route_table[i] = sport; | 1230 | RIO_GLOBAL_TABLE, i, &sport, 0) < 0) |
1231 | continue; | ||
1232 | rdev->rswitch->route_table[i] = sport; | ||
1233 | } | ||
1234 | |||
1235 | rio_unlock_device(rdev->net->hport, | ||
1236 | rdev->rswitch->destid, | ||
1237 | rdev->rswitch->hopcount); | ||
957 | } | 1238 | } |
958 | } | 1239 | } |
959 | 1240 | ||
@@ -1012,6 +1293,13 @@ int __devinit rio_disc_mport(struct rio_mport *mport) | |||
1012 | del_timer_sync(&rio_enum_timer); | 1293 | del_timer_sync(&rio_enum_timer); |
1013 | 1294 | ||
1014 | pr_debug("done\n"); | 1295 | pr_debug("done\n"); |
1296 | |||
1297 | /* Read DestID assigned by enumerator */ | ||
1298 | rio_local_read_config_32(mport, RIO_DID_CSR, | ||
1299 | &mport->host_deviceid); | ||
1300 | mport->host_deviceid = RIO_GET_DID(mport->sys_size, | ||
1301 | mport->host_deviceid); | ||
1302 | |||
1015 | if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), | 1303 | if (rio_disc_peer(net, mport, RIO_ANY_DESTID(mport->sys_size), |
1016 | 0) < 0) { | 1304 | 0) < 0) { |
1017 | printk(KERN_INFO | 1305 | printk(KERN_INFO |
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index 6395c780008b..777e099a3d8f 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c | |||
@@ -5,6 +5,10 @@ | |||
5 | * Copyright 2005 MontaVista Software, Inc. | 5 | * Copyright 2005 MontaVista Software, Inc. |
6 | * Matt Porter <mporter@kernel.crashing.org> | 6 | * Matt Porter <mporter@kernel.crashing.org> |
7 | * | 7 | * |
8 | * Copyright 2009 Integrated Device Technology, Inc. | ||
9 | * Alex Bounine <alexandre.bounine@idt.com> | ||
10 | * - Added Port-Write/Error Management initialization and handling | ||
11 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | 12 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 13 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation; either version 2 of the License, or (at your | 14 | * Free Software Foundation; either version 2 of the License, or (at your |
@@ -333,6 +337,328 @@ int rio_release_outb_dbell(struct rio_dev *rdev, struct resource *res) | |||
333 | } | 337 | } |
334 | 338 | ||
335 | /** | 339 | /** |
340 | * rio_request_inb_pwrite - request inbound port-write message service | ||
341 | * @mport: RIO device to which register inbound port-write callback routine | ||
342 | * @pwcback: Callback routine to execute when port-write is received | ||
343 | * | ||
344 | * Binds a port-write callback function to the RapidIO device. | ||
345 | * Returns 0 if the request has been satisfied. | ||
346 | */ | ||
347 | int rio_request_inb_pwrite(struct rio_dev *rdev, | ||
348 | int (*pwcback)(struct rio_dev *rdev, union rio_pw_msg *msg, int step)) | ||
349 | { | ||
350 | int rc = 0; | ||
351 | |||
352 | spin_lock(&rio_global_list_lock); | ||
353 | if (rdev->pwcback != NULL) | ||
354 | rc = -ENOMEM; | ||
355 | else | ||
356 | rdev->pwcback = pwcback; | ||
357 | |||
358 | spin_unlock(&rio_global_list_lock); | ||
359 | return rc; | ||
360 | } | ||
361 | EXPORT_SYMBOL_GPL(rio_request_inb_pwrite); | ||
362 | |||
363 | /** | ||
364 | * rio_release_inb_pwrite - release inbound port-write message service | ||
365 | * @rdev: RIO device which registered for inbound port-write callback | ||
366 | * | ||
367 | * Removes callback from the rio_dev structure. Returns 0 if the request | ||
368 | * has been satisfied. | ||
369 | */ | ||
370 | int rio_release_inb_pwrite(struct rio_dev *rdev) | ||
371 | { | ||
372 | int rc = -ENOMEM; | ||
373 | |||
374 | spin_lock(&rio_global_list_lock); | ||
375 | if (rdev->pwcback) { | ||
376 | rdev->pwcback = NULL; | ||
377 | rc = 0; | ||
378 | } | ||
379 | |||
380 | spin_unlock(&rio_global_list_lock); | ||
381 | return rc; | ||
382 | } | ||
383 | EXPORT_SYMBOL_GPL(rio_release_inb_pwrite); | ||
384 | |||
385 | /** | ||
386 | * rio_mport_get_physefb - Helper function that returns register offset | ||
387 | * for Physical Layer Extended Features Block. | ||
388 | * @rdev: RIO device | ||
389 | */ | ||
390 | u32 | ||
391 | rio_mport_get_physefb(struct rio_mport *port, int local, | ||
392 | u16 destid, u8 hopcount) | ||
393 | { | ||
394 | u32 ext_ftr_ptr; | ||
395 | u32 ftr_header; | ||
396 | |||
397 | ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, 0); | ||
398 | |||
399 | while (ext_ftr_ptr) { | ||
400 | if (local) | ||
401 | rio_local_read_config_32(port, ext_ftr_ptr, | ||
402 | &ftr_header); | ||
403 | else | ||
404 | rio_mport_read_config_32(port, destid, hopcount, | ||
405 | ext_ftr_ptr, &ftr_header); | ||
406 | |||
407 | ftr_header = RIO_GET_BLOCK_ID(ftr_header); | ||
408 | switch (ftr_header) { | ||
409 | |||
410 | case RIO_EFB_SER_EP_ID_V13P: | ||
411 | case RIO_EFB_SER_EP_REC_ID_V13P: | ||
412 | case RIO_EFB_SER_EP_FREE_ID_V13P: | ||
413 | case RIO_EFB_SER_EP_ID: | ||
414 | case RIO_EFB_SER_EP_REC_ID: | ||
415 | case RIO_EFB_SER_EP_FREE_ID: | ||
416 | case RIO_EFB_SER_EP_FREC_ID: | ||
417 | |||
418 | return ext_ftr_ptr; | ||
419 | |||
420 | default: | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | ext_ftr_ptr = rio_mport_get_efb(port, local, destid, | ||
425 | hopcount, ext_ftr_ptr); | ||
426 | } | ||
427 | |||
428 | return ext_ftr_ptr; | ||
429 | } | ||
430 | |||
431 | /** | ||
432 | * rio_get_comptag - Begin or continue searching for a RIO device by component tag | ||
433 | * @comp_tag: RIO component tad to match | ||
434 | * @from: Previous RIO device found in search, or %NULL for new search | ||
435 | * | ||
436 | * Iterates through the list of known RIO devices. If a RIO device is | ||
437 | * found with a matching @comp_tag, a pointer to its device | ||
438 | * structure is returned. Otherwise, %NULL is returned. A new search | ||
439 | * is initiated by passing %NULL to the @from argument. Otherwise, if | ||
440 | * @from is not %NULL, searches continue from next device on the global | ||
441 | * list. | ||
442 | */ | ||
443 | static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from) | ||
444 | { | ||
445 | struct list_head *n; | ||
446 | struct rio_dev *rdev; | ||
447 | |||
448 | spin_lock(&rio_global_list_lock); | ||
449 | n = from ? from->global_list.next : rio_devices.next; | ||
450 | |||
451 | while (n && (n != &rio_devices)) { | ||
452 | rdev = rio_dev_g(n); | ||
453 | if (rdev->comp_tag == comp_tag) | ||
454 | goto exit; | ||
455 | n = n->next; | ||
456 | } | ||
457 | rdev = NULL; | ||
458 | exit: | ||
459 | spin_unlock(&rio_global_list_lock); | ||
460 | return rdev; | ||
461 | } | ||
462 | |||
463 | /** | ||
464 | * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port. | ||
465 | * @rdev: Pointer to RIO device control structure | ||
466 | * @pnum: Switch port number to set LOCKOUT bit | ||
467 | * @lock: Operation : set (=1) or clear (=0) | ||
468 | */ | ||
469 | int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) | ||
470 | { | ||
471 | u8 hopcount = 0xff; | ||
472 | u16 destid = rdev->destid; | ||
473 | u32 regval; | ||
474 | |||
475 | if (rdev->rswitch) { | ||
476 | destid = rdev->rswitch->destid; | ||
477 | hopcount = rdev->rswitch->hopcount; | ||
478 | } | ||
479 | |||
480 | rio_mport_read_config_32(rdev->net->hport, destid, hopcount, | ||
481 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), | ||
482 | ®val); | ||
483 | if (lock) | ||
484 | regval |= RIO_PORT_N_CTL_LOCKOUT; | ||
485 | else | ||
486 | regval &= ~RIO_PORT_N_CTL_LOCKOUT; | ||
487 | |||
488 | rio_mport_write_config_32(rdev->net->hport, destid, hopcount, | ||
489 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), | ||
490 | regval); | ||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | /** | ||
495 | * rio_inb_pwrite_handler - process inbound port-write message | ||
496 | * @pw_msg: pointer to inbound port-write message | ||
497 | * | ||
498 | * Processes an inbound port-write message. Returns 0 if the request | ||
499 | * has been satisfied. | ||
500 | */ | ||
501 | int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | ||
502 | { | ||
503 | struct rio_dev *rdev; | ||
504 | struct rio_mport *mport; | ||
505 | u8 hopcount; | ||
506 | u16 destid; | ||
507 | u32 err_status; | ||
508 | int rc, portnum; | ||
509 | |||
510 | rdev = rio_get_comptag(pw_msg->em.comptag, NULL); | ||
511 | if (rdev == NULL) { | ||
512 | /* Someting bad here (probably enumeration error) */ | ||
513 | pr_err("RIO: %s No matching device for CTag 0x%08x\n", | ||
514 | __func__, pw_msg->em.comptag); | ||
515 | return -EIO; | ||
516 | } | ||
517 | |||
518 | pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev)); | ||
519 | |||
520 | #ifdef DEBUG_PW | ||
521 | { | ||
522 | u32 i; | ||
523 | for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) { | ||
524 | pr_debug("0x%02x: %08x %08x %08x %08x", | ||
525 | i*4, pw_msg->raw[i], pw_msg->raw[i + 1], | ||
526 | pw_msg->raw[i + 2], pw_msg->raw[i + 3]); | ||
527 | i += 4; | ||
528 | } | ||
529 | pr_debug("\n"); | ||
530 | } | ||
531 | #endif | ||
532 | |||
533 | /* Call an external service function (if such is registered | ||
534 | * for this device). This may be the service for endpoints that send | ||
535 | * device-specific port-write messages. End-point messages expected | ||
536 | * to be handled completely by EP specific device driver. | ||
537 | * For switches rc==0 signals that no standard processing required. | ||
538 | */ | ||
539 | if (rdev->pwcback != NULL) { | ||
540 | rc = rdev->pwcback(rdev, pw_msg, 0); | ||
541 | if (rc == 0) | ||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | /* For End-point devices processing stops here */ | ||
546 | if (!(rdev->pef & RIO_PEF_SWITCH)) | ||
547 | return 0; | ||
548 | |||
549 | if (rdev->phys_efptr == 0) { | ||
550 | pr_err("RIO_PW: Bad switch initialization for %s\n", | ||
551 | rio_name(rdev)); | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | mport = rdev->net->hport; | ||
556 | destid = rdev->rswitch->destid; | ||
557 | hopcount = rdev->rswitch->hopcount; | ||
558 | |||
559 | /* | ||
560 | * Process the port-write notification from switch | ||
561 | */ | ||
562 | |||
563 | portnum = pw_msg->em.is_port & 0xFF; | ||
564 | |||
565 | if (rdev->rswitch->em_handle) | ||
566 | rdev->rswitch->em_handle(rdev, portnum); | ||
567 | |||
568 | rio_mport_read_config_32(mport, destid, hopcount, | ||
569 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | ||
570 | &err_status); | ||
571 | pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status); | ||
572 | |||
573 | if (pw_msg->em.errdetect) { | ||
574 | pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n", | ||
575 | portnum, pw_msg->em.errdetect); | ||
576 | /* Clear EM Port N Error Detect CSR */ | ||
577 | rio_mport_write_config_32(mport, destid, hopcount, | ||
578 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0); | ||
579 | } | ||
580 | |||
581 | if (pw_msg->em.ltlerrdet) { | ||
582 | pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n", | ||
583 | pw_msg->em.ltlerrdet); | ||
584 | /* Clear EM L/T Layer Error Detect CSR */ | ||
585 | rio_mport_write_config_32(mport, destid, hopcount, | ||
586 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0); | ||
587 | } | ||
588 | |||
589 | /* Clear Port Errors */ | ||
590 | rio_mport_write_config_32(mport, destid, hopcount, | ||
591 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | ||
592 | err_status & RIO_PORT_N_ERR_STS_CLR_MASK); | ||
593 | |||
594 | if (rdev->rswitch->port_ok & (1 << portnum)) { | ||
595 | if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) { | ||
596 | rdev->rswitch->port_ok &= ~(1 << portnum); | ||
597 | rio_set_port_lockout(rdev, portnum, 1); | ||
598 | |||
599 | rio_mport_write_config_32(mport, destid, hopcount, | ||
600 | rdev->phys_efptr + | ||
601 | RIO_PORT_N_ACK_STS_CSR(portnum), | ||
602 | RIO_PORT_N_ACK_CLEAR); | ||
603 | |||
604 | /* Schedule Extraction Service */ | ||
605 | pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n", | ||
606 | rio_name(rdev), portnum); | ||
607 | } | ||
608 | } else { | ||
609 | if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) { | ||
610 | rdev->rswitch->port_ok |= (1 << portnum); | ||
611 | rio_set_port_lockout(rdev, portnum, 0); | ||
612 | |||
613 | /* Schedule Insertion Service */ | ||
614 | pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n", | ||
615 | rio_name(rdev), portnum); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | /* Clear Port-Write Pending bit */ | ||
620 | rio_mport_write_config_32(mport, destid, hopcount, | ||
621 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | ||
622 | RIO_PORT_N_ERR_STS_PW_PEND); | ||
623 | |||
624 | return 0; | ||
625 | } | ||
626 | EXPORT_SYMBOL_GPL(rio_inb_pwrite_handler); | ||
627 | |||
628 | /** | ||
629 | * rio_mport_get_efb - get pointer to next extended features block | ||
630 | * @port: Master port to issue transaction | ||
631 | * @local: Indicate a local master port or remote device access | ||
632 | * @destid: Destination ID of the device | ||
633 | * @hopcount: Number of switch hops to the device | ||
634 | * @from: Offset of current Extended Feature block header (if 0 starts | ||
635 | * from ExtFeaturePtr) | ||
636 | */ | ||
637 | u32 | ||
638 | rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, | ||
639 | u8 hopcount, u32 from) | ||
640 | { | ||
641 | u32 reg_val; | ||
642 | |||
643 | if (from == 0) { | ||
644 | if (local) | ||
645 | rio_local_read_config_32(port, RIO_ASM_INFO_CAR, | ||
646 | ®_val); | ||
647 | else | ||
648 | rio_mport_read_config_32(port, destid, hopcount, | ||
649 | RIO_ASM_INFO_CAR, ®_val); | ||
650 | return reg_val & RIO_EXT_FTR_PTR_MASK; | ||
651 | } else { | ||
652 | if (local) | ||
653 | rio_local_read_config_32(port, from, ®_val); | ||
654 | else | ||
655 | rio_mport_read_config_32(port, destid, hopcount, | ||
656 | from, ®_val); | ||
657 | return RIO_GET_BLOCK_ID(reg_val); | ||
658 | } | ||
659 | } | ||
660 | |||
661 | /** | ||
336 | * rio_mport_get_feature - query for devices' extended features | 662 | * rio_mport_get_feature - query for devices' extended features |
337 | * @port: Master port to issue transaction | 663 | * @port: Master port to issue transaction |
338 | * @local: Indicate a local master port or remote device access | 664 | * @local: Indicate a local master port or remote device access |
@@ -451,6 +777,111 @@ struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from) | |||
451 | return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); | 777 | return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); |
452 | } | 778 | } |
453 | 779 | ||
780 | /** | ||
781 | * rio_std_route_add_entry - Add switch route table entry using standard | ||
782 | * registers defined in RIO specification rev.1.3 | ||
783 | * @mport: Master port to issue transaction | ||
784 | * @destid: Destination ID of the device | ||
785 | * @hopcount: Number of switch hops to the device | ||
786 | * @table: routing table ID (global or port-specific) | ||
787 | * @route_destid: destID entry in the RT | ||
788 | * @route_port: destination port for specified destID | ||
789 | */ | ||
790 | int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
791 | u16 table, u16 route_destid, u8 route_port) | ||
792 | { | ||
793 | if (table == RIO_GLOBAL_TABLE) { | ||
794 | rio_mport_write_config_32(mport, destid, hopcount, | ||
795 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, | ||
796 | (u32)route_destid); | ||
797 | rio_mport_write_config_32(mport, destid, hopcount, | ||
798 | RIO_STD_RTE_CONF_PORT_SEL_CSR, | ||
799 | (u32)route_port); | ||
800 | } | ||
801 | |||
802 | udelay(10); | ||
803 | return 0; | ||
804 | } | ||
805 | |||
806 | /** | ||
807 | * rio_std_route_get_entry - Read switch route table entry (port number) | ||
808 | * assosiated with specified destID using standard registers defined in RIO | ||
809 | * specification rev.1.3 | ||
810 | * @mport: Master port to issue transaction | ||
811 | * @destid: Destination ID of the device | ||
812 | * @hopcount: Number of switch hops to the device | ||
813 | * @table: routing table ID (global or port-specific) | ||
814 | * @route_destid: destID entry in the RT | ||
815 | * @route_port: returned destination port for specified destID | ||
816 | */ | ||
817 | int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
818 | u16 table, u16 route_destid, u8 *route_port) | ||
819 | { | ||
820 | u32 result; | ||
821 | |||
822 | if (table == RIO_GLOBAL_TABLE) { | ||
823 | rio_mport_write_config_32(mport, destid, hopcount, | ||
824 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid); | ||
825 | rio_mport_read_config_32(mport, destid, hopcount, | ||
826 | RIO_STD_RTE_CONF_PORT_SEL_CSR, &result); | ||
827 | |||
828 | *route_port = (u8)result; | ||
829 | } | ||
830 | |||
831 | return 0; | ||
832 | } | ||
833 | |||
834 | /** | ||
835 | * rio_std_route_clr_table - Clear swotch route table using standard registers | ||
836 | * defined in RIO specification rev.1.3. | ||
837 | * @mport: Master port to issue transaction | ||
838 | * @local: Indicate a local master port or remote device access | ||
839 | * @destid: Destination ID of the device | ||
840 | * @hopcount: Number of switch hops to the device | ||
841 | * @table: routing table ID (global or port-specific) | ||
842 | */ | ||
843 | int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
844 | u16 table) | ||
845 | { | ||
846 | u32 max_destid = 0xff; | ||
847 | u32 i, pef, id_inc = 1, ext_cfg = 0; | ||
848 | u32 port_sel = RIO_INVALID_ROUTE; | ||
849 | |||
850 | if (table == RIO_GLOBAL_TABLE) { | ||
851 | rio_mport_read_config_32(mport, destid, hopcount, | ||
852 | RIO_PEF_CAR, &pef); | ||
853 | |||
854 | if (mport->sys_size) { | ||
855 | rio_mport_read_config_32(mport, destid, hopcount, | ||
856 | RIO_SWITCH_RT_LIMIT, | ||
857 | &max_destid); | ||
858 | max_destid &= RIO_RT_MAX_DESTID; | ||
859 | } | ||
860 | |||
861 | if (pef & RIO_PEF_EXT_RT) { | ||
862 | ext_cfg = 0x80000000; | ||
863 | id_inc = 4; | ||
864 | port_sel = (RIO_INVALID_ROUTE << 24) | | ||
865 | (RIO_INVALID_ROUTE << 16) | | ||
866 | (RIO_INVALID_ROUTE << 8) | | ||
867 | RIO_INVALID_ROUTE; | ||
868 | } | ||
869 | |||
870 | for (i = 0; i <= max_destid;) { | ||
871 | rio_mport_write_config_32(mport, destid, hopcount, | ||
872 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, | ||
873 | ext_cfg | i); | ||
874 | rio_mport_write_config_32(mport, destid, hopcount, | ||
875 | RIO_STD_RTE_CONF_PORT_SEL_CSR, | ||
876 | port_sel); | ||
877 | i += id_inc; | ||
878 | } | ||
879 | } | ||
880 | |||
881 | udelay(10); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
454 | static void rio_fixup_device(struct rio_dev *dev) | 885 | static void rio_fixup_device(struct rio_dev *dev) |
455 | { | 886 | { |
456 | } | 887 | } |
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index 7786d02581f2..f27b7a9c47d2 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h | |||
@@ -18,38 +18,50 @@ | |||
18 | 18 | ||
19 | extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, | 19 | extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid, |
20 | u8 hopcount, int ftr); | 20 | u8 hopcount, int ftr); |
21 | extern u32 rio_mport_get_physefb(struct rio_mport *port, int local, | ||
22 | u16 destid, u8 hopcount); | ||
23 | extern u32 rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, | ||
24 | u8 hopcount, u32 from); | ||
21 | extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); | 25 | extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); |
22 | extern int rio_enum_mport(struct rio_mport *mport); | 26 | extern int rio_enum_mport(struct rio_mport *mport); |
23 | extern int rio_disc_mport(struct rio_mport *mport); | 27 | extern int rio_disc_mport(struct rio_mport *mport); |
28 | extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, | ||
29 | u8 hopcount, u16 table, u16 route_destid, | ||
30 | u8 route_port); | ||
31 | extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, | ||
32 | u8 hopcount, u16 table, u16 route_destid, | ||
33 | u8 *route_port); | ||
34 | extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, | ||
35 | u8 hopcount, u16 table); | ||
36 | extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock); | ||
24 | 37 | ||
25 | /* Structures internal to the RIO core code */ | 38 | /* Structures internal to the RIO core code */ |
26 | extern struct device_attribute rio_dev_attrs[]; | 39 | extern struct device_attribute rio_dev_attrs[]; |
27 | extern spinlock_t rio_global_list_lock; | 40 | extern spinlock_t rio_global_list_lock; |
28 | 41 | ||
29 | extern struct rio_route_ops __start_rio_route_ops[]; | 42 | extern struct rio_switch_ops __start_rio_switch_ops[]; |
30 | extern struct rio_route_ops __end_rio_route_ops[]; | 43 | extern struct rio_switch_ops __end_rio_switch_ops[]; |
31 | 44 | ||
32 | /* Helpers internal to the RIO core code */ | 45 | /* Helpers internal to the RIO core code */ |
33 | #define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ | 46 | #define DECLARE_RIO_SWITCH_SECTION(section, name, vid, did, init_hook) \ |
34 | static struct rio_route_ops __rio_route_ops __used \ | 47 | static const struct rio_switch_ops __rio_switch_##name __used \ |
35 | __section(section)= { vid, did, add_hook, get_hook }; | 48 | __section(section) = { vid, did, init_hook }; |
36 | 49 | ||
37 | /** | 50 | /** |
38 | * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations | 51 | * DECLARE_RIO_SWITCH_INIT - Registers switch initialization routine |
39 | * @vid: RIO vendor ID | 52 | * @vid: RIO vendor ID |
40 | * @did: RIO device ID | 53 | * @did: RIO device ID |
41 | * @add_hook: Callback that adds a route entry | 54 | * @init_hook: Callback that performs switch-specific initialization |
42 | * @get_hook: Callback that gets a route entry | ||
43 | * | 55 | * |
44 | * Manipulating switch route tables in RIO is switch specific. This | 56 | * Manipulating switch route tables and error management in RIO |
45 | * registers a switch by vendor and device ID with two callbacks for | 57 | * is switch specific. This registers a switch by vendor and device ID with |
46 | * modifying and retrieving route entries in a switch. A &struct | 58 | * initialization callback for setting up switch operations and (if required) |
47 | * rio_route_ops is initialized with the ops and placed into a | 59 | * hardware initialization. A &struct rio_switch_ops is initialized with |
48 | * RIO-specific kernel section. | 60 | * pointer to the init routine and placed into a RIO-specific kernel section. |
49 | */ | 61 | */ |
50 | #define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \ | 62 | #define DECLARE_RIO_SWITCH_INIT(vid, did, init_hook) \ |
51 | DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \ | 63 | DECLARE_RIO_SWITCH_SECTION(.rio_switch_ops, vid##did, \ |
52 | vid, did, add_hook, get_hook) | 64 | vid, did, init_hook) |
53 | 65 | ||
54 | #define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16)) | 66 | #define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16)) |
55 | #define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16)) | 67 | #define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16)) |
diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig new file mode 100644 index 000000000000..2b4e9b2b6631 --- /dev/null +++ b/drivers/rapidio/switches/Kconfig | |||
@@ -0,0 +1,28 @@ | |||
1 | # | ||
2 | # RapidIO switches configuration | ||
3 | # | ||
4 | config RAPIDIO_TSI57X | ||
5 | bool "IDT Tsi57x SRIO switches support" | ||
6 | depends on RAPIDIO | ||
7 | ---help--- | ||
8 | Includes support for IDT Tsi57x family of serial RapidIO switches. | ||
9 | |||
10 | config RAPIDIO_CPS_XX | ||
11 | bool "IDT CPS-xx SRIO switches support" | ||
12 | depends on RAPIDIO | ||
13 | ---help--- | ||
14 | Includes support for IDT CPS-16/12/10/8 serial RapidIO switches. | ||
15 | |||
16 | config RAPIDIO_TSI568 | ||
17 | bool "Tsi568 SRIO switch support" | ||
18 | depends on RAPIDIO | ||
19 | default n | ||
20 | ---help--- | ||
21 | Includes support for IDT Tsi568 serial RapidIO switch. | ||
22 | |||
23 | config RAPIDIO_TSI500 | ||
24 | bool "Tsi500 Parallel RapidIO switch support" | ||
25 | depends on RAPIDIO | ||
26 | default n | ||
27 | ---help--- | ||
28 | Includes support for IDT Tsi500 parallel RapidIO switch. | ||
diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile index b924f8301761..fe4adc3e8d5f 100644 --- a/drivers/rapidio/switches/Makefile +++ b/drivers/rapidio/switches/Makefile | |||
@@ -2,4 +2,11 @@ | |||
2 | # Makefile for RIO switches | 2 | # Makefile for RIO switches |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_RAPIDIO) += tsi500.o | 5 | obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o |
6 | obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o | ||
7 | obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o | ||
8 | obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o | ||
9 | |||
10 | ifeq ($(CONFIG_RAPIDIO_DEBUG),y) | ||
11 | EXTRA_CFLAGS += -DDEBUG | ||
12 | endif | ||
diff --git a/drivers/rapidio/switches/idtcps.c b/drivers/rapidio/switches/idtcps.c new file mode 100644 index 000000000000..2c790c144f89 --- /dev/null +++ b/drivers/rapidio/switches/idtcps.c | |||
@@ -0,0 +1,137 @@ | |||
1 | /* | ||
2 | * IDT CPS RapidIO switches support | ||
3 | * | ||
4 | * Copyright 2009-2010 Integrated Device Technology, Inc. | ||
5 | * Alexandre Bounine <alexandre.bounine@idt.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License as published by the | ||
9 | * Free Software Foundation; either version 2 of the License, or (at your | ||
10 | * option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/rio.h> | ||
14 | #include <linux/rio_drv.h> | ||
15 | #include <linux/rio_ids.h> | ||
16 | #include "../rio.h" | ||
17 | |||
18 | #define CPS_DEFAULT_ROUTE 0xde | ||
19 | #define CPS_NO_ROUTE 0xdf | ||
20 | |||
21 | #define IDTCPS_RIO_DOMAIN 0xf20020 | ||
22 | |||
23 | static int | ||
24 | idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
25 | u16 table, u16 route_destid, u8 route_port) | ||
26 | { | ||
27 | u32 result; | ||
28 | |||
29 | if (table == RIO_GLOBAL_TABLE) { | ||
30 | rio_mport_write_config_32(mport, destid, hopcount, | ||
31 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid); | ||
32 | |||
33 | rio_mport_read_config_32(mport, destid, hopcount, | ||
34 | RIO_STD_RTE_CONF_PORT_SEL_CSR, &result); | ||
35 | |||
36 | result = (0xffffff00 & result) | (u32)route_port; | ||
37 | rio_mport_write_config_32(mport, destid, hopcount, | ||
38 | RIO_STD_RTE_CONF_PORT_SEL_CSR, result); | ||
39 | } | ||
40 | |||
41 | return 0; | ||
42 | } | ||
43 | |||
44 | static int | ||
45 | idtcps_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
46 | u16 table, u16 route_destid, u8 *route_port) | ||
47 | { | ||
48 | u32 result; | ||
49 | |||
50 | if (table == RIO_GLOBAL_TABLE) { | ||
51 | rio_mport_write_config_32(mport, destid, hopcount, | ||
52 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid); | ||
53 | |||
54 | rio_mport_read_config_32(mport, destid, hopcount, | ||
55 | RIO_STD_RTE_CONF_PORT_SEL_CSR, &result); | ||
56 | |||
57 | if (CPS_DEFAULT_ROUTE == (u8)result || | ||
58 | CPS_NO_ROUTE == (u8)result) | ||
59 | *route_port = RIO_INVALID_ROUTE; | ||
60 | else | ||
61 | *route_port = (u8)result; | ||
62 | } | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int | ||
68 | idtcps_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
69 | u16 table) | ||
70 | { | ||
71 | u32 i; | ||
72 | |||
73 | if (table == RIO_GLOBAL_TABLE) { | ||
74 | for (i = 0x80000000; i <= 0x800000ff;) { | ||
75 | rio_mport_write_config_32(mport, destid, hopcount, | ||
76 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, i); | ||
77 | rio_mport_write_config_32(mport, destid, hopcount, | ||
78 | RIO_STD_RTE_CONF_PORT_SEL_CSR, | ||
79 | (CPS_DEFAULT_ROUTE << 24) | | ||
80 | (CPS_DEFAULT_ROUTE << 16) | | ||
81 | (CPS_DEFAULT_ROUTE << 8) | CPS_DEFAULT_ROUTE); | ||
82 | i += 4; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | static int | ||
90 | idtcps_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
91 | u8 sw_domain) | ||
92 | { | ||
93 | /* | ||
94 | * Switch domain configuration operates only at global level | ||
95 | */ | ||
96 | rio_mport_write_config_32(mport, destid, hopcount, | ||
97 | IDTCPS_RIO_DOMAIN, (u32)sw_domain); | ||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static int | ||
102 | idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
103 | u8 *sw_domain) | ||
104 | { | ||
105 | u32 regval; | ||
106 | |||
107 | /* | ||
108 | * Switch domain configuration operates only at global level | ||
109 | */ | ||
110 | rio_mport_read_config_32(mport, destid, hopcount, | ||
111 | IDTCPS_RIO_DOMAIN, ®val); | ||
112 | |||
113 | *sw_domain = (u8)(regval & 0xff); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int idtcps_switch_init(struct rio_dev *rdev, int do_enum) | ||
119 | { | ||
120 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); | ||
121 | rdev->rswitch->add_entry = idtcps_route_add_entry; | ||
122 | rdev->rswitch->get_entry = idtcps_route_get_entry; | ||
123 | rdev->rswitch->clr_table = idtcps_route_clr_table; | ||
124 | rdev->rswitch->set_domain = idtcps_set_domain; | ||
125 | rdev->rswitch->get_domain = idtcps_get_domain; | ||
126 | rdev->rswitch->em_init = NULL; | ||
127 | rdev->rswitch->em_handle = NULL; | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS6Q, idtcps_switch_init); | ||
133 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS8, idtcps_switch_init); | ||
134 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS10Q, idtcps_switch_init); | ||
135 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS12, idtcps_switch_init); | ||
136 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS16, idtcps_switch_init); | ||
137 | DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDT70K200, idtcps_switch_init); | ||
diff --git a/drivers/rapidio/switches/tsi500.c b/drivers/rapidio/switches/tsi500.c index c77c23bd9840..914eddd5aa42 100644 --- a/drivers/rapidio/switches/tsi500.c +++ b/drivers/rapidio/switches/tsi500.c | |||
@@ -1,6 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * RapidIO Tsi500 switch support | 2 | * RapidIO Tsi500 switch support |
3 | * | 3 | * |
4 | * Copyright 2009-2010 Integrated Device Technology, Inc. | ||
5 | * Alexandre Bounine <alexandre.bounine@idt.com> | ||
6 | * - Modified switch operations initialization. | ||
7 | * | ||
4 | * Copyright 2005 MontaVista Software, Inc. | 8 | * Copyright 2005 MontaVista Software, Inc. |
5 | * Matt Porter <mporter@kernel.crashing.org> | 9 | * Matt Porter <mporter@kernel.crashing.org> |
6 | * | 10 | * |
@@ -57,4 +61,18 @@ tsi500_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 tab | |||
57 | return ret; | 61 | return ret; |
58 | } | 62 | } |
59 | 63 | ||
60 | DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry); | 64 | static int tsi500_switch_init(struct rio_dev *rdev, int do_enum) |
65 | { | ||
66 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); | ||
67 | rdev->rswitch->add_entry = tsi500_route_add_entry; | ||
68 | rdev->rswitch->get_entry = tsi500_route_get_entry; | ||
69 | rdev->rswitch->clr_table = NULL; | ||
70 | rdev->rswitch->set_domain = NULL; | ||
71 | rdev->rswitch->get_domain = NULL; | ||
72 | rdev->rswitch->em_init = NULL; | ||
73 | rdev->rswitch->em_handle = NULL; | ||
74 | |||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_switch_init); | ||
diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c new file mode 100644 index 000000000000..f7fd7898606e --- /dev/null +++ b/drivers/rapidio/switches/tsi568.c | |||
@@ -0,0 +1,146 @@ | |||
1 | /* | ||
2 | * RapidIO Tsi568 switch support | ||
3 | * | ||
4 | * Copyright 2009-2010 Integrated Device Technology, Inc. | ||
5 | * Alexandre Bounine <alexandre.bounine@idt.com> | ||
6 | * - Added EM support | ||
7 | * - Modified switch operations initialization. | ||
8 | * | ||
9 | * Copyright 2005 MontaVista Software, Inc. | ||
10 | * Matt Porter <mporter@kernel.crashing.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/rio.h> | ||
19 | #include <linux/rio_drv.h> | ||
20 | #include <linux/rio_ids.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include "../rio.h" | ||
23 | |||
24 | /* Global (broadcast) route registers */ | ||
25 | #define SPBC_ROUTE_CFG_DESTID 0x10070 | ||
26 | #define SPBC_ROUTE_CFG_PORT 0x10074 | ||
27 | |||
28 | /* Per port route registers */ | ||
29 | #define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n) | ||
30 | #define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n) | ||
31 | |||
32 | #define TSI568_SP_MODE_BC 0x10004 | ||
33 | #define TSI568_SP_MODE_PW_DIS 0x08000000 | ||
34 | |||
35 | static int | ||
36 | tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
37 | u16 table, u16 route_destid, u8 route_port) | ||
38 | { | ||
39 | if (table == RIO_GLOBAL_TABLE) { | ||
40 | rio_mport_write_config_32(mport, destid, hopcount, | ||
41 | SPBC_ROUTE_CFG_DESTID, route_destid); | ||
42 | rio_mport_write_config_32(mport, destid, hopcount, | ||
43 | SPBC_ROUTE_CFG_PORT, route_port); | ||
44 | } else { | ||
45 | rio_mport_write_config_32(mport, destid, hopcount, | ||
46 | SPP_ROUTE_CFG_DESTID(table), | ||
47 | route_destid); | ||
48 | rio_mport_write_config_32(mport, destid, hopcount, | ||
49 | SPP_ROUTE_CFG_PORT(table), route_port); | ||
50 | } | ||
51 | |||
52 | udelay(10); | ||
53 | |||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static int | ||
58 | tsi568_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
59 | u16 table, u16 route_destid, u8 *route_port) | ||
60 | { | ||
61 | int ret = 0; | ||
62 | u32 result; | ||
63 | |||
64 | if (table == RIO_GLOBAL_TABLE) { | ||
65 | rio_mport_write_config_32(mport, destid, hopcount, | ||
66 | SPBC_ROUTE_CFG_DESTID, route_destid); | ||
67 | rio_mport_read_config_32(mport, destid, hopcount, | ||
68 | SPBC_ROUTE_CFG_PORT, &result); | ||
69 | } else { | ||
70 | rio_mport_write_config_32(mport, destid, hopcount, | ||
71 | SPP_ROUTE_CFG_DESTID(table), | ||
72 | route_destid); | ||
73 | rio_mport_read_config_32(mport, destid, hopcount, | ||
74 | SPP_ROUTE_CFG_PORT(table), &result); | ||
75 | } | ||
76 | |||
77 | *route_port = result; | ||
78 | if (*route_port > 15) | ||
79 | ret = -1; | ||
80 | |||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | static int | ||
85 | tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
86 | u16 table) | ||
87 | { | ||
88 | u32 route_idx; | ||
89 | u32 lut_size; | ||
90 | |||
91 | lut_size = (mport->sys_size) ? 0x1ff : 0xff; | ||
92 | |||
93 | if (table == RIO_GLOBAL_TABLE) { | ||
94 | rio_mport_write_config_32(mport, destid, hopcount, | ||
95 | SPBC_ROUTE_CFG_DESTID, 0x80000000); | ||
96 | for (route_idx = 0; route_idx <= lut_size; route_idx++) | ||
97 | rio_mport_write_config_32(mport, destid, hopcount, | ||
98 | SPBC_ROUTE_CFG_PORT, | ||
99 | RIO_INVALID_ROUTE); | ||
100 | } else { | ||
101 | rio_mport_write_config_32(mport, destid, hopcount, | ||
102 | SPP_ROUTE_CFG_DESTID(table), | ||
103 | 0x80000000); | ||
104 | for (route_idx = 0; route_idx <= lut_size; route_idx++) | ||
105 | rio_mport_write_config_32(mport, destid, hopcount, | ||
106 | SPP_ROUTE_CFG_PORT(table), | ||
107 | RIO_INVALID_ROUTE); | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | static int | ||
114 | tsi568_em_init(struct rio_dev *rdev) | ||
115 | { | ||
116 | struct rio_mport *mport = rdev->net->hport; | ||
117 | u16 destid = rdev->rswitch->destid; | ||
118 | u8 hopcount = rdev->rswitch->hopcount; | ||
119 | u32 regval; | ||
120 | |||
121 | pr_debug("TSI568 %s [%d:%d]\n", __func__, destid, hopcount); | ||
122 | |||
123 | /* Make sure that Port-Writes are disabled (for all ports) */ | ||
124 | rio_mport_read_config_32(mport, destid, hopcount, | ||
125 | TSI568_SP_MODE_BC, ®val); | ||
126 | rio_mport_write_config_32(mport, destid, hopcount, | ||
127 | TSI568_SP_MODE_BC, regval | TSI568_SP_MODE_PW_DIS); | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int tsi568_switch_init(struct rio_dev *rdev, int do_enum) | ||
133 | { | ||
134 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); | ||
135 | rdev->rswitch->add_entry = tsi568_route_add_entry; | ||
136 | rdev->rswitch->get_entry = tsi568_route_get_entry; | ||
137 | rdev->rswitch->clr_table = tsi568_route_clr_table; | ||
138 | rdev->rswitch->set_domain = NULL; | ||
139 | rdev->rswitch->get_domain = NULL; | ||
140 | rdev->rswitch->em_init = tsi568_em_init; | ||
141 | rdev->rswitch->em_handle = NULL; | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_switch_init); | ||
diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c new file mode 100644 index 000000000000..d34df722d95f --- /dev/null +++ b/drivers/rapidio/switches/tsi57x.c | |||
@@ -0,0 +1,315 @@ | |||
1 | /* | ||
2 | * RapidIO Tsi57x switch family support | ||
3 | * | ||
4 | * Copyright 2009-2010 Integrated Device Technology, Inc. | ||
5 | * Alexandre Bounine <alexandre.bounine@idt.com> | ||
6 | * - Added EM support | ||
7 | * - Modified switch operations initialization. | ||
8 | * | ||
9 | * Copyright 2005 MontaVista Software, Inc. | ||
10 | * Matt Porter <mporter@kernel.crashing.org> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/rio.h> | ||
19 | #include <linux/rio_drv.h> | ||
20 | #include <linux/rio_ids.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include "../rio.h" | ||
23 | |||
24 | /* Global (broadcast) route registers */ | ||
25 | #define SPBC_ROUTE_CFG_DESTID 0x10070 | ||
26 | #define SPBC_ROUTE_CFG_PORT 0x10074 | ||
27 | |||
28 | /* Per port route registers */ | ||
29 | #define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n) | ||
30 | #define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n) | ||
31 | |||
32 | #define TSI578_SP_MODE(n) (0x11004 + n*0x100) | ||
33 | #define TSI578_SP_MODE_GLBL 0x10004 | ||
34 | #define TSI578_SP_MODE_PW_DIS 0x08000000 | ||
35 | #define TSI578_SP_MODE_LUT_512 0x01000000 | ||
36 | |||
37 | #define TSI578_SP_CTL_INDEP(n) (0x13004 + n*0x100) | ||
38 | #define TSI578_SP_LUT_PEINF(n) (0x13010 + n*0x100) | ||
39 | #define TSI578_SP_CS_TX(n) (0x13014 + n*0x100) | ||
40 | #define TSI578_SP_INT_STATUS(n) (0x13018 + n*0x100) | ||
41 | |||
42 | #define TSI578_GLBL_ROUTE_BASE 0x10078 | ||
43 | |||
44 | static int | ||
45 | tsi57x_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
46 | u16 table, u16 route_destid, u8 route_port) | ||
47 | { | ||
48 | if (table == RIO_GLOBAL_TABLE) { | ||
49 | rio_mport_write_config_32(mport, destid, hopcount, | ||
50 | SPBC_ROUTE_CFG_DESTID, route_destid); | ||
51 | rio_mport_write_config_32(mport, destid, hopcount, | ||
52 | SPBC_ROUTE_CFG_PORT, route_port); | ||
53 | } else { | ||
54 | rio_mport_write_config_32(mport, destid, hopcount, | ||
55 | SPP_ROUTE_CFG_DESTID(table), route_destid); | ||
56 | rio_mport_write_config_32(mport, destid, hopcount, | ||
57 | SPP_ROUTE_CFG_PORT(table), route_port); | ||
58 | } | ||
59 | |||
60 | udelay(10); | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int | ||
66 | tsi57x_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
67 | u16 table, u16 route_destid, u8 *route_port) | ||
68 | { | ||
69 | int ret = 0; | ||
70 | u32 result; | ||
71 | |||
72 | if (table == RIO_GLOBAL_TABLE) { | ||
73 | /* Use local RT of the ingress port to avoid possible | ||
74 | race condition */ | ||
75 | rio_mport_read_config_32(mport, destid, hopcount, | ||
76 | RIO_SWP_INFO_CAR, &result); | ||
77 | table = (result & RIO_SWP_INFO_PORT_NUM_MASK); | ||
78 | } | ||
79 | |||
80 | rio_mport_write_config_32(mport, destid, hopcount, | ||
81 | SPP_ROUTE_CFG_DESTID(table), route_destid); | ||
82 | rio_mport_read_config_32(mport, destid, hopcount, | ||
83 | SPP_ROUTE_CFG_PORT(table), &result); | ||
84 | |||
85 | *route_port = (u8)result; | ||
86 | if (*route_port > 15) | ||
87 | ret = -1; | ||
88 | |||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | static int | ||
93 | tsi57x_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
94 | u16 table) | ||
95 | { | ||
96 | u32 route_idx; | ||
97 | u32 lut_size; | ||
98 | |||
99 | lut_size = (mport->sys_size) ? 0x1ff : 0xff; | ||
100 | |||
101 | if (table == RIO_GLOBAL_TABLE) { | ||
102 | rio_mport_write_config_32(mport, destid, hopcount, | ||
103 | SPBC_ROUTE_CFG_DESTID, 0x80000000); | ||
104 | for (route_idx = 0; route_idx <= lut_size; route_idx++) | ||
105 | rio_mport_write_config_32(mport, destid, hopcount, | ||
106 | SPBC_ROUTE_CFG_PORT, | ||
107 | RIO_INVALID_ROUTE); | ||
108 | } else { | ||
109 | rio_mport_write_config_32(mport, destid, hopcount, | ||
110 | SPP_ROUTE_CFG_DESTID(table), 0x80000000); | ||
111 | for (route_idx = 0; route_idx <= lut_size; route_idx++) | ||
112 | rio_mport_write_config_32(mport, destid, hopcount, | ||
113 | SPP_ROUTE_CFG_PORT(table) , RIO_INVALID_ROUTE); | ||
114 | } | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int | ||
120 | tsi57x_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
121 | u8 sw_domain) | ||
122 | { | ||
123 | u32 regval; | ||
124 | |||
125 | /* | ||
126 | * Switch domain configuration operates only at global level | ||
127 | */ | ||
128 | |||
129 | /* Turn off flat (LUT_512) mode */ | ||
130 | rio_mport_read_config_32(mport, destid, hopcount, | ||
131 | TSI578_SP_MODE_GLBL, ®val); | ||
132 | rio_mport_write_config_32(mport, destid, hopcount, TSI578_SP_MODE_GLBL, | ||
133 | regval & ~TSI578_SP_MODE_LUT_512); | ||
134 | /* Set switch domain base */ | ||
135 | rio_mport_write_config_32(mport, destid, hopcount, | ||
136 | TSI578_GLBL_ROUTE_BASE, | ||
137 | (u32)(sw_domain << 24)); | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | static int | ||
142 | tsi57x_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
143 | u8 *sw_domain) | ||
144 | { | ||
145 | u32 regval; | ||
146 | |||
147 | /* | ||
148 | * Switch domain configuration operates only at global level | ||
149 | */ | ||
150 | rio_mport_read_config_32(mport, destid, hopcount, | ||
151 | TSI578_GLBL_ROUTE_BASE, ®val); | ||
152 | |||
153 | *sw_domain = (u8)(regval >> 24); | ||
154 | |||
155 | return 0; | ||
156 | } | ||
157 | |||
158 | static int | ||
159 | tsi57x_em_init(struct rio_dev *rdev) | ||
160 | { | ||
161 | struct rio_mport *mport = rdev->net->hport; | ||
162 | u16 destid = rdev->rswitch->destid; | ||
163 | u8 hopcount = rdev->rswitch->hopcount; | ||
164 | u32 regval; | ||
165 | int portnum; | ||
166 | |||
167 | pr_debug("TSI578 %s [%d:%d]\n", __func__, destid, hopcount); | ||
168 | |||
169 | for (portnum = 0; portnum < 16; portnum++) { | ||
170 | /* Make sure that Port-Writes are enabled (for all ports) */ | ||
171 | rio_mport_read_config_32(mport, destid, hopcount, | ||
172 | TSI578_SP_MODE(portnum), ®val); | ||
173 | rio_mport_write_config_32(mport, destid, hopcount, | ||
174 | TSI578_SP_MODE(portnum), | ||
175 | regval & ~TSI578_SP_MODE_PW_DIS); | ||
176 | |||
177 | /* Clear all pending interrupts */ | ||
178 | rio_mport_read_config_32(mport, destid, hopcount, | ||
179 | rdev->phys_efptr + | ||
180 | RIO_PORT_N_ERR_STS_CSR(portnum), | ||
181 | ®val); | ||
182 | rio_mport_write_config_32(mport, destid, hopcount, | ||
183 | rdev->phys_efptr + | ||
184 | RIO_PORT_N_ERR_STS_CSR(portnum), | ||
185 | regval & 0x07120214); | ||
186 | |||
187 | rio_mport_read_config_32(mport, destid, hopcount, | ||
188 | TSI578_SP_INT_STATUS(portnum), ®val); | ||
189 | rio_mport_write_config_32(mport, destid, hopcount, | ||
190 | TSI578_SP_INT_STATUS(portnum), | ||
191 | regval & 0x000700bd); | ||
192 | |||
193 | /* Enable all interrupts to allow ports to send a port-write */ | ||
194 | rio_mport_read_config_32(mport, destid, hopcount, | ||
195 | TSI578_SP_CTL_INDEP(portnum), ®val); | ||
196 | rio_mport_write_config_32(mport, destid, hopcount, | ||
197 | TSI578_SP_CTL_INDEP(portnum), | ||
198 | regval | 0x000b0000); | ||
199 | |||
200 | /* Skip next (odd) port if the current port is in x4 mode */ | ||
201 | rio_mport_read_config_32(mport, destid, hopcount, | ||
202 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | ||
203 | ®val); | ||
204 | if ((regval & RIO_PORT_N_CTL_PWIDTH) == RIO_PORT_N_CTL_PWIDTH_4) | ||
205 | portnum++; | ||
206 | } | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | static int | ||
212 | tsi57x_em_handler(struct rio_dev *rdev, u8 portnum) | ||
213 | { | ||
214 | struct rio_mport *mport = rdev->net->hport; | ||
215 | u16 destid = rdev->rswitch->destid; | ||
216 | u8 hopcount = rdev->rswitch->hopcount; | ||
217 | u32 intstat, err_status; | ||
218 | int sendcount, checkcount; | ||
219 | u8 route_port; | ||
220 | u32 regval; | ||
221 | |||
222 | rio_mport_read_config_32(mport, destid, hopcount, | ||
223 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | ||
224 | &err_status); | ||
225 | |||
226 | if ((err_status & RIO_PORT_N_ERR_STS_PORT_OK) && | ||
227 | (err_status & (RIO_PORT_N_ERR_STS_PW_OUT_ES | | ||
228 | RIO_PORT_N_ERR_STS_PW_INP_ES))) { | ||
229 | /* Remove any queued packets by locking/unlocking port */ | ||
230 | rio_mport_read_config_32(mport, destid, hopcount, | ||
231 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | ||
232 | ®val); | ||
233 | if (!(regval & RIO_PORT_N_CTL_LOCKOUT)) { | ||
234 | rio_mport_write_config_32(mport, destid, hopcount, | ||
235 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | ||
236 | regval | RIO_PORT_N_CTL_LOCKOUT); | ||
237 | udelay(50); | ||
238 | rio_mport_write_config_32(mport, destid, hopcount, | ||
239 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(portnum), | ||
240 | regval); | ||
241 | } | ||
242 | |||
243 | /* Read from link maintenance response register to clear | ||
244 | * valid bit | ||
245 | */ | ||
246 | rio_mport_read_config_32(mport, destid, hopcount, | ||
247 | rdev->phys_efptr + RIO_PORT_N_MNT_RSP_CSR(portnum), | ||
248 | ®val); | ||
249 | |||
250 | /* Send a Packet-Not-Accepted/Link-Request-Input-Status control | ||
251 | * symbol to recover from IES/OES | ||
252 | */ | ||
253 | sendcount = 3; | ||
254 | while (sendcount) { | ||
255 | rio_mport_write_config_32(mport, destid, hopcount, | ||
256 | TSI578_SP_CS_TX(portnum), 0x40fc8000); | ||
257 | checkcount = 3; | ||
258 | while (checkcount--) { | ||
259 | udelay(50); | ||
260 | rio_mport_read_config_32( | ||
261 | mport, destid, hopcount, | ||
262 | rdev->phys_efptr + | ||
263 | RIO_PORT_N_MNT_RSP_CSR(portnum), | ||
264 | ®val); | ||
265 | if (regval & RIO_PORT_N_MNT_RSP_RVAL) | ||
266 | goto exit_es; | ||
267 | } | ||
268 | |||
269 | sendcount--; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | exit_es: | ||
274 | /* Clear implementation specific error status bits */ | ||
275 | rio_mport_read_config_32(mport, destid, hopcount, | ||
276 | TSI578_SP_INT_STATUS(portnum), &intstat); | ||
277 | pr_debug("TSI578[%x:%x] SP%d_INT_STATUS=0x%08x\n", | ||
278 | destid, hopcount, portnum, intstat); | ||
279 | |||
280 | if (intstat & 0x10000) { | ||
281 | rio_mport_read_config_32(mport, destid, hopcount, | ||
282 | TSI578_SP_LUT_PEINF(portnum), ®val); | ||
283 | regval = (mport->sys_size) ? (regval >> 16) : (regval >> 24); | ||
284 | route_port = rdev->rswitch->route_table[regval]; | ||
285 | pr_debug("RIO: TSI578[%s] P%d LUT Parity Error (destID=%d)\n", | ||
286 | rio_name(rdev), portnum, regval); | ||
287 | tsi57x_route_add_entry(mport, destid, hopcount, | ||
288 | RIO_GLOBAL_TABLE, regval, route_port); | ||
289 | } | ||
290 | |||
291 | rio_mport_write_config_32(mport, destid, hopcount, | ||
292 | TSI578_SP_INT_STATUS(portnum), | ||
293 | intstat & 0x000700bd); | ||
294 | |||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | static int tsi57x_switch_init(struct rio_dev *rdev, int do_enum) | ||
299 | { | ||
300 | pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); | ||
301 | rdev->rswitch->add_entry = tsi57x_route_add_entry; | ||
302 | rdev->rswitch->get_entry = tsi57x_route_get_entry; | ||
303 | rdev->rswitch->clr_table = tsi57x_route_clr_table; | ||
304 | rdev->rswitch->set_domain = tsi57x_set_domain; | ||
305 | rdev->rswitch->get_domain = tsi57x_get_domain; | ||
306 | rdev->rswitch->em_init = tsi57x_em_init; | ||
307 | rdev->rswitch->em_handle = tsi57x_em_handler; | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_switch_init); | ||
313 | DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_switch_init); | ||
314 | DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_switch_init); | ||
315 | DECLARE_RIO_SWITCH_INIT(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_switch_init); | ||
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index f1598324344c..10ba12c8c5e0 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -611,6 +611,13 @@ config RTC_DRV_AB3100 | |||
611 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC | 611 | Select this to enable the ST-Ericsson AB3100 Mixed Signal IC RTC |
612 | support. This chip contains a battery- and capacitor-backed RTC. | 612 | support. This chip contains a battery- and capacitor-backed RTC. |
613 | 613 | ||
614 | config RTC_DRV_AB8500 | ||
615 | tristate "ST-Ericsson AB8500 RTC" | ||
616 | depends on AB8500_CORE | ||
617 | help | ||
618 | Select this to enable the ST-Ericsson AB8500 power management IC RTC | ||
619 | support. This chip contains a battery- and capacitor-backed RTC. | ||
620 | |||
614 | config RTC_DRV_NUC900 | 621 | config RTC_DRV_NUC900 |
615 | tristate "NUC910/NUC920 RTC driver" | 622 | tristate "NUC910/NUC920 RTC driver" |
616 | depends on RTC_CLASS && ARCH_W90X900 | 623 | depends on RTC_CLASS && ARCH_W90X900 |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 245311a1348f..5adbba7cf89c 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -18,6 +18,7 @@ rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o | |||
18 | # Keep the list ordered. | 18 | # Keep the list ordered. |
19 | 19 | ||
20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o | 20 | obj-$(CONFIG_RTC_DRV_AB3100) += rtc-ab3100.o |
21 | obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o | ||
21 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o | 22 | obj-$(CONFIG_RTC_DRV_AT32AP700X)+= rtc-at32ap700x.o |
22 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o | 23 | obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o |
23 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o | 24 | obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o |
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c new file mode 100644 index 000000000000..2fda03125e55 --- /dev/null +++ b/drivers/rtc/rtc-ab8500.c | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | * Author: Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com> | ||
6 | * | ||
7 | * RTC clock driver for the RTC part of the AB8500 Power management chip. | ||
8 | * Based on RTC clock driver for the AB3100 Analog Baseband Chip by | ||
9 | * Linus Walleij <linus.walleij@stericsson.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/rtc.h> | ||
17 | #include <linux/mfd/ab8500.h> | ||
18 | #include <linux/delay.h> | ||
19 | |||
20 | #define AB8500_RTC_SOFF_STAT_REG 0x0F00 | ||
21 | #define AB8500_RTC_CC_CONF_REG 0x0F01 | ||
22 | #define AB8500_RTC_READ_REQ_REG 0x0F02 | ||
23 | #define AB8500_RTC_WATCH_TSECMID_REG 0x0F03 | ||
24 | #define AB8500_RTC_WATCH_TSECHI_REG 0x0F04 | ||
25 | #define AB8500_RTC_WATCH_TMIN_LOW_REG 0x0F05 | ||
26 | #define AB8500_RTC_WATCH_TMIN_MID_REG 0x0F06 | ||
27 | #define AB8500_RTC_WATCH_TMIN_HI_REG 0x0F07 | ||
28 | #define AB8500_RTC_ALRM_MIN_LOW_REG 0x0F08 | ||
29 | #define AB8500_RTC_ALRM_MIN_MID_REG 0x0F09 | ||
30 | #define AB8500_RTC_ALRM_MIN_HI_REG 0x0F0A | ||
31 | #define AB8500_RTC_STAT_REG 0x0F0B | ||
32 | #define AB8500_RTC_BKUP_CHG_REG 0x0F0C | ||
33 | #define AB8500_RTC_FORCE_BKUP_REG 0x0F0D | ||
34 | #define AB8500_RTC_CALIB_REG 0x0F0E | ||
35 | #define AB8500_RTC_SWITCH_STAT_REG 0x0F0F | ||
36 | #define AB8500_REV_REG 0x1080 | ||
37 | |||
38 | /* RtcReadRequest bits */ | ||
39 | #define RTC_READ_REQUEST 0x01 | ||
40 | #define RTC_WRITE_REQUEST 0x02 | ||
41 | |||
42 | /* RtcCtrl bits */ | ||
43 | #define RTC_ALARM_ENA 0x04 | ||
44 | #define RTC_STATUS_DATA 0x01 | ||
45 | |||
46 | #define COUNTS_PER_SEC (0xF000 / 60) | ||
47 | #define AB8500_RTC_EPOCH 2000 | ||
48 | |||
49 | static const unsigned long ab8500_rtc_time_regs[] = { | ||
50 | AB8500_RTC_WATCH_TMIN_HI_REG, AB8500_RTC_WATCH_TMIN_MID_REG, | ||
51 | AB8500_RTC_WATCH_TMIN_LOW_REG, AB8500_RTC_WATCH_TSECHI_REG, | ||
52 | AB8500_RTC_WATCH_TSECMID_REG | ||
53 | }; | ||
54 | |||
55 | static const unsigned long ab8500_rtc_alarm_regs[] = { | ||
56 | AB8500_RTC_ALRM_MIN_HI_REG, AB8500_RTC_ALRM_MIN_MID_REG, | ||
57 | AB8500_RTC_ALRM_MIN_LOW_REG | ||
58 | }; | ||
59 | |||
60 | /* Calculate the seconds from 1970 to 01-01-2000 00:00:00 */ | ||
61 | static unsigned long get_elapsed_seconds(int year) | ||
62 | { | ||
63 | unsigned long secs; | ||
64 | struct rtc_time tm = { | ||
65 | .tm_year = year - 1900, | ||
66 | .tm_mday = 1, | ||
67 | }; | ||
68 | |||
69 | /* | ||
70 | * This function calculates secs from 1970 and not from | ||
71 | * 1900, even if we supply the offset from year 1900. | ||
72 | */ | ||
73 | rtc_tm_to_time(&tm, &secs); | ||
74 | return secs; | ||
75 | } | ||
76 | |||
77 | static int ab8500_rtc_read_time(struct device *dev, struct rtc_time *tm) | ||
78 | { | ||
79 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
80 | unsigned long timeout = jiffies + HZ; | ||
81 | int retval, i; | ||
82 | unsigned long mins, secs; | ||
83 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
84 | |||
85 | /* Request a data read */ | ||
86 | retval = ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, | ||
87 | RTC_READ_REQUEST); | ||
88 | if (retval < 0) | ||
89 | return retval; | ||
90 | |||
91 | /* Early AB8500 chips will not clear the rtc read request bit */ | ||
92 | if (ab8500->revision == 0) { | ||
93 | msleep(1); | ||
94 | } else { | ||
95 | /* Wait for some cycles after enabling the rtc read in ab8500 */ | ||
96 | while (time_before(jiffies, timeout)) { | ||
97 | retval = ab8500_read(ab8500, AB8500_RTC_READ_REQ_REG); | ||
98 | if (retval < 0) | ||
99 | return retval; | ||
100 | |||
101 | if (!(retval & RTC_READ_REQUEST)) | ||
102 | break; | ||
103 | |||
104 | msleep(1); | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /* Read the Watchtime registers */ | ||
109 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
110 | retval = ab8500_read(ab8500, ab8500_rtc_time_regs[i]); | ||
111 | if (retval < 0) | ||
112 | return retval; | ||
113 | buf[i] = retval; | ||
114 | } | ||
115 | |||
116 | mins = (buf[0] << 16) | (buf[1] << 8) | buf[2]; | ||
117 | |||
118 | secs = (buf[3] << 8) | buf[4]; | ||
119 | secs = secs / COUNTS_PER_SEC; | ||
120 | secs = secs + (mins * 60); | ||
121 | |||
122 | /* Add back the initially subtracted number of seconds */ | ||
123 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
124 | |||
125 | rtc_time_to_tm(secs, tm); | ||
126 | return rtc_valid_tm(tm); | ||
127 | } | ||
128 | |||
129 | static int ab8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | ||
130 | { | ||
131 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
132 | int retval, i; | ||
133 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_time_regs)]; | ||
134 | unsigned long no_secs, no_mins, secs = 0; | ||
135 | |||
136 | if (tm->tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
137 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
138 | AB8500_RTC_EPOCH); | ||
139 | return -EINVAL; | ||
140 | } | ||
141 | |||
142 | /* Get the number of seconds since 1970 */ | ||
143 | rtc_tm_to_time(tm, &secs); | ||
144 | |||
145 | /* | ||
146 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
147 | * we only have a small counter in the RTC. | ||
148 | */ | ||
149 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
150 | |||
151 | no_mins = secs / 60; | ||
152 | |||
153 | no_secs = secs % 60; | ||
154 | /* Make the seconds count as per the RTC resolution */ | ||
155 | no_secs = no_secs * COUNTS_PER_SEC; | ||
156 | |||
157 | buf[4] = no_secs & 0xFF; | ||
158 | buf[3] = (no_secs >> 8) & 0xFF; | ||
159 | |||
160 | buf[2] = no_mins & 0xFF; | ||
161 | buf[1] = (no_mins >> 8) & 0xFF; | ||
162 | buf[0] = (no_mins >> 16) & 0xFF; | ||
163 | |||
164 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_time_regs); i++) { | ||
165 | retval = ab8500_write(ab8500, ab8500_rtc_time_regs[i], buf[i]); | ||
166 | if (retval < 0) | ||
167 | return retval; | ||
168 | } | ||
169 | |||
170 | /* Request a data write */ | ||
171 | return ab8500_write(ab8500, AB8500_RTC_READ_REQ_REG, RTC_WRITE_REQUEST); | ||
172 | } | ||
173 | |||
174 | static int ab8500_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
175 | { | ||
176 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
177 | int retval, i; | ||
178 | int rtc_ctrl; | ||
179 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
180 | unsigned long secs, mins; | ||
181 | |||
182 | /* Check if the alarm is enabled or not */ | ||
183 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | ||
184 | if (rtc_ctrl < 0) | ||
185 | return rtc_ctrl; | ||
186 | |||
187 | if (rtc_ctrl & RTC_ALARM_ENA) | ||
188 | alarm->enabled = 1; | ||
189 | else | ||
190 | alarm->enabled = 0; | ||
191 | |||
192 | alarm->pending = 0; | ||
193 | |||
194 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
195 | retval = ab8500_read(ab8500, ab8500_rtc_alarm_regs[i]); | ||
196 | if (retval < 0) | ||
197 | return retval; | ||
198 | buf[i] = retval; | ||
199 | } | ||
200 | |||
201 | mins = (buf[0] << 16) | (buf[1] << 8) | (buf[2]); | ||
202 | secs = mins * 60; | ||
203 | |||
204 | /* Add back the initially subtracted number of seconds */ | ||
205 | secs += get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
206 | |||
207 | rtc_time_to_tm(secs, &alarm->time); | ||
208 | |||
209 | return rtc_valid_tm(&alarm->time); | ||
210 | } | ||
211 | |||
212 | static int ab8500_rtc_irq_enable(struct device *dev, unsigned int enabled) | ||
213 | { | ||
214 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
215 | |||
216 | return ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_ALARM_ENA, | ||
217 | enabled ? RTC_ALARM_ENA : 0); | ||
218 | } | ||
219 | |||
220 | static int ab8500_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | ||
221 | { | ||
222 | struct ab8500 *ab8500 = dev_get_drvdata(dev->parent); | ||
223 | int retval, i; | ||
224 | unsigned char buf[ARRAY_SIZE(ab8500_rtc_alarm_regs)]; | ||
225 | unsigned long mins, secs = 0; | ||
226 | |||
227 | if (alarm->time.tm_year < (AB8500_RTC_EPOCH - 1900)) { | ||
228 | dev_dbg(dev, "year should be equal to or greater than %d\n", | ||
229 | AB8500_RTC_EPOCH); | ||
230 | return -EINVAL; | ||
231 | } | ||
232 | |||
233 | /* Get the number of seconds since 1970 */ | ||
234 | rtc_tm_to_time(&alarm->time, &secs); | ||
235 | |||
236 | /* | ||
237 | * Convert it to the number of seconds since 01-01-2000 00:00:00, since | ||
238 | * we only have a small counter in the RTC. | ||
239 | */ | ||
240 | secs -= get_elapsed_seconds(AB8500_RTC_EPOCH); | ||
241 | |||
242 | mins = secs / 60; | ||
243 | |||
244 | buf[2] = mins & 0xFF; | ||
245 | buf[1] = (mins >> 8) & 0xFF; | ||
246 | buf[0] = (mins >> 16) & 0xFF; | ||
247 | |||
248 | /* Set the alarm time */ | ||
249 | for (i = 0; i < ARRAY_SIZE(ab8500_rtc_alarm_regs); i++) { | ||
250 | retval = ab8500_write(ab8500, ab8500_rtc_alarm_regs[i], buf[i]); | ||
251 | if (retval < 0) | ||
252 | return retval; | ||
253 | } | ||
254 | |||
255 | return ab8500_rtc_irq_enable(dev, alarm->enabled); | ||
256 | } | ||
257 | |||
258 | static irqreturn_t rtc_alarm_handler(int irq, void *data) | ||
259 | { | ||
260 | struct rtc_device *rtc = data; | ||
261 | unsigned long events = RTC_IRQF | RTC_AF; | ||
262 | |||
263 | dev_dbg(&rtc->dev, "%s\n", __func__); | ||
264 | rtc_update_irq(rtc, 1, events); | ||
265 | |||
266 | return IRQ_HANDLED; | ||
267 | } | ||
268 | |||
269 | static const struct rtc_class_ops ab8500_rtc_ops = { | ||
270 | .read_time = ab8500_rtc_read_time, | ||
271 | .set_time = ab8500_rtc_set_time, | ||
272 | .read_alarm = ab8500_rtc_read_alarm, | ||
273 | .set_alarm = ab8500_rtc_set_alarm, | ||
274 | .alarm_irq_enable = ab8500_rtc_irq_enable, | ||
275 | }; | ||
276 | |||
277 | static int __devinit ab8500_rtc_probe(struct platform_device *pdev) | ||
278 | { | ||
279 | struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent); | ||
280 | int err; | ||
281 | struct rtc_device *rtc; | ||
282 | int rtc_ctrl; | ||
283 | int irq; | ||
284 | |||
285 | irq = platform_get_irq_byname(pdev, "ALARM"); | ||
286 | if (irq < 0) | ||
287 | return irq; | ||
288 | |||
289 | /* For RTC supply test */ | ||
290 | err = ab8500_set_bits(ab8500, AB8500_RTC_STAT_REG, RTC_STATUS_DATA, | ||
291 | RTC_STATUS_DATA); | ||
292 | if (err < 0) | ||
293 | return err; | ||
294 | |||
295 | /* Wait for reset by the PorRtc */ | ||
296 | msleep(1); | ||
297 | |||
298 | rtc_ctrl = ab8500_read(ab8500, AB8500_RTC_STAT_REG); | ||
299 | if (rtc_ctrl < 0) | ||
300 | return rtc_ctrl; | ||
301 | |||
302 | /* Check if the RTC Supply fails */ | ||
303 | if (!(rtc_ctrl & RTC_STATUS_DATA)) { | ||
304 | dev_err(&pdev->dev, "RTC supply failure\n"); | ||
305 | return -ENODEV; | ||
306 | } | ||
307 | |||
308 | rtc = rtc_device_register("ab8500-rtc", &pdev->dev, &ab8500_rtc_ops, | ||
309 | THIS_MODULE); | ||
310 | if (IS_ERR(rtc)) { | ||
311 | dev_err(&pdev->dev, "Registration failed\n"); | ||
312 | err = PTR_ERR(rtc); | ||
313 | return err; | ||
314 | } | ||
315 | |||
316 | err = request_threaded_irq(irq, NULL, rtc_alarm_handler, 0, | ||
317 | "ab8500-rtc", rtc); | ||
318 | if (err < 0) { | ||
319 | rtc_device_unregister(rtc); | ||
320 | return err; | ||
321 | } | ||
322 | |||
323 | platform_set_drvdata(pdev, rtc); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int __devexit ab8500_rtc_remove(struct platform_device *pdev) | ||
329 | { | ||
330 | struct rtc_device *rtc = platform_get_drvdata(pdev); | ||
331 | int irq = platform_get_irq_byname(pdev, "ALARM"); | ||
332 | |||
333 | free_irq(irq, rtc); | ||
334 | rtc_device_unregister(rtc); | ||
335 | platform_set_drvdata(pdev, NULL); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static struct platform_driver ab8500_rtc_driver = { | ||
341 | .driver = { | ||
342 | .name = "ab8500-rtc", | ||
343 | .owner = THIS_MODULE, | ||
344 | }, | ||
345 | .probe = ab8500_rtc_probe, | ||
346 | .remove = __devexit_p(ab8500_rtc_remove), | ||
347 | }; | ||
348 | |||
349 | static int __init ab8500_rtc_init(void) | ||
350 | { | ||
351 | return platform_driver_register(&ab8500_rtc_driver); | ||
352 | } | ||
353 | |||
354 | static void __exit ab8500_rtc_exit(void) | ||
355 | { | ||
356 | platform_driver_unregister(&ab8500_rtc_driver); | ||
357 | } | ||
358 | |||
359 | module_init(ab8500_rtc_init); | ||
360 | module_exit(ab8500_rtc_exit); | ||
361 | MODULE_AUTHOR("Virupax Sadashivpetimath <virupax.sadashivpetimath@stericsson.com>"); | ||
362 | MODULE_DESCRIPTION("AB8500 RTC Driver"); | ||
363 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 038095d99976..6dc4e6241418 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c | |||
@@ -595,10 +595,6 @@ static void wdt_disable(void) | |||
595 | static ssize_t wdt_write(struct file *file, const char __user *buf, | 595 | static ssize_t wdt_write(struct file *file, const char __user *buf, |
596 | size_t count, loff_t *ppos) | 596 | size_t count, loff_t *ppos) |
597 | { | 597 | { |
598 | /* Can't seek (pwrite) on this device | ||
599 | if (ppos != &file->f_pos) | ||
600 | return -ESPIPE; | ||
601 | */ | ||
602 | if (count) { | 598 | if (count) { |
603 | wdt_ping(); | 599 | wdt_ping(); |
604 | return 1; | 600 | return 1; |
@@ -707,7 +703,7 @@ static int wdt_open(struct inode *inode, struct file *file) | |||
707 | */ | 703 | */ |
708 | wdt_is_open = 1; | 704 | wdt_is_open = 1; |
709 | unlock_kernel(); | 705 | unlock_kernel(); |
710 | return 0; | 706 | return nonseekable_open(inode, file); |
711 | } | 707 | } |
712 | return -ENODEV; | 708 | return -ENODEV; |
713 | } | 709 | } |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 0e86247d791e..33975e922d65 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -1186,6 +1186,29 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
1186 | dasd_schedule_device_bh(device); | 1186 | dasd_schedule_device_bh(device); |
1187 | } | 1187 | } |
1188 | 1188 | ||
1189 | enum uc_todo dasd_generic_uc_handler(struct ccw_device *cdev, struct irb *irb) | ||
1190 | { | ||
1191 | struct dasd_device *device; | ||
1192 | |||
1193 | device = dasd_device_from_cdev_locked(cdev); | ||
1194 | |||
1195 | if (IS_ERR(device)) | ||
1196 | goto out; | ||
1197 | if (test_bit(DASD_FLAG_OFFLINE, &device->flags) || | ||
1198 | device->state != device->target || | ||
1199 | !device->discipline->handle_unsolicited_interrupt){ | ||
1200 | dasd_put_device(device); | ||
1201 | goto out; | ||
1202 | } | ||
1203 | |||
1204 | dasd_device_clear_timer(device); | ||
1205 | device->discipline->handle_unsolicited_interrupt(device, irb); | ||
1206 | dasd_put_device(device); | ||
1207 | out: | ||
1208 | return UC_TODO_RETRY; | ||
1209 | } | ||
1210 | EXPORT_SYMBOL_GPL(dasd_generic_uc_handler); | ||
1211 | |||
1189 | /* | 1212 | /* |
1190 | * If we have an error on a dasd_block layer request then we cancel | 1213 | * If we have an error on a dasd_block layer request then we cancel |
1191 | * and return all further requests from the same dasd_block as well. | 1214 | * and return all further requests from the same dasd_block as well. |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 5b1cd8d6e971..ab84da5592e8 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -3436,6 +3436,7 @@ static struct ccw_driver dasd_eckd_driver = { | |||
3436 | .freeze = dasd_generic_pm_freeze, | 3436 | .freeze = dasd_generic_pm_freeze, |
3437 | .thaw = dasd_generic_restore_device, | 3437 | .thaw = dasd_generic_restore_device, |
3438 | .restore = dasd_generic_restore_device, | 3438 | .restore = dasd_generic_restore_device, |
3439 | .uc_handler = dasd_generic_uc_handler, | ||
3439 | }; | 3440 | }; |
3440 | 3441 | ||
3441 | /* | 3442 | /* |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 32fac186ba3f..49b431d135e0 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -617,6 +617,7 @@ int dasd_generic_notify(struct ccw_device *, int); | |||
617 | void dasd_generic_handle_state_change(struct dasd_device *); | 617 | void dasd_generic_handle_state_change(struct dasd_device *); |
618 | int dasd_generic_pm_freeze(struct ccw_device *); | 618 | int dasd_generic_pm_freeze(struct ccw_device *); |
619 | int dasd_generic_restore_device(struct ccw_device *); | 619 | int dasd_generic_restore_device(struct ccw_device *); |
620 | enum uc_todo dasd_generic_uc_handler(struct ccw_device *, struct irb *); | ||
620 | 621 | ||
621 | int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); | 622 | int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); |
622 | char *dasd_get_sense(struct irb *); | 623 | char *dasd_get_sense(struct irb *); |
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5f97ea2ee6b1..97b25d68e3e7 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -123,8 +123,10 @@ ccwgroup_release (struct device *dev) | |||
123 | 123 | ||
124 | for (i = 0; i < gdev->count; i++) { | 124 | for (i = 0; i < gdev->count; i++) { |
125 | if (gdev->cdev[i]) { | 125 | if (gdev->cdev[i]) { |
126 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
126 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) | 127 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) |
127 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); | 128 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); |
129 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
128 | put_device(&gdev->cdev[i]->dev); | 130 | put_device(&gdev->cdev[i]->dev); |
129 | } | 131 | } |
130 | } | 132 | } |
@@ -262,11 +264,14 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
262 | goto error; | 264 | goto error; |
263 | } | 265 | } |
264 | /* Don't allow a device to belong to more than one group. */ | 266 | /* Don't allow a device to belong to more than one group. */ |
267 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
265 | if (dev_get_drvdata(&gdev->cdev[i]->dev)) { | 268 | if (dev_get_drvdata(&gdev->cdev[i]->dev)) { |
269 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
266 | rc = -EINVAL; | 270 | rc = -EINVAL; |
267 | goto error; | 271 | goto error; |
268 | } | 272 | } |
269 | dev_set_drvdata(&gdev->cdev[i]->dev, gdev); | 273 | dev_set_drvdata(&gdev->cdev[i]->dev, gdev); |
274 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
270 | } | 275 | } |
271 | /* Check for sufficient number of bus ids. */ | 276 | /* Check for sufficient number of bus ids. */ |
272 | if (i < num_devices && !curr_buf) { | 277 | if (i < num_devices && !curr_buf) { |
@@ -303,8 +308,10 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, | |||
303 | error: | 308 | error: |
304 | for (i = 0; i < num_devices; i++) | 309 | for (i = 0; i < num_devices; i++) |
305 | if (gdev->cdev[i]) { | 310 | if (gdev->cdev[i]) { |
311 | spin_lock_irq(gdev->cdev[i]->ccwlock); | ||
306 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) | 312 | if (dev_get_drvdata(&gdev->cdev[i]->dev) == gdev) |
307 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); | 313 | dev_set_drvdata(&gdev->cdev[i]->dev, NULL); |
314 | spin_unlock_irq(gdev->cdev[i]->ccwlock); | ||
308 | put_device(&gdev->cdev[i]->dev); | 315 | put_device(&gdev->cdev[i]->dev); |
309 | gdev->cdev[i] = NULL; | 316 | gdev->cdev[i] = NULL; |
310 | } | 317 | } |
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c index 37df42af05ec..7f206ed44fdf 100644 --- a/drivers/s390/cio/ccwreq.c +++ b/drivers/s390/cio/ccwreq.c | |||
@@ -159,6 +159,7 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
159 | { | 159 | { |
160 | struct irb *irb = &cdev->private->irb; | 160 | struct irb *irb = &cdev->private->irb; |
161 | struct cmd_scsw *scsw = &irb->scsw.cmd; | 161 | struct cmd_scsw *scsw = &irb->scsw.cmd; |
162 | enum uc_todo todo; | ||
162 | 163 | ||
163 | /* Perform BASIC SENSE if needed. */ | 164 | /* Perform BASIC SENSE if needed. */ |
164 | if (ccw_device_accumulate_and_sense(cdev, lcirb)) | 165 | if (ccw_device_accumulate_and_sense(cdev, lcirb)) |
@@ -178,6 +179,20 @@ static enum io_status ccwreq_status(struct ccw_device *cdev, struct irb *lcirb) | |||
178 | /* Check for command reject. */ | 179 | /* Check for command reject. */ |
179 | if (irb->ecw[0] & SNS0_CMD_REJECT) | 180 | if (irb->ecw[0] & SNS0_CMD_REJECT) |
180 | return IO_REJECTED; | 181 | return IO_REJECTED; |
182 | /* Ask the driver what to do */ | ||
183 | if (cdev->drv && cdev->drv->uc_handler) { | ||
184 | todo = cdev->drv->uc_handler(cdev, lcirb); | ||
185 | switch (todo) { | ||
186 | case UC_TODO_RETRY: | ||
187 | return IO_STATUS_ERROR; | ||
188 | case UC_TODO_RETRY_ON_NEW_PATH: | ||
189 | return IO_PATH_ERROR; | ||
190 | case UC_TODO_STOP: | ||
191 | return IO_REJECTED; | ||
192 | default: | ||
193 | return IO_STATUS_ERROR; | ||
194 | } | ||
195 | } | ||
181 | /* Assume that unexpected SENSE data implies an error. */ | 196 | /* Assume that unexpected SENSE data implies an error. */ |
182 | return IO_STATUS_ERROR; | 197 | return IO_STATUS_ERROR; |
183 | } | 198 | } |
diff --git a/drivers/s390/cio/ioasm.h b/drivers/s390/cio/ioasm.h index 759262792633..fac06155773f 100644 --- a/drivers/s390/cio/ioasm.h +++ b/drivers/s390/cio/ioasm.h | |||
@@ -23,21 +23,6 @@ struct tpi_info { | |||
23 | * Some S390 specific IO instructions as inline | 23 | * Some S390 specific IO instructions as inline |
24 | */ | 24 | */ |
25 | 25 | ||
26 | static inline int stsch(struct subchannel_id schid, struct schib *addr) | ||
27 | { | ||
28 | register struct subchannel_id reg1 asm ("1") = schid; | ||
29 | int ccode; | ||
30 | |||
31 | asm volatile( | ||
32 | " stsch 0(%3)\n" | ||
33 | " ipm %0\n" | ||
34 | " srl %0,28" | ||
35 | : "=d" (ccode), "=m" (*addr) | ||
36 | : "d" (reg1), "a" (addr) | ||
37 | : "cc"); | ||
38 | return ccode; | ||
39 | } | ||
40 | |||
41 | static inline int stsch_err(struct subchannel_id schid, struct schib *addr) | 26 | static inline int stsch_err(struct subchannel_id schid, struct schib *addr) |
42 | { | 27 | { |
43 | register struct subchannel_id reg1 asm ("1") = schid; | 28 | register struct subchannel_id reg1 asm ("1") = schid; |
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index 308541ff85cf..1bb5d3f0e260 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c | |||
@@ -1,34 +1,31 @@ | |||
1 | #include <linux/types.h> | 1 | #include <linux/types.h> |
2 | #include <linux/mm.h> | ||
3 | #include <linux/slab.h> | ||
4 | #include <linux/blkdev.h> | ||
5 | #include <linux/init.h> | 2 | #include <linux/init.h> |
6 | #include <linux/interrupt.h> | 3 | #include <linux/interrupt.h> |
4 | #include <linux/mm.h> | ||
5 | #include <linux/slab.h> | ||
6 | #include <linux/spinlock.h> | ||
7 | #include <linux/zorro.h> | ||
7 | 8 | ||
8 | #include <asm/setup.h> | ||
9 | #include <asm/page.h> | 9 | #include <asm/page.h> |
10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
11 | #include <asm/amigaints.h> | 11 | #include <asm/amigaints.h> |
12 | #include <asm/amigahw.h> | 12 | #include <asm/amigahw.h> |
13 | #include <linux/zorro.h> | ||
14 | #include <asm/irq.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | 13 | ||
17 | #include "scsi.h" | 14 | #include "scsi.h" |
18 | #include <scsi/scsi_host.h> | ||
19 | #include "wd33c93.h" | 15 | #include "wd33c93.h" |
20 | #include "a2091.h" | 16 | #include "a2091.h" |
21 | 17 | ||
22 | #include <linux/stat.h> | ||
23 | |||
24 | 18 | ||
25 | static int a2091_release(struct Scsi_Host *instance); | 19 | struct a2091_hostdata { |
20 | struct WD33C93_hostdata wh; | ||
21 | struct a2091_scsiregs *regs; | ||
22 | }; | ||
26 | 23 | ||
27 | static irqreturn_t a2091_intr(int irq, void *data) | 24 | static irqreturn_t a2091_intr(int irq, void *data) |
28 | { | 25 | { |
29 | struct Scsi_Host *instance = data; | 26 | struct Scsi_Host *instance = data; |
30 | a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); | 27 | struct a2091_hostdata *hdata = shost_priv(instance); |
31 | unsigned int status = regs->ISTR; | 28 | unsigned int status = hdata->regs->ISTR; |
32 | unsigned long flags; | 29 | unsigned long flags; |
33 | 30 | ||
34 | if (!(status & (ISTR_INT_F | ISTR_INT_P)) || !(status & ISTR_INTS)) | 31 | if (!(status & (ISTR_INT_F | ISTR_INT_P)) || !(status & ISTR_INTS)) |
@@ -43,38 +40,39 @@ static irqreturn_t a2091_intr(int irq, void *data) | |||
43 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | 40 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) |
44 | { | 41 | { |
45 | struct Scsi_Host *instance = cmd->device->host; | 42 | struct Scsi_Host *instance = cmd->device->host; |
46 | struct WD33C93_hostdata *hdata = shost_priv(instance); | 43 | struct a2091_hostdata *hdata = shost_priv(instance); |
47 | a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); | 44 | struct WD33C93_hostdata *wh = &hdata->wh; |
45 | struct a2091_scsiregs *regs = hdata->regs; | ||
48 | unsigned short cntr = CNTR_PDMD | CNTR_INTEN; | 46 | unsigned short cntr = CNTR_PDMD | CNTR_INTEN; |
49 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); | 47 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); |
50 | 48 | ||
51 | /* don't allow DMA if the physical address is bad */ | 49 | /* don't allow DMA if the physical address is bad */ |
52 | if (addr & A2091_XFER_MASK) { | 50 | if (addr & A2091_XFER_MASK) { |
53 | hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; | 51 | wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; |
54 | hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, | 52 | wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len, |
55 | GFP_KERNEL); | 53 | GFP_KERNEL); |
56 | 54 | ||
57 | /* can't allocate memory; use PIO */ | 55 | /* can't allocate memory; use PIO */ |
58 | if (!hdata->dma_bounce_buffer) { | 56 | if (!wh->dma_bounce_buffer) { |
59 | hdata->dma_bounce_len = 0; | 57 | wh->dma_bounce_len = 0; |
60 | return 1; | 58 | return 1; |
61 | } | 59 | } |
62 | 60 | ||
63 | /* get the physical address of the bounce buffer */ | 61 | /* get the physical address of the bounce buffer */ |
64 | addr = virt_to_bus(hdata->dma_bounce_buffer); | 62 | addr = virt_to_bus(wh->dma_bounce_buffer); |
65 | 63 | ||
66 | /* the bounce buffer may not be in the first 16M of physmem */ | 64 | /* the bounce buffer may not be in the first 16M of physmem */ |
67 | if (addr & A2091_XFER_MASK) { | 65 | if (addr & A2091_XFER_MASK) { |
68 | /* we could use chipmem... maybe later */ | 66 | /* we could use chipmem... maybe later */ |
69 | kfree(hdata->dma_bounce_buffer); | 67 | kfree(wh->dma_bounce_buffer); |
70 | hdata->dma_bounce_buffer = NULL; | 68 | wh->dma_bounce_buffer = NULL; |
71 | hdata->dma_bounce_len = 0; | 69 | wh->dma_bounce_len = 0; |
72 | return 1; | 70 | return 1; |
73 | } | 71 | } |
74 | 72 | ||
75 | if (!dir_in) { | 73 | if (!dir_in) { |
76 | /* copy to bounce buffer for a write */ | 74 | /* copy to bounce buffer for a write */ |
77 | memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, | 75 | memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr, |
78 | cmd->SCp.this_residual); | 76 | cmd->SCp.this_residual); |
79 | } | 77 | } |
80 | } | 78 | } |
@@ -84,7 +82,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
84 | cntr |= CNTR_DDIR; | 82 | cntr |= CNTR_DDIR; |
85 | 83 | ||
86 | /* remember direction */ | 84 | /* remember direction */ |
87 | hdata->dma_dir = dir_in; | 85 | wh->dma_dir = dir_in; |
88 | 86 | ||
89 | regs->CNTR = cntr; | 87 | regs->CNTR = cntr; |
90 | 88 | ||
@@ -108,20 +106,21 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
108 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | 106 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, |
109 | int status) | 107 | int status) |
110 | { | 108 | { |
111 | struct WD33C93_hostdata *hdata = shost_priv(instance); | 109 | struct a2091_hostdata *hdata = shost_priv(instance); |
112 | a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); | 110 | struct WD33C93_hostdata *wh = &hdata->wh; |
111 | struct a2091_scsiregs *regs = hdata->regs; | ||
113 | 112 | ||
114 | /* disable SCSI interrupts */ | 113 | /* disable SCSI interrupts */ |
115 | unsigned short cntr = CNTR_PDMD; | 114 | unsigned short cntr = CNTR_PDMD; |
116 | 115 | ||
117 | if (!hdata->dma_dir) | 116 | if (!wh->dma_dir) |
118 | cntr |= CNTR_DDIR; | 117 | cntr |= CNTR_DDIR; |
119 | 118 | ||
120 | /* disable SCSI interrupts */ | 119 | /* disable SCSI interrupts */ |
121 | regs->CNTR = cntr; | 120 | regs->CNTR = cntr; |
122 | 121 | ||
123 | /* flush if we were reading */ | 122 | /* flush if we were reading */ |
124 | if (hdata->dma_dir) { | 123 | if (wh->dma_dir) { |
125 | regs->FLUSH = 1; | 124 | regs->FLUSH = 1; |
126 | while (!(regs->ISTR & ISTR_FE_FLG)) | 125 | while (!(regs->ISTR & ISTR_FE_FLG)) |
127 | ; | 126 | ; |
@@ -137,95 +136,37 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | |||
137 | regs->CNTR = CNTR_PDMD | CNTR_INTEN; | 136 | regs->CNTR = CNTR_PDMD | CNTR_INTEN; |
138 | 137 | ||
139 | /* copy from a bounce buffer, if necessary */ | 138 | /* copy from a bounce buffer, if necessary */ |
140 | if (status && hdata->dma_bounce_buffer) { | 139 | if (status && wh->dma_bounce_buffer) { |
141 | if (hdata->dma_dir) | 140 | if (wh->dma_dir) |
142 | memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer, | 141 | memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer, |
143 | SCpnt->SCp.this_residual); | 142 | SCpnt->SCp.this_residual); |
144 | kfree(hdata->dma_bounce_buffer); | 143 | kfree(wh->dma_bounce_buffer); |
145 | hdata->dma_bounce_buffer = NULL; | 144 | wh->dma_bounce_buffer = NULL; |
146 | hdata->dma_bounce_len = 0; | 145 | wh->dma_bounce_len = 0; |
147 | } | ||
148 | } | ||
149 | |||
150 | static int __init a2091_detect(struct scsi_host_template *tpnt) | ||
151 | { | ||
152 | static unsigned char called = 0; | ||
153 | struct Scsi_Host *instance; | ||
154 | unsigned long address; | ||
155 | struct zorro_dev *z = NULL; | ||
156 | wd33c93_regs wdregs; | ||
157 | a2091_scsiregs *regs; | ||
158 | struct WD33C93_hostdata *hdata; | ||
159 | int num_a2091 = 0; | ||
160 | |||
161 | if (!MACH_IS_AMIGA || called) | ||
162 | return 0; | ||
163 | called = 1; | ||
164 | |||
165 | tpnt->proc_name = "A2091"; | ||
166 | tpnt->proc_info = &wd33c93_proc_info; | ||
167 | |||
168 | while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { | ||
169 | if (z->id != ZORRO_PROD_CBM_A590_A2091_1 && | ||
170 | z->id != ZORRO_PROD_CBM_A590_A2091_2) | ||
171 | continue; | ||
172 | address = z->resource.start; | ||
173 | if (!request_mem_region(address, 256, "wd33c93")) | ||
174 | continue; | ||
175 | |||
176 | instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); | ||
177 | if (instance == NULL) | ||
178 | goto release; | ||
179 | instance->base = ZTWO_VADDR(address); | ||
180 | instance->irq = IRQ_AMIGA_PORTS; | ||
181 | instance->unique_id = z->slotaddr; | ||
182 | regs = (a2091_scsiregs *)(instance->base); | ||
183 | regs->DAWR = DAWR_A2091; | ||
184 | wdregs.SASR = ®s->SASR; | ||
185 | wdregs.SCMD = ®s->SCMD; | ||
186 | hdata = shost_priv(instance); | ||
187 | hdata->no_sync = 0xff; | ||
188 | hdata->fast = 0; | ||
189 | hdata->dma_mode = CTRL_DMA; | ||
190 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, | ||
191 | WD33C93_FS_8_10); | ||
192 | if (request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, | ||
193 | "A2091 SCSI", instance)) | ||
194 | goto unregister; | ||
195 | regs->CNTR = CNTR_PDMD | CNTR_INTEN; | ||
196 | num_a2091++; | ||
197 | continue; | ||
198 | |||
199 | unregister: | ||
200 | scsi_unregister(instance); | ||
201 | release: | ||
202 | release_mem_region(address, 256); | ||
203 | } | 146 | } |
204 | |||
205 | return num_a2091; | ||
206 | } | 147 | } |
207 | 148 | ||
208 | static int a2091_bus_reset(struct scsi_cmnd *cmd) | 149 | static int a2091_bus_reset(struct scsi_cmnd *cmd) |
209 | { | 150 | { |
151 | struct Scsi_Host *instance = cmd->device->host; | ||
152 | |||
210 | /* FIXME perform bus-specific reset */ | 153 | /* FIXME perform bus-specific reset */ |
211 | 154 | ||
212 | /* FIXME 2: kill this function, and let midlayer fall back | 155 | /* FIXME 2: kill this function, and let midlayer fall back |
213 | to the same action, calling wd33c93_host_reset() */ | 156 | to the same action, calling wd33c93_host_reset() */ |
214 | 157 | ||
215 | spin_lock_irq(cmd->device->host->host_lock); | 158 | spin_lock_irq(instance->host_lock); |
216 | wd33c93_host_reset(cmd); | 159 | wd33c93_host_reset(cmd); |
217 | spin_unlock_irq(cmd->device->host->host_lock); | 160 | spin_unlock_irq(instance->host_lock); |
218 | 161 | ||
219 | return SUCCESS; | 162 | return SUCCESS; |
220 | } | 163 | } |
221 | 164 | ||
222 | #define HOSTS_C | 165 | static struct scsi_host_template a2091_scsi_template = { |
223 | 166 | .module = THIS_MODULE, | |
224 | static struct scsi_host_template driver_template = { | ||
225 | .proc_name = "A2901", | ||
226 | .name = "Commodore A2091/A590 SCSI", | 167 | .name = "Commodore A2091/A590 SCSI", |
227 | .detect = a2091_detect, | 168 | .proc_info = wd33c93_proc_info, |
228 | .release = a2091_release, | 169 | .proc_name = "A2901", |
229 | .queuecommand = wd33c93_queuecommand, | 170 | .queuecommand = wd33c93_queuecommand, |
230 | .eh_abort_handler = wd33c93_abort, | 171 | .eh_abort_handler = wd33c93_abort, |
231 | .eh_bus_reset_handler = a2091_bus_reset, | 172 | .eh_bus_reset_handler = a2091_bus_reset, |
@@ -237,19 +178,103 @@ static struct scsi_host_template driver_template = { | |||
237 | .use_clustering = DISABLE_CLUSTERING | 178 | .use_clustering = DISABLE_CLUSTERING |
238 | }; | 179 | }; |
239 | 180 | ||
181 | static int __devinit a2091_probe(struct zorro_dev *z, | ||
182 | const struct zorro_device_id *ent) | ||
183 | { | ||
184 | struct Scsi_Host *instance; | ||
185 | int error; | ||
186 | struct a2091_scsiregs *regs; | ||
187 | wd33c93_regs wdregs; | ||
188 | struct a2091_hostdata *hdata; | ||
240 | 189 | ||
241 | #include "scsi_module.c" | 190 | if (!request_mem_region(z->resource.start, 256, "wd33c93")) |
191 | return -EBUSY; | ||
242 | 192 | ||
243 | static int a2091_release(struct Scsi_Host *instance) | 193 | instance = scsi_host_alloc(&a2091_scsi_template, |
194 | sizeof(struct a2091_hostdata)); | ||
195 | if (!instance) { | ||
196 | error = -ENOMEM; | ||
197 | goto fail_alloc; | ||
198 | } | ||
199 | |||
200 | instance->irq = IRQ_AMIGA_PORTS; | ||
201 | instance->unique_id = z->slotaddr; | ||
202 | |||
203 | regs = (struct a2091_scsiregs *)ZTWO_VADDR(z->resource.start); | ||
204 | regs->DAWR = DAWR_A2091; | ||
205 | |||
206 | wdregs.SASR = ®s->SASR; | ||
207 | wdregs.SCMD = ®s->SCMD; | ||
208 | |||
209 | hdata = shost_priv(instance); | ||
210 | hdata->wh.no_sync = 0xff; | ||
211 | hdata->wh.fast = 0; | ||
212 | hdata->wh.dma_mode = CTRL_DMA; | ||
213 | hdata->regs = regs; | ||
214 | |||
215 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_8_10); | ||
216 | error = request_irq(IRQ_AMIGA_PORTS, a2091_intr, IRQF_SHARED, | ||
217 | "A2091 SCSI", instance); | ||
218 | if (error) | ||
219 | goto fail_irq; | ||
220 | |||
221 | regs->CNTR = CNTR_PDMD | CNTR_INTEN; | ||
222 | |||
223 | error = scsi_add_host(instance, NULL); | ||
224 | if (error) | ||
225 | goto fail_host; | ||
226 | |||
227 | zorro_set_drvdata(z, instance); | ||
228 | |||
229 | scsi_scan_host(instance); | ||
230 | return 0; | ||
231 | |||
232 | fail_host: | ||
233 | free_irq(IRQ_AMIGA_PORTS, instance); | ||
234 | fail_irq: | ||
235 | scsi_host_put(instance); | ||
236 | fail_alloc: | ||
237 | release_mem_region(z->resource.start, 256); | ||
238 | return error; | ||
239 | } | ||
240 | |||
241 | static void __devexit a2091_remove(struct zorro_dev *z) | ||
244 | { | 242 | { |
245 | #ifdef MODULE | 243 | struct Scsi_Host *instance = zorro_get_drvdata(z); |
246 | a2091_scsiregs *regs = (a2091_scsiregs *)(instance->base); | 244 | struct a2091_hostdata *hdata = shost_priv(instance); |
247 | 245 | ||
248 | regs->CNTR = 0; | 246 | hdata->regs->CNTR = 0; |
249 | release_mem_region(ZTWO_PADDR(instance->base), 256); | 247 | scsi_remove_host(instance); |
250 | free_irq(IRQ_AMIGA_PORTS, instance); | 248 | free_irq(IRQ_AMIGA_PORTS, instance); |
251 | #endif | 249 | scsi_host_put(instance); |
252 | return 1; | 250 | release_mem_region(z->resource.start, 256); |
251 | } | ||
252 | |||
253 | static struct zorro_device_id a2091_zorro_tbl[] __devinitdata = { | ||
254 | { ZORRO_PROD_CBM_A590_A2091_1 }, | ||
255 | { ZORRO_PROD_CBM_A590_A2091_2 }, | ||
256 | { 0 } | ||
257 | }; | ||
258 | MODULE_DEVICE_TABLE(zorro, a2091_zorro_tbl); | ||
259 | |||
260 | static struct zorro_driver a2091_driver = { | ||
261 | .name = "a2091", | ||
262 | .id_table = a2091_zorro_tbl, | ||
263 | .probe = a2091_probe, | ||
264 | .remove = __devexit_p(a2091_remove), | ||
265 | }; | ||
266 | |||
267 | static int __init a2091_init(void) | ||
268 | { | ||
269 | return zorro_register_driver(&a2091_driver); | ||
270 | } | ||
271 | module_init(a2091_init); | ||
272 | |||
273 | static void __exit a2091_exit(void) | ||
274 | { | ||
275 | zorro_unregister_driver(&a2091_driver); | ||
253 | } | 276 | } |
277 | module_exit(a2091_exit); | ||
254 | 278 | ||
279 | MODULE_DESCRIPTION("Commodore A2091/A590 SCSI"); | ||
255 | MODULE_LICENSE("GPL"); | 280 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h index 1c3daa1fd754..794b8e65c711 100644 --- a/drivers/scsi/a2091.h +++ b/drivers/scsi/a2091.h | |||
@@ -25,7 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | #define A2091_XFER_MASK (0xff000001) | 26 | #define A2091_XFER_MASK (0xff000001) |
27 | 27 | ||
28 | typedef struct { | 28 | struct a2091_scsiregs { |
29 | unsigned char pad1[64]; | 29 | unsigned char pad1[64]; |
30 | volatile unsigned short ISTR; | 30 | volatile unsigned short ISTR; |
31 | volatile unsigned short CNTR; | 31 | volatile unsigned short CNTR; |
@@ -44,7 +44,7 @@ typedef struct { | |||
44 | volatile unsigned short CINT; | 44 | volatile unsigned short CINT; |
45 | unsigned char pad7[2]; | 45 | unsigned char pad7[2]; |
46 | volatile unsigned short FLUSH; | 46 | volatile unsigned short FLUSH; |
47 | } a2091_scsiregs; | 47 | }; |
48 | 48 | ||
49 | #define DAWR_A2091 (3) | 49 | #define DAWR_A2091 (3) |
50 | 50 | ||
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c index bc6eb69f5fd0..d9468027fb61 100644 --- a/drivers/scsi/a3000.c +++ b/drivers/scsi/a3000.c | |||
@@ -1,53 +1,52 @@ | |||
1 | #include <linux/types.h> | 1 | #include <linux/types.h> |
2 | #include <linux/mm.h> | 2 | #include <linux/mm.h> |
3 | #include <linux/slab.h> | ||
4 | #include <linux/blkdev.h> | ||
5 | #include <linux/ioport.h> | 3 | #include <linux/ioport.h> |
6 | #include <linux/init.h> | 4 | #include <linux/init.h> |
5 | #include <linux/slab.h> | ||
7 | #include <linux/spinlock.h> | 6 | #include <linux/spinlock.h> |
8 | #include <linux/interrupt.h> | 7 | #include <linux/interrupt.h> |
8 | #include <linux/platform_device.h> | ||
9 | 9 | ||
10 | #include <asm/setup.h> | ||
11 | #include <asm/page.h> | 10 | #include <asm/page.h> |
12 | #include <asm/pgtable.h> | 11 | #include <asm/pgtable.h> |
13 | #include <asm/amigaints.h> | 12 | #include <asm/amigaints.h> |
14 | #include <asm/amigahw.h> | 13 | #include <asm/amigahw.h> |
15 | #include <asm/irq.h> | ||
16 | 14 | ||
17 | #include "scsi.h" | 15 | #include "scsi.h" |
18 | #include <scsi/scsi_host.h> | ||
19 | #include "wd33c93.h" | 16 | #include "wd33c93.h" |
20 | #include "a3000.h" | 17 | #include "a3000.h" |
21 | 18 | ||
22 | #include <linux/stat.h> | ||
23 | |||
24 | 19 | ||
25 | #define DMA(ptr) ((a3000_scsiregs *)((ptr)->base)) | 20 | struct a3000_hostdata { |
26 | 21 | struct WD33C93_hostdata wh; | |
27 | static struct Scsi_Host *a3000_host = NULL; | 22 | struct a3000_scsiregs *regs; |
28 | 23 | }; | |
29 | static int a3000_release(struct Scsi_Host *instance); | ||
30 | 24 | ||
31 | static irqreturn_t a3000_intr(int irq, void *dummy) | 25 | static irqreturn_t a3000_intr(int irq, void *data) |
32 | { | 26 | { |
27 | struct Scsi_Host *instance = data; | ||
28 | struct a3000_hostdata *hdata = shost_priv(instance); | ||
29 | unsigned int status = hdata->regs->ISTR; | ||
33 | unsigned long flags; | 30 | unsigned long flags; |
34 | unsigned int status = DMA(a3000_host)->ISTR; | ||
35 | 31 | ||
36 | if (!(status & ISTR_INT_P)) | 32 | if (!(status & ISTR_INT_P)) |
37 | return IRQ_NONE; | 33 | return IRQ_NONE; |
38 | if (status & ISTR_INTS) { | 34 | if (status & ISTR_INTS) { |
39 | spin_lock_irqsave(a3000_host->host_lock, flags); | 35 | spin_lock_irqsave(instance->host_lock, flags); |
40 | wd33c93_intr(a3000_host); | 36 | wd33c93_intr(instance); |
41 | spin_unlock_irqrestore(a3000_host->host_lock, flags); | 37 | spin_unlock_irqrestore(instance->host_lock, flags); |
42 | return IRQ_HANDLED; | 38 | return IRQ_HANDLED; |
43 | } | 39 | } |
44 | printk("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); | 40 | pr_warning("Non-serviced A3000 SCSI-interrupt? ISTR = %02x\n", status); |
45 | return IRQ_NONE; | 41 | return IRQ_NONE; |
46 | } | 42 | } |
47 | 43 | ||
48 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | 44 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) |
49 | { | 45 | { |
50 | struct WD33C93_hostdata *hdata = shost_priv(a3000_host); | 46 | struct Scsi_Host *instance = cmd->device->host; |
47 | struct a3000_hostdata *hdata = shost_priv(instance); | ||
48 | struct WD33C93_hostdata *wh = &hdata->wh; | ||
49 | struct a3000_scsiregs *regs = hdata->regs; | ||
51 | unsigned short cntr = CNTR_PDMD | CNTR_INTEN; | 50 | unsigned short cntr = CNTR_PDMD | CNTR_INTEN; |
52 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); | 51 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); |
53 | 52 | ||
@@ -58,23 +57,23 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
58 | * buffer | 57 | * buffer |
59 | */ | 58 | */ |
60 | if (addr & A3000_XFER_MASK) { | 59 | if (addr & A3000_XFER_MASK) { |
61 | hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; | 60 | wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; |
62 | hdata->dma_bounce_buffer = kmalloc(hdata->dma_bounce_len, | 61 | wh->dma_bounce_buffer = kmalloc(wh->dma_bounce_len, |
63 | GFP_KERNEL); | 62 | GFP_KERNEL); |
64 | 63 | ||
65 | /* can't allocate memory; use PIO */ | 64 | /* can't allocate memory; use PIO */ |
66 | if (!hdata->dma_bounce_buffer) { | 65 | if (!wh->dma_bounce_buffer) { |
67 | hdata->dma_bounce_len = 0; | 66 | wh->dma_bounce_len = 0; |
68 | return 1; | 67 | return 1; |
69 | } | 68 | } |
70 | 69 | ||
71 | if (!dir_in) { | 70 | if (!dir_in) { |
72 | /* copy to bounce buffer for a write */ | 71 | /* copy to bounce buffer for a write */ |
73 | memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, | 72 | memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr, |
74 | cmd->SCp.this_residual); | 73 | cmd->SCp.this_residual); |
75 | } | 74 | } |
76 | 75 | ||
77 | addr = virt_to_bus(hdata->dma_bounce_buffer); | 76 | addr = virt_to_bus(wh->dma_bounce_buffer); |
78 | } | 77 | } |
79 | 78 | ||
80 | /* setup dma direction */ | 79 | /* setup dma direction */ |
@@ -82,12 +81,12 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
82 | cntr |= CNTR_DDIR; | 81 | cntr |= CNTR_DDIR; |
83 | 82 | ||
84 | /* remember direction */ | 83 | /* remember direction */ |
85 | hdata->dma_dir = dir_in; | 84 | wh->dma_dir = dir_in; |
86 | 85 | ||
87 | DMA(a3000_host)->CNTR = cntr; | 86 | regs->CNTR = cntr; |
88 | 87 | ||
89 | /* setup DMA *physical* address */ | 88 | /* setup DMA *physical* address */ |
90 | DMA(a3000_host)->ACR = addr; | 89 | regs->ACR = addr; |
91 | 90 | ||
92 | if (dir_in) { | 91 | if (dir_in) { |
93 | /* invalidate any cache */ | 92 | /* invalidate any cache */ |
@@ -99,7 +98,7 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
99 | 98 | ||
100 | /* start DMA */ | 99 | /* start DMA */ |
101 | mb(); /* make sure setup is completed */ | 100 | mb(); /* make sure setup is completed */ |
102 | DMA(a3000_host)->ST_DMA = 1; | 101 | regs->ST_DMA = 1; |
103 | mb(); /* make sure DMA has started before next IO */ | 102 | mb(); /* make sure DMA has started before next IO */ |
104 | 103 | ||
105 | /* return success */ | 104 | /* return success */ |
@@ -109,22 +108,24 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
109 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | 108 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, |
110 | int status) | 109 | int status) |
111 | { | 110 | { |
112 | struct WD33C93_hostdata *hdata = shost_priv(instance); | 111 | struct a3000_hostdata *hdata = shost_priv(instance); |
112 | struct WD33C93_hostdata *wh = &hdata->wh; | ||
113 | struct a3000_scsiregs *regs = hdata->regs; | ||
113 | 114 | ||
114 | /* disable SCSI interrupts */ | 115 | /* disable SCSI interrupts */ |
115 | unsigned short cntr = CNTR_PDMD; | 116 | unsigned short cntr = CNTR_PDMD; |
116 | 117 | ||
117 | if (!hdata->dma_dir) | 118 | if (!wh->dma_dir) |
118 | cntr |= CNTR_DDIR; | 119 | cntr |= CNTR_DDIR; |
119 | 120 | ||
120 | DMA(instance)->CNTR = cntr; | 121 | regs->CNTR = cntr; |
121 | mb(); /* make sure CNTR is updated before next IO */ | 122 | mb(); /* make sure CNTR is updated before next IO */ |
122 | 123 | ||
123 | /* flush if we were reading */ | 124 | /* flush if we were reading */ |
124 | if (hdata->dma_dir) { | 125 | if (wh->dma_dir) { |
125 | DMA(instance)->FLUSH = 1; | 126 | regs->FLUSH = 1; |
126 | mb(); /* don't allow prefetch */ | 127 | mb(); /* don't allow prefetch */ |
127 | while (!(DMA(instance)->ISTR & ISTR_FE_FLG)) | 128 | while (!(regs->ISTR & ISTR_FE_FLG)) |
128 | barrier(); | 129 | barrier(); |
129 | mb(); /* no IO until FLUSH is done */ | 130 | mb(); /* no IO until FLUSH is done */ |
130 | } | 131 | } |
@@ -133,96 +134,54 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | |||
133 | /* I think that this CINT is only necessary if you are | 134 | /* I think that this CINT is only necessary if you are |
134 | * using the terminal count features. HM 7 Mar 1994 | 135 | * using the terminal count features. HM 7 Mar 1994 |
135 | */ | 136 | */ |
136 | DMA(instance)->CINT = 1; | 137 | regs->CINT = 1; |
137 | 138 | ||
138 | /* stop DMA */ | 139 | /* stop DMA */ |
139 | DMA(instance)->SP_DMA = 1; | 140 | regs->SP_DMA = 1; |
140 | mb(); /* make sure DMA is stopped before next IO */ | 141 | mb(); /* make sure DMA is stopped before next IO */ |
141 | 142 | ||
142 | /* restore the CONTROL bits (minus the direction flag) */ | 143 | /* restore the CONTROL bits (minus the direction flag) */ |
143 | DMA(instance)->CNTR = CNTR_PDMD | CNTR_INTEN; | 144 | regs->CNTR = CNTR_PDMD | CNTR_INTEN; |
144 | mb(); /* make sure CNTR is updated before next IO */ | 145 | mb(); /* make sure CNTR is updated before next IO */ |
145 | 146 | ||
146 | /* copy from a bounce buffer, if necessary */ | 147 | /* copy from a bounce buffer, if necessary */ |
147 | if (status && hdata->dma_bounce_buffer) { | 148 | if (status && wh->dma_bounce_buffer) { |
148 | if (SCpnt) { | 149 | if (SCpnt) { |
149 | if (hdata->dma_dir && SCpnt) | 150 | if (wh->dma_dir && SCpnt) |
150 | memcpy(SCpnt->SCp.ptr, | 151 | memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer, |
151 | hdata->dma_bounce_buffer, | ||
152 | SCpnt->SCp.this_residual); | 152 | SCpnt->SCp.this_residual); |
153 | kfree(hdata->dma_bounce_buffer); | 153 | kfree(wh->dma_bounce_buffer); |
154 | hdata->dma_bounce_buffer = NULL; | 154 | wh->dma_bounce_buffer = NULL; |
155 | hdata->dma_bounce_len = 0; | 155 | wh->dma_bounce_len = 0; |
156 | } else { | 156 | } else { |
157 | kfree(hdata->dma_bounce_buffer); | 157 | kfree(wh->dma_bounce_buffer); |
158 | hdata->dma_bounce_buffer = NULL; | 158 | wh->dma_bounce_buffer = NULL; |
159 | hdata->dma_bounce_len = 0; | 159 | wh->dma_bounce_len = 0; |
160 | } | 160 | } |
161 | } | 161 | } |
162 | } | 162 | } |
163 | 163 | ||
164 | static int __init a3000_detect(struct scsi_host_template *tpnt) | ||
165 | { | ||
166 | wd33c93_regs regs; | ||
167 | struct WD33C93_hostdata *hdata; | ||
168 | |||
169 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(A3000_SCSI)) | ||
170 | return 0; | ||
171 | if (!request_mem_region(0xDD0000, 256, "wd33c93")) | ||
172 | return 0; | ||
173 | |||
174 | tpnt->proc_name = "A3000"; | ||
175 | tpnt->proc_info = &wd33c93_proc_info; | ||
176 | |||
177 | a3000_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); | ||
178 | if (a3000_host == NULL) | ||
179 | goto fail_register; | ||
180 | |||
181 | a3000_host->base = ZTWO_VADDR(0xDD0000); | ||
182 | a3000_host->irq = IRQ_AMIGA_PORTS; | ||
183 | DMA(a3000_host)->DAWR = DAWR_A3000; | ||
184 | regs.SASR = &(DMA(a3000_host)->SASR); | ||
185 | regs.SCMD = &(DMA(a3000_host)->SCMD); | ||
186 | hdata = shost_priv(a3000_host); | ||
187 | hdata->no_sync = 0xff; | ||
188 | hdata->fast = 0; | ||
189 | hdata->dma_mode = CTRL_DMA; | ||
190 | wd33c93_init(a3000_host, regs, dma_setup, dma_stop, WD33C93_FS_12_15); | ||
191 | if (request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, "A3000 SCSI", | ||
192 | a3000_intr)) | ||
193 | goto fail_irq; | ||
194 | DMA(a3000_host)->CNTR = CNTR_PDMD | CNTR_INTEN; | ||
195 | |||
196 | return 1; | ||
197 | |||
198 | fail_irq: | ||
199 | scsi_unregister(a3000_host); | ||
200 | fail_register: | ||
201 | release_mem_region(0xDD0000, 256); | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | static int a3000_bus_reset(struct scsi_cmnd *cmd) | 164 | static int a3000_bus_reset(struct scsi_cmnd *cmd) |
206 | { | 165 | { |
166 | struct Scsi_Host *instance = cmd->device->host; | ||
167 | |||
207 | /* FIXME perform bus-specific reset */ | 168 | /* FIXME perform bus-specific reset */ |
208 | 169 | ||
209 | /* FIXME 2: kill this entire function, which should | 170 | /* FIXME 2: kill this entire function, which should |
210 | cause mid-layer to call wd33c93_host_reset anyway? */ | 171 | cause mid-layer to call wd33c93_host_reset anyway? */ |
211 | 172 | ||
212 | spin_lock_irq(cmd->device->host->host_lock); | 173 | spin_lock_irq(instance->host_lock); |
213 | wd33c93_host_reset(cmd); | 174 | wd33c93_host_reset(cmd); |
214 | spin_unlock_irq(cmd->device->host->host_lock); | 175 | spin_unlock_irq(instance->host_lock); |
215 | 176 | ||
216 | return SUCCESS; | 177 | return SUCCESS; |
217 | } | 178 | } |
218 | 179 | ||
219 | #define HOSTS_C | 180 | static struct scsi_host_template amiga_a3000_scsi_template = { |
220 | 181 | .module = THIS_MODULE, | |
221 | static struct scsi_host_template driver_template = { | ||
222 | .proc_name = "A3000", | ||
223 | .name = "Amiga 3000 built-in SCSI", | 182 | .name = "Amiga 3000 built-in SCSI", |
224 | .detect = a3000_detect, | 183 | .proc_info = wd33c93_proc_info, |
225 | .release = a3000_release, | 184 | .proc_name = "A3000", |
226 | .queuecommand = wd33c93_queuecommand, | 185 | .queuecommand = wd33c93_queuecommand, |
227 | .eh_abort_handler = wd33c93_abort, | 186 | .eh_abort_handler = wd33c93_abort, |
228 | .eh_bus_reset_handler = a3000_bus_reset, | 187 | .eh_bus_reset_handler = a3000_bus_reset, |
@@ -234,15 +193,104 @@ static struct scsi_host_template driver_template = { | |||
234 | .use_clustering = ENABLE_CLUSTERING | 193 | .use_clustering = ENABLE_CLUSTERING |
235 | }; | 194 | }; |
236 | 195 | ||
196 | static int __init amiga_a3000_scsi_probe(struct platform_device *pdev) | ||
197 | { | ||
198 | struct resource *res; | ||
199 | struct Scsi_Host *instance; | ||
200 | int error; | ||
201 | struct a3000_scsiregs *regs; | ||
202 | wd33c93_regs wdregs; | ||
203 | struct a3000_hostdata *hdata; | ||
204 | |||
205 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
206 | if (!res) | ||
207 | return -ENODEV; | ||
208 | |||
209 | if (!request_mem_region(res->start, resource_size(res), "wd33c93")) | ||
210 | return -EBUSY; | ||
211 | |||
212 | instance = scsi_host_alloc(&amiga_a3000_scsi_template, | ||
213 | sizeof(struct a3000_hostdata)); | ||
214 | if (!instance) { | ||
215 | error = -ENOMEM; | ||
216 | goto fail_alloc; | ||
217 | } | ||
218 | |||
219 | instance->irq = IRQ_AMIGA_PORTS; | ||
237 | 220 | ||
238 | #include "scsi_module.c" | 221 | regs = (struct a3000_scsiregs *)ZTWO_VADDR(res->start); |
222 | regs->DAWR = DAWR_A3000; | ||
223 | |||
224 | wdregs.SASR = ®s->SASR; | ||
225 | wdregs.SCMD = ®s->SCMD; | ||
226 | |||
227 | hdata = shost_priv(instance); | ||
228 | hdata->wh.no_sync = 0xff; | ||
229 | hdata->wh.fast = 0; | ||
230 | hdata->wh.dma_mode = CTRL_DMA; | ||
231 | hdata->regs = regs; | ||
232 | |||
233 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, WD33C93_FS_12_15); | ||
234 | error = request_irq(IRQ_AMIGA_PORTS, a3000_intr, IRQF_SHARED, | ||
235 | "A3000 SCSI", instance); | ||
236 | if (error) | ||
237 | goto fail_irq; | ||
238 | |||
239 | regs->CNTR = CNTR_PDMD | CNTR_INTEN; | ||
240 | |||
241 | error = scsi_add_host(instance, NULL); | ||
242 | if (error) | ||
243 | goto fail_host; | ||
244 | |||
245 | platform_set_drvdata(pdev, instance); | ||
246 | |||
247 | scsi_scan_host(instance); | ||
248 | return 0; | ||
249 | |||
250 | fail_host: | ||
251 | free_irq(IRQ_AMIGA_PORTS, instance); | ||
252 | fail_irq: | ||
253 | scsi_host_put(instance); | ||
254 | fail_alloc: | ||
255 | release_mem_region(res->start, resource_size(res)); | ||
256 | return error; | ||
257 | } | ||
258 | |||
259 | static int __exit amiga_a3000_scsi_remove(struct platform_device *pdev) | ||
260 | { | ||
261 | struct Scsi_Host *instance = platform_get_drvdata(pdev); | ||
262 | struct a3000_hostdata *hdata = shost_priv(instance); | ||
263 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
264 | |||
265 | hdata->regs->CNTR = 0; | ||
266 | scsi_remove_host(instance); | ||
267 | free_irq(IRQ_AMIGA_PORTS, instance); | ||
268 | scsi_host_put(instance); | ||
269 | release_mem_region(res->start, resource_size(res)); | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static struct platform_driver amiga_a3000_scsi_driver = { | ||
274 | .remove = __exit_p(amiga_a3000_scsi_remove), | ||
275 | .driver = { | ||
276 | .name = "amiga-a3000-scsi", | ||
277 | .owner = THIS_MODULE, | ||
278 | }, | ||
279 | }; | ||
280 | |||
281 | static int __init amiga_a3000_scsi_init(void) | ||
282 | { | ||
283 | return platform_driver_probe(&amiga_a3000_scsi_driver, | ||
284 | amiga_a3000_scsi_probe); | ||
285 | } | ||
286 | module_init(amiga_a3000_scsi_init); | ||
239 | 287 | ||
240 | static int a3000_release(struct Scsi_Host *instance) | 288 | static void __exit amiga_a3000_scsi_exit(void) |
241 | { | 289 | { |
242 | DMA(instance)->CNTR = 0; | 290 | platform_driver_unregister(&amiga_a3000_scsi_driver); |
243 | release_mem_region(0xDD0000, 256); | ||
244 | free_irq(IRQ_AMIGA_PORTS, a3000_intr); | ||
245 | return 1; | ||
246 | } | 291 | } |
292 | module_exit(amiga_a3000_scsi_exit); | ||
247 | 293 | ||
294 | MODULE_DESCRIPTION("Amiga 3000 built-in SCSI"); | ||
248 | MODULE_LICENSE("GPL"); | 295 | MODULE_LICENSE("GPL"); |
296 | MODULE_ALIAS("platform:amiga-a3000-scsi"); | ||
diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h index 684813ee378c..49db4a335aab 100644 --- a/drivers/scsi/a3000.h +++ b/drivers/scsi/a3000.h | |||
@@ -25,7 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | #define A3000_XFER_MASK (0x00000003) | 26 | #define A3000_XFER_MASK (0x00000003) |
27 | 27 | ||
28 | typedef struct { | 28 | struct a3000_scsiregs { |
29 | unsigned char pad1[2]; | 29 | unsigned char pad1[2]; |
30 | volatile unsigned short DAWR; | 30 | volatile unsigned short DAWR; |
31 | volatile unsigned int WTC; | 31 | volatile unsigned int WTC; |
@@ -46,7 +46,7 @@ typedef struct { | |||
46 | volatile unsigned char SASR; | 46 | volatile unsigned char SASR; |
47 | unsigned char pad9; | 47 | unsigned char pad9; |
48 | volatile unsigned char SCMD; | 48 | volatile unsigned char SCMD; |
49 | } a3000_scsiregs; | 49 | }; |
50 | 50 | ||
51 | #define DAWR_A3000 (3) | 51 | #define DAWR_A3000 (3) |
52 | 52 | ||
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 11ae6be8aeaf..23c76f41883c 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c | |||
@@ -20,10 +20,6 @@ | |||
20 | 20 | ||
21 | #include "53c700.h" | 21 | #include "53c700.h" |
22 | 22 | ||
23 | MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / Kars de Jong <jongk@linux-m68k.org>"); | ||
24 | MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); | ||
25 | MODULE_LICENSE("GPL"); | ||
26 | |||
27 | 23 | ||
28 | static struct scsi_host_template a4000t_scsi_driver_template = { | 24 | static struct scsi_host_template a4000t_scsi_driver_template = { |
29 | .name = "A4000T builtin SCSI", | 25 | .name = "A4000T builtin SCSI", |
@@ -32,30 +28,35 @@ static struct scsi_host_template a4000t_scsi_driver_template = { | |||
32 | .module = THIS_MODULE, | 28 | .module = THIS_MODULE, |
33 | }; | 29 | }; |
34 | 30 | ||
35 | static struct platform_device *a4000t_scsi_device; | ||
36 | 31 | ||
37 | #define A4000T_SCSI_ADDR 0xdd0040 | 32 | #define A4000T_SCSI_OFFSET 0x40 |
38 | 33 | ||
39 | static int __devinit a4000t_probe(struct platform_device *dev) | 34 | static int __init amiga_a4000t_scsi_probe(struct platform_device *pdev) |
40 | { | 35 | { |
41 | struct Scsi_Host *host; | 36 | struct resource *res; |
37 | phys_addr_t scsi_addr; | ||
42 | struct NCR_700_Host_Parameters *hostdata; | 38 | struct NCR_700_Host_Parameters *hostdata; |
39 | struct Scsi_Host *host; | ||
43 | 40 | ||
44 | if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) | 41 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
45 | goto out; | 42 | if (!res) |
43 | return -ENODEV; | ||
46 | 44 | ||
47 | if (!request_mem_region(A4000T_SCSI_ADDR, 0x1000, | 45 | if (!request_mem_region(res->start, resource_size(res), |
48 | "A4000T builtin SCSI")) | 46 | "A4000T builtin SCSI")) |
49 | goto out; | 47 | return -EBUSY; |
50 | 48 | ||
51 | hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); | 49 | hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), |
50 | GFP_KERNEL); | ||
52 | if (!hostdata) { | 51 | if (!hostdata) { |
53 | printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); | 52 | dev_err(&pdev->dev, "Failed to allocate host data\n"); |
54 | goto out_release; | 53 | goto out_release; |
55 | } | 54 | } |
56 | 55 | ||
56 | scsi_addr = res->start + A4000T_SCSI_OFFSET; | ||
57 | |||
57 | /* Fill in the required pieces of hostdata */ | 58 | /* Fill in the required pieces of hostdata */ |
58 | hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); | 59 | hostdata->base = (void __iomem *)ZTWO_VADDR(scsi_addr); |
59 | hostdata->clock = 50; | 60 | hostdata->clock = 50; |
60 | hostdata->chip710 = 1; | 61 | hostdata->chip710 = 1; |
61 | hostdata->dmode_extra = DMODE_FC2; | 62 | hostdata->dmode_extra = DMODE_FC2; |
@@ -63,26 +64,25 @@ static int __devinit a4000t_probe(struct platform_device *dev) | |||
63 | 64 | ||
64 | /* and register the chip */ | 65 | /* and register the chip */ |
65 | host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, | 66 | host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, |
66 | &dev->dev); | 67 | &pdev->dev); |
67 | if (!host) { | 68 | if (!host) { |
68 | printk(KERN_ERR "a4000t-scsi: No host detected; " | 69 | dev_err(&pdev->dev, |
69 | "board configuration problem?\n"); | 70 | "No host detected; board configuration problem?\n"); |
70 | goto out_free; | 71 | goto out_free; |
71 | } | 72 | } |
72 | 73 | ||
73 | host->this_id = 7; | 74 | host->this_id = 7; |
74 | host->base = A4000T_SCSI_ADDR; | 75 | host->base = scsi_addr; |
75 | host->irq = IRQ_AMIGA_PORTS; | 76 | host->irq = IRQ_AMIGA_PORTS; |
76 | 77 | ||
77 | if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", | 78 | if (request_irq(host->irq, NCR_700_intr, IRQF_SHARED, "a4000t-scsi", |
78 | host)) { | 79 | host)) { |
79 | printk(KERN_ERR "a4000t-scsi: request_irq failed\n"); | 80 | dev_err(&pdev->dev, "request_irq failed\n"); |
80 | goto out_put_host; | 81 | goto out_put_host; |
81 | } | 82 | } |
82 | 83 | ||
83 | platform_set_drvdata(dev, host); | 84 | platform_set_drvdata(pdev, host); |
84 | scsi_scan_host(host); | 85 | scsi_scan_host(host); |
85 | |||
86 | return 0; | 86 | return 0; |
87 | 87 | ||
88 | out_put_host: | 88 | out_put_host: |
@@ -90,58 +90,49 @@ static int __devinit a4000t_probe(struct platform_device *dev) | |||
90 | out_free: | 90 | out_free: |
91 | kfree(hostdata); | 91 | kfree(hostdata); |
92 | out_release: | 92 | out_release: |
93 | release_mem_region(A4000T_SCSI_ADDR, 0x1000); | 93 | release_mem_region(res->start, resource_size(res)); |
94 | out: | ||
95 | return -ENODEV; | 94 | return -ENODEV; |
96 | } | 95 | } |
97 | 96 | ||
98 | static __devexit int a4000t_device_remove(struct platform_device *dev) | 97 | static int __exit amiga_a4000t_scsi_remove(struct platform_device *pdev) |
99 | { | 98 | { |
100 | struct Scsi_Host *host = platform_get_drvdata(dev); | 99 | struct Scsi_Host *host = platform_get_drvdata(pdev); |
101 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); | 100 | struct NCR_700_Host_Parameters *hostdata = shost_priv(host); |
101 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
102 | 102 | ||
103 | scsi_remove_host(host); | 103 | scsi_remove_host(host); |
104 | |||
105 | NCR_700_release(host); | 104 | NCR_700_release(host); |
106 | kfree(hostdata); | 105 | kfree(hostdata); |
107 | free_irq(host->irq, host); | 106 | free_irq(host->irq, host); |
108 | release_mem_region(A4000T_SCSI_ADDR, 0x1000); | 107 | release_mem_region(res->start, resource_size(res)); |
109 | |||
110 | return 0; | 108 | return 0; |
111 | } | 109 | } |
112 | 110 | ||
113 | static struct platform_driver a4000t_scsi_driver = { | 111 | static struct platform_driver amiga_a4000t_scsi_driver = { |
114 | .driver = { | 112 | .remove = __exit_p(amiga_a4000t_scsi_remove), |
115 | .name = "a4000t-scsi", | 113 | .driver = { |
116 | .owner = THIS_MODULE, | 114 | .name = "amiga-a4000t-scsi", |
115 | .owner = THIS_MODULE, | ||
117 | }, | 116 | }, |
118 | .probe = a4000t_probe, | ||
119 | .remove = __devexit_p(a4000t_device_remove), | ||
120 | }; | 117 | }; |
121 | 118 | ||
122 | static int __init a4000t_scsi_init(void) | 119 | static int __init amiga_a4000t_scsi_init(void) |
123 | { | 120 | { |
124 | int err; | 121 | return platform_driver_probe(&amiga_a4000t_scsi_driver, |
125 | 122 | amiga_a4000t_scsi_probe); | |
126 | err = platform_driver_register(&a4000t_scsi_driver); | ||
127 | if (err) | ||
128 | return err; | ||
129 | |||
130 | a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", | ||
131 | -1, NULL, 0); | ||
132 | if (IS_ERR(a4000t_scsi_device)) { | ||
133 | platform_driver_unregister(&a4000t_scsi_driver); | ||
134 | return PTR_ERR(a4000t_scsi_device); | ||
135 | } | ||
136 | |||
137 | return err; | ||
138 | } | 123 | } |
139 | 124 | ||
140 | static void __exit a4000t_scsi_exit(void) | 125 | module_init(amiga_a4000t_scsi_init); |
126 | |||
127 | static void __exit amiga_a4000t_scsi_exit(void) | ||
141 | { | 128 | { |
142 | platform_device_unregister(a4000t_scsi_device); | 129 | platform_driver_unregister(&amiga_a4000t_scsi_driver); |
143 | platform_driver_unregister(&a4000t_scsi_driver); | ||
144 | } | 130 | } |
145 | 131 | ||
146 | module_init(a4000t_scsi_init); | 132 | module_exit(amiga_a4000t_scsi_exit); |
147 | module_exit(a4000t_scsi_exit); | 133 | |
134 | MODULE_AUTHOR("Alan Hourihane <alanh@fairlite.demon.co.uk> / " | ||
135 | "Kars de Jong <jongk@linux-m68k.org>"); | ||
136 | MODULE_DESCRIPTION("Amiga A4000T NCR53C710 driver"); | ||
137 | MODULE_LICENSE("GPL"); | ||
138 | MODULE_ALIAS("platform:amiga-a4000t-scsi"); | ||
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 9c0c91178538..1a5bf5724750 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c | |||
@@ -655,9 +655,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) | |||
655 | /* Does this really need to be GFP_DMA? */ | 655 | /* Does this really need to be GFP_DMA? */ |
656 | p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); | 656 | p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA); |
657 | if(!p) { | 657 | if(!p) { |
658 | kfree (usg); | 658 | dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", |
659 | dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n", | ||
660 | usg->sg[i].count,i,usg->count)); | 659 | usg->sg[i].count,i,usg->count)); |
660 | kfree(usg); | ||
661 | rcode = -ENOMEM; | 661 | rcode = -ENOMEM; |
662 | goto cleanup; | 662 | goto cleanup; |
663 | } | 663 | } |
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index ab646e580d64..ce5371b3cdd5 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h | |||
@@ -48,7 +48,7 @@ struct device_attribute; | |||
48 | /*The limit of outstanding scsi command that firmware can handle*/ | 48 | /*The limit of outstanding scsi command that firmware can handle*/ |
49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 | 49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 |
50 | #define ARCMSR_MAX_FREECCB_NUM 320 | 50 | #define ARCMSR_MAX_FREECCB_NUM 320 |
51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/02/27" | 51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/11/03" |
52 | #define ARCMSR_SCSI_INITIATOR_ID 255 | 52 | #define ARCMSR_SCSI_INITIATOR_ID 255 |
53 | #define ARCMSR_MAX_XFER_SECTORS 512 | 53 | #define ARCMSR_MAX_XFER_SECTORS 512 |
54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 | 54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 |
@@ -110,6 +110,8 @@ struct CMD_MESSAGE_FIELD | |||
110 | #define FUNCTION_SAY_HELLO 0x0807 | 110 | #define FUNCTION_SAY_HELLO 0x0807 |
111 | #define FUNCTION_SAY_GOODBYE 0x0808 | 111 | #define FUNCTION_SAY_GOODBYE 0x0808 |
112 | #define FUNCTION_FLUSH_ADAPTER_CACHE 0x0809 | 112 | #define FUNCTION_FLUSH_ADAPTER_CACHE 0x0809 |
113 | #define FUNCTION_GET_FIRMWARE_STATUS 0x080A | ||
114 | #define FUNCTION_HARDWARE_RESET 0x080B | ||
113 | /* ARECA IO CONTROL CODE*/ | 115 | /* ARECA IO CONTROL CODE*/ |
114 | #define ARCMSR_MESSAGE_READ_RQBUFFER \ | 116 | #define ARCMSR_MESSAGE_READ_RQBUFFER \ |
115 | ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER | 117 | ARECA_SATA_RAID | FUNCTION_READ_RQBUFFER |
@@ -133,6 +135,7 @@ struct CMD_MESSAGE_FIELD | |||
133 | #define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 | 135 | #define ARCMSR_MESSAGE_RETURNCODE_OK 0x00000001 |
134 | #define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 | 136 | #define ARCMSR_MESSAGE_RETURNCODE_ERROR 0x00000006 |
135 | #define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F | 137 | #define ARCMSR_MESSAGE_RETURNCODE_3F 0x0000003F |
138 | #define ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON 0x00000088 | ||
136 | /* | 139 | /* |
137 | ************************************************************* | 140 | ************************************************************* |
138 | ** structure for holding DMA address data | 141 | ** structure for holding DMA address data |
@@ -341,13 +344,13 @@ struct MessageUnit_B | |||
341 | uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; | 344 | uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; |
342 | uint32_t postq_index; | 345 | uint32_t postq_index; |
343 | uint32_t doneq_index; | 346 | uint32_t doneq_index; |
344 | void __iomem *drv2iop_doorbell_reg; | 347 | uint32_t __iomem *drv2iop_doorbell_reg; |
345 | void __iomem *drv2iop_doorbell_mask_reg; | 348 | uint32_t __iomem *drv2iop_doorbell_mask_reg; |
346 | void __iomem *iop2drv_doorbell_reg; | 349 | uint32_t __iomem *iop2drv_doorbell_reg; |
347 | void __iomem *iop2drv_doorbell_mask_reg; | 350 | uint32_t __iomem *iop2drv_doorbell_mask_reg; |
348 | void __iomem *msgcode_rwbuffer_reg; | 351 | uint32_t __iomem *msgcode_rwbuffer_reg; |
349 | void __iomem *ioctl_wbuffer_reg; | 352 | uint32_t __iomem *ioctl_wbuffer_reg; |
350 | void __iomem *ioctl_rbuffer_reg; | 353 | uint32_t __iomem *ioctl_rbuffer_reg; |
351 | }; | 354 | }; |
352 | 355 | ||
353 | /* | 356 | /* |
@@ -375,6 +378,7 @@ struct AdapterControlBlock | |||
375 | /* message unit ATU inbound base address0 */ | 378 | /* message unit ATU inbound base address0 */ |
376 | 379 | ||
377 | uint32_t acb_flags; | 380 | uint32_t acb_flags; |
381 | uint8_t adapter_index; | ||
378 | #define ACB_F_SCSISTOPADAPTER 0x0001 | 382 | #define ACB_F_SCSISTOPADAPTER 0x0001 |
379 | #define ACB_F_MSG_STOP_BGRB 0x0002 | 383 | #define ACB_F_MSG_STOP_BGRB 0x0002 |
380 | /* stop RAID background rebuild */ | 384 | /* stop RAID background rebuild */ |
@@ -390,7 +394,7 @@ struct AdapterControlBlock | |||
390 | #define ACB_F_BUS_RESET 0x0080 | 394 | #define ACB_F_BUS_RESET 0x0080 |
391 | #define ACB_F_IOP_INITED 0x0100 | 395 | #define ACB_F_IOP_INITED 0x0100 |
392 | /* iop init */ | 396 | /* iop init */ |
393 | 397 | #define ACB_F_FIRMWARE_TRAP 0x0400 | |
394 | struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; | 398 | struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; |
395 | /* used for memory free */ | 399 | /* used for memory free */ |
396 | struct list_head ccb_free_list; | 400 | struct list_head ccb_free_list; |
@@ -423,12 +427,19 @@ struct AdapterControlBlock | |||
423 | #define ARECA_RAID_GOOD 0xaa | 427 | #define ARECA_RAID_GOOD 0xaa |
424 | uint32_t num_resets; | 428 | uint32_t num_resets; |
425 | uint32_t num_aborts; | 429 | uint32_t num_aborts; |
430 | uint32_t signature; | ||
426 | uint32_t firm_request_len; | 431 | uint32_t firm_request_len; |
427 | uint32_t firm_numbers_queue; | 432 | uint32_t firm_numbers_queue; |
428 | uint32_t firm_sdram_size; | 433 | uint32_t firm_sdram_size; |
429 | uint32_t firm_hd_channels; | 434 | uint32_t firm_hd_channels; |
430 | char firm_model[12]; | 435 | char firm_model[12]; |
431 | char firm_version[20]; | 436 | char firm_version[20]; |
437 | char device_map[20]; /*21,84-99*/ | ||
438 | struct work_struct arcmsr_do_message_isr_bh; | ||
439 | struct timer_list eternal_timer; | ||
440 | unsigned short fw_state; | ||
441 | atomic_t rq_map_token; | ||
442 | int ante_token_value; | ||
432 | };/* HW_DEVICE_EXTENSION */ | 443 | };/* HW_DEVICE_EXTENSION */ |
433 | /* | 444 | /* |
434 | ******************************************************************************* | 445 | ******************************************************************************* |
diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index a4e04c50c436..07fdfe57e38e 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c | |||
@@ -192,6 +192,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { | |||
192 | .attr = { | 192 | .attr = { |
193 | .name = "mu_read", | 193 | .name = "mu_read", |
194 | .mode = S_IRUSR , | 194 | .mode = S_IRUSR , |
195 | .owner = THIS_MODULE, | ||
195 | }, | 196 | }, |
196 | .size = 1032, | 197 | .size = 1032, |
197 | .read = arcmsr_sysfs_iop_message_read, | 198 | .read = arcmsr_sysfs_iop_message_read, |
@@ -201,6 +202,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { | |||
201 | .attr = { | 202 | .attr = { |
202 | .name = "mu_write", | 203 | .name = "mu_write", |
203 | .mode = S_IWUSR, | 204 | .mode = S_IWUSR, |
205 | .owner = THIS_MODULE, | ||
204 | }, | 206 | }, |
205 | .size = 1032, | 207 | .size = 1032, |
206 | .write = arcmsr_sysfs_iop_message_write, | 208 | .write = arcmsr_sysfs_iop_message_write, |
@@ -210,6 +212,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { | |||
210 | .attr = { | 212 | .attr = { |
211 | .name = "mu_clear", | 213 | .name = "mu_clear", |
212 | .mode = S_IWUSR, | 214 | .mode = S_IWUSR, |
215 | .owner = THIS_MODULE, | ||
213 | }, | 216 | }, |
214 | .size = 1, | 217 | .size = 1, |
215 | .write = arcmsr_sysfs_iop_message_clear, | 218 | .write = arcmsr_sysfs_iop_message_clear, |
diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index ffbe2192da3c..ffa54792bb33 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c | |||
@@ -72,8 +72,16 @@ | |||
72 | #include <scsi/scsicam.h> | 72 | #include <scsi/scsicam.h> |
73 | #include "arcmsr.h" | 73 | #include "arcmsr.h" |
74 | 74 | ||
75 | #ifdef CONFIG_SCSI_ARCMSR_RESET | ||
76 | static int sleeptime = 20; | ||
77 | static int retrycount = 12; | ||
78 | module_param(sleeptime, int, S_IRUGO|S_IWUSR); | ||
79 | MODULE_PARM_DESC(sleeptime, "The waiting period for FW ready while bus reset"); | ||
80 | module_param(retrycount, int, S_IRUGO|S_IWUSR); | ||
81 | MODULE_PARM_DESC(retrycount, "The retry count for FW ready while bus reset"); | ||
82 | #endif | ||
75 | MODULE_AUTHOR("Erich Chen <support@areca.com.tw>"); | 83 | MODULE_AUTHOR("Erich Chen <support@areca.com.tw>"); |
76 | MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); | 84 | MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Bus Adapter"); |
77 | MODULE_LICENSE("Dual BSD/GPL"); | 85 | MODULE_LICENSE("Dual BSD/GPL"); |
78 | MODULE_VERSION(ARCMSR_DRIVER_VERSION); | 86 | MODULE_VERSION(ARCMSR_DRIVER_VERSION); |
79 | 87 | ||
@@ -96,6 +104,13 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); | |||
96 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); | 104 | static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); |
97 | static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); | 105 | static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); |
98 | static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); | 106 | static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); |
107 | static void arcmsr_request_device_map(unsigned long pacb); | ||
108 | static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb); | ||
109 | static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb); | ||
110 | static void arcmsr_message_isr_bh_fn(struct work_struct *work); | ||
111 | static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode); | ||
112 | static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb); | ||
113 | |||
99 | static const char *arcmsr_info(struct Scsi_Host *); | 114 | static const char *arcmsr_info(struct Scsi_Host *); |
100 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); | 115 | static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); |
101 | static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, | 116 | static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, |
@@ -112,7 +127,7 @@ static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, | |||
112 | 127 | ||
113 | static struct scsi_host_template arcmsr_scsi_host_template = { | 128 | static struct scsi_host_template arcmsr_scsi_host_template = { |
114 | .module = THIS_MODULE, | 129 | .module = THIS_MODULE, |
115 | .name = "ARCMSR ARECA SATA/SAS RAID HOST Adapter" | 130 | .name = "ARCMSR ARECA SATA/SAS RAID Host Bus Adapter" |
116 | ARCMSR_DRIVER_VERSION, | 131 | ARCMSR_DRIVER_VERSION, |
117 | .info = arcmsr_info, | 132 | .info = arcmsr_info, |
118 | .queuecommand = arcmsr_queue_command, | 133 | .queuecommand = arcmsr_queue_command, |
@@ -128,16 +143,6 @@ static struct scsi_host_template arcmsr_scsi_host_template = { | |||
128 | .use_clustering = ENABLE_CLUSTERING, | 143 | .use_clustering = ENABLE_CLUSTERING, |
129 | .shost_attrs = arcmsr_host_attrs, | 144 | .shost_attrs = arcmsr_host_attrs, |
130 | }; | 145 | }; |
131 | #ifdef CONFIG_SCSI_ARCMSR_AER | ||
132 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); | ||
133 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, | ||
134 | pci_channel_state_t state); | ||
135 | |||
136 | static struct pci_error_handlers arcmsr_pci_error_handlers = { | ||
137 | .error_detected = arcmsr_pci_error_detected, | ||
138 | .slot_reset = arcmsr_pci_slot_reset, | ||
139 | }; | ||
140 | #endif | ||
141 | static struct pci_device_id arcmsr_device_id_table[] = { | 146 | static struct pci_device_id arcmsr_device_id_table[] = { |
142 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, | 147 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, |
143 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, | 148 | {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, |
@@ -166,9 +171,6 @@ static struct pci_driver arcmsr_pci_driver = { | |||
166 | .probe = arcmsr_probe, | 171 | .probe = arcmsr_probe, |
167 | .remove = arcmsr_remove, | 172 | .remove = arcmsr_remove, |
168 | .shutdown = arcmsr_shutdown, | 173 | .shutdown = arcmsr_shutdown, |
169 | #ifdef CONFIG_SCSI_ARCMSR_AER | ||
170 | .err_handler = &arcmsr_pci_error_handlers, | ||
171 | #endif | ||
172 | }; | 174 | }; |
173 | 175 | ||
174 | static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) | 176 | static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) |
@@ -236,10 +238,9 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
236 | void *dma_coherent; | 238 | void *dma_coherent; |
237 | dma_addr_t dma_coherent_handle, dma_addr; | 239 | dma_addr_t dma_coherent_handle, dma_addr; |
238 | struct CommandControlBlock *ccb_tmp; | 240 | struct CommandControlBlock *ccb_tmp; |
239 | uint32_t intmask_org; | ||
240 | int i, j; | 241 | int i, j; |
241 | 242 | ||
242 | acb->pmuA = pci_ioremap_bar(pdev, 0); | 243 | acb->pmuA = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); |
243 | if (!acb->pmuA) { | 244 | if (!acb->pmuA) { |
244 | printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", | 245 | printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", |
245 | acb->host->host_no); | 246 | acb->host->host_no); |
@@ -281,12 +282,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
281 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) | 282 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) |
282 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) | 283 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) |
283 | acb->devstate[i][j] = ARECA_RAID_GONE; | 284 | acb->devstate[i][j] = ARECA_RAID_GONE; |
284 | |||
285 | /* | ||
286 | ** here we need to tell iop 331 our ccb_tmp.HighPart | ||
287 | ** if ccb_tmp.HighPart is not zero | ||
288 | */ | ||
289 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
290 | } | 285 | } |
291 | break; | 286 | break; |
292 | 287 | ||
@@ -297,7 +292,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
297 | void __iomem *mem_base0, *mem_base1; | 292 | void __iomem *mem_base0, *mem_base1; |
298 | void *dma_coherent; | 293 | void *dma_coherent; |
299 | dma_addr_t dma_coherent_handle, dma_addr; | 294 | dma_addr_t dma_coherent_handle, dma_addr; |
300 | uint32_t intmask_org; | ||
301 | struct CommandControlBlock *ccb_tmp; | 295 | struct CommandControlBlock *ccb_tmp; |
302 | int i, j; | 296 | int i, j; |
303 | 297 | ||
@@ -333,11 +327,13 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
333 | reg = (struct MessageUnit_B *)(dma_coherent + | 327 | reg = (struct MessageUnit_B *)(dma_coherent + |
334 | ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); | 328 | ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); |
335 | acb->pmuB = reg; | 329 | acb->pmuB = reg; |
336 | mem_base0 = pci_ioremap_bar(pdev, 0); | 330 | mem_base0 = ioremap(pci_resource_start(pdev, 0), |
331 | pci_resource_len(pdev, 0)); | ||
337 | if (!mem_base0) | 332 | if (!mem_base0) |
338 | goto out; | 333 | goto out; |
339 | 334 | ||
340 | mem_base1 = pci_ioremap_bar(pdev, 2); | 335 | mem_base1 = ioremap(pci_resource_start(pdev, 2), |
336 | pci_resource_len(pdev, 2)); | ||
341 | if (!mem_base1) { | 337 | if (!mem_base1) { |
342 | iounmap(mem_base0); | 338 | iounmap(mem_base0); |
343 | goto out; | 339 | goto out; |
@@ -357,12 +353,6 @@ static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) | |||
357 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) | 353 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) |
358 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) | 354 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) |
359 | acb->devstate[i][j] = ARECA_RAID_GOOD; | 355 | acb->devstate[i][j] = ARECA_RAID_GOOD; |
360 | |||
361 | /* | ||
362 | ** here we need to tell iop 331 our ccb_tmp.HighPart | ||
363 | ** if ccb_tmp.HighPart is not zero | ||
364 | */ | ||
365 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
366 | } | 356 | } |
367 | break; | 357 | break; |
368 | } | 358 | } |
@@ -374,6 +364,88 @@ out: | |||
374 | sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); | 364 | sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); |
375 | return -ENOMEM; | 365 | return -ENOMEM; |
376 | } | 366 | } |
367 | static void arcmsr_message_isr_bh_fn(struct work_struct *work) | ||
368 | { | ||
369 | struct AdapterControlBlock *acb = container_of(work, struct AdapterControlBlock, arcmsr_do_message_isr_bh); | ||
370 | |||
371 | switch (acb->adapter_type) { | ||
372 | case ACB_ADAPTER_TYPE_A: { | ||
373 | |||
374 | struct MessageUnit_A __iomem *reg = acb->pmuA; | ||
375 | char *acb_dev_map = (char *)acb->device_map; | ||
376 | uint32_t __iomem *signature = (uint32_t __iomem *) (®->message_rwbuffer[0]); | ||
377 | char __iomem *devicemap = (char __iomem *) (®->message_rwbuffer[21]); | ||
378 | int target, lun; | ||
379 | struct scsi_device *psdev; | ||
380 | char diff; | ||
381 | |||
382 | atomic_inc(&acb->rq_map_token); | ||
383 | if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { | ||
384 | for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) { | ||
385 | diff = (*acb_dev_map)^readb(devicemap); | ||
386 | if (diff != 0) { | ||
387 | char temp; | ||
388 | *acb_dev_map = readb(devicemap); | ||
389 | temp = *acb_dev_map; | ||
390 | for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { | ||
391 | if ((temp & 0x01) == 1 && (diff & 0x01) == 1) { | ||
392 | scsi_add_device(acb->host, 0, target, lun); | ||
393 | } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) { | ||
394 | psdev = scsi_device_lookup(acb->host, 0, target, lun); | ||
395 | if (psdev != NULL) { | ||
396 | scsi_remove_device(psdev); | ||
397 | scsi_device_put(psdev); | ||
398 | } | ||
399 | } | ||
400 | temp >>= 1; | ||
401 | diff >>= 1; | ||
402 | } | ||
403 | } | ||
404 | devicemap++; | ||
405 | acb_dev_map++; | ||
406 | } | ||
407 | } | ||
408 | break; | ||
409 | } | ||
410 | |||
411 | case ACB_ADAPTER_TYPE_B: { | ||
412 | struct MessageUnit_B *reg = acb->pmuB; | ||
413 | char *acb_dev_map = (char *)acb->device_map; | ||
414 | uint32_t __iomem *signature = (uint32_t __iomem *)(®->msgcode_rwbuffer_reg[0]); | ||
415 | char __iomem *devicemap = (char __iomem *)(®->msgcode_rwbuffer_reg[21]); | ||
416 | int target, lun; | ||
417 | struct scsi_device *psdev; | ||
418 | char diff; | ||
419 | |||
420 | atomic_inc(&acb->rq_map_token); | ||
421 | if (readl(signature) == ARCMSR_SIGNATURE_GET_CONFIG) { | ||
422 | for (target = 0; target < ARCMSR_MAX_TARGETID - 1; target++) { | ||
423 | diff = (*acb_dev_map)^readb(devicemap); | ||
424 | if (diff != 0) { | ||
425 | char temp; | ||
426 | *acb_dev_map = readb(devicemap); | ||
427 | temp = *acb_dev_map; | ||
428 | for (lun = 0; lun < ARCMSR_MAX_TARGETLUN; lun++) { | ||
429 | if ((temp & 0x01) == 1 && (diff & 0x01) == 1) { | ||
430 | scsi_add_device(acb->host, 0, target, lun); | ||
431 | } else if ((temp & 0x01) == 0 && (diff & 0x01) == 1) { | ||
432 | psdev = scsi_device_lookup(acb->host, 0, target, lun); | ||
433 | if (psdev != NULL) { | ||
434 | scsi_remove_device(psdev); | ||
435 | scsi_device_put(psdev); | ||
436 | } | ||
437 | } | ||
438 | temp >>= 1; | ||
439 | diff >>= 1; | ||
440 | } | ||
441 | } | ||
442 | devicemap++; | ||
443 | acb_dev_map++; | ||
444 | } | ||
445 | } | ||
446 | } | ||
447 | } | ||
448 | } | ||
377 | 449 | ||
378 | static int arcmsr_probe(struct pci_dev *pdev, | 450 | static int arcmsr_probe(struct pci_dev *pdev, |
379 | const struct pci_device_id *id) | 451 | const struct pci_device_id *id) |
@@ -432,17 +504,17 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
432 | ACB_F_MESSAGE_WQBUFFER_READED); | 504 | ACB_F_MESSAGE_WQBUFFER_READED); |
433 | acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; | 505 | acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; |
434 | INIT_LIST_HEAD(&acb->ccb_free_list); | 506 | INIT_LIST_HEAD(&acb->ccb_free_list); |
435 | 507 | INIT_WORK(&acb->arcmsr_do_message_isr_bh, arcmsr_message_isr_bh_fn); | |
436 | error = arcmsr_alloc_ccb_pool(acb); | 508 | error = arcmsr_alloc_ccb_pool(acb); |
437 | if (error) | 509 | if (error) |
438 | goto out_release_regions; | 510 | goto out_release_regions; |
439 | 511 | ||
512 | arcmsr_iop_init(acb); | ||
440 | error = request_irq(pdev->irq, arcmsr_do_interrupt, | 513 | error = request_irq(pdev->irq, arcmsr_do_interrupt, |
441 | IRQF_SHARED, "arcmsr", acb); | 514 | IRQF_SHARED, "arcmsr", acb); |
442 | if (error) | 515 | if (error) |
443 | goto out_free_ccb_pool; | 516 | goto out_free_ccb_pool; |
444 | 517 | ||
445 | arcmsr_iop_init(acb); | ||
446 | pci_set_drvdata(pdev, host); | 518 | pci_set_drvdata(pdev, host); |
447 | if (strncmp(acb->firm_version, "V1.42", 5) >= 0) | 519 | if (strncmp(acb->firm_version, "V1.42", 5) >= 0) |
448 | host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B; | 520 | host->max_sectors= ARCMSR_MAX_XFER_SECTORS_B; |
@@ -459,6 +531,14 @@ static int arcmsr_probe(struct pci_dev *pdev, | |||
459 | #ifdef CONFIG_SCSI_ARCMSR_AER | 531 | #ifdef CONFIG_SCSI_ARCMSR_AER |
460 | pci_enable_pcie_error_reporting(pdev); | 532 | pci_enable_pcie_error_reporting(pdev); |
461 | #endif | 533 | #endif |
534 | atomic_set(&acb->rq_map_token, 16); | ||
535 | acb->fw_state = true; | ||
536 | init_timer(&acb->eternal_timer); | ||
537 | acb->eternal_timer.expires = jiffies + msecs_to_jiffies(10*HZ); | ||
538 | acb->eternal_timer.data = (unsigned long) acb; | ||
539 | acb->eternal_timer.function = &arcmsr_request_device_map; | ||
540 | add_timer(&acb->eternal_timer); | ||
541 | |||
462 | return 0; | 542 | return 0; |
463 | out_free_sysfs: | 543 | out_free_sysfs: |
464 | out_free_irq: | 544 | out_free_irq: |
@@ -518,40 +598,48 @@ static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) | |||
518 | return 0xff; | 598 | return 0xff; |
519 | } | 599 | } |
520 | 600 | ||
521 | static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) | 601 | static uint8_t arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) |
522 | { | 602 | { |
523 | struct MessageUnit_A __iomem *reg = acb->pmuA; | 603 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
524 | 604 | ||
525 | writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); | 605 | writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); |
526 | if (arcmsr_hba_wait_msgint_ready(acb)) | 606 | if (arcmsr_hba_wait_msgint_ready(acb)) { |
527 | printk(KERN_NOTICE | 607 | printk(KERN_NOTICE |
528 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" | 608 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" |
529 | , acb->host->host_no); | 609 | , acb->host->host_no); |
610 | return 0xff; | ||
611 | } | ||
612 | return 0x00; | ||
530 | } | 613 | } |
531 | 614 | ||
532 | static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) | 615 | static uint8_t arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) |
533 | { | 616 | { |
534 | struct MessageUnit_B *reg = acb->pmuB; | 617 | struct MessageUnit_B *reg = acb->pmuB; |
535 | 618 | ||
536 | writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); | 619 | writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); |
537 | if (arcmsr_hbb_wait_msgint_ready(acb)) | 620 | if (arcmsr_hbb_wait_msgint_ready(acb)) { |
538 | printk(KERN_NOTICE | 621 | printk(KERN_NOTICE |
539 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" | 622 | "arcmsr%d: wait 'abort all outstanding command' timeout \n" |
540 | , acb->host->host_no); | 623 | , acb->host->host_no); |
624 | return 0xff; | ||
625 | } | ||
626 | return 0x00; | ||
541 | } | 627 | } |
542 | 628 | ||
543 | static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) | 629 | static uint8_t arcmsr_abort_allcmd(struct AdapterControlBlock *acb) |
544 | { | 630 | { |
631 | uint8_t rtnval = 0; | ||
545 | switch (acb->adapter_type) { | 632 | switch (acb->adapter_type) { |
546 | case ACB_ADAPTER_TYPE_A: { | 633 | case ACB_ADAPTER_TYPE_A: { |
547 | arcmsr_abort_hba_allcmd(acb); | 634 | rtnval = arcmsr_abort_hba_allcmd(acb); |
548 | } | 635 | } |
549 | break; | 636 | break; |
550 | 637 | ||
551 | case ACB_ADAPTER_TYPE_B: { | 638 | case ACB_ADAPTER_TYPE_B: { |
552 | arcmsr_abort_hbb_allcmd(acb); | 639 | rtnval = arcmsr_abort_hbb_allcmd(acb); |
553 | } | 640 | } |
554 | } | 641 | } |
642 | return rtnval; | ||
555 | } | 643 | } |
556 | 644 | ||
557 | static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) | 645 | static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) |
@@ -649,8 +737,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) | |||
649 | 737 | ||
650 | case ACB_ADAPTER_TYPE_A : { | 738 | case ACB_ADAPTER_TYPE_A : { |
651 | struct MessageUnit_A __iomem *reg = acb->pmuA; | 739 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
652 | orig_mask = readl(®->outbound_intmask)|\ | 740 | orig_mask = readl(®->outbound_intmask); |
653 | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; | ||
654 | writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ | 741 | writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ |
655 | ®->outbound_intmask); | 742 | ®->outbound_intmask); |
656 | } | 743 | } |
@@ -658,8 +745,7 @@ static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) | |||
658 | 745 | ||
659 | case ACB_ADAPTER_TYPE_B : { | 746 | case ACB_ADAPTER_TYPE_B : { |
660 | struct MessageUnit_B *reg = acb->pmuB; | 747 | struct MessageUnit_B *reg = acb->pmuB; |
661 | orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ | 748 | orig_mask = readl(reg->iop2drv_doorbell_mask_reg); |
662 | (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); | ||
663 | writel(0, reg->iop2drv_doorbell_mask_reg); | 749 | writel(0, reg->iop2drv_doorbell_mask_reg); |
664 | } | 750 | } |
665 | break; | 751 | break; |
@@ -795,12 +881,13 @@ static void arcmsr_remove(struct pci_dev *pdev) | |||
795 | struct AdapterControlBlock *acb = | 881 | struct AdapterControlBlock *acb = |
796 | (struct AdapterControlBlock *) host->hostdata; | 882 | (struct AdapterControlBlock *) host->hostdata; |
797 | int poll_count = 0; | 883 | int poll_count = 0; |
798 | |||
799 | arcmsr_free_sysfs_attr(acb); | 884 | arcmsr_free_sysfs_attr(acb); |
800 | scsi_remove_host(host); | 885 | scsi_remove_host(host); |
886 | flush_scheduled_work(); | ||
887 | del_timer_sync(&acb->eternal_timer); | ||
888 | arcmsr_disable_outbound_ints(acb); | ||
801 | arcmsr_stop_adapter_bgrb(acb); | 889 | arcmsr_stop_adapter_bgrb(acb); |
802 | arcmsr_flush_adapter_cache(acb); | 890 | arcmsr_flush_adapter_cache(acb); |
803 | arcmsr_disable_outbound_ints(acb); | ||
804 | acb->acb_flags |= ACB_F_SCSISTOPADAPTER; | 891 | acb->acb_flags |= ACB_F_SCSISTOPADAPTER; |
805 | acb->acb_flags &= ~ACB_F_IOP_INITED; | 892 | acb->acb_flags &= ~ACB_F_IOP_INITED; |
806 | 893 | ||
@@ -841,7 +928,9 @@ static void arcmsr_shutdown(struct pci_dev *pdev) | |||
841 | struct Scsi_Host *host = pci_get_drvdata(pdev); | 928 | struct Scsi_Host *host = pci_get_drvdata(pdev); |
842 | struct AdapterControlBlock *acb = | 929 | struct AdapterControlBlock *acb = |
843 | (struct AdapterControlBlock *)host->hostdata; | 930 | (struct AdapterControlBlock *)host->hostdata; |
844 | 931 | del_timer_sync(&acb->eternal_timer); | |
932 | arcmsr_disable_outbound_ints(acb); | ||
933 | flush_scheduled_work(); | ||
845 | arcmsr_stop_adapter_bgrb(acb); | 934 | arcmsr_stop_adapter_bgrb(acb); |
846 | arcmsr_flush_adapter_cache(acb); | 935 | arcmsr_flush_adapter_cache(acb); |
847 | } | 936 | } |
@@ -861,7 +950,7 @@ static void arcmsr_module_exit(void) | |||
861 | module_init(arcmsr_module_init); | 950 | module_init(arcmsr_module_init); |
862 | module_exit(arcmsr_module_exit); | 951 | module_exit(arcmsr_module_exit); |
863 | 952 | ||
864 | static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ | 953 | static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, |
865 | u32 intmask_org) | 954 | u32 intmask_org) |
866 | { | 955 | { |
867 | u32 mask; | 956 | u32 mask; |
@@ -871,7 +960,8 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ | |||
871 | case ACB_ADAPTER_TYPE_A : { | 960 | case ACB_ADAPTER_TYPE_A : { |
872 | struct MessageUnit_A __iomem *reg = acb->pmuA; | 961 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
873 | mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | | 962 | mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | |
874 | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); | 963 | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE| |
964 | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE); | ||
875 | writel(mask, ®->outbound_intmask); | 965 | writel(mask, ®->outbound_intmask); |
876 | acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; | 966 | acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; |
877 | } | 967 | } |
@@ -879,8 +969,10 @@ static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ | |||
879 | 969 | ||
880 | case ACB_ADAPTER_TYPE_B : { | 970 | case ACB_ADAPTER_TYPE_B : { |
881 | struct MessageUnit_B *reg = acb->pmuB; | 971 | struct MessageUnit_B *reg = acb->pmuB; |
882 | mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ | 972 | mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | |
883 | ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); | 973 | ARCMSR_IOP2DRV_DATA_READ_OK | |
974 | ARCMSR_IOP2DRV_CDB_DONE | | ||
975 | ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); | ||
884 | writel(mask, reg->iop2drv_doorbell_mask_reg); | 976 | writel(mask, reg->iop2drv_doorbell_mask_reg); |
885 | acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; | 977 | acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; |
886 | } | 978 | } |
@@ -1048,8 +1140,8 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) | |||
1048 | } | 1140 | } |
1049 | case ACB_ADAPTER_TYPE_B: { | 1141 | case ACB_ADAPTER_TYPE_B: { |
1050 | struct MessageUnit_B *reg = acb->pmuB; | 1142 | struct MessageUnit_B *reg = acb->pmuB; |
1051 | iounmap(reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); | 1143 | iounmap((u8 *)reg->drv2iop_doorbell_reg - ARCMSR_DRV2IOP_DOORBELL); |
1052 | iounmap(reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); | 1144 | iounmap((u8 *)reg->ioctl_wbuffer_reg - ARCMSR_IOCTL_WBUFFER); |
1053 | dma_free_coherent(&acb->pdev->dev, | 1145 | dma_free_coherent(&acb->pdev->dev, |
1054 | (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + | 1146 | (ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock) + 0x20 + |
1055 | sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); | 1147 | sizeof(struct MessageUnit_B)), acb->dma_coherent, acb->dma_coherent_handle); |
@@ -1249,13 +1341,36 @@ static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) | |||
1249 | reg->doneq_index = index; | 1341 | reg->doneq_index = index; |
1250 | } | 1342 | } |
1251 | } | 1343 | } |
1344 | /* | ||
1345 | ********************************************************************************** | ||
1346 | ** Handle a message interrupt | ||
1347 | ** | ||
1348 | ** The only message interrupt we expect is in response to a query for the current adapter config. | ||
1349 | ** We want this in order to compare the drivemap so that we can detect newly-attached drives. | ||
1350 | ********************************************************************************** | ||
1351 | */ | ||
1352 | static void arcmsr_hba_message_isr(struct AdapterControlBlock *acb) | ||
1353 | { | ||
1354 | struct MessageUnit_A *reg = acb->pmuA; | ||
1355 | |||
1356 | /*clear interrupt and message state*/ | ||
1357 | writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, ®->outbound_intstatus); | ||
1358 | schedule_work(&acb->arcmsr_do_message_isr_bh); | ||
1359 | } | ||
1360 | static void arcmsr_hbb_message_isr(struct AdapterControlBlock *acb) | ||
1361 | { | ||
1362 | struct MessageUnit_B *reg = acb->pmuB; | ||
1252 | 1363 | ||
1364 | /*clear interrupt and message state*/ | ||
1365 | writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); | ||
1366 | schedule_work(&acb->arcmsr_do_message_isr_bh); | ||
1367 | } | ||
1253 | static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) | 1368 | static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) |
1254 | { | 1369 | { |
1255 | uint32_t outbound_intstatus; | 1370 | uint32_t outbound_intstatus; |
1256 | struct MessageUnit_A __iomem *reg = acb->pmuA; | 1371 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
1257 | 1372 | ||
1258 | outbound_intstatus = readl(®->outbound_intstatus) & \ | 1373 | outbound_intstatus = readl(®->outbound_intstatus) & |
1259 | acb->outbound_int_enable; | 1374 | acb->outbound_int_enable; |
1260 | if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { | 1375 | if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { |
1261 | return 1; | 1376 | return 1; |
@@ -1267,6 +1382,10 @@ static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) | |||
1267 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { | 1382 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { |
1268 | arcmsr_hba_postqueue_isr(acb); | 1383 | arcmsr_hba_postqueue_isr(acb); |
1269 | } | 1384 | } |
1385 | if (outbound_intstatus & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { | ||
1386 | /* messenger of "driver to iop commands" */ | ||
1387 | arcmsr_hba_message_isr(acb); | ||
1388 | } | ||
1270 | return 0; | 1389 | return 0; |
1271 | } | 1390 | } |
1272 | 1391 | ||
@@ -1275,13 +1394,14 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) | |||
1275 | uint32_t outbound_doorbell; | 1394 | uint32_t outbound_doorbell; |
1276 | struct MessageUnit_B *reg = acb->pmuB; | 1395 | struct MessageUnit_B *reg = acb->pmuB; |
1277 | 1396 | ||
1278 | outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ | 1397 | outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & |
1279 | acb->outbound_int_enable; | 1398 | acb->outbound_int_enable; |
1280 | if (!outbound_doorbell) | 1399 | if (!outbound_doorbell) |
1281 | return 1; | 1400 | return 1; |
1282 | 1401 | ||
1283 | writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); | 1402 | writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); |
1284 | /*in case the last action of doorbell interrupt clearance is cached, this action can push HW to write down the clear bit*/ | 1403 | /*in case the last action of doorbell interrupt clearance is cached, |
1404 | this action can push HW to write down the clear bit*/ | ||
1285 | readl(reg->iop2drv_doorbell_reg); | 1405 | readl(reg->iop2drv_doorbell_reg); |
1286 | writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); | 1406 | writel(ARCMSR_DRV2IOP_END_OF_INTERRUPT, reg->drv2iop_doorbell_reg); |
1287 | if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { | 1407 | if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { |
@@ -1293,6 +1413,10 @@ static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) | |||
1293 | if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { | 1413 | if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { |
1294 | arcmsr_hbb_postqueue_isr(acb); | 1414 | arcmsr_hbb_postqueue_isr(acb); |
1295 | } | 1415 | } |
1416 | if (outbound_doorbell & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { | ||
1417 | /* messenger of "driver to iop commands" */ | ||
1418 | arcmsr_hbb_message_isr(acb); | ||
1419 | } | ||
1296 | 1420 | ||
1297 | return 0; | 1421 | return 0; |
1298 | } | 1422 | } |
@@ -1360,7 +1484,7 @@ void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) | |||
1360 | } | 1484 | } |
1361 | } | 1485 | } |
1362 | 1486 | ||
1363 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | 1487 | static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, |
1364 | struct scsi_cmnd *cmd) | 1488 | struct scsi_cmnd *cmd) |
1365 | { | 1489 | { |
1366 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; | 1490 | struct CMD_MESSAGE_FIELD *pcmdmessagefld; |
@@ -1398,6 +1522,13 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1398 | retvalue = ARCMSR_MESSAGE_FAIL; | 1522 | retvalue = ARCMSR_MESSAGE_FAIL; |
1399 | goto message_out; | 1523 | goto message_out; |
1400 | } | 1524 | } |
1525 | |||
1526 | if (!acb->fw_state) { | ||
1527 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1528 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1529 | goto message_out; | ||
1530 | } | ||
1531 | |||
1401 | ptmpQbuffer = ver_addr; | 1532 | ptmpQbuffer = ver_addr; |
1402 | while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) | 1533 | while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) |
1403 | && (allxfer_len < 1031)) { | 1534 | && (allxfer_len < 1031)) { |
@@ -1444,6 +1575,12 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1444 | retvalue = ARCMSR_MESSAGE_FAIL; | 1575 | retvalue = ARCMSR_MESSAGE_FAIL; |
1445 | goto message_out; | 1576 | goto message_out; |
1446 | } | 1577 | } |
1578 | if (!acb->fw_state) { | ||
1579 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1580 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1581 | goto message_out; | ||
1582 | } | ||
1583 | |||
1447 | ptmpuserbuffer = ver_addr; | 1584 | ptmpuserbuffer = ver_addr; |
1448 | user_len = pcmdmessagefld->cmdmessage.Length; | 1585 | user_len = pcmdmessagefld->cmdmessage.Length; |
1449 | memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); | 1586 | memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); |
@@ -1496,6 +1633,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1496 | 1633 | ||
1497 | case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { | 1634 | case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { |
1498 | uint8_t *pQbuffer = acb->rqbuffer; | 1635 | uint8_t *pQbuffer = acb->rqbuffer; |
1636 | if (!acb->fw_state) { | ||
1637 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1638 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1639 | goto message_out; | ||
1640 | } | ||
1499 | 1641 | ||
1500 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 1642 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
1501 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 1643 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
@@ -1511,6 +1653,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1511 | 1653 | ||
1512 | case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { | 1654 | case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { |
1513 | uint8_t *pQbuffer = acb->wqbuffer; | 1655 | uint8_t *pQbuffer = acb->wqbuffer; |
1656 | if (!acb->fw_state) { | ||
1657 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1658 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1659 | goto message_out; | ||
1660 | } | ||
1514 | 1661 | ||
1515 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 1662 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
1516 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 1663 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
@@ -1529,6 +1676,11 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1529 | 1676 | ||
1530 | case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { | 1677 | case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { |
1531 | uint8_t *pQbuffer; | 1678 | uint8_t *pQbuffer; |
1679 | if (!acb->fw_state) { | ||
1680 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1681 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1682 | goto message_out; | ||
1683 | } | ||
1532 | 1684 | ||
1533 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { | 1685 | if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { |
1534 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; | 1686 | acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; |
@@ -1551,13 +1703,22 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1551 | break; | 1703 | break; |
1552 | 1704 | ||
1553 | case ARCMSR_MESSAGE_RETURN_CODE_3F: { | 1705 | case ARCMSR_MESSAGE_RETURN_CODE_3F: { |
1706 | if (!acb->fw_state) { | ||
1707 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1708 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1709 | goto message_out; | ||
1710 | } | ||
1554 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; | 1711 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; |
1555 | } | 1712 | } |
1556 | break; | 1713 | break; |
1557 | 1714 | ||
1558 | case ARCMSR_MESSAGE_SAY_HELLO: { | 1715 | case ARCMSR_MESSAGE_SAY_HELLO: { |
1559 | int8_t *hello_string = "Hello! I am ARCMSR"; | 1716 | int8_t *hello_string = "Hello! I am ARCMSR"; |
1560 | 1717 | if (!acb->fw_state) { | |
1718 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1719 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1720 | goto message_out; | ||
1721 | } | ||
1561 | memcpy(pcmdmessagefld->messagedatabuffer, hello_string | 1722 | memcpy(pcmdmessagefld->messagedatabuffer, hello_string |
1562 | , (int16_t)strlen(hello_string)); | 1723 | , (int16_t)strlen(hello_string)); |
1563 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; | 1724 | pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; |
@@ -1565,10 +1726,20 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ | |||
1565 | break; | 1726 | break; |
1566 | 1727 | ||
1567 | case ARCMSR_MESSAGE_SAY_GOODBYE: | 1728 | case ARCMSR_MESSAGE_SAY_GOODBYE: |
1729 | if (!acb->fw_state) { | ||
1730 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1731 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1732 | goto message_out; | ||
1733 | } | ||
1568 | arcmsr_iop_parking(acb); | 1734 | arcmsr_iop_parking(acb); |
1569 | break; | 1735 | break; |
1570 | 1736 | ||
1571 | case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: | 1737 | case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: |
1738 | if (!acb->fw_state) { | ||
1739 | pcmdmessagefld->cmdmessage.ReturnCode = | ||
1740 | ARCMSR_MESSAGE_RETURNCODE_BUS_HANG_ON; | ||
1741 | goto message_out; | ||
1742 | } | ||
1572 | arcmsr_flush_adapter_cache(acb); | 1743 | arcmsr_flush_adapter_cache(acb); |
1573 | break; | 1744 | break; |
1574 | 1745 | ||
@@ -1651,16 +1822,57 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, | |||
1651 | struct CommandControlBlock *ccb; | 1822 | struct CommandControlBlock *ccb; |
1652 | int target = cmd->device->id; | 1823 | int target = cmd->device->id; |
1653 | int lun = cmd->device->lun; | 1824 | int lun = cmd->device->lun; |
1654 | 1825 | uint8_t scsicmd = cmd->cmnd[0]; | |
1655 | cmd->scsi_done = done; | 1826 | cmd->scsi_done = done; |
1656 | cmd->host_scribble = NULL; | 1827 | cmd->host_scribble = NULL; |
1657 | cmd->result = 0; | 1828 | cmd->result = 0; |
1829 | |||
1830 | if ((scsicmd == SYNCHRONIZE_CACHE) || (scsicmd == SEND_DIAGNOSTIC)) { | ||
1831 | if (acb->devstate[target][lun] == ARECA_RAID_GONE) { | ||
1832 | cmd->result = (DID_NO_CONNECT << 16); | ||
1833 | } | ||
1834 | cmd->scsi_done(cmd); | ||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1658 | if (acb->acb_flags & ACB_F_BUS_RESET) { | 1838 | if (acb->acb_flags & ACB_F_BUS_RESET) { |
1659 | printk(KERN_NOTICE "arcmsr%d: bus reset" | 1839 | switch (acb->adapter_type) { |
1660 | " and return busy \n" | 1840 | case ACB_ADAPTER_TYPE_A: { |
1661 | , acb->host->host_no); | 1841 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
1842 | uint32_t intmask_org, outbound_doorbell; | ||
1843 | |||
1844 | if ((readl(®->outbound_msgaddr1) & | ||
1845 | ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { | ||
1846 | printk(KERN_NOTICE "arcmsr%d: bus reset and return busy\n", | ||
1847 | acb->host->host_no); | ||
1662 | return SCSI_MLQUEUE_HOST_BUSY; | 1848 | return SCSI_MLQUEUE_HOST_BUSY; |
1663 | } | 1849 | } |
1850 | |||
1851 | acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP; | ||
1852 | printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok\n", | ||
1853 | acb->host->host_no); | ||
1854 | /* disable all outbound interrupt */ | ||
1855 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
1856 | arcmsr_get_firmware_spec(acb, 1); | ||
1857 | /*start background rebuild*/ | ||
1858 | arcmsr_start_adapter_bgrb(acb); | ||
1859 | /* clear Qbuffer if door bell ringed */ | ||
1860 | outbound_doorbell = readl(®->outbound_doorbell); | ||
1861 | /*clear interrupt */ | ||
1862 | writel(outbound_doorbell, ®->outbound_doorbell); | ||
1863 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, | ||
1864 | ®->inbound_doorbell); | ||
1865 | /* enable outbound Post Queue,outbound doorbell Interrupt */ | ||
1866 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
1867 | acb->acb_flags |= ACB_F_IOP_INITED; | ||
1868 | acb->acb_flags &= ~ACB_F_BUS_RESET; | ||
1869 | } | ||
1870 | break; | ||
1871 | case ACB_ADAPTER_TYPE_B: { | ||
1872 | } | ||
1873 | } | ||
1874 | } | ||
1875 | |||
1664 | if (target == 16) { | 1876 | if (target == 16) { |
1665 | /* virtual device for iop message transfer */ | 1877 | /* virtual device for iop message transfer */ |
1666 | arcmsr_handle_virtual_command(acb, cmd); | 1878 | arcmsr_handle_virtual_command(acb, cmd); |
@@ -1699,21 +1911,25 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, | |||
1699 | return 0; | 1911 | return 0; |
1700 | } | 1912 | } |
1701 | 1913 | ||
1702 | static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) | 1914 | static void *arcmsr_get_hba_config(struct AdapterControlBlock *acb, int mode) |
1703 | { | 1915 | { |
1704 | struct MessageUnit_A __iomem *reg = acb->pmuA; | 1916 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
1705 | char *acb_firm_model = acb->firm_model; | 1917 | char *acb_firm_model = acb->firm_model; |
1706 | char *acb_firm_version = acb->firm_version; | 1918 | char *acb_firm_version = acb->firm_version; |
1919 | char *acb_device_map = acb->device_map; | ||
1707 | char __iomem *iop_firm_model = (char __iomem *)(®->message_rwbuffer[15]); | 1920 | char __iomem *iop_firm_model = (char __iomem *)(®->message_rwbuffer[15]); |
1708 | char __iomem *iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]); | 1921 | char __iomem *iop_firm_version = (char __iomem *)(®->message_rwbuffer[17]); |
1922 | char __iomem *iop_device_map = (char __iomem *) (®->message_rwbuffer[21]); | ||
1709 | int count; | 1923 | int count; |
1710 | 1924 | ||
1711 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); | 1925 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); |
1712 | if (arcmsr_hba_wait_msgint_ready(acb)) { | 1926 | if (arcmsr_hba_wait_msgint_ready(acb)) { |
1713 | printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ | 1927 | printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ |
1714 | miscellaneous data' timeout \n", acb->host->host_no); | 1928 | miscellaneous data' timeout \n", acb->host->host_no); |
1929 | return NULL; | ||
1715 | } | 1930 | } |
1716 | 1931 | ||
1932 | if (mode == 1) { | ||
1717 | count = 8; | 1933 | count = 8; |
1718 | while (count) { | 1934 | while (count) { |
1719 | *acb_firm_model = readb(iop_firm_model); | 1935 | *acb_firm_model = readb(iop_firm_model); |
@@ -1730,34 +1946,48 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) | |||
1730 | count--; | 1946 | count--; |
1731 | } | 1947 | } |
1732 | 1948 | ||
1949 | count = 16; | ||
1950 | while (count) { | ||
1951 | *acb_device_map = readb(iop_device_map); | ||
1952 | acb_device_map++; | ||
1953 | iop_device_map++; | ||
1954 | count--; | ||
1955 | } | ||
1956 | |||
1733 | printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" | 1957 | printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" |
1734 | , acb->host->host_no | 1958 | , acb->host->host_no |
1735 | , acb->firm_version); | 1959 | , acb->firm_version); |
1736 | 1960 | acb->signature = readl(®->message_rwbuffer[0]); | |
1737 | acb->firm_request_len = readl(®->message_rwbuffer[1]); | 1961 | acb->firm_request_len = readl(®->message_rwbuffer[1]); |
1738 | acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); | 1962 | acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); |
1739 | acb->firm_sdram_size = readl(®->message_rwbuffer[3]); | 1963 | acb->firm_sdram_size = readl(®->message_rwbuffer[3]); |
1740 | acb->firm_hd_channels = readl(®->message_rwbuffer[4]); | 1964 | acb->firm_hd_channels = readl(®->message_rwbuffer[4]); |
1741 | } | 1965 | } |
1742 | 1966 | return reg->message_rwbuffer; | |
1743 | static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) | 1967 | } |
1968 | static void __iomem *arcmsr_get_hbb_config(struct AdapterControlBlock *acb, int mode) | ||
1744 | { | 1969 | { |
1745 | struct MessageUnit_B *reg = acb->pmuB; | 1970 | struct MessageUnit_B *reg = acb->pmuB; |
1746 | uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg; | 1971 | uint32_t __iomem *lrwbuffer = reg->msgcode_rwbuffer_reg; |
1747 | char *acb_firm_model = acb->firm_model; | 1972 | char *acb_firm_model = acb->firm_model; |
1748 | char *acb_firm_version = acb->firm_version; | 1973 | char *acb_firm_version = acb->firm_version; |
1974 | char *acb_device_map = acb->device_map; | ||
1749 | char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]); | 1975 | char __iomem *iop_firm_model = (char __iomem *)(&lrwbuffer[15]); |
1750 | /*firm_model,15,60-67*/ | 1976 | /*firm_model,15,60-67*/ |
1751 | char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]); | 1977 | char __iomem *iop_firm_version = (char __iomem *)(&lrwbuffer[17]); |
1752 | /*firm_version,17,68-83*/ | 1978 | /*firm_version,17,68-83*/ |
1979 | char __iomem *iop_device_map = (char __iomem *) (&lrwbuffer[21]); | ||
1980 | /*firm_version,21,84-99*/ | ||
1753 | int count; | 1981 | int count; |
1754 | 1982 | ||
1755 | writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); | 1983 | writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); |
1756 | if (arcmsr_hbb_wait_msgint_ready(acb)) { | 1984 | if (arcmsr_hbb_wait_msgint_ready(acb)) { |
1757 | printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ | 1985 | printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ |
1758 | miscellaneous data' timeout \n", acb->host->host_no); | 1986 | miscellaneous data' timeout \n", acb->host->host_no); |
1987 | return NULL; | ||
1759 | } | 1988 | } |
1760 | 1989 | ||
1990 | if (mode == 1) { | ||
1761 | count = 8; | 1991 | count = 8; |
1762 | while (count) | 1992 | while (count) |
1763 | { | 1993 | { |
@@ -1776,11 +2006,20 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) | |||
1776 | count--; | 2006 | count--; |
1777 | } | 2007 | } |
1778 | 2008 | ||
2009 | count = 16; | ||
2010 | while (count) { | ||
2011 | *acb_device_map = readb(iop_device_map); | ||
2012 | acb_device_map++; | ||
2013 | iop_device_map++; | ||
2014 | count--; | ||
2015 | } | ||
2016 | |||
1779 | printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", | 2017 | printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", |
1780 | acb->host->host_no, | 2018 | acb->host->host_no, |
1781 | acb->firm_version); | 2019 | acb->firm_version); |
1782 | 2020 | ||
1783 | lrwbuffer++; | 2021 | acb->signature = readl(lrwbuffer++); |
2022 | /*firm_signature,1,00-03*/ | ||
1784 | acb->firm_request_len = readl(lrwbuffer++); | 2023 | acb->firm_request_len = readl(lrwbuffer++); |
1785 | /*firm_request_len,1,04-07*/ | 2024 | /*firm_request_len,1,04-07*/ |
1786 | acb->firm_numbers_queue = readl(lrwbuffer++); | 2025 | acb->firm_numbers_queue = readl(lrwbuffer++); |
@@ -1790,20 +2029,23 @@ static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) | |||
1790 | acb->firm_hd_channels = readl(lrwbuffer); | 2029 | acb->firm_hd_channels = readl(lrwbuffer); |
1791 | /*firm_ide_channels,4,16-19*/ | 2030 | /*firm_ide_channels,4,16-19*/ |
1792 | } | 2031 | } |
1793 | 2032 | return reg->msgcode_rwbuffer_reg; | |
1794 | static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) | 2033 | } |
2034 | static void *arcmsr_get_firmware_spec(struct AdapterControlBlock *acb, int mode) | ||
1795 | { | 2035 | { |
2036 | void *rtnval = 0; | ||
1796 | switch (acb->adapter_type) { | 2037 | switch (acb->adapter_type) { |
1797 | case ACB_ADAPTER_TYPE_A: { | 2038 | case ACB_ADAPTER_TYPE_A: { |
1798 | arcmsr_get_hba_config(acb); | 2039 | rtnval = arcmsr_get_hba_config(acb, mode); |
1799 | } | 2040 | } |
1800 | break; | 2041 | break; |
1801 | 2042 | ||
1802 | case ACB_ADAPTER_TYPE_B: { | 2043 | case ACB_ADAPTER_TYPE_B: { |
1803 | arcmsr_get_hbb_config(acb); | 2044 | rtnval = arcmsr_get_hbb_config(acb, mode); |
1804 | } | 2045 | } |
1805 | break; | 2046 | break; |
1806 | } | 2047 | } |
2048 | return rtnval; | ||
1807 | } | 2049 | } |
1808 | 2050 | ||
1809 | static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, | 2051 | static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, |
@@ -2043,6 +2285,66 @@ static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) | |||
2043 | } | 2285 | } |
2044 | } | 2286 | } |
2045 | 2287 | ||
2288 | static void arcmsr_request_hba_device_map(struct AdapterControlBlock *acb) | ||
2289 | { | ||
2290 | struct MessageUnit_A __iomem *reg = acb->pmuA; | ||
2291 | |||
2292 | if (unlikely(atomic_read(&acb->rq_map_token) == 0)) { | ||
2293 | acb->fw_state = false; | ||
2294 | } else { | ||
2295 | /*to prevent rq_map_token from changing by other interrupt, then | ||
2296 | avoid the dead-lock*/ | ||
2297 | acb->fw_state = true; | ||
2298 | atomic_dec(&acb->rq_map_token); | ||
2299 | if (!(acb->fw_state) || | ||
2300 | (acb->ante_token_value == atomic_read(&acb->rq_map_token))) { | ||
2301 | atomic_set(&acb->rq_map_token, 16); | ||
2302 | } | ||
2303 | acb->ante_token_value = atomic_read(&acb->rq_map_token); | ||
2304 | writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); | ||
2305 | } | ||
2306 | mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000)); | ||
2307 | return; | ||
2308 | } | ||
2309 | |||
2310 | static void arcmsr_request_hbb_device_map(struct AdapterControlBlock *acb) | ||
2311 | { | ||
2312 | struct MessageUnit_B __iomem *reg = acb->pmuB; | ||
2313 | |||
2314 | if (unlikely(atomic_read(&acb->rq_map_token) == 0)) { | ||
2315 | acb->fw_state = false; | ||
2316 | } else { | ||
2317 | /*to prevent rq_map_token from changing by other interrupt, then | ||
2318 | avoid the dead-lock*/ | ||
2319 | acb->fw_state = true; | ||
2320 | atomic_dec(&acb->rq_map_token); | ||
2321 | if (!(acb->fw_state) || | ||
2322 | (acb->ante_token_value == atomic_read(&acb->rq_map_token))) { | ||
2323 | atomic_set(&acb->rq_map_token, 16); | ||
2324 | } | ||
2325 | acb->ante_token_value = atomic_read(&acb->rq_map_token); | ||
2326 | writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); | ||
2327 | } | ||
2328 | mod_timer(&acb->eternal_timer, jiffies + msecs_to_jiffies(6000)); | ||
2329 | return; | ||
2330 | } | ||
2331 | |||
2332 | static void arcmsr_request_device_map(unsigned long pacb) | ||
2333 | { | ||
2334 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *)pacb; | ||
2335 | |||
2336 | switch (acb->adapter_type) { | ||
2337 | case ACB_ADAPTER_TYPE_A: { | ||
2338 | arcmsr_request_hba_device_map(acb); | ||
2339 | } | ||
2340 | break; | ||
2341 | case ACB_ADAPTER_TYPE_B: { | ||
2342 | arcmsr_request_hbb_device_map(acb); | ||
2343 | } | ||
2344 | break; | ||
2345 | } | ||
2346 | } | ||
2347 | |||
2046 | static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) | 2348 | static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) |
2047 | { | 2349 | { |
2048 | struct MessageUnit_A __iomem *reg = acb->pmuA; | 2350 | struct MessageUnit_A __iomem *reg = acb->pmuA; |
@@ -2121,6 +2423,60 @@ static void arcmsr_enable_eoi_mode(struct AdapterControlBlock *acb) | |||
2121 | return; | 2423 | return; |
2122 | } | 2424 | } |
2123 | 2425 | ||
2426 | static void arcmsr_hardware_reset(struct AdapterControlBlock *acb) | ||
2427 | { | ||
2428 | uint8_t value[64]; | ||
2429 | int i; | ||
2430 | |||
2431 | /* backup pci config data */ | ||
2432 | for (i = 0; i < 64; i++) { | ||
2433 | pci_read_config_byte(acb->pdev, i, &value[i]); | ||
2434 | } | ||
2435 | /* hardware reset signal */ | ||
2436 | pci_write_config_byte(acb->pdev, 0x84, 0x20); | ||
2437 | msleep(1000); | ||
2438 | /* write back pci config data */ | ||
2439 | for (i = 0; i < 64; i++) { | ||
2440 | pci_write_config_byte(acb->pdev, i, value[i]); | ||
2441 | } | ||
2442 | msleep(1000); | ||
2443 | return; | ||
2444 | } | ||
2445 | /* | ||
2446 | **************************************************************************** | ||
2447 | **************************************************************************** | ||
2448 | */ | ||
2449 | #ifdef CONFIG_SCSI_ARCMSR_RESET | ||
2450 | int arcmsr_sleep_for_bus_reset(struct scsi_cmnd *cmd) | ||
2451 | { | ||
2452 | struct Scsi_Host *shost = NULL; | ||
2453 | spinlock_t *host_lock = NULL; | ||
2454 | int i, isleep; | ||
2455 | |||
2456 | shost = cmd->device->host; | ||
2457 | host_lock = shost->host_lock; | ||
2458 | |||
2459 | printk(KERN_NOTICE "Host %d bus reset over, sleep %d seconds (busy %d, can queue %d) ...........\n", | ||
2460 | shost->host_no, sleeptime, shost->host_busy, shost->can_queue); | ||
2461 | isleep = sleeptime / 10; | ||
2462 | spin_unlock_irq(host_lock); | ||
2463 | if (isleep > 0) { | ||
2464 | for (i = 0; i < isleep; i++) { | ||
2465 | msleep(10000); | ||
2466 | printk(KERN_NOTICE "^%d^\n", i); | ||
2467 | } | ||
2468 | } | ||
2469 | |||
2470 | isleep = sleeptime % 10; | ||
2471 | if (isleep > 0) { | ||
2472 | msleep(isleep * 1000); | ||
2473 | printk(KERN_NOTICE "^v^\n"); | ||
2474 | } | ||
2475 | spin_lock_irq(host_lock); | ||
2476 | printk(KERN_NOTICE "***** wake up *****\n"); | ||
2477 | return 0; | ||
2478 | } | ||
2479 | #endif | ||
2124 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) | 2480 | static void arcmsr_iop_init(struct AdapterControlBlock *acb) |
2125 | { | 2481 | { |
2126 | uint32_t intmask_org; | 2482 | uint32_t intmask_org; |
@@ -2129,7 +2485,7 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb) | |||
2129 | intmask_org = arcmsr_disable_outbound_ints(acb); | 2485 | intmask_org = arcmsr_disable_outbound_ints(acb); |
2130 | arcmsr_wait_firmware_ready(acb); | 2486 | arcmsr_wait_firmware_ready(acb); |
2131 | arcmsr_iop_confirm(acb); | 2487 | arcmsr_iop_confirm(acb); |
2132 | arcmsr_get_firmware_spec(acb); | 2488 | arcmsr_get_firmware_spec(acb, 1); |
2133 | /*start background rebuild*/ | 2489 | /*start background rebuild*/ |
2134 | arcmsr_start_adapter_bgrb(acb); | 2490 | arcmsr_start_adapter_bgrb(acb); |
2135 | /* empty doorbell Qbuffer if door bell ringed */ | 2491 | /* empty doorbell Qbuffer if door bell ringed */ |
@@ -2140,51 +2496,110 @@ static void arcmsr_iop_init(struct AdapterControlBlock *acb) | |||
2140 | acb->acb_flags |= ACB_F_IOP_INITED; | 2496 | acb->acb_flags |= ACB_F_IOP_INITED; |
2141 | } | 2497 | } |
2142 | 2498 | ||
2143 | static void arcmsr_iop_reset(struct AdapterControlBlock *acb) | 2499 | static uint8_t arcmsr_iop_reset(struct AdapterControlBlock *acb) |
2144 | { | 2500 | { |
2145 | struct CommandControlBlock *ccb; | 2501 | struct CommandControlBlock *ccb; |
2146 | uint32_t intmask_org; | 2502 | uint32_t intmask_org; |
2503 | uint8_t rtnval = 0x00; | ||
2147 | int i = 0; | 2504 | int i = 0; |
2148 | 2505 | ||
2149 | if (atomic_read(&acb->ccboutstandingcount) != 0) { | 2506 | if (atomic_read(&acb->ccboutstandingcount) != 0) { |
2507 | /* disable all outbound interrupt */ | ||
2508 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
2150 | /* talk to iop 331 outstanding command aborted */ | 2509 | /* talk to iop 331 outstanding command aborted */ |
2151 | arcmsr_abort_allcmd(acb); | 2510 | rtnval = arcmsr_abort_allcmd(acb); |
2152 | |||
2153 | /* wait for 3 sec for all command aborted*/ | 2511 | /* wait for 3 sec for all command aborted*/ |
2154 | ssleep(3); | 2512 | ssleep(3); |
2155 | |||
2156 | /* disable all outbound interrupt */ | ||
2157 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
2158 | /* clear all outbound posted Q */ | 2513 | /* clear all outbound posted Q */ |
2159 | arcmsr_done4abort_postqueue(acb); | 2514 | arcmsr_done4abort_postqueue(acb); |
2160 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | 2515 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { |
2161 | ccb = acb->pccb_pool[i]; | 2516 | ccb = acb->pccb_pool[i]; |
2162 | if (ccb->startdone == ARCMSR_CCB_START) { | 2517 | if (ccb->startdone == ARCMSR_CCB_START) { |
2163 | ccb->startdone = ARCMSR_CCB_ABORTED; | ||
2164 | arcmsr_ccb_complete(ccb, 1); | 2518 | arcmsr_ccb_complete(ccb, 1); |
2165 | } | 2519 | } |
2166 | } | 2520 | } |
2521 | atomic_set(&acb->ccboutstandingcount, 0); | ||
2167 | /* enable all outbound interrupt */ | 2522 | /* enable all outbound interrupt */ |
2168 | arcmsr_enable_outbound_ints(acb, intmask_org); | 2523 | arcmsr_enable_outbound_ints(acb, intmask_org); |
2524 | return rtnval; | ||
2169 | } | 2525 | } |
2526 | return rtnval; | ||
2170 | } | 2527 | } |
2171 | 2528 | ||
2172 | static int arcmsr_bus_reset(struct scsi_cmnd *cmd) | 2529 | static int arcmsr_bus_reset(struct scsi_cmnd *cmd) |
2173 | { | 2530 | { |
2174 | struct AdapterControlBlock *acb = | 2531 | struct AdapterControlBlock *acb = |
2175 | (struct AdapterControlBlock *)cmd->device->host->hostdata; | 2532 | (struct AdapterControlBlock *)cmd->device->host->hostdata; |
2176 | int i; | 2533 | int retry = 0; |
2177 | 2534 | ||
2178 | acb->num_resets++; | 2535 | if (acb->acb_flags & ACB_F_BUS_RESET) |
2536 | return SUCCESS; | ||
2537 | |||
2538 | printk(KERN_NOTICE "arcmsr%d: bus reset ..... \n", acb->adapter_index); | ||
2179 | acb->acb_flags |= ACB_F_BUS_RESET; | 2539 | acb->acb_flags |= ACB_F_BUS_RESET; |
2180 | for (i = 0; i < 400; i++) { | 2540 | acb->num_resets++; |
2181 | if (!atomic_read(&acb->ccboutstandingcount)) | 2541 | while (atomic_read(&acb->ccboutstandingcount) != 0 && retry < 4) { |
2542 | arcmsr_interrupt(acb); | ||
2543 | retry++; | ||
2544 | } | ||
2545 | |||
2546 | if (arcmsr_iop_reset(acb)) { | ||
2547 | switch (acb->adapter_type) { | ||
2548 | case ACB_ADAPTER_TYPE_A: { | ||
2549 | printk(KERN_NOTICE "arcmsr%d: do hardware bus reset, num_resets = %d num_aborts = %d \n", | ||
2550 | acb->adapter_index, acb->num_resets, acb->num_aborts); | ||
2551 | arcmsr_hardware_reset(acb); | ||
2552 | acb->acb_flags |= ACB_F_FIRMWARE_TRAP; | ||
2553 | acb->acb_flags &= ~ACB_F_IOP_INITED; | ||
2554 | #ifdef CONFIG_SCSI_ARCMSR_RESET | ||
2555 | struct MessageUnit_A __iomem *reg = acb->pmuA; | ||
2556 | uint32_t intmask_org, outbound_doorbell; | ||
2557 | int retry_count = 0; | ||
2558 | sleep_again: | ||
2559 | arcmsr_sleep_for_bus_reset(cmd); | ||
2560 | if ((readl(®->outbound_msgaddr1) & | ||
2561 | ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0) { | ||
2562 | printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry=%d \n", | ||
2563 | acb->host->host_no, retry_count); | ||
2564 | if (retry_count > retrycount) { | ||
2565 | printk(KERN_NOTICE "arcmsr%d: hardware bus reset and return busy, retry aborted \n", | ||
2566 | acb->host->host_no); | ||
2567 | return SUCCESS; | ||
2568 | } | ||
2569 | retry_count++; | ||
2570 | goto sleep_again; | ||
2571 | } | ||
2572 | acb->acb_flags &= ~ACB_F_FIRMWARE_TRAP; | ||
2573 | acb->acb_flags |= ACB_F_IOP_INITED; | ||
2574 | acb->acb_flags &= ~ACB_F_BUS_RESET; | ||
2575 | printk(KERN_NOTICE "arcmsr%d: hardware bus reset and reset ok \n", | ||
2576 | acb->host->host_no); | ||
2577 | /* disable all outbound interrupt */ | ||
2578 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
2579 | arcmsr_get_firmware_spec(acb, 1); | ||
2580 | /*start background rebuild*/ | ||
2581 | arcmsr_start_adapter_bgrb(acb); | ||
2582 | /* clear Qbuffer if door bell ringed */ | ||
2583 | outbound_doorbell = readl(®->outbound_doorbell); | ||
2584 | writel(outbound_doorbell, ®->outbound_doorbell); /*clear interrupt */ | ||
2585 | writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); | ||
2586 | /* enable outbound Post Queue,outbound doorbell Interrupt */ | ||
2587 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
2588 | atomic_set(&acb->rq_map_token, 16); | ||
2589 | init_timer(&acb->eternal_timer); | ||
2590 | acb->eternal_timer.expires = jiffies + msecs_to_jiffies(20*HZ); | ||
2591 | acb->eternal_timer.data = (unsigned long) acb; | ||
2592 | acb->eternal_timer.function = &arcmsr_request_device_map; | ||
2593 | add_timer(&acb->eternal_timer); | ||
2594 | #endif | ||
2595 | } | ||
2182 | break; | 2596 | break; |
2183 | arcmsr_interrupt(acb);/* FIXME: need spinlock */ | 2597 | case ACB_ADAPTER_TYPE_B: { |
2184 | msleep(25); | ||
2185 | } | 2598 | } |
2186 | arcmsr_iop_reset(acb); | 2599 | } |
2600 | } else { | ||
2187 | acb->acb_flags &= ~ACB_F_BUS_RESET; | 2601 | acb->acb_flags &= ~ACB_F_BUS_RESET; |
2602 | } | ||
2188 | return SUCCESS; | 2603 | return SUCCESS; |
2189 | } | 2604 | } |
2190 | 2605 | ||
@@ -2277,98 +2692,3 @@ static const char *arcmsr_info(struct Scsi_Host *host) | |||
2277 | ARCMSR_DRIVER_VERSION); | 2692 | ARCMSR_DRIVER_VERSION); |
2278 | return buf; | 2693 | return buf; |
2279 | } | 2694 | } |
2280 | #ifdef CONFIG_SCSI_ARCMSR_AER | ||
2281 | static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) | ||
2282 | { | ||
2283 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
2284 | struct AdapterControlBlock *acb = | ||
2285 | (struct AdapterControlBlock *) host->hostdata; | ||
2286 | uint32_t intmask_org; | ||
2287 | int i, j; | ||
2288 | |||
2289 | if (pci_enable_device(pdev)) { | ||
2290 | return PCI_ERS_RESULT_DISCONNECT; | ||
2291 | } | ||
2292 | pci_set_master(pdev); | ||
2293 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
2294 | acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | | ||
2295 | ACB_F_MESSAGE_RQBUFFER_CLEARED | | ||
2296 | ACB_F_MESSAGE_WQBUFFER_READED); | ||
2297 | acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; | ||
2298 | for (i = 0; i < ARCMSR_MAX_TARGETID; i++) | ||
2299 | for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) | ||
2300 | acb->devstate[i][j] = ARECA_RAID_GONE; | ||
2301 | |||
2302 | arcmsr_wait_firmware_ready(acb); | ||
2303 | arcmsr_iop_confirm(acb); | ||
2304 | /* disable all outbound interrupt */ | ||
2305 | arcmsr_get_firmware_spec(acb); | ||
2306 | /*start background rebuild*/ | ||
2307 | arcmsr_start_adapter_bgrb(acb); | ||
2308 | /* empty doorbell Qbuffer if door bell ringed */ | ||
2309 | arcmsr_clear_doorbell_queue_buffer(acb); | ||
2310 | arcmsr_enable_eoi_mode(acb); | ||
2311 | /* enable outbound Post Queue,outbound doorbell Interrupt */ | ||
2312 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
2313 | acb->acb_flags |= ACB_F_IOP_INITED; | ||
2314 | |||
2315 | pci_enable_pcie_error_reporting(pdev); | ||
2316 | return PCI_ERS_RESULT_RECOVERED; | ||
2317 | } | ||
2318 | |||
2319 | static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev) | ||
2320 | { | ||
2321 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
2322 | struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; | ||
2323 | struct CommandControlBlock *ccb; | ||
2324 | uint32_t intmask_org; | ||
2325 | int i = 0; | ||
2326 | |||
2327 | if (atomic_read(&acb->ccboutstandingcount) != 0) { | ||
2328 | /* talk to iop 331 outstanding command aborted */ | ||
2329 | arcmsr_abort_allcmd(acb); | ||
2330 | /* wait for 3 sec for all command aborted*/ | ||
2331 | ssleep(3); | ||
2332 | /* disable all outbound interrupt */ | ||
2333 | intmask_org = arcmsr_disable_outbound_ints(acb); | ||
2334 | /* clear all outbound posted Q */ | ||
2335 | arcmsr_done4abort_postqueue(acb); | ||
2336 | for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { | ||
2337 | ccb = acb->pccb_pool[i]; | ||
2338 | if (ccb->startdone == ARCMSR_CCB_START) { | ||
2339 | ccb->startdone = ARCMSR_CCB_ABORTED; | ||
2340 | arcmsr_ccb_complete(ccb, 1); | ||
2341 | } | ||
2342 | } | ||
2343 | /* enable all outbound interrupt */ | ||
2344 | arcmsr_enable_outbound_ints(acb, intmask_org); | ||
2345 | } | ||
2346 | pci_disable_device(pdev); | ||
2347 | } | ||
2348 | |||
2349 | static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev) | ||
2350 | { | ||
2351 | struct Scsi_Host *host = pci_get_drvdata(pdev); | ||
2352 | struct AdapterControlBlock *acb = \ | ||
2353 | (struct AdapterControlBlock *)host->hostdata; | ||
2354 | |||
2355 | arcmsr_stop_adapter_bgrb(acb); | ||
2356 | arcmsr_flush_adapter_cache(acb); | ||
2357 | } | ||
2358 | |||
2359 | static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, | ||
2360 | pci_channel_state_t state) | ||
2361 | { | ||
2362 | switch (state) { | ||
2363 | case pci_channel_io_frozen: | ||
2364 | arcmsr_pci_ers_need_reset_forepart(pdev); | ||
2365 | return PCI_ERS_RESULT_NEED_RESET; | ||
2366 | case pci_channel_io_perm_failure: | ||
2367 | arcmsr_pci_ers_disconnect_forepart(pdev); | ||
2368 | return PCI_ERS_RESULT_DISCONNECT; | ||
2369 | break; | ||
2370 | default: | ||
2371 | return PCI_ERS_RESULT_NEED_RESET; | ||
2372 | } | ||
2373 | } | ||
2374 | #endif | ||
diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index e641922f20bc..350cbeaae160 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c | |||
@@ -167,10 +167,9 @@ unsigned char mgmt_invalidate_icds(struct beiscsi_hba *phba, | |||
167 | &nonemb_cmd.dma); | 167 | &nonemb_cmd.dma); |
168 | if (nonemb_cmd.va == NULL) { | 168 | if (nonemb_cmd.va == NULL) { |
169 | SE_DEBUG(DBG_LVL_1, | 169 | SE_DEBUG(DBG_LVL_1, |
170 | "Failed to allocate memory for" | 170 | "Failed to allocate memory for mgmt_invalidate_icds\n"); |
171 | "mgmt_invalidate_icds \n"); | ||
172 | spin_unlock(&ctrl->mbox_lock); | 171 | spin_unlock(&ctrl->mbox_lock); |
173 | return -1; | 172 | return 0; |
174 | } | 173 | } |
175 | nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); | 174 | nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); |
176 | req = nonemb_cmd.va; | 175 | req = nonemb_cmd.va; |
diff --git a/drivers/scsi/bfa/bfa_core.c b/drivers/scsi/bfa/bfa_core.c index 0c08e185a766..3a7b3f88932f 100644 --- a/drivers/scsi/bfa/bfa_core.c +++ b/drivers/scsi/bfa/bfa_core.c | |||
@@ -84,11 +84,32 @@ bfa_cfg_get_meminfo(struct bfa_iocfc_cfg_s *cfg, struct bfa_meminfo_s *meminfo) | |||
84 | for (i = 0; hal_mods[i]; i++) | 84 | for (i = 0; hal_mods[i]; i++) |
85 | hal_mods[i]->meminfo(cfg, &km_len, &dm_len); | 85 | hal_mods[i]->meminfo(cfg, &km_len, &dm_len); |
86 | 86 | ||
87 | dm_len += bfa_port_meminfo(); | ||
87 | 88 | ||
88 | meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len; | 89 | meminfo->meminfo[BFA_MEM_TYPE_KVA - 1].mem_len = km_len; |
89 | meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len; | 90 | meminfo->meminfo[BFA_MEM_TYPE_DMA - 1].mem_len = dm_len; |
90 | } | 91 | } |
91 | 92 | ||
93 | static void | ||
94 | bfa_com_port_attach(struct bfa_s *bfa, struct bfa_meminfo_s *mi) | ||
95 | { | ||
96 | struct bfa_port_s *port = &bfa->modules.port; | ||
97 | uint32_t dm_len; | ||
98 | uint8_t *dm_kva; | ||
99 | uint64_t dm_pa; | ||
100 | |||
101 | dm_len = bfa_port_meminfo(); | ||
102 | dm_kva = bfa_meminfo_dma_virt(mi); | ||
103 | dm_pa = bfa_meminfo_dma_phys(mi); | ||
104 | |||
105 | memset(port, 0, sizeof(struct bfa_port_s)); | ||
106 | bfa_port_attach(port, &bfa->ioc, bfa, bfa->trcmod, bfa->logm); | ||
107 | bfa_port_mem_claim(port, dm_kva, dm_pa); | ||
108 | |||
109 | bfa_meminfo_dma_virt(mi) = dm_kva + dm_len; | ||
110 | bfa_meminfo_dma_phys(mi) = dm_pa + dm_len; | ||
111 | } | ||
112 | |||
92 | /** | 113 | /** |
93 | * Use this function to do attach the driver instance with the BFA | 114 | * Use this function to do attach the driver instance with the BFA |
94 | * library. This function will not trigger any HW initialization | 115 | * library. This function will not trigger any HW initialization |
@@ -140,6 +161,7 @@ bfa_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, | |||
140 | for (i = 0; hal_mods[i]; i++) | 161 | for (i = 0; hal_mods[i]; i++) |
141 | hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev); | 162 | hal_mods[i]->attach(bfa, bfad, cfg, meminfo, pcidev); |
142 | 163 | ||
164 | bfa_com_port_attach(bfa, meminfo); | ||
143 | } | 165 | } |
144 | 166 | ||
145 | /** | 167 | /** |
diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index 18b7102bb80e..2ce26eb7a1ec 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c | |||
@@ -1,36 +1,35 @@ | |||
1 | #include <linux/types.h> | 1 | #include <linux/types.h> |
2 | #include <linux/mm.h> | ||
3 | #include <linux/slab.h> | ||
4 | #include <linux/blkdev.h> | ||
5 | #include <linux/init.h> | 2 | #include <linux/init.h> |
6 | #include <linux/interrupt.h> | 3 | #include <linux/interrupt.h> |
4 | #include <linux/mm.h> | ||
5 | #include <linux/slab.h> | ||
6 | #include <linux/spinlock.h> | ||
7 | #include <linux/zorro.h> | ||
7 | 8 | ||
8 | #include <asm/setup.h> | ||
9 | #include <asm/page.h> | 9 | #include <asm/page.h> |
10 | #include <asm/pgtable.h> | 10 | #include <asm/pgtable.h> |
11 | #include <asm/amigaints.h> | 11 | #include <asm/amigaints.h> |
12 | #include <asm/amigahw.h> | 12 | #include <asm/amigahw.h> |
13 | #include <linux/zorro.h> | ||
14 | #include <asm/irq.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | 13 | ||
17 | #include "scsi.h" | 14 | #include "scsi.h" |
18 | #include <scsi/scsi_host.h> | ||
19 | #include "wd33c93.h" | 15 | #include "wd33c93.h" |
20 | #include "gvp11.h" | 16 | #include "gvp11.h" |
21 | 17 | ||
22 | #include <linux/stat.h> | ||
23 | 18 | ||
19 | #define CHECK_WD33C93 | ||
24 | 20 | ||
25 | #define DMA(ptr) ((gvp11_scsiregs *)((ptr)->base)) | 21 | struct gvp11_hostdata { |
22 | struct WD33C93_hostdata wh; | ||
23 | struct gvp11_scsiregs *regs; | ||
24 | }; | ||
26 | 25 | ||
27 | static irqreturn_t gvp11_intr(int irq, void *_instance) | 26 | static irqreturn_t gvp11_intr(int irq, void *data) |
28 | { | 27 | { |
28 | struct Scsi_Host *instance = data; | ||
29 | struct gvp11_hostdata *hdata = shost_priv(instance); | ||
30 | unsigned int status = hdata->regs->CNTR; | ||
29 | unsigned long flags; | 31 | unsigned long flags; |
30 | unsigned int status; | ||
31 | struct Scsi_Host *instance = (struct Scsi_Host *)_instance; | ||
32 | 32 | ||
33 | status = DMA(instance)->CNTR; | ||
34 | if (!(status & GVP11_DMAC_INT_PENDING)) | 33 | if (!(status & GVP11_DMAC_INT_PENDING)) |
35 | return IRQ_NONE; | 34 | return IRQ_NONE; |
36 | 35 | ||
@@ -50,64 +49,66 @@ void gvp11_setup(char *str, int *ints) | |||
50 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | 49 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) |
51 | { | 50 | { |
52 | struct Scsi_Host *instance = cmd->device->host; | 51 | struct Scsi_Host *instance = cmd->device->host; |
53 | struct WD33C93_hostdata *hdata = shost_priv(instance); | 52 | struct gvp11_hostdata *hdata = shost_priv(instance); |
53 | struct WD33C93_hostdata *wh = &hdata->wh; | ||
54 | struct gvp11_scsiregs *regs = hdata->regs; | ||
54 | unsigned short cntr = GVP11_DMAC_INT_ENABLE; | 55 | unsigned short cntr = GVP11_DMAC_INT_ENABLE; |
55 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); | 56 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); |
56 | int bank_mask; | 57 | int bank_mask; |
57 | static int scsi_alloc_out_of_range = 0; | 58 | static int scsi_alloc_out_of_range = 0; |
58 | 59 | ||
59 | /* use bounce buffer if the physical address is bad */ | 60 | /* use bounce buffer if the physical address is bad */ |
60 | if (addr & hdata->dma_xfer_mask) { | 61 | if (addr & wh->dma_xfer_mask) { |
61 | hdata->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; | 62 | wh->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; |
62 | 63 | ||
63 | if (!scsi_alloc_out_of_range) { | 64 | if (!scsi_alloc_out_of_range) { |
64 | hdata->dma_bounce_buffer = | 65 | wh->dma_bounce_buffer = |
65 | kmalloc(hdata->dma_bounce_len, GFP_KERNEL); | 66 | kmalloc(wh->dma_bounce_len, GFP_KERNEL); |
66 | hdata->dma_buffer_pool = BUF_SCSI_ALLOCED; | 67 | wh->dma_buffer_pool = BUF_SCSI_ALLOCED; |
67 | } | 68 | } |
68 | 69 | ||
69 | if (scsi_alloc_out_of_range || | 70 | if (scsi_alloc_out_of_range || |
70 | !hdata->dma_bounce_buffer) { | 71 | !wh->dma_bounce_buffer) { |
71 | hdata->dma_bounce_buffer = | 72 | wh->dma_bounce_buffer = |
72 | amiga_chip_alloc(hdata->dma_bounce_len, | 73 | amiga_chip_alloc(wh->dma_bounce_len, |
73 | "GVP II SCSI Bounce Buffer"); | 74 | "GVP II SCSI Bounce Buffer"); |
74 | 75 | ||
75 | if (!hdata->dma_bounce_buffer) { | 76 | if (!wh->dma_bounce_buffer) { |
76 | hdata->dma_bounce_len = 0; | 77 | wh->dma_bounce_len = 0; |
77 | return 1; | 78 | return 1; |
78 | } | 79 | } |
79 | 80 | ||
80 | hdata->dma_buffer_pool = BUF_CHIP_ALLOCED; | 81 | wh->dma_buffer_pool = BUF_CHIP_ALLOCED; |
81 | } | 82 | } |
82 | 83 | ||
83 | /* check if the address of the bounce buffer is OK */ | 84 | /* check if the address of the bounce buffer is OK */ |
84 | addr = virt_to_bus(hdata->dma_bounce_buffer); | 85 | addr = virt_to_bus(wh->dma_bounce_buffer); |
85 | 86 | ||
86 | if (addr & hdata->dma_xfer_mask) { | 87 | if (addr & wh->dma_xfer_mask) { |
87 | /* fall back to Chip RAM if address out of range */ | 88 | /* fall back to Chip RAM if address out of range */ |
88 | if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) { | 89 | if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) { |
89 | kfree(hdata->dma_bounce_buffer); | 90 | kfree(wh->dma_bounce_buffer); |
90 | scsi_alloc_out_of_range = 1; | 91 | scsi_alloc_out_of_range = 1; |
91 | } else { | 92 | } else { |
92 | amiga_chip_free(hdata->dma_bounce_buffer); | 93 | amiga_chip_free(wh->dma_bounce_buffer); |
93 | } | 94 | } |
94 | 95 | ||
95 | hdata->dma_bounce_buffer = | 96 | wh->dma_bounce_buffer = |
96 | amiga_chip_alloc(hdata->dma_bounce_len, | 97 | amiga_chip_alloc(wh->dma_bounce_len, |
97 | "GVP II SCSI Bounce Buffer"); | 98 | "GVP II SCSI Bounce Buffer"); |
98 | 99 | ||
99 | if (!hdata->dma_bounce_buffer) { | 100 | if (!wh->dma_bounce_buffer) { |
100 | hdata->dma_bounce_len = 0; | 101 | wh->dma_bounce_len = 0; |
101 | return 1; | 102 | return 1; |
102 | } | 103 | } |
103 | 104 | ||
104 | addr = virt_to_bus(hdata->dma_bounce_buffer); | 105 | addr = virt_to_bus(wh->dma_bounce_buffer); |
105 | hdata->dma_buffer_pool = BUF_CHIP_ALLOCED; | 106 | wh->dma_buffer_pool = BUF_CHIP_ALLOCED; |
106 | } | 107 | } |
107 | 108 | ||
108 | if (!dir_in) { | 109 | if (!dir_in) { |
109 | /* copy to bounce buffer for a write */ | 110 | /* copy to bounce buffer for a write */ |
110 | memcpy(hdata->dma_bounce_buffer, cmd->SCp.ptr, | 111 | memcpy(wh->dma_bounce_buffer, cmd->SCp.ptr, |
111 | cmd->SCp.this_residual); | 112 | cmd->SCp.this_residual); |
112 | } | 113 | } |
113 | } | 114 | } |
@@ -116,11 +117,11 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
116 | if (!dir_in) | 117 | if (!dir_in) |
117 | cntr |= GVP11_DMAC_DIR_WRITE; | 118 | cntr |= GVP11_DMAC_DIR_WRITE; |
118 | 119 | ||
119 | hdata->dma_dir = dir_in; | 120 | wh->dma_dir = dir_in; |
120 | DMA(cmd->device->host)->CNTR = cntr; | 121 | regs->CNTR = cntr; |
121 | 122 | ||
122 | /* setup DMA *physical* address */ | 123 | /* setup DMA *physical* address */ |
123 | DMA(cmd->device->host)->ACR = addr; | 124 | regs->ACR = addr; |
124 | 125 | ||
125 | if (dir_in) { | 126 | if (dir_in) { |
126 | /* invalidate any cache */ | 127 | /* invalidate any cache */ |
@@ -130,12 +131,12 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
130 | cache_push(addr, cmd->SCp.this_residual); | 131 | cache_push(addr, cmd->SCp.this_residual); |
131 | } | 132 | } |
132 | 133 | ||
133 | bank_mask = (~hdata->dma_xfer_mask >> 18) & 0x01c0; | 134 | bank_mask = (~wh->dma_xfer_mask >> 18) & 0x01c0; |
134 | if (bank_mask) | 135 | if (bank_mask) |
135 | DMA(cmd->device->host)->BANK = bank_mask & (addr >> 18); | 136 | regs->BANK = bank_mask & (addr >> 18); |
136 | 137 | ||
137 | /* start DMA */ | 138 | /* start DMA */ |
138 | DMA(cmd->device->host)->ST_DMA = 1; | 139 | regs->ST_DMA = 1; |
139 | 140 | ||
140 | /* return success */ | 141 | /* return success */ |
141 | return 0; | 142 | return 0; |
@@ -144,236 +145,53 @@ static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | |||
144 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | 145 | static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, |
145 | int status) | 146 | int status) |
146 | { | 147 | { |
147 | struct WD33C93_hostdata *hdata = shost_priv(instance); | 148 | struct gvp11_hostdata *hdata = shost_priv(instance); |
149 | struct WD33C93_hostdata *wh = &hdata->wh; | ||
150 | struct gvp11_scsiregs *regs = hdata->regs; | ||
148 | 151 | ||
149 | /* stop DMA */ | 152 | /* stop DMA */ |
150 | DMA(instance)->SP_DMA = 1; | 153 | regs->SP_DMA = 1; |
151 | /* remove write bit from CONTROL bits */ | 154 | /* remove write bit from CONTROL bits */ |
152 | DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE; | 155 | regs->CNTR = GVP11_DMAC_INT_ENABLE; |
153 | 156 | ||
154 | /* copy from a bounce buffer, if necessary */ | 157 | /* copy from a bounce buffer, if necessary */ |
155 | if (status && hdata->dma_bounce_buffer) { | 158 | if (status && wh->dma_bounce_buffer) { |
156 | if (hdata->dma_dir && SCpnt) | 159 | if (wh->dma_dir && SCpnt) |
157 | memcpy(SCpnt->SCp.ptr, hdata->dma_bounce_buffer, | 160 | memcpy(SCpnt->SCp.ptr, wh->dma_bounce_buffer, |
158 | SCpnt->SCp.this_residual); | 161 | SCpnt->SCp.this_residual); |
159 | 162 | ||
160 | if (hdata->dma_buffer_pool == BUF_SCSI_ALLOCED) | 163 | if (wh->dma_buffer_pool == BUF_SCSI_ALLOCED) |
161 | kfree(hdata->dma_bounce_buffer); | 164 | kfree(wh->dma_bounce_buffer); |
162 | else | ||
163 | amiga_chip_free(hdata->dma_bounce_buffer); | ||
164 | |||
165 | hdata->dma_bounce_buffer = NULL; | ||
166 | hdata->dma_bounce_len = 0; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | #define CHECK_WD33C93 | ||
171 | |||
172 | int __init gvp11_detect(struct scsi_host_template *tpnt) | ||
173 | { | ||
174 | static unsigned char called = 0; | ||
175 | struct Scsi_Host *instance; | ||
176 | unsigned long address; | ||
177 | unsigned int epc; | ||
178 | struct zorro_dev *z = NULL; | ||
179 | unsigned int default_dma_xfer_mask; | ||
180 | struct WD33C93_hostdata *hdata; | ||
181 | wd33c93_regs regs; | ||
182 | int num_gvp11 = 0; | ||
183 | #ifdef CHECK_WD33C93 | ||
184 | volatile unsigned char *sasr_3393, *scmd_3393; | ||
185 | unsigned char save_sasr; | ||
186 | unsigned char q, qq; | ||
187 | #endif | ||
188 | |||
189 | if (!MACH_IS_AMIGA || called) | ||
190 | return 0; | ||
191 | called = 1; | ||
192 | |||
193 | tpnt->proc_name = "GVP11"; | ||
194 | tpnt->proc_info = &wd33c93_proc_info; | ||
195 | |||
196 | while ((z = zorro_find_device(ZORRO_WILDCARD, z))) { | ||
197 | /* | ||
198 | * This should (hopefully) be the correct way to identify | ||
199 | * all the different GVP SCSI controllers (except for the | ||
200 | * SERIES I though). | ||
201 | */ | ||
202 | |||
203 | if (z->id == ZORRO_PROD_GVP_COMBO_030_R3_SCSI || | ||
204 | z->id == ZORRO_PROD_GVP_SERIES_II) | ||
205 | default_dma_xfer_mask = ~0x00ffffff; | ||
206 | else if (z->id == ZORRO_PROD_GVP_GFORCE_030_SCSI || | ||
207 | z->id == ZORRO_PROD_GVP_A530_SCSI || | ||
208 | z->id == ZORRO_PROD_GVP_COMBO_030_R4_SCSI) | ||
209 | default_dma_xfer_mask = ~0x01ffffff; | ||
210 | else if (z->id == ZORRO_PROD_GVP_A1291 || | ||
211 | z->id == ZORRO_PROD_GVP_GFORCE_040_SCSI_1) | ||
212 | default_dma_xfer_mask = ~0x07ffffff; | ||
213 | else | 165 | else |
214 | continue; | 166 | amiga_chip_free(wh->dma_bounce_buffer); |
215 | |||
216 | /* | ||
217 | * Rumors state that some GVP ram boards use the same product | ||
218 | * code as the SCSI controllers. Therefore if the board-size | ||
219 | * is not 64KB we asume it is a ram board and bail out. | ||
220 | */ | ||
221 | if (z->resource.end - z->resource.start != 0xffff) | ||
222 | continue; | ||
223 | 167 | ||
224 | address = z->resource.start; | 168 | wh->dma_bounce_buffer = NULL; |
225 | if (!request_mem_region(address, 256, "wd33c93")) | 169 | wh->dma_bounce_len = 0; |
226 | continue; | ||
227 | |||
228 | #ifdef CHECK_WD33C93 | ||
229 | |||
230 | /* | ||
231 | * These darn GVP boards are a problem - it can be tough to tell | ||
232 | * whether or not they include a SCSI controller. This is the | ||
233 | * ultimate Yet-Another-GVP-Detection-Hack in that it actually | ||
234 | * probes for a WD33c93 chip: If we find one, it's extremely | ||
235 | * likely that this card supports SCSI, regardless of Product_ | ||
236 | * Code, Board_Size, etc. | ||
237 | */ | ||
238 | |||
239 | /* Get pointers to the presumed register locations and save contents */ | ||
240 | |||
241 | sasr_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SASR); | ||
242 | scmd_3393 = &(((gvp11_scsiregs *)(ZTWO_VADDR(address)))->SCMD); | ||
243 | save_sasr = *sasr_3393; | ||
244 | |||
245 | /* First test the AuxStatus Reg */ | ||
246 | |||
247 | q = *sasr_3393; /* read it */ | ||
248 | if (q & 0x08) /* bit 3 should always be clear */ | ||
249 | goto release; | ||
250 | *sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */ | ||
251 | if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */ | ||
252 | *sasr_3393 = save_sasr; /* Oops - restore this byte */ | ||
253 | goto release; | ||
254 | } | ||
255 | if (*sasr_3393 != q) { /* should still read the same */ | ||
256 | *sasr_3393 = save_sasr; /* Oops - restore this byte */ | ||
257 | goto release; | ||
258 | } | ||
259 | if (*scmd_3393 != q) /* and so should the image at 0x1f */ | ||
260 | goto release; | ||
261 | |||
262 | /* | ||
263 | * Ok, we probably have a wd33c93, but let's check a few other places | ||
264 | * for good measure. Make sure that this works for both 'A and 'B | ||
265 | * chip versions. | ||
266 | */ | ||
267 | |||
268 | *sasr_3393 = WD_SCSI_STATUS; | ||
269 | q = *scmd_3393; | ||
270 | *sasr_3393 = WD_SCSI_STATUS; | ||
271 | *scmd_3393 = ~q; | ||
272 | *sasr_3393 = WD_SCSI_STATUS; | ||
273 | qq = *scmd_3393; | ||
274 | *sasr_3393 = WD_SCSI_STATUS; | ||
275 | *scmd_3393 = q; | ||
276 | if (qq != q) /* should be read only */ | ||
277 | goto release; | ||
278 | *sasr_3393 = 0x1e; /* this register is unimplemented */ | ||
279 | q = *scmd_3393; | ||
280 | *sasr_3393 = 0x1e; | ||
281 | *scmd_3393 = ~q; | ||
282 | *sasr_3393 = 0x1e; | ||
283 | qq = *scmd_3393; | ||
284 | *sasr_3393 = 0x1e; | ||
285 | *scmd_3393 = q; | ||
286 | if (qq != q || qq != 0xff) /* should be read only, all 1's */ | ||
287 | goto release; | ||
288 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
289 | q = *scmd_3393; | ||
290 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
291 | *scmd_3393 = ~q; | ||
292 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
293 | qq = *scmd_3393; | ||
294 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
295 | *scmd_3393 = q; | ||
296 | if (qq != (~q & 0xff)) /* should be read/write */ | ||
297 | goto release; | ||
298 | #endif | ||
299 | |||
300 | instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); | ||
301 | if (instance == NULL) | ||
302 | goto release; | ||
303 | instance->base = ZTWO_VADDR(address); | ||
304 | instance->irq = IRQ_AMIGA_PORTS; | ||
305 | instance->unique_id = z->slotaddr; | ||
306 | |||
307 | hdata = shost_priv(instance); | ||
308 | if (gvp11_xfer_mask) | ||
309 | hdata->dma_xfer_mask = gvp11_xfer_mask; | ||
310 | else | ||
311 | hdata->dma_xfer_mask = default_dma_xfer_mask; | ||
312 | |||
313 | DMA(instance)->secret2 = 1; | ||
314 | DMA(instance)->secret1 = 0; | ||
315 | DMA(instance)->secret3 = 15; | ||
316 | while (DMA(instance)->CNTR & GVP11_DMAC_BUSY) | ||
317 | ; | ||
318 | DMA(instance)->CNTR = 0; | ||
319 | |||
320 | DMA(instance)->BANK = 0; | ||
321 | |||
322 | epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000); | ||
323 | |||
324 | /* | ||
325 | * Check for 14MHz SCSI clock | ||
326 | */ | ||
327 | regs.SASR = &(DMA(instance)->SASR); | ||
328 | regs.SCMD = &(DMA(instance)->SCMD); | ||
329 | hdata->no_sync = 0xff; | ||
330 | hdata->fast = 0; | ||
331 | hdata->dma_mode = CTRL_DMA; | ||
332 | wd33c93_init(instance, regs, dma_setup, dma_stop, | ||
333 | (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10 | ||
334 | : WD33C93_FS_12_15); | ||
335 | |||
336 | if (request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, | ||
337 | "GVP11 SCSI", instance)) | ||
338 | goto unregister; | ||
339 | DMA(instance)->CNTR = GVP11_DMAC_INT_ENABLE; | ||
340 | num_gvp11++; | ||
341 | continue; | ||
342 | |||
343 | unregister: | ||
344 | scsi_unregister(instance); | ||
345 | release: | ||
346 | release_mem_region(address, 256); | ||
347 | } | 170 | } |
348 | |||
349 | return num_gvp11; | ||
350 | } | 171 | } |
351 | 172 | ||
352 | static int gvp11_bus_reset(struct scsi_cmnd *cmd) | 173 | static int gvp11_bus_reset(struct scsi_cmnd *cmd) |
353 | { | 174 | { |
175 | struct Scsi_Host *instance = cmd->device->host; | ||
176 | |||
354 | /* FIXME perform bus-specific reset */ | 177 | /* FIXME perform bus-specific reset */ |
355 | 178 | ||
356 | /* FIXME 2: shouldn't we no-op this function (return | 179 | /* FIXME 2: shouldn't we no-op this function (return |
357 | FAILED), and fall back to host reset function, | 180 | FAILED), and fall back to host reset function, |
358 | wd33c93_host_reset ? */ | 181 | wd33c93_host_reset ? */ |
359 | 182 | ||
360 | spin_lock_irq(cmd->device->host->host_lock); | 183 | spin_lock_irq(instance->host_lock); |
361 | wd33c93_host_reset(cmd); | 184 | wd33c93_host_reset(cmd); |
362 | spin_unlock_irq(cmd->device->host->host_lock); | 185 | spin_unlock_irq(instance->host_lock); |
363 | 186 | ||
364 | return SUCCESS; | 187 | return SUCCESS; |
365 | } | 188 | } |
366 | 189 | ||
367 | 190 | static struct scsi_host_template gvp11_scsi_template = { | |
368 | #define HOSTS_C | 191 | .module = THIS_MODULE, |
369 | |||
370 | #include "gvp11.h" | ||
371 | |||
372 | static struct scsi_host_template driver_template = { | ||
373 | .proc_name = "GVP11", | ||
374 | .name = "GVP Series II SCSI", | 192 | .name = "GVP Series II SCSI", |
375 | .detect = gvp11_detect, | 193 | .proc_info = wd33c93_proc_info, |
376 | .release = gvp11_release, | 194 | .proc_name = "GVP11", |
377 | .queuecommand = wd33c93_queuecommand, | 195 | .queuecommand = wd33c93_queuecommand, |
378 | .eh_abort_handler = wd33c93_abort, | 196 | .eh_abort_handler = wd33c93_abort, |
379 | .eh_bus_reset_handler = gvp11_bus_reset, | 197 | .eh_bus_reset_handler = gvp11_bus_reset, |
@@ -385,17 +203,230 @@ static struct scsi_host_template driver_template = { | |||
385 | .use_clustering = DISABLE_CLUSTERING | 203 | .use_clustering = DISABLE_CLUSTERING |
386 | }; | 204 | }; |
387 | 205 | ||
206 | static int __devinit check_wd33c93(struct gvp11_scsiregs *regs) | ||
207 | { | ||
208 | #ifdef CHECK_WD33C93 | ||
209 | volatile unsigned char *sasr_3393, *scmd_3393; | ||
210 | unsigned char save_sasr; | ||
211 | unsigned char q, qq; | ||
388 | 212 | ||
389 | #include "scsi_module.c" | 213 | /* |
214 | * These darn GVP boards are a problem - it can be tough to tell | ||
215 | * whether or not they include a SCSI controller. This is the | ||
216 | * ultimate Yet-Another-GVP-Detection-Hack in that it actually | ||
217 | * probes for a WD33c93 chip: If we find one, it's extremely | ||
218 | * likely that this card supports SCSI, regardless of Product_ | ||
219 | * Code, Board_Size, etc. | ||
220 | */ | ||
221 | |||
222 | /* Get pointers to the presumed register locations and save contents */ | ||
223 | |||
224 | sasr_3393 = ®s->SASR; | ||
225 | scmd_3393 = ®s->SCMD; | ||
226 | save_sasr = *sasr_3393; | ||
227 | |||
228 | /* First test the AuxStatus Reg */ | ||
229 | |||
230 | q = *sasr_3393; /* read it */ | ||
231 | if (q & 0x08) /* bit 3 should always be clear */ | ||
232 | return -ENODEV; | ||
233 | *sasr_3393 = WD_AUXILIARY_STATUS; /* setup indirect address */ | ||
234 | if (*sasr_3393 == WD_AUXILIARY_STATUS) { /* shouldn't retain the write */ | ||
235 | *sasr_3393 = save_sasr; /* Oops - restore this byte */ | ||
236 | return -ENODEV; | ||
237 | } | ||
238 | if (*sasr_3393 != q) { /* should still read the same */ | ||
239 | *sasr_3393 = save_sasr; /* Oops - restore this byte */ | ||
240 | return -ENODEV; | ||
241 | } | ||
242 | if (*scmd_3393 != q) /* and so should the image at 0x1f */ | ||
243 | return -ENODEV; | ||
244 | |||
245 | /* | ||
246 | * Ok, we probably have a wd33c93, but let's check a few other places | ||
247 | * for good measure. Make sure that this works for both 'A and 'B | ||
248 | * chip versions. | ||
249 | */ | ||
250 | |||
251 | *sasr_3393 = WD_SCSI_STATUS; | ||
252 | q = *scmd_3393; | ||
253 | *sasr_3393 = WD_SCSI_STATUS; | ||
254 | *scmd_3393 = ~q; | ||
255 | *sasr_3393 = WD_SCSI_STATUS; | ||
256 | qq = *scmd_3393; | ||
257 | *sasr_3393 = WD_SCSI_STATUS; | ||
258 | *scmd_3393 = q; | ||
259 | if (qq != q) /* should be read only */ | ||
260 | return -ENODEV; | ||
261 | *sasr_3393 = 0x1e; /* this register is unimplemented */ | ||
262 | q = *scmd_3393; | ||
263 | *sasr_3393 = 0x1e; | ||
264 | *scmd_3393 = ~q; | ||
265 | *sasr_3393 = 0x1e; | ||
266 | qq = *scmd_3393; | ||
267 | *sasr_3393 = 0x1e; | ||
268 | *scmd_3393 = q; | ||
269 | if (qq != q || qq != 0xff) /* should be read only, all 1's */ | ||
270 | return -ENODEV; | ||
271 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
272 | q = *scmd_3393; | ||
273 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
274 | *scmd_3393 = ~q; | ||
275 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
276 | qq = *scmd_3393; | ||
277 | *sasr_3393 = WD_TIMEOUT_PERIOD; | ||
278 | *scmd_3393 = q; | ||
279 | if (qq != (~q & 0xff)) /* should be read/write */ | ||
280 | return -ENODEV; | ||
281 | #endif /* CHECK_WD33C93 */ | ||
390 | 282 | ||
391 | int gvp11_release(struct Scsi_Host *instance) | 283 | return 0; |
284 | } | ||
285 | |||
286 | static int __devinit gvp11_probe(struct zorro_dev *z, | ||
287 | const struct zorro_device_id *ent) | ||
392 | { | 288 | { |
393 | #ifdef MODULE | 289 | struct Scsi_Host *instance; |
394 | DMA(instance)->CNTR = 0; | 290 | unsigned long address; |
395 | release_mem_region(ZTWO_PADDR(instance->base), 256); | 291 | int error; |
292 | unsigned int epc; | ||
293 | unsigned int default_dma_xfer_mask; | ||
294 | struct gvp11_hostdata *hdata; | ||
295 | struct gvp11_scsiregs *regs; | ||
296 | wd33c93_regs wdregs; | ||
297 | |||
298 | default_dma_xfer_mask = ent->driver_data; | ||
299 | |||
300 | /* | ||
301 | * Rumors state that some GVP ram boards use the same product | ||
302 | * code as the SCSI controllers. Therefore if the board-size | ||
303 | * is not 64KB we asume it is a ram board and bail out. | ||
304 | */ | ||
305 | if (zorro_resource_len(z) != 0x10000) | ||
306 | return -ENODEV; | ||
307 | |||
308 | address = z->resource.start; | ||
309 | if (!request_mem_region(address, 256, "wd33c93")) | ||
310 | return -EBUSY; | ||
311 | |||
312 | regs = (struct gvp11_scsiregs *)(ZTWO_VADDR(address)); | ||
313 | |||
314 | error = check_wd33c93(regs); | ||
315 | if (error) | ||
316 | goto fail_check_or_alloc; | ||
317 | |||
318 | instance = scsi_host_alloc(&gvp11_scsi_template, | ||
319 | sizeof(struct gvp11_hostdata)); | ||
320 | if (!instance) { | ||
321 | error = -ENOMEM; | ||
322 | goto fail_check_or_alloc; | ||
323 | } | ||
324 | |||
325 | instance->irq = IRQ_AMIGA_PORTS; | ||
326 | instance->unique_id = z->slotaddr; | ||
327 | |||
328 | regs->secret2 = 1; | ||
329 | regs->secret1 = 0; | ||
330 | regs->secret3 = 15; | ||
331 | while (regs->CNTR & GVP11_DMAC_BUSY) | ||
332 | ; | ||
333 | regs->CNTR = 0; | ||
334 | regs->BANK = 0; | ||
335 | |||
336 | wdregs.SASR = ®s->SASR; | ||
337 | wdregs.SCMD = ®s->SCMD; | ||
338 | |||
339 | hdata = shost_priv(instance); | ||
340 | if (gvp11_xfer_mask) | ||
341 | hdata->wh.dma_xfer_mask = gvp11_xfer_mask; | ||
342 | else | ||
343 | hdata->wh.dma_xfer_mask = default_dma_xfer_mask; | ||
344 | |||
345 | hdata->wh.no_sync = 0xff; | ||
346 | hdata->wh.fast = 0; | ||
347 | hdata->wh.dma_mode = CTRL_DMA; | ||
348 | hdata->regs = regs; | ||
349 | |||
350 | /* | ||
351 | * Check for 14MHz SCSI clock | ||
352 | */ | ||
353 | epc = *(unsigned short *)(ZTWO_VADDR(address) + 0x8000); | ||
354 | wd33c93_init(instance, wdregs, dma_setup, dma_stop, | ||
355 | (epc & GVP_SCSICLKMASK) ? WD33C93_FS_8_10 | ||
356 | : WD33C93_FS_12_15); | ||
357 | |||
358 | error = request_irq(IRQ_AMIGA_PORTS, gvp11_intr, IRQF_SHARED, | ||
359 | "GVP11 SCSI", instance); | ||
360 | if (error) | ||
361 | goto fail_irq; | ||
362 | |||
363 | regs->CNTR = GVP11_DMAC_INT_ENABLE; | ||
364 | |||
365 | error = scsi_add_host(instance, NULL); | ||
366 | if (error) | ||
367 | goto fail_host; | ||
368 | |||
369 | zorro_set_drvdata(z, instance); | ||
370 | scsi_scan_host(instance); | ||
371 | return 0; | ||
372 | |||
373 | fail_host: | ||
396 | free_irq(IRQ_AMIGA_PORTS, instance); | 374 | free_irq(IRQ_AMIGA_PORTS, instance); |
397 | #endif | 375 | fail_irq: |
398 | return 1; | 376 | scsi_host_put(instance); |
377 | fail_check_or_alloc: | ||
378 | release_mem_region(address, 256); | ||
379 | return error; | ||
380 | } | ||
381 | |||
382 | static void __devexit gvp11_remove(struct zorro_dev *z) | ||
383 | { | ||
384 | struct Scsi_Host *instance = zorro_get_drvdata(z); | ||
385 | struct gvp11_hostdata *hdata = shost_priv(instance); | ||
386 | |||
387 | hdata->regs->CNTR = 0; | ||
388 | scsi_remove_host(instance); | ||
389 | free_irq(IRQ_AMIGA_PORTS, instance); | ||
390 | scsi_host_put(instance); | ||
391 | release_mem_region(z->resource.start, 256); | ||
392 | } | ||
393 | |||
394 | /* | ||
395 | * This should (hopefully) be the correct way to identify | ||
396 | * all the different GVP SCSI controllers (except for the | ||
397 | * SERIES I though). | ||
398 | */ | ||
399 | |||
400 | static struct zorro_device_id gvp11_zorro_tbl[] __devinitdata = { | ||
401 | { ZORRO_PROD_GVP_COMBO_030_R3_SCSI, ~0x00ffffff }, | ||
402 | { ZORRO_PROD_GVP_SERIES_II, ~0x00ffffff }, | ||
403 | { ZORRO_PROD_GVP_GFORCE_030_SCSI, ~0x01ffffff }, | ||
404 | { ZORRO_PROD_GVP_A530_SCSI, ~0x01ffffff }, | ||
405 | { ZORRO_PROD_GVP_COMBO_030_R4_SCSI, ~0x01ffffff }, | ||
406 | { ZORRO_PROD_GVP_A1291, ~0x07ffffff }, | ||
407 | { ZORRO_PROD_GVP_GFORCE_040_SCSI_1, ~0x07ffffff }, | ||
408 | { 0 } | ||
409 | }; | ||
410 | MODULE_DEVICE_TABLE(zorro, gvp11_zorro_tbl); | ||
411 | |||
412 | static struct zorro_driver gvp11_driver = { | ||
413 | .name = "gvp11", | ||
414 | .id_table = gvp11_zorro_tbl, | ||
415 | .probe = gvp11_probe, | ||
416 | .remove = __devexit_p(gvp11_remove), | ||
417 | }; | ||
418 | |||
419 | static int __init gvp11_init(void) | ||
420 | { | ||
421 | return zorro_register_driver(&gvp11_driver); | ||
422 | } | ||
423 | module_init(gvp11_init); | ||
424 | |||
425 | static void __exit gvp11_exit(void) | ||
426 | { | ||
427 | zorro_unregister_driver(&gvp11_driver); | ||
399 | } | 428 | } |
429 | module_exit(gvp11_exit); | ||
400 | 430 | ||
431 | MODULE_DESCRIPTION("GVP Series II SCSI"); | ||
401 | MODULE_LICENSE("GPL"); | 432 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/scsi/gvp11.h b/drivers/scsi/gvp11.h index e2efdf9601ef..852913cde5dd 100644 --- a/drivers/scsi/gvp11.h +++ b/drivers/scsi/gvp11.h | |||
@@ -11,9 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | 13 | ||
14 | int gvp11_detect(struct scsi_host_template *); | ||
15 | int gvp11_release(struct Scsi_Host *); | ||
16 | |||
17 | #ifndef CMD_PER_LUN | 14 | #ifndef CMD_PER_LUN |
18 | #define CMD_PER_LUN 2 | 15 | #define CMD_PER_LUN 2 |
19 | #endif | 16 | #endif |
@@ -22,15 +19,13 @@ int gvp11_release(struct Scsi_Host *); | |||
22 | #define CAN_QUEUE 16 | 19 | #define CAN_QUEUE 16 |
23 | #endif | 20 | #endif |
24 | 21 | ||
25 | #ifndef HOSTS_C | ||
26 | |||
27 | /* | 22 | /* |
28 | * if the transfer address ANDed with this results in a non-zero | 23 | * if the transfer address ANDed with this results in a non-zero |
29 | * result, then we can't use DMA. | 24 | * result, then we can't use DMA. |
30 | */ | 25 | */ |
31 | #define GVP11_XFER_MASK (0xff000001) | 26 | #define GVP11_XFER_MASK (0xff000001) |
32 | 27 | ||
33 | typedef struct { | 28 | struct gvp11_scsiregs { |
34 | unsigned char pad1[64]; | 29 | unsigned char pad1[64]; |
35 | volatile unsigned short CNTR; | 30 | volatile unsigned short CNTR; |
36 | unsigned char pad2[31]; | 31 | unsigned char pad2[31]; |
@@ -46,7 +41,7 @@ typedef struct { | |||
46 | volatile unsigned short SP_DMA; | 41 | volatile unsigned short SP_DMA; |
47 | volatile unsigned short secret2; /* store 1 here */ | 42 | volatile unsigned short secret2; /* store 1 here */ |
48 | volatile unsigned short secret3; /* store 15 here */ | 43 | volatile unsigned short secret3; /* store 15 here */ |
49 | } gvp11_scsiregs; | 44 | }; |
50 | 45 | ||
51 | /* bits in CNTR */ | 46 | /* bits in CNTR */ |
52 | #define GVP11_DMAC_BUSY (1<<0) | 47 | #define GVP11_DMAC_BUSY (1<<0) |
@@ -54,6 +49,4 @@ typedef struct { | |||
54 | #define GVP11_DMAC_INT_ENABLE (1<<3) | 49 | #define GVP11_DMAC_INT_ENABLE (1<<3) |
55 | #define GVP11_DMAC_DIR_WRITE (1<<4) | 50 | #define GVP11_DMAC_DIR_WRITE (1<<4) |
56 | 51 | ||
57 | #endif /* else def HOSTS_C */ | ||
58 | |||
59 | #endif /* GVP11_H */ | 52 | #endif /* GVP11_H */ |
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 6a6661c35b2f..82ea4a8226b0 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c | |||
@@ -567,7 +567,8 @@ static void ipr_trc_hook(struct ipr_cmnd *ipr_cmd, | |||
567 | static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) | 567 | static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) |
568 | { | 568 | { |
569 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | 569 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; |
570 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; | 570 | struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; |
571 | struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64; | ||
571 | dma_addr_t dma_addr = ipr_cmd->dma_addr; | 572 | dma_addr_t dma_addr = ipr_cmd->dma_addr; |
572 | 573 | ||
573 | memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); | 574 | memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); |
@@ -576,19 +577,19 @@ static void ipr_reinit_ipr_cmnd(struct ipr_cmnd *ipr_cmd) | |||
576 | ioarcb->ioadl_len = 0; | 577 | ioarcb->ioadl_len = 0; |
577 | ioarcb->read_ioadl_len = 0; | 578 | ioarcb->read_ioadl_len = 0; |
578 | 579 | ||
579 | if (ipr_cmd->ioa_cfg->sis64) | 580 | if (ipr_cmd->ioa_cfg->sis64) { |
580 | ioarcb->u.sis64_addr_data.data_ioadl_addr = | 581 | ioarcb->u.sis64_addr_data.data_ioadl_addr = |
581 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); | 582 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); |
582 | else { | 583 | ioasa64->u.gata.status = 0; |
584 | } else { | ||
583 | ioarcb->write_ioadl_addr = | 585 | ioarcb->write_ioadl_addr = |
584 | cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); | 586 | cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); |
585 | ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; | 587 | ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; |
588 | ioasa->u.gata.status = 0; | ||
586 | } | 589 | } |
587 | 590 | ||
588 | ioasa->ioasc = 0; | 591 | ioasa->hdr.ioasc = 0; |
589 | ioasa->residual_data_len = 0; | 592 | ioasa->hdr.residual_data_len = 0; |
590 | ioasa->u.gata.status = 0; | ||
591 | |||
592 | ipr_cmd->scsi_cmd = NULL; | 593 | ipr_cmd->scsi_cmd = NULL; |
593 | ipr_cmd->qc = NULL; | 594 | ipr_cmd->qc = NULL; |
594 | ipr_cmd->sense_buffer[0] = 0; | 595 | ipr_cmd->sense_buffer[0] = 0; |
@@ -768,8 +769,8 @@ static void ipr_fail_all_ops(struct ipr_ioa_cfg *ioa_cfg) | |||
768 | list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) { | 769 | list_for_each_entry_safe(ipr_cmd, temp, &ioa_cfg->pending_q, queue) { |
769 | list_del(&ipr_cmd->queue); | 770 | list_del(&ipr_cmd->queue); |
770 | 771 | ||
771 | ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET); | 772 | ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_IOA_WAS_RESET); |
772 | ipr_cmd->ioasa.ilid = cpu_to_be32(IPR_DRIVER_ILID); | 773 | ipr_cmd->s.ioasa.hdr.ilid = cpu_to_be32(IPR_DRIVER_ILID); |
773 | 774 | ||
774 | if (ipr_cmd->scsi_cmd) | 775 | if (ipr_cmd->scsi_cmd) |
775 | ipr_cmd->done = ipr_scsi_eh_done; | 776 | ipr_cmd->done = ipr_scsi_eh_done; |
@@ -1040,7 +1041,7 @@ static void ipr_init_res_entry(struct ipr_resource_entry *res, | |||
1040 | proto = cfgtew->u.cfgte64->proto; | 1041 | proto = cfgtew->u.cfgte64->proto; |
1041 | res->res_flags = cfgtew->u.cfgte64->res_flags; | 1042 | res->res_flags = cfgtew->u.cfgte64->res_flags; |
1042 | res->qmodel = IPR_QUEUEING_MODEL64(res); | 1043 | res->qmodel = IPR_QUEUEING_MODEL64(res); |
1043 | res->type = cfgtew->u.cfgte64->res_type & 0x0f; | 1044 | res->type = cfgtew->u.cfgte64->res_type; |
1044 | 1045 | ||
1045 | memcpy(res->res_path, &cfgtew->u.cfgte64->res_path, | 1046 | memcpy(res->res_path, &cfgtew->u.cfgte64->res_path, |
1046 | sizeof(res->res_path)); | 1047 | sizeof(res->res_path)); |
@@ -1319,7 +1320,7 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd) | |||
1319 | { | 1320 | { |
1320 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 1321 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
1321 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; | 1322 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; |
1322 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 1323 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
1323 | 1324 | ||
1324 | list_del(&hostrcb->queue); | 1325 | list_del(&hostrcb->queue); |
1325 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); | 1326 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); |
@@ -2354,7 +2355,7 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd) | |||
2354 | { | 2355 | { |
2355 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 2356 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
2356 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; | 2357 | struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb; |
2357 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 2358 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
2358 | u32 fd_ioasc; | 2359 | u32 fd_ioasc; |
2359 | 2360 | ||
2360 | if (ioa_cfg->sis64) | 2361 | if (ioa_cfg->sis64) |
@@ -4509,11 +4510,16 @@ static int ipr_device_reset(struct ipr_ioa_cfg *ioa_cfg, | |||
4509 | } | 4510 | } |
4510 | 4511 | ||
4511 | ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); | 4512 | ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); |
4512 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 4513 | ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
4513 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); | 4514 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); |
4514 | if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) | 4515 | if (ipr_is_gata(res) && res->sata_port && ioasc != IPR_IOASC_IOA_WAS_RESET) { |
4515 | memcpy(&res->sata_port->ioasa, &ipr_cmd->ioasa.u.gata, | 4516 | if (ipr_cmd->ioa_cfg->sis64) |
4516 | sizeof(struct ipr_ioasa_gata)); | 4517 | memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata, |
4518 | sizeof(struct ipr_ioasa_gata)); | ||
4519 | else | ||
4520 | memcpy(&res->sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata, | ||
4521 | sizeof(struct ipr_ioasa_gata)); | ||
4522 | } | ||
4517 | 4523 | ||
4518 | LEAVE; | 4524 | LEAVE; |
4519 | return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0); | 4525 | return (IPR_IOASC_SENSE_KEY(ioasc) ? -EIO : 0); |
@@ -4768,7 +4774,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd) | |||
4768 | scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n", | 4774 | scmd_printk(KERN_ERR, scsi_cmd, "Aborting command: %02X\n", |
4769 | scsi_cmd->cmnd[0]); | 4775 | scsi_cmd->cmnd[0]); |
4770 | ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); | 4776 | ipr_send_blocking_cmd(ipr_cmd, ipr_abort_timeout, IPR_CANCEL_ALL_TIMEOUT); |
4771 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 4777 | ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
4772 | 4778 | ||
4773 | /* | 4779 | /* |
4774 | * If the abort task timed out and we sent a bus reset, we will get | 4780 | * If the abort task timed out and we sent a bus reset, we will get |
@@ -4812,15 +4818,39 @@ static int ipr_eh_abort(struct scsi_cmnd * scsi_cmd) | |||
4812 | /** | 4818 | /** |
4813 | * ipr_handle_other_interrupt - Handle "other" interrupts | 4819 | * ipr_handle_other_interrupt - Handle "other" interrupts |
4814 | * @ioa_cfg: ioa config struct | 4820 | * @ioa_cfg: ioa config struct |
4815 | * @int_reg: interrupt register | ||
4816 | * | 4821 | * |
4817 | * Return value: | 4822 | * Return value: |
4818 | * IRQ_NONE / IRQ_HANDLED | 4823 | * IRQ_NONE / IRQ_HANDLED |
4819 | **/ | 4824 | **/ |
4820 | static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg, | 4825 | static irqreturn_t ipr_handle_other_interrupt(struct ipr_ioa_cfg *ioa_cfg) |
4821 | volatile u32 int_reg) | ||
4822 | { | 4826 | { |
4823 | irqreturn_t rc = IRQ_HANDLED; | 4827 | irqreturn_t rc = IRQ_HANDLED; |
4828 | volatile u32 int_reg, int_mask_reg; | ||
4829 | |||
4830 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); | ||
4831 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; | ||
4832 | |||
4833 | /* If an interrupt on the adapter did not occur, ignore it. | ||
4834 | * Or in the case of SIS 64, check for a stage change interrupt. | ||
4835 | */ | ||
4836 | if ((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0) { | ||
4837 | if (ioa_cfg->sis64) { | ||
4838 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); | ||
4839 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4840 | if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { | ||
4841 | |||
4842 | /* clear stage change */ | ||
4843 | writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); | ||
4844 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4845 | list_del(&ioa_cfg->reset_cmd->queue); | ||
4846 | del_timer(&ioa_cfg->reset_cmd->timer); | ||
4847 | ipr_reset_ioa_job(ioa_cfg->reset_cmd); | ||
4848 | return IRQ_HANDLED; | ||
4849 | } | ||
4850 | } | ||
4851 | |||
4852 | return IRQ_NONE; | ||
4853 | } | ||
4824 | 4854 | ||
4825 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { | 4855 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { |
4826 | /* Mask the interrupt */ | 4856 | /* Mask the interrupt */ |
@@ -4881,7 +4911,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4881 | { | 4911 | { |
4882 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; | 4912 | struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; |
4883 | unsigned long lock_flags = 0; | 4913 | unsigned long lock_flags = 0; |
4884 | volatile u32 int_reg, int_mask_reg; | 4914 | volatile u32 int_reg; |
4885 | u32 ioasc; | 4915 | u32 ioasc; |
4886 | u16 cmd_index; | 4916 | u16 cmd_index; |
4887 | int num_hrrq = 0; | 4917 | int num_hrrq = 0; |
@@ -4896,33 +4926,6 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4896 | return IRQ_NONE; | 4926 | return IRQ_NONE; |
4897 | } | 4927 | } |
4898 | 4928 | ||
4899 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg32); | ||
4900 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; | ||
4901 | |||
4902 | /* If an interrupt on the adapter did not occur, ignore it. | ||
4903 | * Or in the case of SIS 64, check for a stage change interrupt. | ||
4904 | */ | ||
4905 | if (unlikely((int_reg & IPR_PCII_OPER_INTERRUPTS) == 0)) { | ||
4906 | if (ioa_cfg->sis64) { | ||
4907 | int_mask_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); | ||
4908 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4909 | if (int_reg & IPR_PCII_IPL_STAGE_CHANGE) { | ||
4910 | |||
4911 | /* clear stage change */ | ||
4912 | writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_reg); | ||
4913 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg) & ~int_mask_reg; | ||
4914 | list_del(&ioa_cfg->reset_cmd->queue); | ||
4915 | del_timer(&ioa_cfg->reset_cmd->timer); | ||
4916 | ipr_reset_ioa_job(ioa_cfg->reset_cmd); | ||
4917 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
4918 | return IRQ_HANDLED; | ||
4919 | } | ||
4920 | } | ||
4921 | |||
4922 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | ||
4923 | return IRQ_NONE; | ||
4924 | } | ||
4925 | |||
4926 | while (1) { | 4929 | while (1) { |
4927 | ipr_cmd = NULL; | 4930 | ipr_cmd = NULL; |
4928 | 4931 | ||
@@ -4940,7 +4943,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4940 | 4943 | ||
4941 | ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index]; | 4944 | ipr_cmd = ioa_cfg->ipr_cmnd_list[cmd_index]; |
4942 | 4945 | ||
4943 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 4946 | ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
4944 | 4947 | ||
4945 | ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc); | 4948 | ipr_trc_hook(ipr_cmd, IPR_TRACE_FINISH, ioasc); |
4946 | 4949 | ||
@@ -4962,7 +4965,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4962 | /* Clear the PCI interrupt */ | 4965 | /* Clear the PCI interrupt */ |
4963 | do { | 4966 | do { |
4964 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); | 4967 | writel(IPR_PCII_HRRQ_UPDATED, ioa_cfg->regs.clr_interrupt_reg32); |
4965 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32) & ~int_mask_reg; | 4968 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); |
4966 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && | 4969 | } while (int_reg & IPR_PCII_HRRQ_UPDATED && |
4967 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); | 4970 | num_hrrq++ < IPR_MAX_HRRQ_RETRIES); |
4968 | 4971 | ||
@@ -4977,7 +4980,7 @@ static irqreturn_t ipr_isr(int irq, void *devp) | |||
4977 | } | 4980 | } |
4978 | 4981 | ||
4979 | if (unlikely(rc == IRQ_NONE)) | 4982 | if (unlikely(rc == IRQ_NONE)) |
4980 | rc = ipr_handle_other_interrupt(ioa_cfg, int_reg); | 4983 | rc = ipr_handle_other_interrupt(ioa_cfg); |
4981 | 4984 | ||
4982 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); | 4985 | spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); |
4983 | return rc; | 4986 | return rc; |
@@ -5014,6 +5017,10 @@ static int ipr_build_ioadl64(struct ipr_ioa_cfg *ioa_cfg, | |||
5014 | 5017 | ||
5015 | ipr_cmd->dma_use_sg = nseg; | 5018 | ipr_cmd->dma_use_sg = nseg; |
5016 | 5019 | ||
5020 | ioarcb->data_transfer_length = cpu_to_be32(length); | ||
5021 | ioarcb->ioadl_len = | ||
5022 | cpu_to_be32(sizeof(struct ipr_ioadl64_desc) * ipr_cmd->dma_use_sg); | ||
5023 | |||
5017 | if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { | 5024 | if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { |
5018 | ioadl_flags = IPR_IOADL_FLAGS_WRITE; | 5025 | ioadl_flags = IPR_IOADL_FLAGS_WRITE; |
5019 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; | 5026 | ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; |
@@ -5135,7 +5142,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) | |||
5135 | struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; | 5142 | struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; |
5136 | struct ipr_resource_entry *res = scsi_cmd->device->hostdata; | 5143 | struct ipr_resource_entry *res = scsi_cmd->device->hostdata; |
5137 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 5144 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
5138 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 5145 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
5139 | 5146 | ||
5140 | if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { | 5147 | if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { |
5141 | scsi_cmd->result |= (DID_ERROR << 16); | 5148 | scsi_cmd->result |= (DID_ERROR << 16); |
@@ -5166,7 +5173,7 @@ static void ipr_erp_done(struct ipr_cmnd *ipr_cmd) | |||
5166 | static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) | 5173 | static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) |
5167 | { | 5174 | { |
5168 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; | 5175 | struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; |
5169 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; | 5176 | struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; |
5170 | dma_addr_t dma_addr = ipr_cmd->dma_addr; | 5177 | dma_addr_t dma_addr = ipr_cmd->dma_addr; |
5171 | 5178 | ||
5172 | memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); | 5179 | memset(&ioarcb->cmd_pkt, 0, sizeof(struct ipr_cmd_pkt)); |
@@ -5174,8 +5181,8 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) | |||
5174 | ioarcb->read_data_transfer_length = 0; | 5181 | ioarcb->read_data_transfer_length = 0; |
5175 | ioarcb->ioadl_len = 0; | 5182 | ioarcb->ioadl_len = 0; |
5176 | ioarcb->read_ioadl_len = 0; | 5183 | ioarcb->read_ioadl_len = 0; |
5177 | ioasa->ioasc = 0; | 5184 | ioasa->hdr.ioasc = 0; |
5178 | ioasa->residual_data_len = 0; | 5185 | ioasa->hdr.residual_data_len = 0; |
5179 | 5186 | ||
5180 | if (ipr_cmd->ioa_cfg->sis64) | 5187 | if (ipr_cmd->ioa_cfg->sis64) |
5181 | ioarcb->u.sis64_addr_data.data_ioadl_addr = | 5188 | ioarcb->u.sis64_addr_data.data_ioadl_addr = |
@@ -5200,7 +5207,7 @@ static void ipr_reinit_ipr_cmnd_for_erp(struct ipr_cmnd *ipr_cmd) | |||
5200 | static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd) | 5207 | static void ipr_erp_request_sense(struct ipr_cmnd *ipr_cmd) |
5201 | { | 5208 | { |
5202 | struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; | 5209 | struct ipr_cmd_pkt *cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; |
5203 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 5210 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
5204 | 5211 | ||
5205 | if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { | 5212 | if (IPR_IOASC_SENSE_KEY(ioasc) > 0) { |
5206 | ipr_erp_done(ipr_cmd); | 5213 | ipr_erp_done(ipr_cmd); |
@@ -5277,12 +5284,12 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, | |||
5277 | int i; | 5284 | int i; |
5278 | u16 data_len; | 5285 | u16 data_len; |
5279 | u32 ioasc, fd_ioasc; | 5286 | u32 ioasc, fd_ioasc; |
5280 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; | 5287 | struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; |
5281 | __be32 *ioasa_data = (__be32 *)ioasa; | 5288 | __be32 *ioasa_data = (__be32 *)ioasa; |
5282 | int error_index; | 5289 | int error_index; |
5283 | 5290 | ||
5284 | ioasc = be32_to_cpu(ioasa->ioasc) & IPR_IOASC_IOASC_MASK; | 5291 | ioasc = be32_to_cpu(ioasa->hdr.ioasc) & IPR_IOASC_IOASC_MASK; |
5285 | fd_ioasc = be32_to_cpu(ioasa->fd_ioasc) & IPR_IOASC_IOASC_MASK; | 5292 | fd_ioasc = be32_to_cpu(ioasa->hdr.fd_ioasc) & IPR_IOASC_IOASC_MASK; |
5286 | 5293 | ||
5287 | if (0 == ioasc) | 5294 | if (0 == ioasc) |
5288 | return; | 5295 | return; |
@@ -5297,7 +5304,7 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, | |||
5297 | 5304 | ||
5298 | if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) { | 5305 | if (ioa_cfg->log_level < IPR_MAX_LOG_LEVEL) { |
5299 | /* Don't log an error if the IOA already logged one */ | 5306 | /* Don't log an error if the IOA already logged one */ |
5300 | if (ioasa->ilid != 0) | 5307 | if (ioasa->hdr.ilid != 0) |
5301 | return; | 5308 | return; |
5302 | 5309 | ||
5303 | if (!ipr_is_gscsi(res)) | 5310 | if (!ipr_is_gscsi(res)) |
@@ -5309,10 +5316,11 @@ static void ipr_dump_ioasa(struct ipr_ioa_cfg *ioa_cfg, | |||
5309 | 5316 | ||
5310 | ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error); | 5317 | ipr_res_err(ioa_cfg, res, "%s\n", ipr_error_table[error_index].error); |
5311 | 5318 | ||
5312 | if (sizeof(struct ipr_ioasa) < be16_to_cpu(ioasa->ret_stat_len)) | 5319 | data_len = be16_to_cpu(ioasa->hdr.ret_stat_len); |
5320 | if (ioa_cfg->sis64 && sizeof(struct ipr_ioasa64) < data_len) | ||
5321 | data_len = sizeof(struct ipr_ioasa64); | ||
5322 | else if (!ioa_cfg->sis64 && sizeof(struct ipr_ioasa) < data_len) | ||
5313 | data_len = sizeof(struct ipr_ioasa); | 5323 | data_len = sizeof(struct ipr_ioasa); |
5314 | else | ||
5315 | data_len = be16_to_cpu(ioasa->ret_stat_len); | ||
5316 | 5324 | ||
5317 | ipr_err("IOASA Dump:\n"); | 5325 | ipr_err("IOASA Dump:\n"); |
5318 | 5326 | ||
@@ -5338,8 +5346,8 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) | |||
5338 | u32 failing_lba; | 5346 | u32 failing_lba; |
5339 | u8 *sense_buf = ipr_cmd->scsi_cmd->sense_buffer; | 5347 | u8 *sense_buf = ipr_cmd->scsi_cmd->sense_buffer; |
5340 | struct ipr_resource_entry *res = ipr_cmd->scsi_cmd->device->hostdata; | 5348 | struct ipr_resource_entry *res = ipr_cmd->scsi_cmd->device->hostdata; |
5341 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; | 5349 | struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; |
5342 | u32 ioasc = be32_to_cpu(ioasa->ioasc); | 5350 | u32 ioasc = be32_to_cpu(ioasa->hdr.ioasc); |
5343 | 5351 | ||
5344 | memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); | 5352 | memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE); |
5345 | 5353 | ||
@@ -5382,7 +5390,7 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) | |||
5382 | 5390 | ||
5383 | /* Illegal request */ | 5391 | /* Illegal request */ |
5384 | if ((IPR_IOASC_SENSE_KEY(ioasc) == 0x05) && | 5392 | if ((IPR_IOASC_SENSE_KEY(ioasc) == 0x05) && |
5385 | (be32_to_cpu(ioasa->ioasc_specific) & IPR_FIELD_POINTER_VALID)) { | 5393 | (be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_FIELD_POINTER_VALID)) { |
5386 | sense_buf[7] = 10; /* additional length */ | 5394 | sense_buf[7] = 10; /* additional length */ |
5387 | 5395 | ||
5388 | /* IOARCB was in error */ | 5396 | /* IOARCB was in error */ |
@@ -5393,10 +5401,10 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) | |||
5393 | 5401 | ||
5394 | sense_buf[16] = | 5402 | sense_buf[16] = |
5395 | ((IPR_FIELD_POINTER_MASK & | 5403 | ((IPR_FIELD_POINTER_MASK & |
5396 | be32_to_cpu(ioasa->ioasc_specific)) >> 8) & 0xff; | 5404 | be32_to_cpu(ioasa->hdr.ioasc_specific)) >> 8) & 0xff; |
5397 | sense_buf[17] = | 5405 | sense_buf[17] = |
5398 | (IPR_FIELD_POINTER_MASK & | 5406 | (IPR_FIELD_POINTER_MASK & |
5399 | be32_to_cpu(ioasa->ioasc_specific)) & 0xff; | 5407 | be32_to_cpu(ioasa->hdr.ioasc_specific)) & 0xff; |
5400 | } else { | 5408 | } else { |
5401 | if (ioasc == IPR_IOASC_MED_DO_NOT_REALLOC) { | 5409 | if (ioasc == IPR_IOASC_MED_DO_NOT_REALLOC) { |
5402 | if (ipr_is_vset_device(res)) | 5410 | if (ipr_is_vset_device(res)) |
@@ -5428,14 +5436,20 @@ static void ipr_gen_sense(struct ipr_cmnd *ipr_cmd) | |||
5428 | **/ | 5436 | **/ |
5429 | static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd) | 5437 | static int ipr_get_autosense(struct ipr_cmnd *ipr_cmd) |
5430 | { | 5438 | { |
5431 | struct ipr_ioasa *ioasa = &ipr_cmd->ioasa; | 5439 | struct ipr_ioasa *ioasa = &ipr_cmd->s.ioasa; |
5440 | struct ipr_ioasa64 *ioasa64 = &ipr_cmd->s.ioasa64; | ||
5432 | 5441 | ||
5433 | if ((be32_to_cpu(ioasa->ioasc_specific) & IPR_AUTOSENSE_VALID) == 0) | 5442 | if ((be32_to_cpu(ioasa->hdr.ioasc_specific) & IPR_AUTOSENSE_VALID) == 0) |
5434 | return 0; | 5443 | return 0; |
5435 | 5444 | ||
5436 | memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, | 5445 | if (ipr_cmd->ioa_cfg->sis64) |
5437 | min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len), | 5446 | memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa64->auto_sense.data, |
5438 | SCSI_SENSE_BUFFERSIZE)); | 5447 | min_t(u16, be16_to_cpu(ioasa64->auto_sense.auto_sense_len), |
5448 | SCSI_SENSE_BUFFERSIZE)); | ||
5449 | else | ||
5450 | memcpy(ipr_cmd->scsi_cmd->sense_buffer, ioasa->auto_sense.data, | ||
5451 | min_t(u16, be16_to_cpu(ioasa->auto_sense.auto_sense_len), | ||
5452 | SCSI_SENSE_BUFFERSIZE)); | ||
5439 | return 1; | 5453 | return 1; |
5440 | } | 5454 | } |
5441 | 5455 | ||
@@ -5455,7 +5469,7 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg, | |||
5455 | { | 5469 | { |
5456 | struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; | 5470 | struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; |
5457 | struct ipr_resource_entry *res = scsi_cmd->device->hostdata; | 5471 | struct ipr_resource_entry *res = scsi_cmd->device->hostdata; |
5458 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 5472 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
5459 | u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK; | 5473 | u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK; |
5460 | 5474 | ||
5461 | if (!res) { | 5475 | if (!res) { |
@@ -5547,9 +5561,9 @@ static void ipr_scsi_done(struct ipr_cmnd *ipr_cmd) | |||
5547 | { | 5561 | { |
5548 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 5562 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
5549 | struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; | 5563 | struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; |
5550 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 5564 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
5551 | 5565 | ||
5552 | scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->ioasa.residual_data_len)); | 5566 | scsi_set_resid(scsi_cmd, be32_to_cpu(ipr_cmd->s.ioasa.hdr.residual_data_len)); |
5553 | 5567 | ||
5554 | if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { | 5568 | if (likely(IPR_IOASC_SENSE_KEY(ioasc) == 0)) { |
5555 | scsi_dma_unmap(ipr_cmd->scsi_cmd); | 5569 | scsi_dma_unmap(ipr_cmd->scsi_cmd); |
@@ -5839,19 +5853,23 @@ static void ipr_sata_done(struct ipr_cmnd *ipr_cmd) | |||
5839 | struct ata_queued_cmd *qc = ipr_cmd->qc; | 5853 | struct ata_queued_cmd *qc = ipr_cmd->qc; |
5840 | struct ipr_sata_port *sata_port = qc->ap->private_data; | 5854 | struct ipr_sata_port *sata_port = qc->ap->private_data; |
5841 | struct ipr_resource_entry *res = sata_port->res; | 5855 | struct ipr_resource_entry *res = sata_port->res; |
5842 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 5856 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
5843 | 5857 | ||
5844 | memcpy(&sata_port->ioasa, &ipr_cmd->ioasa.u.gata, | 5858 | if (ipr_cmd->ioa_cfg->sis64) |
5845 | sizeof(struct ipr_ioasa_gata)); | 5859 | memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa64.u.gata, |
5860 | sizeof(struct ipr_ioasa_gata)); | ||
5861 | else | ||
5862 | memcpy(&sata_port->ioasa, &ipr_cmd->s.ioasa.u.gata, | ||
5863 | sizeof(struct ipr_ioasa_gata)); | ||
5846 | ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); | 5864 | ipr_dump_ioasa(ioa_cfg, ipr_cmd, res); |
5847 | 5865 | ||
5848 | if (be32_to_cpu(ipr_cmd->ioasa.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET) | 5866 | if (be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc_specific) & IPR_ATA_DEVICE_WAS_RESET) |
5849 | scsi_report_device_reset(ioa_cfg->host, res->bus, res->target); | 5867 | scsi_report_device_reset(ioa_cfg->host, res->bus, res->target); |
5850 | 5868 | ||
5851 | if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR) | 5869 | if (IPR_IOASC_SENSE_KEY(ioasc) > RECOVERED_ERROR) |
5852 | qc->err_mask |= __ac_err_mask(ipr_cmd->ioasa.u.gata.status); | 5870 | qc->err_mask |= __ac_err_mask(sata_port->ioasa.status); |
5853 | else | 5871 | else |
5854 | qc->err_mask |= ac_err_mask(ipr_cmd->ioasa.u.gata.status); | 5872 | qc->err_mask |= ac_err_mask(sata_port->ioasa.status); |
5855 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); | 5873 | list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); |
5856 | ata_qc_complete(qc); | 5874 | ata_qc_complete(qc); |
5857 | } | 5875 | } |
@@ -6520,7 +6538,7 @@ static void ipr_build_mode_sense(struct ipr_cmnd *ipr_cmd, | |||
6520 | static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd) | 6538 | static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd) |
6521 | { | 6539 | { |
6522 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 6540 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
6523 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 6541 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
6524 | 6542 | ||
6525 | dev_err(&ioa_cfg->pdev->dev, | 6543 | dev_err(&ioa_cfg->pdev->dev, |
6526 | "0x%02X failed with IOASC: 0x%08X\n", | 6544 | "0x%02X failed with IOASC: 0x%08X\n", |
@@ -6544,7 +6562,7 @@ static int ipr_reset_cmd_failed(struct ipr_cmnd *ipr_cmd) | |||
6544 | static int ipr_reset_mode_sense_failed(struct ipr_cmnd *ipr_cmd) | 6562 | static int ipr_reset_mode_sense_failed(struct ipr_cmnd *ipr_cmd) |
6545 | { | 6563 | { |
6546 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 6564 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
6547 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 6565 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
6548 | 6566 | ||
6549 | if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { | 6567 | if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { |
6550 | ipr_cmd->job_step = ipr_set_supported_devs; | 6568 | ipr_cmd->job_step = ipr_set_supported_devs; |
@@ -6634,7 +6652,7 @@ static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd) | |||
6634 | **/ | 6652 | **/ |
6635 | static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd) | 6653 | static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd) |
6636 | { | 6654 | { |
6637 | u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 6655 | u32 ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
6638 | 6656 | ||
6639 | if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { | 6657 | if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) { |
6640 | ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; | 6658 | ipr_cmd->job_step = ipr_ioafp_mode_sense_page28; |
@@ -6706,7 +6724,7 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd) | |||
6706 | list_move_tail(&res->queue, &old_res); | 6724 | list_move_tail(&res->queue, &old_res); |
6707 | 6725 | ||
6708 | if (ioa_cfg->sis64) | 6726 | if (ioa_cfg->sis64) |
6709 | entries = ioa_cfg->u.cfg_table64->hdr64.num_entries; | 6727 | entries = be16_to_cpu(ioa_cfg->u.cfg_table64->hdr64.num_entries); |
6710 | else | 6728 | else |
6711 | entries = ioa_cfg->u.cfg_table->hdr.num_entries; | 6729 | entries = ioa_cfg->u.cfg_table->hdr.num_entries; |
6712 | 6730 | ||
@@ -6792,6 +6810,7 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd) | |||
6792 | ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); | 6810 | ioarcb->res_handle = cpu_to_be32(IPR_IOA_RES_HANDLE); |
6793 | 6811 | ||
6794 | ioarcb->cmd_pkt.cdb[0] = IPR_QUERY_IOA_CONFIG; | 6812 | ioarcb->cmd_pkt.cdb[0] = IPR_QUERY_IOA_CONFIG; |
6813 | ioarcb->cmd_pkt.cdb[6] = (ioa_cfg->cfg_table_size >> 16) & 0xff; | ||
6795 | ioarcb->cmd_pkt.cdb[7] = (ioa_cfg->cfg_table_size >> 8) & 0xff; | 6814 | ioarcb->cmd_pkt.cdb[7] = (ioa_cfg->cfg_table_size >> 8) & 0xff; |
6796 | ioarcb->cmd_pkt.cdb[8] = ioa_cfg->cfg_table_size & 0xff; | 6815 | ioarcb->cmd_pkt.cdb[8] = ioa_cfg->cfg_table_size & 0xff; |
6797 | 6816 | ||
@@ -7122,7 +7141,9 @@ static int ipr_reset_next_stage(struct ipr_cmnd *ipr_cmd) | |||
7122 | ipr_dbg("IPL stage = 0x%lx, IPL stage time = %ld\n", stage, stage_time); | 7141 | ipr_dbg("IPL stage = 0x%lx, IPL stage time = %ld\n", stage, stage_time); |
7123 | 7142 | ||
7124 | /* sanity check the stage_time value */ | 7143 | /* sanity check the stage_time value */ |
7125 | if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME) | 7144 | if (stage_time == 0) |
7145 | stage_time = IPR_IPL_INIT_DEFAULT_STAGE_TIME; | ||
7146 | else if (stage_time < IPR_IPL_INIT_MIN_STAGE_TIME) | ||
7126 | stage_time = IPR_IPL_INIT_MIN_STAGE_TIME; | 7147 | stage_time = IPR_IPL_INIT_MIN_STAGE_TIME; |
7127 | else if (stage_time > IPR_LONG_OPERATIONAL_TIMEOUT) | 7148 | else if (stage_time > IPR_LONG_OPERATIONAL_TIMEOUT) |
7128 | stage_time = IPR_LONG_OPERATIONAL_TIMEOUT; | 7149 | stage_time = IPR_LONG_OPERATIONAL_TIMEOUT; |
@@ -7165,13 +7186,14 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) | |||
7165 | { | 7186 | { |
7166 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 7187 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
7167 | volatile u32 int_reg; | 7188 | volatile u32 int_reg; |
7189 | volatile u64 maskval; | ||
7168 | 7190 | ||
7169 | ENTER; | 7191 | ENTER; |
7170 | ipr_cmd->job_step = ipr_ioafp_identify_hrrq; | 7192 | ipr_cmd->job_step = ipr_ioafp_identify_hrrq; |
7171 | ipr_init_ioa_mem(ioa_cfg); | 7193 | ipr_init_ioa_mem(ioa_cfg); |
7172 | 7194 | ||
7173 | ioa_cfg->allow_interrupts = 1; | 7195 | ioa_cfg->allow_interrupts = 1; |
7174 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); | 7196 | int_reg = readl(ioa_cfg->regs.sense_interrupt_reg32); |
7175 | 7197 | ||
7176 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { | 7198 | if (int_reg & IPR_PCII_IOA_TRANS_TO_OPER) { |
7177 | writel((IPR_PCII_ERROR_INTERRUPTS | IPR_PCII_HRRQ_UPDATED), | 7199 | writel((IPR_PCII_ERROR_INTERRUPTS | IPR_PCII_HRRQ_UPDATED), |
@@ -7183,9 +7205,12 @@ static int ipr_reset_enable_ioa(struct ipr_cmnd *ipr_cmd) | |||
7183 | /* Enable destructive diagnostics on IOA */ | 7205 | /* Enable destructive diagnostics on IOA */ |
7184 | writel(ioa_cfg->doorbell, ioa_cfg->regs.set_uproc_interrupt_reg32); | 7206 | writel(ioa_cfg->doorbell, ioa_cfg->regs.set_uproc_interrupt_reg32); |
7185 | 7207 | ||
7186 | writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32); | 7208 | if (ioa_cfg->sis64) { |
7187 | if (ioa_cfg->sis64) | 7209 | maskval = IPR_PCII_IPL_STAGE_CHANGE; |
7188 | writel(IPR_PCII_IPL_STAGE_CHANGE, ioa_cfg->regs.clr_interrupt_mask_reg); | 7210 | maskval = (maskval << 32) | IPR_PCII_OPER_INTERRUPTS; |
7211 | writeq(maskval, ioa_cfg->regs.clr_interrupt_mask_reg); | ||
7212 | } else | ||
7213 | writel(IPR_PCII_OPER_INTERRUPTS, ioa_cfg->regs.clr_interrupt_mask_reg32); | ||
7189 | 7214 | ||
7190 | int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); | 7215 | int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); |
7191 | 7216 | ||
@@ -7332,12 +7357,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) | |||
7332 | rc = pci_restore_state(ioa_cfg->pdev); | 7357 | rc = pci_restore_state(ioa_cfg->pdev); |
7333 | 7358 | ||
7334 | if (rc != PCIBIOS_SUCCESSFUL) { | 7359 | if (rc != PCIBIOS_SUCCESSFUL) { |
7335 | ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); | 7360 | ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); |
7336 | return IPR_RC_JOB_CONTINUE; | 7361 | return IPR_RC_JOB_CONTINUE; |
7337 | } | 7362 | } |
7338 | 7363 | ||
7339 | if (ipr_set_pcix_cmd_reg(ioa_cfg)) { | 7364 | if (ipr_set_pcix_cmd_reg(ioa_cfg)) { |
7340 | ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); | 7365 | ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); |
7341 | return IPR_RC_JOB_CONTINUE; | 7366 | return IPR_RC_JOB_CONTINUE; |
7342 | } | 7367 | } |
7343 | 7368 | ||
@@ -7364,7 +7389,7 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd) | |||
7364 | } | 7389 | } |
7365 | } | 7390 | } |
7366 | 7391 | ||
7367 | ENTER; | 7392 | LEAVE; |
7368 | return IPR_RC_JOB_CONTINUE; | 7393 | return IPR_RC_JOB_CONTINUE; |
7369 | } | 7394 | } |
7370 | 7395 | ||
@@ -7406,7 +7431,7 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd) | |||
7406 | 7431 | ||
7407 | if (rc != PCIBIOS_SUCCESSFUL) { | 7432 | if (rc != PCIBIOS_SUCCESSFUL) { |
7408 | pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); | 7433 | pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev); |
7409 | ipr_cmd->ioasa.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); | 7434 | ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR); |
7410 | rc = IPR_RC_JOB_CONTINUE; | 7435 | rc = IPR_RC_JOB_CONTINUE; |
7411 | } else { | 7436 | } else { |
7412 | ipr_cmd->job_step = ipr_reset_bist_done; | 7437 | ipr_cmd->job_step = ipr_reset_bist_done; |
@@ -7665,7 +7690,7 @@ static void ipr_reset_ioa_job(struct ipr_cmnd *ipr_cmd) | |||
7665 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; | 7690 | struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; |
7666 | 7691 | ||
7667 | do { | 7692 | do { |
7668 | ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc); | 7693 | ioasc = be32_to_cpu(ipr_cmd->s.ioasa.hdr.ioasc); |
7669 | 7694 | ||
7670 | if (ioa_cfg->reset_cmd != ipr_cmd) { | 7695 | if (ioa_cfg->reset_cmd != ipr_cmd) { |
7671 | /* | 7696 | /* |
@@ -8048,13 +8073,13 @@ static int __devinit ipr_alloc_cmd_blks(struct ipr_ioa_cfg *ioa_cfg) | |||
8048 | ioarcb->u.sis64_addr_data.data_ioadl_addr = | 8073 | ioarcb->u.sis64_addr_data.data_ioadl_addr = |
8049 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); | 8074 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, i.ioadl64)); |
8050 | ioarcb->u.sis64_addr_data.ioasa_host_pci_addr = | 8075 | ioarcb->u.sis64_addr_data.ioasa_host_pci_addr = |
8051 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, ioasa)); | 8076 | cpu_to_be64(dma_addr + offsetof(struct ipr_cmnd, s.ioasa64)); |
8052 | } else { | 8077 | } else { |
8053 | ioarcb->write_ioadl_addr = | 8078 | ioarcb->write_ioadl_addr = |
8054 | cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); | 8079 | cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, i.ioadl)); |
8055 | ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; | 8080 | ioarcb->read_ioadl_addr = ioarcb->write_ioadl_addr; |
8056 | ioarcb->ioasa_host_pci_addr = | 8081 | ioarcb->ioasa_host_pci_addr = |
8057 | cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, ioasa)); | 8082 | cpu_to_be32(dma_addr + offsetof(struct ipr_cmnd, s.ioasa)); |
8058 | } | 8083 | } |
8059 | ioarcb->ioasa_len = cpu_to_be16(sizeof(struct ipr_ioasa)); | 8084 | ioarcb->ioasa_len = cpu_to_be16(sizeof(struct ipr_ioasa)); |
8060 | ipr_cmd->cmd_index = i; | 8085 | ipr_cmd->cmd_index = i; |
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 4c267b5e0b96..9ecd2259eb39 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h | |||
@@ -244,6 +244,7 @@ | |||
244 | #define IPR_RUNTIME_RESET 0x40000000 | 244 | #define IPR_RUNTIME_RESET 0x40000000 |
245 | 245 | ||
246 | #define IPR_IPL_INIT_MIN_STAGE_TIME 5 | 246 | #define IPR_IPL_INIT_MIN_STAGE_TIME 5 |
247 | #define IPR_IPL_INIT_DEFAULT_STAGE_TIME 15 | ||
247 | #define IPR_IPL_INIT_STAGE_UNKNOWN 0x0 | 248 | #define IPR_IPL_INIT_STAGE_UNKNOWN 0x0 |
248 | #define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000 | 249 | #define IPR_IPL_INIT_STAGE_TRANSOP 0xB0000000 |
249 | #define IPR_IPL_INIT_STAGE_MASK 0xff000000 | 250 | #define IPR_IPL_INIT_STAGE_MASK 0xff000000 |
@@ -613,7 +614,7 @@ struct ipr_auto_sense { | |||
613 | __be32 data[SCSI_SENSE_BUFFERSIZE/sizeof(__be32)]; | 614 | __be32 data[SCSI_SENSE_BUFFERSIZE/sizeof(__be32)]; |
614 | }; | 615 | }; |
615 | 616 | ||
616 | struct ipr_ioasa { | 617 | struct ipr_ioasa_hdr { |
617 | __be32 ioasc; | 618 | __be32 ioasc; |
618 | #define IPR_IOASC_SENSE_KEY(ioasc) ((ioasc) >> 24) | 619 | #define IPR_IOASC_SENSE_KEY(ioasc) ((ioasc) >> 24) |
619 | #define IPR_IOASC_SENSE_CODE(ioasc) (((ioasc) & 0x00ff0000) >> 16) | 620 | #define IPR_IOASC_SENSE_CODE(ioasc) (((ioasc) & 0x00ff0000) >> 16) |
@@ -645,6 +646,25 @@ struct ipr_ioasa { | |||
645 | #define IPR_FIELD_POINTER_VALID (0x80000000 >> 8) | 646 | #define IPR_FIELD_POINTER_VALID (0x80000000 >> 8) |
646 | #define IPR_FIELD_POINTER_MASK 0x0000ffff | 647 | #define IPR_FIELD_POINTER_MASK 0x0000ffff |
647 | 648 | ||
649 | }__attribute__((packed, aligned (4))); | ||
650 | |||
651 | struct ipr_ioasa { | ||
652 | struct ipr_ioasa_hdr hdr; | ||
653 | |||
654 | union { | ||
655 | struct ipr_ioasa_vset vset; | ||
656 | struct ipr_ioasa_af_dasd dasd; | ||
657 | struct ipr_ioasa_gpdd gpdd; | ||
658 | struct ipr_ioasa_gata gata; | ||
659 | } u; | ||
660 | |||
661 | struct ipr_auto_sense auto_sense; | ||
662 | }__attribute__((packed, aligned (4))); | ||
663 | |||
664 | struct ipr_ioasa64 { | ||
665 | struct ipr_ioasa_hdr hdr; | ||
666 | u8 fd_res_path[8]; | ||
667 | |||
648 | union { | 668 | union { |
649 | struct ipr_ioasa_vset vset; | 669 | struct ipr_ioasa_vset vset; |
650 | struct ipr_ioasa_af_dasd dasd; | 670 | struct ipr_ioasa_af_dasd dasd; |
@@ -804,7 +824,7 @@ struct ipr_hostrcb_array_data_entry_enhanced { | |||
804 | }__attribute__((packed, aligned (4))); | 824 | }__attribute__((packed, aligned (4))); |
805 | 825 | ||
806 | struct ipr_hostrcb_type_ff_error { | 826 | struct ipr_hostrcb_type_ff_error { |
807 | __be32 ioa_data[502]; | 827 | __be32 ioa_data[758]; |
808 | }__attribute__((packed, aligned (4))); | 828 | }__attribute__((packed, aligned (4))); |
809 | 829 | ||
810 | struct ipr_hostrcb_type_01_error { | 830 | struct ipr_hostrcb_type_01_error { |
@@ -1181,7 +1201,7 @@ struct ipr_resource_entry { | |||
1181 | u8 flags; | 1201 | u8 flags; |
1182 | __be16 res_flags; | 1202 | __be16 res_flags; |
1183 | 1203 | ||
1184 | __be32 type; | 1204 | u8 type; |
1185 | 1205 | ||
1186 | u8 qmodel; | 1206 | u8 qmodel; |
1187 | struct ipr_std_inq_data std_inq_data; | 1207 | struct ipr_std_inq_data std_inq_data; |
@@ -1464,7 +1484,10 @@ struct ipr_cmnd { | |||
1464 | struct ipr_ioadl64_desc ioadl64[IPR_NUM_IOADL_ENTRIES]; | 1484 | struct ipr_ioadl64_desc ioadl64[IPR_NUM_IOADL_ENTRIES]; |
1465 | struct ipr_ata64_ioadl ata_ioadl; | 1485 | struct ipr_ata64_ioadl ata_ioadl; |
1466 | } i; | 1486 | } i; |
1467 | struct ipr_ioasa ioasa; | 1487 | union { |
1488 | struct ipr_ioasa ioasa; | ||
1489 | struct ipr_ioasa64 ioasa64; | ||
1490 | } s; | ||
1468 | struct list_head queue; | 1491 | struct list_head queue; |
1469 | struct scsi_cmnd *scsi_cmd; | 1492 | struct scsi_cmnd *scsi_cmd; |
1470 | struct ata_queued_cmd *qc; | 1493 | struct ata_queued_cmd *qc; |
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index bf55d3057413..fec47de72535 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -601,10 +601,8 @@ static void iscsi_sw_tcp_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) | |||
601 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); | 601 | set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_rx); |
602 | write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock); | 602 | write_unlock_bh(&tcp_sw_conn->sock->sk->sk_callback_lock); |
603 | 603 | ||
604 | if (sk_sleep(sock->sk)) { | 604 | sock->sk->sk_err = EIO; |
605 | sock->sk->sk_err = EIO; | 605 | wake_up_interruptible(sk_sleep(sock->sk)); |
606 | wake_up_interruptible(sk_sleep(sock->sk)); | ||
607 | } | ||
608 | 606 | ||
609 | iscsi_conn_stop(cls_conn, flag); | 607 | iscsi_conn_stop(cls_conn, flag); |
610 | iscsi_sw_tcp_release_conn(conn); | 608 | iscsi_sw_tcp_release_conn(conn); |
diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index 716d1785cda7..c29d0dbb9660 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c | |||
@@ -16,12 +16,12 @@ | |||
16 | #include <linux/stat.h> | 16 | #include <linux/stat.h> |
17 | 17 | ||
18 | 18 | ||
19 | static struct Scsi_Host *mvme147_host = NULL; | 19 | static irqreturn_t mvme147_intr(int irq, void *data) |
20 | |||
21 | static irqreturn_t mvme147_intr(int irq, void *dummy) | ||
22 | { | 20 | { |
21 | struct Scsi_Host *instance = data; | ||
22 | |||
23 | if (irq == MVME147_IRQ_SCSI_PORT) | 23 | if (irq == MVME147_IRQ_SCSI_PORT) |
24 | wd33c93_intr(mvme147_host); | 24 | wd33c93_intr(instance); |
25 | else | 25 | else |
26 | m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ | 26 | m147_pcc->dma_intr = 0x89; /* Ack and enable ints */ |
27 | return IRQ_HANDLED; | 27 | return IRQ_HANDLED; |
@@ -29,7 +29,8 @@ static irqreturn_t mvme147_intr(int irq, void *dummy) | |||
29 | 29 | ||
30 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) | 30 | static int dma_setup(struct scsi_cmnd *cmd, int dir_in) |
31 | { | 31 | { |
32 | struct WD33C93_hostdata *hdata = shost_priv(mvme147_host); | 32 | struct Scsi_Host *instance = cmd->device->host; |
33 | struct WD33C93_hostdata *hdata = shost_priv(instance); | ||
33 | unsigned char flags = 0x01; | 34 | unsigned char flags = 0x01; |
34 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); | 35 | unsigned long addr = virt_to_bus(cmd->SCp.ptr); |
35 | 36 | ||
@@ -66,6 +67,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt, | |||
66 | int mvme147_detect(struct scsi_host_template *tpnt) | 67 | int mvme147_detect(struct scsi_host_template *tpnt) |
67 | { | 68 | { |
68 | static unsigned char called = 0; | 69 | static unsigned char called = 0; |
70 | struct Scsi_Host *instance; | ||
69 | wd33c93_regs regs; | 71 | wd33c93_regs regs; |
70 | struct WD33C93_hostdata *hdata; | 72 | struct WD33C93_hostdata *hdata; |
71 | 73 | ||
@@ -76,25 +78,25 @@ int mvme147_detect(struct scsi_host_template *tpnt) | |||
76 | tpnt->proc_name = "MVME147"; | 78 | tpnt->proc_name = "MVME147"; |
77 | tpnt->proc_info = &wd33c93_proc_info; | 79 | tpnt->proc_info = &wd33c93_proc_info; |
78 | 80 | ||
79 | mvme147_host = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); | 81 | instance = scsi_register(tpnt, sizeof(struct WD33C93_hostdata)); |
80 | if (!mvme147_host) | 82 | if (!instance) |
81 | goto err_out; | 83 | goto err_out; |
82 | 84 | ||
83 | mvme147_host->base = 0xfffe4000; | 85 | instance->base = 0xfffe4000; |
84 | mvme147_host->irq = MVME147_IRQ_SCSI_PORT; | 86 | instance->irq = MVME147_IRQ_SCSI_PORT; |
85 | regs.SASR = (volatile unsigned char *)0xfffe4000; | 87 | regs.SASR = (volatile unsigned char *)0xfffe4000; |
86 | regs.SCMD = (volatile unsigned char *)0xfffe4001; | 88 | regs.SCMD = (volatile unsigned char *)0xfffe4001; |
87 | hdata = shost_priv(mvme147_host); | 89 | hdata = shost_priv(instance); |
88 | hdata->no_sync = 0xff; | 90 | hdata->no_sync = 0xff; |
89 | hdata->fast = 0; | 91 | hdata->fast = 0; |
90 | hdata->dma_mode = CTRL_DMA; | 92 | hdata->dma_mode = CTRL_DMA; |
91 | wd33c93_init(mvme147_host, regs, dma_setup, dma_stop, WD33C93_FS_8_10); | 93 | wd33c93_init(instance, regs, dma_setup, dma_stop, WD33C93_FS_8_10); |
92 | 94 | ||
93 | if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, | 95 | if (request_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr, 0, |
94 | "MVME147 SCSI PORT", mvme147_intr)) | 96 | "MVME147 SCSI PORT", instance)) |
95 | goto err_unregister; | 97 | goto err_unregister; |
96 | if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, | 98 | if (request_irq(MVME147_IRQ_SCSI_DMA, mvme147_intr, 0, |
97 | "MVME147 SCSI DMA", mvme147_intr)) | 99 | "MVME147 SCSI DMA", instance)) |
98 | goto err_free_irq; | 100 | goto err_free_irq; |
99 | #if 0 /* Disabled; causes problems booting */ | 101 | #if 0 /* Disabled; causes problems booting */ |
100 | m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ | 102 | m147_pcc->scsi_interrupt = 0x10; /* Assert SCSI bus reset */ |
@@ -113,7 +115,7 @@ int mvme147_detect(struct scsi_host_template *tpnt) | |||
113 | err_free_irq: | 115 | err_free_irq: |
114 | free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); | 116 | free_irq(MVME147_IRQ_SCSI_PORT, mvme147_intr); |
115 | err_unregister: | 117 | err_unregister: |
116 | scsi_unregister(mvme147_host); | 118 | scsi_unregister(instance); |
117 | err_out: | 119 | err_out: |
118 | return 0; | 120 | return 0; |
119 | } | 121 | } |
@@ -132,9 +134,6 @@ static int mvme147_bus_reset(struct scsi_cmnd *cmd) | |||
132 | return SUCCESS; | 134 | return SUCCESS; |
133 | } | 135 | } |
134 | 136 | ||
135 | #define HOSTS_C | ||
136 | |||
137 | #include "mvme147.h" | ||
138 | 137 | ||
139 | static struct scsi_host_template driver_template = { | 138 | static struct scsi_host_template driver_template = { |
140 | .proc_name = "MVME147", | 139 | .proc_name = "MVME147", |
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 8dbf1c3afb7b..d64b7178fa08 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c | |||
@@ -3587,7 +3587,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name | |||
3587 | if (i == (-ENOSPC)) { | 3587 | if (i == (-ENOSPC)) { |
3588 | transfer = STp->buffer->writing; /* FIXME -- check this logic */ | 3588 | transfer = STp->buffer->writing; /* FIXME -- check this logic */ |
3589 | if (transfer <= do_count) { | 3589 | if (transfer <= do_count) { |
3590 | filp->f_pos += do_count - transfer; | 3590 | *ppos += do_count - transfer; |
3591 | count -= do_count - transfer; | 3591 | count -= do_count - transfer; |
3592 | if (STps->drv_block >= 0) { | 3592 | if (STps->drv_block >= 0) { |
3593 | STps->drv_block += (do_count - transfer) / STp->block_size; | 3593 | STps->drv_block += (do_count - transfer) / STp->block_size; |
@@ -3625,7 +3625,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name | |||
3625 | goto out; | 3625 | goto out; |
3626 | } | 3626 | } |
3627 | 3627 | ||
3628 | filp->f_pos += do_count; | 3628 | *ppos += do_count; |
3629 | b_point += do_count; | 3629 | b_point += do_count; |
3630 | count -= do_count; | 3630 | count -= do_count; |
3631 | if (STps->drv_block >= 0) { | 3631 | if (STps->drv_block >= 0) { |
@@ -3647,7 +3647,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name | |||
3647 | if (STps->drv_block >= 0) { | 3647 | if (STps->drv_block >= 0) { |
3648 | STps->drv_block += blks; | 3648 | STps->drv_block += blks; |
3649 | } | 3649 | } |
3650 | filp->f_pos += count; | 3650 | *ppos += count; |
3651 | count = 0; | 3651 | count = 0; |
3652 | } | 3652 | } |
3653 | 3653 | ||
@@ -3823,7 +3823,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo | |||
3823 | } | 3823 | } |
3824 | STp->logical_blk_num += transfer / STp->block_size; | 3824 | STp->logical_blk_num += transfer / STp->block_size; |
3825 | STps->drv_block += transfer / STp->block_size; | 3825 | STps->drv_block += transfer / STp->block_size; |
3826 | filp->f_pos += transfer; | 3826 | *ppos += transfer; |
3827 | buf += transfer; | 3827 | buf += transfer; |
3828 | total += transfer; | 3828 | total += transfer; |
3829 | } | 3829 | } |
@@ -5626,6 +5626,7 @@ static const struct file_operations osst_fops = { | |||
5626 | .open = os_scsi_tape_open, | 5626 | .open = os_scsi_tape_open, |
5627 | .flush = os_scsi_tape_flush, | 5627 | .flush = os_scsi_tape_flush, |
5628 | .release = os_scsi_tape_close, | 5628 | .release = os_scsi_tape_close, |
5629 | .llseek = noop_llseek, | ||
5629 | }; | 5630 | }; |
5630 | 5631 | ||
5631 | static int osst_supports(struct scsi_device * SDp) | 5632 | static int osst_supports(struct scsi_device * SDp) |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 9798c2c06b93..1c027a97d8b9 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -492,19 +492,20 @@ void scsi_target_reap(struct scsi_target *starget) | |||
492 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); | 492 | struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); |
493 | unsigned long flags; | 493 | unsigned long flags; |
494 | enum scsi_target_state state; | 494 | enum scsi_target_state state; |
495 | int empty; | 495 | int empty = 0; |
496 | 496 | ||
497 | spin_lock_irqsave(shost->host_lock, flags); | 497 | spin_lock_irqsave(shost->host_lock, flags); |
498 | state = starget->state; | 498 | state = starget->state; |
499 | empty = --starget->reap_ref == 0 && | 499 | if (--starget->reap_ref == 0 && list_empty(&starget->devices)) { |
500 | list_empty(&starget->devices) ? 1 : 0; | 500 | empty = 1; |
501 | starget->state = STARGET_DEL; | ||
502 | } | ||
501 | spin_unlock_irqrestore(shost->host_lock, flags); | 503 | spin_unlock_irqrestore(shost->host_lock, flags); |
502 | 504 | ||
503 | if (!empty) | 505 | if (!empty) |
504 | return; | 506 | return; |
505 | 507 | ||
506 | BUG_ON(state == STARGET_DEL); | 508 | BUG_ON(state == STARGET_DEL); |
507 | starget->state = STARGET_DEL; | ||
508 | if (state == STARGET_CREATED) | 509 | if (state == STARGET_CREATED) |
509 | scsi_target_destroy(starget); | 510 | scsi_target_destroy(starget); |
510 | else | 511 | else |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 3ea1a713ef25..24211d0efa6d 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
@@ -3962,6 +3962,7 @@ static const struct file_operations st_fops = | |||
3962 | .open = st_open, | 3962 | .open = st_open, |
3963 | .flush = st_flush, | 3963 | .flush = st_flush, |
3964 | .release = st_release, | 3964 | .release = st_release, |
3965 | .llseek = noop_llseek, | ||
3965 | }; | 3966 | }; |
3966 | 3967 | ||
3967 | static int st_probe(struct device *dev) | 3968 | static int st_probe(struct device *dev) |
diff --git a/drivers/sfi/sfi_acpi.c b/drivers/sfi/sfi_acpi.c index 34aba30eb84b..f5b4ca581541 100644 --- a/drivers/sfi/sfi_acpi.c +++ b/drivers/sfi/sfi_acpi.c | |||
@@ -173,3 +173,44 @@ int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, | |||
173 | sfi_acpi_put_table(table); | 173 | sfi_acpi_put_table(table); |
174 | return ret; | 174 | return ret; |
175 | } | 175 | } |
176 | |||
177 | static ssize_t sfi_acpi_table_show(struct file *filp, struct kobject *kobj, | ||
178 | struct bin_attribute *bin_attr, char *buf, | ||
179 | loff_t offset, size_t count) | ||
180 | { | ||
181 | struct sfi_table_attr *tbl_attr = | ||
182 | container_of(bin_attr, struct sfi_table_attr, attr); | ||
183 | struct acpi_table_header *th = NULL; | ||
184 | struct sfi_table_key key; | ||
185 | ssize_t cnt; | ||
186 | |||
187 | key.sig = tbl_attr->name; | ||
188 | key.oem_id = NULL; | ||
189 | key.oem_table_id = NULL; | ||
190 | |||
191 | th = sfi_acpi_get_table(&key); | ||
192 | if (!th) | ||
193 | return 0; | ||
194 | |||
195 | cnt = memory_read_from_buffer(buf, count, &offset, | ||
196 | th, th->length); | ||
197 | sfi_acpi_put_table(th); | ||
198 | |||
199 | return cnt; | ||
200 | } | ||
201 | |||
202 | |||
203 | void __init sfi_acpi_sysfs_init(void) | ||
204 | { | ||
205 | u32 tbl_cnt, i; | ||
206 | struct sfi_table_attr *tbl_attr; | ||
207 | |||
208 | tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); | ||
209 | for (i = 0; i < tbl_cnt; i++) { | ||
210 | tbl_attr = | ||
211 | sfi_sysfs_install_table(xsdt_va->table_offset_entry[i]); | ||
212 | tbl_attr->attr.read = sfi_acpi_table_show; | ||
213 | } | ||
214 | |||
215 | return; | ||
216 | } | ||
diff --git a/drivers/sfi/sfi_core.c b/drivers/sfi/sfi_core.c index b204a0929139..005195958647 100644 --- a/drivers/sfi/sfi_core.c +++ b/drivers/sfi/sfi_core.c | |||
@@ -67,6 +67,7 @@ | |||
67 | #include <linux/acpi.h> | 67 | #include <linux/acpi.h> |
68 | #include <linux/init.h> | 68 | #include <linux/init.h> |
69 | #include <linux/sfi.h> | 69 | #include <linux/sfi.h> |
70 | #include <linux/slab.h> | ||
70 | 71 | ||
71 | #include "sfi_core.h" | 72 | #include "sfi_core.h" |
72 | 73 | ||
@@ -382,6 +383,102 @@ static __init int sfi_find_syst(void) | |||
382 | return -1; | 383 | return -1; |
383 | } | 384 | } |
384 | 385 | ||
386 | static struct kobject *sfi_kobj; | ||
387 | static struct kobject *tables_kobj; | ||
388 | |||
389 | static ssize_t sfi_table_show(struct file *filp, struct kobject *kobj, | ||
390 | struct bin_attribute *bin_attr, char *buf, | ||
391 | loff_t offset, size_t count) | ||
392 | { | ||
393 | struct sfi_table_attr *tbl_attr = | ||
394 | container_of(bin_attr, struct sfi_table_attr, attr); | ||
395 | struct sfi_table_header *th = NULL; | ||
396 | struct sfi_table_key key; | ||
397 | ssize_t cnt; | ||
398 | |||
399 | key.sig = tbl_attr->name; | ||
400 | key.oem_id = NULL; | ||
401 | key.oem_table_id = NULL; | ||
402 | |||
403 | if (strncmp(SFI_SIG_SYST, tbl_attr->name, SFI_SIGNATURE_SIZE)) { | ||
404 | th = sfi_get_table(&key); | ||
405 | if (!th) | ||
406 | return 0; | ||
407 | |||
408 | cnt = memory_read_from_buffer(buf, count, &offset, | ||
409 | th, th->len); | ||
410 | sfi_put_table(th); | ||
411 | } else | ||
412 | cnt = memory_read_from_buffer(buf, count, &offset, | ||
413 | syst_va, syst_va->header.len); | ||
414 | |||
415 | return cnt; | ||
416 | } | ||
417 | |||
418 | struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa) | ||
419 | { | ||
420 | struct sfi_table_attr *tbl_attr; | ||
421 | struct sfi_table_header *th; | ||
422 | int ret; | ||
423 | |||
424 | tbl_attr = kzalloc(sizeof(struct sfi_table_attr), GFP_KERNEL); | ||
425 | if (!tbl_attr) | ||
426 | return NULL; | ||
427 | |||
428 | th = sfi_map_table(pa); | ||
429 | if (!th || !th->sig[0]) { | ||
430 | kfree(tbl_attr); | ||
431 | return NULL; | ||
432 | } | ||
433 | |||
434 | sysfs_attr_init(&tbl_attr->attr.attr); | ||
435 | memcpy(tbl_attr->name, th->sig, SFI_SIGNATURE_SIZE); | ||
436 | |||
437 | tbl_attr->attr.size = 0; | ||
438 | tbl_attr->attr.read = sfi_table_show; | ||
439 | tbl_attr->attr.attr.name = tbl_attr->name; | ||
440 | tbl_attr->attr.attr.mode = 0400; | ||
441 | |||
442 | ret = sysfs_create_bin_file(tables_kobj, | ||
443 | &tbl_attr->attr); | ||
444 | if (ret) | ||
445 | kfree(tbl_attr); | ||
446 | |||
447 | sfi_unmap_table(th); | ||
448 | return tbl_attr; | ||
449 | } | ||
450 | |||
451 | static int __init sfi_sysfs_init(void) | ||
452 | { | ||
453 | int tbl_cnt, i; | ||
454 | |||
455 | if (sfi_disabled) | ||
456 | return 0; | ||
457 | |||
458 | sfi_kobj = kobject_create_and_add("sfi", firmware_kobj); | ||
459 | if (!sfi_kobj) | ||
460 | return 0; | ||
461 | |||
462 | tables_kobj = kobject_create_and_add("tables", sfi_kobj); | ||
463 | if (!tables_kobj) { | ||
464 | kobject_put(sfi_kobj); | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | sfi_sysfs_install_table(syst_pa); | ||
469 | |||
470 | tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); | ||
471 | |||
472 | for (i = 0; i < tbl_cnt; i++) | ||
473 | sfi_sysfs_install_table(syst_va->pentry[i]); | ||
474 | |||
475 | sfi_acpi_sysfs_init(); | ||
476 | kobject_uevent(sfi_kobj, KOBJ_ADD); | ||
477 | kobject_uevent(tables_kobj, KOBJ_ADD); | ||
478 | pr_info("SFI sysfs interfaces init success\n"); | ||
479 | return 0; | ||
480 | } | ||
481 | |||
385 | void __init sfi_init(void) | 482 | void __init sfi_init(void) |
386 | { | 483 | { |
387 | if (!acpi_disabled) | 484 | if (!acpi_disabled) |
@@ -390,7 +487,7 @@ void __init sfi_init(void) | |||
390 | if (sfi_disabled) | 487 | if (sfi_disabled) |
391 | return; | 488 | return; |
392 | 489 | ||
393 | pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); | 490 | pr_info("Simple Firmware Interface v0.81 http://simplefirmware.org\n"); |
394 | 491 | ||
395 | if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) | 492 | if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) |
396 | disable_sfi(); | 493 | disable_sfi(); |
@@ -414,3 +511,9 @@ void __init sfi_init_late(void) | |||
414 | 511 | ||
415 | sfi_acpi_init(); | 512 | sfi_acpi_init(); |
416 | } | 513 | } |
514 | |||
515 | /* | ||
516 | * The reason we put it here becasue we need wait till the /sys/firmware | ||
517 | * is setup, then our interface can be registered in /sys/firmware/sfi | ||
518 | */ | ||
519 | core_initcall(sfi_sysfs_init); | ||
diff --git a/drivers/sfi/sfi_core.h b/drivers/sfi/sfi_core.h index da82d39e104d..b7cf220d44ec 100644 --- a/drivers/sfi/sfi_core.h +++ b/drivers/sfi/sfi_core.h | |||
@@ -61,6 +61,12 @@ struct sfi_table_key{ | |||
61 | char *oem_table_id; | 61 | char *oem_table_id; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | /* sysfs interface */ | ||
65 | struct sfi_table_attr { | ||
66 | struct bin_attribute attr; | ||
67 | char name[8]; | ||
68 | }; | ||
69 | |||
64 | #define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } | 70 | #define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } |
65 | 71 | ||
66 | extern int __init sfi_acpi_init(void); | 72 | extern int __init sfi_acpi_init(void); |
@@ -68,3 +74,5 @@ extern struct sfi_table_header *sfi_check_table(u64 paddr, | |||
68 | struct sfi_table_key *key); | 74 | struct sfi_table_key *key); |
69 | struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); | 75 | struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); |
70 | extern void sfi_put_table(struct sfi_table_header *table); | 76 | extern void sfi_put_table(struct sfi_table_header *table); |
77 | extern struct sfi_table_attr __init *sfi_sysfs_install_table(u64 pa); | ||
78 | extern void __init sfi_acpi_sysfs_init(void); | ||
diff --git a/drivers/staging/go7007/saa7134-go7007.c b/drivers/staging/go7007/saa7134-go7007.c index 49f0d31c118a..cf7c34a99459 100644 --- a/drivers/staging/go7007/saa7134-go7007.c +++ b/drivers/staging/go7007/saa7134-go7007.c | |||
@@ -242,13 +242,13 @@ static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev, | |||
242 | printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", | 242 | printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n", |
243 | (status >> 16) & 0x0f); | 243 | (status >> 16) & 0x0f); |
244 | if (status & 0x100000) { | 244 | if (status & 0x100000) { |
245 | dma_sync_single(&dev->pci->dev, | 245 | dma_sync_single_for_cpu(&dev->pci->dev, |
246 | saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE); | 246 | saa->bottom_dma, PAGE_SIZE, DMA_FROM_DEVICE); |
247 | go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE); | 247 | go7007_parse_video_stream(go, saa->bottom, PAGE_SIZE); |
248 | saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma)); | 248 | saa_writel(SAA7134_RS_BA2(5), cpu_to_le32(saa->bottom_dma)); |
249 | } else { | 249 | } else { |
250 | dma_sync_single(&dev->pci->dev, | 250 | dma_sync_single_for_cpu(&dev->pci->dev, |
251 | saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE); | 251 | saa->top_dma, PAGE_SIZE, DMA_FROM_DEVICE); |
252 | go7007_parse_video_stream(go, saa->top, PAGE_SIZE); | 252 | go7007_parse_video_stream(go, saa->top, PAGE_SIZE); |
253 | saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma)); | 253 | saa_writel(SAA7134_RS_BA1(5), cpu_to_le32(saa->top_dma)); |
254 | } | 254 | } |
diff --git a/drivers/telephony/ixj.c b/drivers/telephony/ixj.c index e89304c72568..b53deee25d74 100644 --- a/drivers/telephony/ixj.c +++ b/drivers/telephony/ixj.c | |||
@@ -5879,20 +5879,13 @@ out: | |||
5879 | static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp) | 5879 | static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE __user * cp) |
5880 | { | 5880 | { |
5881 | IXJ_FILTER_CADENCE *lcp; | 5881 | IXJ_FILTER_CADENCE *lcp; |
5882 | lcp = kmalloc(sizeof(IXJ_FILTER_CADENCE), GFP_KERNEL); | 5882 | lcp = memdup_user(cp, sizeof(IXJ_FILTER_CADENCE)); |
5883 | if (lcp == NULL) { | 5883 | if (IS_ERR(lcp)) { |
5884 | if(ixjdebug & 0x0001) { | 5884 | if(ixjdebug & 0x0001) { |
5885 | printk(KERN_INFO "Could not allocate memory for cadence\n"); | 5885 | printk(KERN_INFO "Could not allocate memory for cadence or could not copy cadence to kernel\n"); |
5886 | } | 5886 | } |
5887 | return -ENOMEM; | 5887 | return PTR_ERR(lcp); |
5888 | } | 5888 | } |
5889 | if (copy_from_user(lcp, cp, sizeof(IXJ_FILTER_CADENCE))) { | ||
5890 | if(ixjdebug & 0x0001) { | ||
5891 | printk(KERN_INFO "Could not copy cadence to kernel\n"); | ||
5892 | } | ||
5893 | kfree(lcp); | ||
5894 | return -EFAULT; | ||
5895 | } | ||
5896 | if (lcp->filter > 5) { | 5889 | if (lcp->filter > 5) { |
5897 | if(ixjdebug & 0x0001) { | 5890 | if(ixjdebug & 0x0001) { |
5898 | printk(KERN_INFO "Cadence out of range\n"); | 5891 | printk(KERN_INFO "Cadence out of range\n"); |
diff --git a/drivers/video/backlight/88pm860x_bl.c b/drivers/video/backlight/88pm860x_bl.c index 68d2518fadaa..38ffc3fbcbe4 100644 --- a/drivers/video/backlight/88pm860x_bl.c +++ b/drivers/video/backlight/88pm860x_bl.c | |||
@@ -222,6 +222,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
222 | data->port = __check_device(pdata, name); | 222 | data->port = __check_device(pdata, name); |
223 | if (data->port < 0) { | 223 | if (data->port < 0) { |
224 | dev_err(&pdev->dev, "wrong platform data is assigned"); | 224 | dev_err(&pdev->dev, "wrong platform data is assigned"); |
225 | kfree(data); | ||
225 | return -EINVAL; | 226 | return -EINVAL; |
226 | } | 227 | } |
227 | 228 | ||
@@ -266,6 +267,7 @@ static int pm860x_backlight_probe(struct platform_device *pdev) | |||
266 | backlight_update_status(bl); | 267 | backlight_update_status(bl); |
267 | return 0; | 268 | return 0; |
268 | out: | 269 | out: |
270 | backlight_device_unregister(bl); | ||
269 | kfree(data); | 271 | kfree(data); |
270 | return ret; | 272 | return ret; |
271 | } | 273 | } |
diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig index c025c84601b0..e54a337227ea 100644 --- a/drivers/video/backlight/Kconfig +++ b/drivers/video/backlight/Kconfig | |||
@@ -8,12 +8,13 @@ menuconfig BACKLIGHT_LCD_SUPPORT | |||
8 | Enable this to be able to choose the drivers for controlling the | 8 | Enable this to be able to choose the drivers for controlling the |
9 | backlight and the LCD panel on some platforms, for example on PDAs. | 9 | backlight and the LCD panel on some platforms, for example on PDAs. |
10 | 10 | ||
11 | if BACKLIGHT_LCD_SUPPORT | ||
12 | |||
11 | # | 13 | # |
12 | # LCD | 14 | # LCD |
13 | # | 15 | # |
14 | config LCD_CLASS_DEVICE | 16 | config LCD_CLASS_DEVICE |
15 | tristate "Lowlevel LCD controls" | 17 | tristate "Lowlevel LCD controls" |
16 | depends on BACKLIGHT_LCD_SUPPORT | ||
17 | default m | 18 | default m |
18 | help | 19 | help |
19 | This framework adds support for low-level control of LCD. | 20 | This framework adds support for low-level control of LCD. |
@@ -24,31 +25,32 @@ config LCD_CLASS_DEVICE | |||
24 | To have support for your specific LCD panel you will have to | 25 | To have support for your specific LCD panel you will have to |
25 | select the proper drivers which depend on this option. | 26 | select the proper drivers which depend on this option. |
26 | 27 | ||
28 | if LCD_CLASS_DEVICE | ||
29 | |||
27 | config LCD_CORGI | 30 | config LCD_CORGI |
28 | tristate "LCD Panel support for SHARP corgi/spitz model" | 31 | tristate "LCD Panel support for SHARP corgi/spitz model" |
29 | depends on LCD_CLASS_DEVICE && SPI_MASTER && PXA_SHARPSL | 32 | depends on SPI_MASTER && PXA_SHARPSL |
30 | help | 33 | help |
31 | Say y here to support the LCD panels usually found on SHARP | 34 | Say y here to support the LCD panels usually found on SHARP |
32 | corgi (C7x0) and spitz (Cxx00) models. | 35 | corgi (C7x0) and spitz (Cxx00) models. |
33 | 36 | ||
34 | config LCD_L4F00242T03 | 37 | config LCD_L4F00242T03 |
35 | tristate "Epson L4F00242T03 LCD" | 38 | tristate "Epson L4F00242T03 LCD" |
36 | depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO | 39 | depends on SPI_MASTER && GENERIC_GPIO |
37 | help | 40 | help |
38 | SPI driver for Epson L4F00242T03. This provides basic support | 41 | SPI driver for Epson L4F00242T03. This provides basic support |
39 | for init and powering the LCD up/down through a sysfs interface. | 42 | for init and powering the LCD up/down through a sysfs interface. |
40 | 43 | ||
41 | config LCD_LMS283GF05 | 44 | config LCD_LMS283GF05 |
42 | tristate "Samsung LMS283GF05 LCD" | 45 | tristate "Samsung LMS283GF05 LCD" |
43 | depends on LCD_CLASS_DEVICE && SPI_MASTER && GENERIC_GPIO | 46 | depends on SPI_MASTER && GENERIC_GPIO |
44 | help | 47 | help |
45 | SPI driver for Samsung LMS283GF05. This provides basic support | 48 | SPI driver for Samsung LMS283GF05. This provides basic support |
46 | for powering the LCD up/down through a sysfs interface. | 49 | for powering the LCD up/down through a sysfs interface. |
47 | 50 | ||
48 | config LCD_LTV350QV | 51 | config LCD_LTV350QV |
49 | tristate "Samsung LTV350QV LCD Panel" | 52 | tristate "Samsung LTV350QV LCD Panel" |
50 | depends on LCD_CLASS_DEVICE && SPI_MASTER | 53 | depends on SPI_MASTER |
51 | default n | ||
52 | help | 54 | help |
53 | If you have a Samsung LTV350QV LCD panel, say y to include a | 55 | If you have a Samsung LTV350QV LCD panel, say y to include a |
54 | power control driver for it. The panel starts up in power | 56 | power control driver for it. The panel starts up in power |
@@ -59,60 +61,61 @@ config LCD_LTV350QV | |||
59 | 61 | ||
60 | config LCD_ILI9320 | 62 | config LCD_ILI9320 |
61 | tristate | 63 | tristate |
62 | depends on LCD_CLASS_DEVICE && BACKLIGHT_LCD_SUPPORT | ||
63 | default n | ||
64 | help | 64 | help |
65 | If you have a panel based on the ILI9320 controller chip | 65 | If you have a panel based on the ILI9320 controller chip |
66 | then say y to include a power driver for it. | 66 | then say y to include a power driver for it. |
67 | 67 | ||
68 | config LCD_TDO24M | 68 | config LCD_TDO24M |
69 | tristate "Toppoly TDO24M and TDO35S LCD Panels support" | 69 | tristate "Toppoly TDO24M and TDO35S LCD Panels support" |
70 | depends on LCD_CLASS_DEVICE && SPI_MASTER | 70 | depends on SPI_MASTER |
71 | default n | ||
72 | help | 71 | help |
73 | If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to | 72 | If you have a Toppoly TDO24M/TDO35S series LCD panel, say y here to |
74 | include the support for it. | 73 | include the support for it. |
75 | 74 | ||
76 | config LCD_VGG2432A4 | 75 | config LCD_VGG2432A4 |
77 | tristate "VGG2432A4 LCM device support" | 76 | tristate "VGG2432A4 LCM device support" |
78 | depends on BACKLIGHT_LCD_SUPPORT && LCD_CLASS_DEVICE && SPI_MASTER | 77 | depends on SPI_MASTER |
79 | select LCD_ILI9320 | 78 | select LCD_ILI9320 |
80 | default n | ||
81 | help | 79 | help |
82 | If you have a VGG2432A4 panel based on the ILI9320 controller chip | 80 | If you have a VGG2432A4 panel based on the ILI9320 controller chip |
83 | then say y to include a power driver for it. | 81 | then say y to include a power driver for it. |
84 | 82 | ||
85 | config LCD_PLATFORM | 83 | config LCD_PLATFORM |
86 | tristate "Platform LCD controls" | 84 | tristate "Platform LCD controls" |
87 | depends on LCD_CLASS_DEVICE | ||
88 | help | 85 | help |
89 | This driver provides a platform-device registered LCD power | 86 | This driver provides a platform-device registered LCD power |
90 | control interface. | 87 | control interface. |
91 | 88 | ||
92 | config LCD_TOSA | 89 | config LCD_TOSA |
93 | tristate "Sharp SL-6000 LCD Driver" | 90 | tristate "Sharp SL-6000 LCD Driver" |
94 | depends on LCD_CLASS_DEVICE && SPI | 91 | depends on SPI && MACH_TOSA |
95 | depends on MACH_TOSA | ||
96 | default n | ||
97 | help | 92 | help |
98 | If you have an Sharp SL-6000 Zaurus say Y to enable a driver | 93 | If you have an Sharp SL-6000 Zaurus say Y to enable a driver |
99 | for its LCD. | 94 | for its LCD. |
100 | 95 | ||
101 | config LCD_HP700 | 96 | config LCD_HP700 |
102 | tristate "HP Jornada 700 series LCD Driver" | 97 | tristate "HP Jornada 700 series LCD Driver" |
103 | depends on LCD_CLASS_DEVICE | ||
104 | depends on SA1100_JORNADA720_SSP && !PREEMPT | 98 | depends on SA1100_JORNADA720_SSP && !PREEMPT |
105 | default y | 99 | default y |
106 | help | 100 | help |
107 | If you have an HP Jornada 700 series handheld (710/720/728) | 101 | If you have an HP Jornada 700 series handheld (710/720/728) |
108 | say Y to enable LCD control driver. | 102 | say Y to enable LCD control driver. |
109 | 103 | ||
104 | config LCD_S6E63M0 | ||
105 | tristate "S6E63M0 AMOLED LCD Driver" | ||
106 | depends on SPI && BACKLIGHT_CLASS_DEVICE | ||
107 | default n | ||
108 | help | ||
109 | If you have an S6E63M0 LCD Panel, say Y to enable its | ||
110 | LCD control driver. | ||
111 | |||
112 | endif # LCD_CLASS_DEVICE | ||
113 | |||
110 | # | 114 | # |
111 | # Backlight | 115 | # Backlight |
112 | # | 116 | # |
113 | config BACKLIGHT_CLASS_DEVICE | 117 | config BACKLIGHT_CLASS_DEVICE |
114 | tristate "Lowlevel Backlight controls" | 118 | tristate "Lowlevel Backlight controls" |
115 | depends on BACKLIGHT_LCD_SUPPORT | ||
116 | default m | 119 | default m |
117 | help | 120 | help |
118 | This framework adds support for low-level control of the LCD | 121 | This framework adds support for low-level control of the LCD |
@@ -121,9 +124,11 @@ config BACKLIGHT_CLASS_DEVICE | |||
121 | To have support for your specific LCD panel you will have to | 124 | To have support for your specific LCD panel you will have to |
122 | select the proper drivers which depend on this option. | 125 | select the proper drivers which depend on this option. |
123 | 126 | ||
127 | if BACKLIGHT_CLASS_DEVICE | ||
128 | |||
124 | config BACKLIGHT_ATMEL_LCDC | 129 | config BACKLIGHT_ATMEL_LCDC |
125 | bool "Atmel LCDC Contrast-as-Backlight control" | 130 | bool "Atmel LCDC Contrast-as-Backlight control" |
126 | depends on BACKLIGHT_CLASS_DEVICE && FB_ATMEL | 131 | depends on FB_ATMEL |
127 | default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK | 132 | default y if MACH_SAM9261EK || MACH_SAM9G10EK || MACH_SAM9263EK |
128 | help | 133 | help |
129 | This provides a backlight control internal to the Atmel LCDC | 134 | This provides a backlight control internal to the Atmel LCDC |
@@ -136,8 +141,7 @@ config BACKLIGHT_ATMEL_LCDC | |||
136 | 141 | ||
137 | config BACKLIGHT_ATMEL_PWM | 142 | config BACKLIGHT_ATMEL_PWM |
138 | tristate "Atmel PWM backlight control" | 143 | tristate "Atmel PWM backlight control" |
139 | depends on BACKLIGHT_CLASS_DEVICE && ATMEL_PWM | 144 | depends on ATMEL_PWM |
140 | default n | ||
141 | help | 145 | help |
142 | Say Y here if you want to use the PWM peripheral in Atmel AT91 and | 146 | Say Y here if you want to use the PWM peripheral in Atmel AT91 and |
143 | AVR32 devices. This driver will need additional platform data to know | 147 | AVR32 devices. This driver will need additional platform data to know |
@@ -146,9 +150,18 @@ config BACKLIGHT_ATMEL_PWM | |||
146 | To compile this driver as a module, choose M here: the module will be | 150 | To compile this driver as a module, choose M here: the module will be |
147 | called atmel-pwm-bl. | 151 | called atmel-pwm-bl. |
148 | 152 | ||
153 | config BACKLIGHT_EP93XX | ||
154 | tristate "Cirrus EP93xx Backlight Driver" | ||
155 | depends on FB_EP93XX | ||
156 | help | ||
157 | If you have a LCD backlight connected to the BRIGHT output of | ||
158 | the EP93xx, say Y here to enable this driver. | ||
159 | |||
160 | To compile this driver as a module, choose M here: the module will | ||
161 | be called ep93xx_bl. | ||
162 | |||
149 | config BACKLIGHT_GENERIC | 163 | config BACKLIGHT_GENERIC |
150 | tristate "Generic (aka Sharp Corgi) Backlight Driver" | 164 | tristate "Generic (aka Sharp Corgi) Backlight Driver" |
151 | depends on BACKLIGHT_CLASS_DEVICE | ||
152 | default y | 165 | default y |
153 | help | 166 | help |
154 | Say y to enable the generic platform backlight driver previously | 167 | Say y to enable the generic platform backlight driver previously |
@@ -157,7 +170,7 @@ config BACKLIGHT_GENERIC | |||
157 | 170 | ||
158 | config BACKLIGHT_LOCOMO | 171 | config BACKLIGHT_LOCOMO |
159 | tristate "Sharp LOCOMO LCD/Backlight Driver" | 172 | tristate "Sharp LOCOMO LCD/Backlight Driver" |
160 | depends on BACKLIGHT_CLASS_DEVICE && SHARP_LOCOMO | 173 | depends on SHARP_LOCOMO |
161 | default y | 174 | default y |
162 | help | 175 | help |
163 | If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to | 176 | If you have a Sharp Zaurus SL-5500 (Collie) or SL-5600 (Poodle) say y to |
@@ -165,7 +178,7 @@ config BACKLIGHT_LOCOMO | |||
165 | 178 | ||
166 | config BACKLIGHT_OMAP1 | 179 | config BACKLIGHT_OMAP1 |
167 | tristate "OMAP1 PWL-based LCD Backlight" | 180 | tristate "OMAP1 PWL-based LCD Backlight" |
168 | depends on BACKLIGHT_CLASS_DEVICE && ARCH_OMAP1 | 181 | depends on ARCH_OMAP1 |
169 | default y | 182 | default y |
170 | help | 183 | help |
171 | This driver controls the LCD backlight level and power for | 184 | This driver controls the LCD backlight level and power for |
@@ -174,7 +187,7 @@ config BACKLIGHT_OMAP1 | |||
174 | 187 | ||
175 | config BACKLIGHT_HP680 | 188 | config BACKLIGHT_HP680 |
176 | tristate "HP Jornada 680 Backlight Driver" | 189 | tristate "HP Jornada 680 Backlight Driver" |
177 | depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX | 190 | depends on SH_HP6XX |
178 | default y | 191 | default y |
179 | help | 192 | help |
180 | If you have a HP Jornada 680, say y to enable the | 193 | If you have a HP Jornada 680, say y to enable the |
@@ -182,7 +195,6 @@ config BACKLIGHT_HP680 | |||
182 | 195 | ||
183 | config BACKLIGHT_HP700 | 196 | config BACKLIGHT_HP700 |
184 | tristate "HP Jornada 700 series Backlight Driver" | 197 | tristate "HP Jornada 700 series Backlight Driver" |
185 | depends on BACKLIGHT_CLASS_DEVICE | ||
186 | depends on SA1100_JORNADA720_SSP && !PREEMPT | 198 | depends on SA1100_JORNADA720_SSP && !PREEMPT |
187 | default y | 199 | default y |
188 | help | 200 | help |
@@ -191,76 +203,70 @@ config BACKLIGHT_HP700 | |||
191 | 203 | ||
192 | config BACKLIGHT_PROGEAR | 204 | config BACKLIGHT_PROGEAR |
193 | tristate "Frontpath ProGear Backlight Driver" | 205 | tristate "Frontpath ProGear Backlight Driver" |
194 | depends on BACKLIGHT_CLASS_DEVICE && PCI && X86 | 206 | depends on PCI && X86 |
195 | default n | ||
196 | help | 207 | help |
197 | If you have a Frontpath ProGear say Y to enable the | 208 | If you have a Frontpath ProGear say Y to enable the |
198 | backlight driver. | 209 | backlight driver. |
199 | 210 | ||
200 | config BACKLIGHT_CARILLO_RANCH | 211 | config BACKLIGHT_CARILLO_RANCH |
201 | tristate "Intel Carillo Ranch Backlight Driver" | 212 | tristate "Intel Carillo Ranch Backlight Driver" |
202 | depends on BACKLIGHT_CLASS_DEVICE && LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 | 213 | depends on LCD_CLASS_DEVICE && PCI && X86 && FB_LE80578 |
203 | default n | ||
204 | help | 214 | help |
205 | If you have a Intel LE80578 (Carillo Ranch) say Y to enable the | 215 | If you have a Intel LE80578 (Carillo Ranch) say Y to enable the |
206 | backlight driver. | 216 | backlight driver. |
207 | 217 | ||
208 | config BACKLIGHT_PWM | 218 | config BACKLIGHT_PWM |
209 | tristate "Generic PWM based Backlight Driver" | 219 | tristate "Generic PWM based Backlight Driver" |
210 | depends on BACKLIGHT_CLASS_DEVICE && HAVE_PWM | 220 | depends on HAVE_PWM |
211 | help | 221 | help |
212 | If you have a LCD backlight adjustable by PWM, say Y to enable | 222 | If you have a LCD backlight adjustable by PWM, say Y to enable |
213 | this driver. | 223 | this driver. |
214 | 224 | ||
215 | config BACKLIGHT_DA903X | 225 | config BACKLIGHT_DA903X |
216 | tristate "Backlight Driver for DA9030/DA9034 using WLED" | 226 | tristate "Backlight Driver for DA9030/DA9034 using WLED" |
217 | depends on BACKLIGHT_CLASS_DEVICE && PMIC_DA903X | 227 | depends on PMIC_DA903X |
218 | help | 228 | help |
219 | If you have a LCD backlight connected to the WLED output of DA9030 | 229 | If you have a LCD backlight connected to the WLED output of DA9030 |
220 | or DA9034 WLED output, say Y here to enable this driver. | 230 | or DA9034 WLED output, say Y here to enable this driver. |
221 | 231 | ||
222 | config BACKLIGHT_MAX8925 | 232 | config BACKLIGHT_MAX8925 |
223 | tristate "Backlight driver for MAX8925" | 233 | tristate "Backlight driver for MAX8925" |
224 | depends on BACKLIGHT_CLASS_DEVICE && MFD_MAX8925 | 234 | depends on MFD_MAX8925 |
225 | help | 235 | help |
226 | If you have a LCD backlight connected to the WLED output of MAX8925 | 236 | If you have a LCD backlight connected to the WLED output of MAX8925 |
227 | WLED output, say Y here to enable this driver. | 237 | WLED output, say Y here to enable this driver. |
228 | 238 | ||
229 | config BACKLIGHT_MBP_NVIDIA | 239 | config BACKLIGHT_MBP_NVIDIA |
230 | tristate "MacBook Pro Nvidia Backlight Driver" | 240 | tristate "MacBook Pro Nvidia Backlight Driver" |
231 | depends on BACKLIGHT_CLASS_DEVICE && X86 | 241 | depends on X86 |
232 | default n | ||
233 | help | 242 | help |
234 | If you have an Apple Macbook Pro with Nvidia graphics hardware say Y | 243 | If you have an Apple Macbook Pro with Nvidia graphics hardware say Y |
235 | to enable a driver for its backlight | 244 | to enable a driver for its backlight |
236 | 245 | ||
237 | config BACKLIGHT_TOSA | 246 | config BACKLIGHT_TOSA |
238 | tristate "Sharp SL-6000 Backlight Driver" | 247 | tristate "Sharp SL-6000 Backlight Driver" |
239 | depends on BACKLIGHT_CLASS_DEVICE && I2C | 248 | depends on I2C && MACH_TOSA && LCD_TOSA |
240 | depends on MACH_TOSA && LCD_TOSA | ||
241 | default n | ||
242 | help | 249 | help |
243 | If you have an Sharp SL-6000 Zaurus say Y to enable a driver | 250 | If you have an Sharp SL-6000 Zaurus say Y to enable a driver |
244 | for its backlight | 251 | for its backlight |
245 | 252 | ||
246 | config BACKLIGHT_SAHARA | 253 | config BACKLIGHT_SAHARA |
247 | tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" | 254 | tristate "Tabletkiosk Sahara Touch-iT Backlight Driver" |
248 | depends on BACKLIGHT_CLASS_DEVICE && X86 | 255 | depends on X86 |
249 | default n | ||
250 | help | 256 | help |
251 | If you have a Tabletkiosk Sahara Touch-iT, say y to enable the | 257 | If you have a Tabletkiosk Sahara Touch-iT, say y to enable the |
252 | backlight driver. | 258 | backlight driver. |
253 | 259 | ||
254 | config BACKLIGHT_WM831X | 260 | config BACKLIGHT_WM831X |
255 | tristate "WM831x PMIC Backlight Driver" | 261 | tristate "WM831x PMIC Backlight Driver" |
256 | depends on BACKLIGHT_CLASS_DEVICE && MFD_WM831X | 262 | depends on MFD_WM831X |
257 | help | 263 | help |
258 | If you have a backlight driven by the ISINK and DCDC of a | 264 | If you have a backlight driven by the ISINK and DCDC of a |
259 | WM831x PMIC say y to enable the backlight driver for it. | 265 | WM831x PMIC say y to enable the backlight driver for it. |
260 | 266 | ||
261 | config BACKLIGHT_ADX | 267 | config BACKLIGHT_ADX |
262 | tristate "Avionic Design Xanthos Backlight Driver" | 268 | tristate "Avionic Design Xanthos Backlight Driver" |
263 | depends on BACKLIGHT_CLASS_DEVICE && ARCH_PXA_ADX | 269 | depends on ARCH_PXA_ADX |
264 | default y | 270 | default y |
265 | help | 271 | help |
266 | Say Y to enable the backlight driver on Avionic Design Xanthos-based | 272 | Say Y to enable the backlight driver on Avionic Design Xanthos-based |
@@ -268,7 +274,7 @@ config BACKLIGHT_ADX | |||
268 | 274 | ||
269 | config BACKLIGHT_ADP5520 | 275 | config BACKLIGHT_ADP5520 |
270 | tristate "Backlight Driver for ADP5520/ADP5501 using WLED" | 276 | tristate "Backlight Driver for ADP5520/ADP5501 using WLED" |
271 | depends on BACKLIGHT_CLASS_DEVICE && PMIC_ADP5520 | 277 | depends on PMIC_ADP5520 |
272 | help | 278 | help |
273 | If you have a LCD backlight connected to the BST/BL_SNK output of | 279 | If you have a LCD backlight connected to the BST/BL_SNK output of |
274 | ADP5520 or ADP5501, say Y here to enable this driver. | 280 | ADP5520 or ADP5501, say Y here to enable this driver. |
@@ -276,9 +282,31 @@ config BACKLIGHT_ADP5520 | |||
276 | To compile this driver as a module, choose M here: the module will | 282 | To compile this driver as a module, choose M here: the module will |
277 | be called adp5520_bl. | 283 | be called adp5520_bl. |
278 | 284 | ||
285 | config BACKLIGHT_ADP8860 | ||
286 | tristate "Backlight Driver for ADP8860/ADP8861/ADP8863 using WLED" | ||
287 | depends on BACKLIGHT_CLASS_DEVICE && I2C | ||
288 | select NEW_LEDS | ||
289 | select LEDS_CLASS | ||
290 | help | ||
291 | If you have a LCD backlight connected to the ADP8860, ADP8861 or | ||
292 | ADP8863 say Y here to enable this driver. | ||
293 | |||
294 | To compile this driver as a module, choose M here: the module will | ||
295 | be called adp8860_bl. | ||
296 | |||
279 | config BACKLIGHT_88PM860X | 297 | config BACKLIGHT_88PM860X |
280 | tristate "Backlight Driver for 88PM8606 using WLED" | 298 | tristate "Backlight Driver for 88PM8606 using WLED" |
281 | depends on BACKLIGHT_CLASS_DEVICE && MFD_88PM860X | 299 | depends on MFD_88PM860X |
282 | help | 300 | help |
283 | Say Y to enable the backlight driver for Marvell 88PM8606. | 301 | Say Y to enable the backlight driver for Marvell 88PM8606. |
284 | 302 | ||
303 | config BACKLIGHT_PCF50633 | ||
304 | tristate "Backlight driver for NXP PCF50633 MFD" | ||
305 | depends on BACKLIGHT_CLASS_DEVICE && MFD_PCF50633 | ||
306 | help | ||
307 | If you have a backlight driven by a NXP PCF50633 MFD, say Y here to | ||
308 | enable its driver. | ||
309 | |||
310 | endif # BACKLIGHT_CLASS_DEVICE | ||
311 | |||
312 | endif # BACKLIGHT_LCD_SUPPORT | ||
diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile index 09d1f14d6257..44c0f81ad85d 100644 --- a/drivers/video/backlight/Makefile +++ b/drivers/video/backlight/Makefile | |||
@@ -11,9 +11,11 @@ obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o | |||
11 | obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o | 11 | obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o |
12 | obj-$(CONFIG_LCD_TDO24M) += tdo24m.o | 12 | obj-$(CONFIG_LCD_TDO24M) += tdo24m.o |
13 | obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o | 13 | obj-$(CONFIG_LCD_TOSA) += tosa_lcd.o |
14 | obj-$(CONFIG_LCD_S6E63M0) += s6e63m0.o | ||
14 | 15 | ||
15 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o | 16 | obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o |
16 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o | 17 | obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o |
18 | obj-$(CONFIG_BACKLIGHT_EP93XX) += ep93xx_bl.o | ||
17 | obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o | 19 | obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o |
18 | obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o | 20 | obj-$(CONFIG_BACKLIGHT_HP700) += jornada720_bl.o |
19 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o | 21 | obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o |
@@ -30,5 +32,7 @@ obj-$(CONFIG_BACKLIGHT_SAHARA) += kb3886_bl.o | |||
30 | obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o | 32 | obj-$(CONFIG_BACKLIGHT_WM831X) += wm831x_bl.o |
31 | obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o | 33 | obj-$(CONFIG_BACKLIGHT_ADX) += adx_bl.o |
32 | obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o | 34 | obj-$(CONFIG_BACKLIGHT_ADP5520) += adp5520_bl.o |
35 | obj-$(CONFIG_BACKLIGHT_ADP8860) += adp8860_bl.o | ||
33 | obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o | 36 | obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o |
37 | obj-$(CONFIG_BACKLIGHT_PCF50633) += pcf50633-backlight.o | ||
34 | 38 | ||
diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c new file mode 100644 index 000000000000..921ca37398f3 --- /dev/null +++ b/drivers/video/backlight/adp8860_bl.c | |||
@@ -0,0 +1,838 @@ | |||
1 | /* | ||
2 | * Backlight driver for Analog Devices ADP8860 Backlight Devices | ||
3 | * | ||
4 | * Copyright 2009-2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/version.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include <linux/platform_device.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/fb.h> | ||
17 | #include <linux/backlight.h> | ||
18 | #include <linux/leds.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/workqueue.h> | ||
21 | |||
22 | #include <linux/i2c/adp8860.h> | ||
23 | #define ADP8860_EXT_FEATURES | ||
24 | #define ADP8860_USE_LEDS | ||
25 | |||
26 | #define ADP8860_MFDVID 0x00 /* Manufacturer and device ID */ | ||
27 | #define ADP8860_MDCR 0x01 /* Device mode and status */ | ||
28 | #define ADP8860_MDCR2 0x02 /* Device mode and Status Register 2 */ | ||
29 | #define ADP8860_INTR_EN 0x03 /* Interrupts enable */ | ||
30 | #define ADP8860_CFGR 0x04 /* Configuration register */ | ||
31 | #define ADP8860_BLSEN 0x05 /* Sink enable backlight or independent */ | ||
32 | #define ADP8860_BLOFF 0x06 /* Backlight off timeout */ | ||
33 | #define ADP8860_BLDIM 0x07 /* Backlight dim timeout */ | ||
34 | #define ADP8860_BLFR 0x08 /* Backlight fade in and out rates */ | ||
35 | #define ADP8860_BLMX1 0x09 /* Backlight (Brightness Level 1-daylight) maximum current */ | ||
36 | #define ADP8860_BLDM1 0x0A /* Backlight (Brightness Level 1-daylight) dim current */ | ||
37 | #define ADP8860_BLMX2 0x0B /* Backlight (Brightness Level 2-office) maximum current */ | ||
38 | #define ADP8860_BLDM2 0x0C /* Backlight (Brightness Level 2-office) dim current */ | ||
39 | #define ADP8860_BLMX3 0x0D /* Backlight (Brightness Level 3-dark) maximum current */ | ||
40 | #define ADP8860_BLDM3 0x0E /* Backlight (Brightness Level 3-dark) dim current */ | ||
41 | #define ADP8860_ISCFR 0x0F /* Independent sink current fade control register */ | ||
42 | #define ADP8860_ISCC 0x10 /* Independent sink current control register */ | ||
43 | #define ADP8860_ISCT1 0x11 /* Independent Sink Current Timer Register LED[7:5] */ | ||
44 | #define ADP8860_ISCT2 0x12 /* Independent Sink Current Timer Register LED[4:1] */ | ||
45 | #define ADP8860_ISCF 0x13 /* Independent sink current fade register */ | ||
46 | #define ADP8860_ISC7 0x14 /* Independent Sink Current LED7 */ | ||
47 | #define ADP8860_ISC6 0x15 /* Independent Sink Current LED6 */ | ||
48 | #define ADP8860_ISC5 0x16 /* Independent Sink Current LED5 */ | ||
49 | #define ADP8860_ISC4 0x17 /* Independent Sink Current LED4 */ | ||
50 | #define ADP8860_ISC3 0x18 /* Independent Sink Current LED3 */ | ||
51 | #define ADP8860_ISC2 0x19 /* Independent Sink Current LED2 */ | ||
52 | #define ADP8860_ISC1 0x1A /* Independent Sink Current LED1 */ | ||
53 | #define ADP8860_CCFG 0x1B /* Comparator configuration */ | ||
54 | #define ADP8860_CCFG2 0x1C /* Second comparator configuration */ | ||
55 | #define ADP8860_L2_TRP 0x1D /* L2 comparator reference */ | ||
56 | #define ADP8860_L2_HYS 0x1E /* L2 hysteresis */ | ||
57 | #define ADP8860_L3_TRP 0x1F /* L3 comparator reference */ | ||
58 | #define ADP8860_L3_HYS 0x20 /* L3 hysteresis */ | ||
59 | #define ADP8860_PH1LEVL 0x21 /* First phototransistor ambient light level-low byte register */ | ||
60 | #define ADP8860_PH1LEVH 0x22 /* First phototransistor ambient light level-high byte register */ | ||
61 | #define ADP8860_PH2LEVL 0x23 /* Second phototransistor ambient light level-low byte register */ | ||
62 | #define ADP8860_PH2LEVH 0x24 /* Second phototransistor ambient light level-high byte register */ | ||
63 | |||
64 | #define ADP8860_MANUFID 0x0 /* Analog Devices ADP8860 Manufacturer ID */ | ||
65 | #define ADP8861_MANUFID 0x4 /* Analog Devices ADP8861 Manufacturer ID */ | ||
66 | #define ADP8863_MANUFID 0x2 /* Analog Devices ADP8863 Manufacturer ID */ | ||
67 | |||
68 | #define ADP8860_DEVID(x) ((x) & 0xF) | ||
69 | #define ADP8860_MANID(x) ((x) >> 4) | ||
70 | |||
71 | /* MDCR Device mode and status */ | ||
72 | #define INT_CFG (1 << 6) | ||
73 | #define NSTBY (1 << 5) | ||
74 | #define DIM_EN (1 << 4) | ||
75 | #define GDWN_DIS (1 << 3) | ||
76 | #define SIS_EN (1 << 2) | ||
77 | #define CMP_AUTOEN (1 << 1) | ||
78 | #define BLEN (1 << 0) | ||
79 | |||
80 | /* ADP8860_CCFG Main ALS comparator level enable */ | ||
81 | #define L3_EN (1 << 1) | ||
82 | #define L2_EN (1 << 0) | ||
83 | |||
84 | #define CFGR_BLV_SHIFT 3 | ||
85 | #define CFGR_BLV_MASK 0x3 | ||
86 | #define ADP8860_FLAG_LED_MASK 0xFF | ||
87 | |||
88 | #define FADE_VAL(in, out) ((0xF & (in)) | ((0xF & (out)) << 4)) | ||
89 | #define BL_CFGR_VAL(law, blv) ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1)) | ||
90 | #define ALS_CCFG_VAL(filt) ((0x7 & filt) << 5) | ||
91 | |||
92 | enum { | ||
93 | adp8860, | ||
94 | adp8861, | ||
95 | adp8863 | ||
96 | }; | ||
97 | |||
98 | struct adp8860_led { | ||
99 | struct led_classdev cdev; | ||
100 | struct work_struct work; | ||
101 | struct i2c_client *client; | ||
102 | enum led_brightness new_brightness; | ||
103 | int id; | ||
104 | int flags; | ||
105 | }; | ||
106 | |||
107 | struct adp8860_bl { | ||
108 | struct i2c_client *client; | ||
109 | struct backlight_device *bl; | ||
110 | struct adp8860_led *led; | ||
111 | struct adp8860_backlight_platform_data *pdata; | ||
112 | struct mutex lock; | ||
113 | unsigned long cached_daylight_max; | ||
114 | int id; | ||
115 | int revid; | ||
116 | int current_brightness; | ||
117 | unsigned en_ambl_sens:1; | ||
118 | unsigned gdwn_dis:1; | ||
119 | }; | ||
120 | |||
121 | static int adp8860_read(struct i2c_client *client, int reg, uint8_t *val) | ||
122 | { | ||
123 | int ret; | ||
124 | |||
125 | ret = i2c_smbus_read_byte_data(client, reg); | ||
126 | if (ret < 0) { | ||
127 | dev_err(&client->dev, "failed reading at 0x%02x\n", reg); | ||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | *val = (uint8_t)ret; | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int adp8860_write(struct i2c_client *client, u8 reg, u8 val) | ||
136 | { | ||
137 | return i2c_smbus_write_byte_data(client, reg, val); | ||
138 | } | ||
139 | |||
140 | static int adp8860_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask) | ||
141 | { | ||
142 | struct adp8860_bl *data = i2c_get_clientdata(client); | ||
143 | uint8_t reg_val; | ||
144 | int ret; | ||
145 | |||
146 | mutex_lock(&data->lock); | ||
147 | |||
148 | ret = adp8860_read(client, reg, ®_val); | ||
149 | |||
150 | if (!ret && ((reg_val & bit_mask) == 0)) { | ||
151 | reg_val |= bit_mask; | ||
152 | ret = adp8860_write(client, reg, reg_val); | ||
153 | } | ||
154 | |||
155 | mutex_unlock(&data->lock); | ||
156 | return ret; | ||
157 | } | ||
158 | |||
159 | static int adp8860_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask) | ||
160 | { | ||
161 | struct adp8860_bl *data = i2c_get_clientdata(client); | ||
162 | uint8_t reg_val; | ||
163 | int ret; | ||
164 | |||
165 | mutex_lock(&data->lock); | ||
166 | |||
167 | ret = adp8860_read(client, reg, ®_val); | ||
168 | |||
169 | if (!ret && (reg_val & bit_mask)) { | ||
170 | reg_val &= ~bit_mask; | ||
171 | ret = adp8860_write(client, reg, reg_val); | ||
172 | } | ||
173 | |||
174 | mutex_unlock(&data->lock); | ||
175 | return ret; | ||
176 | } | ||
177 | |||
178 | /* | ||
179 | * Independent sink / LED | ||
180 | */ | ||
181 | #if defined(ADP8860_USE_LEDS) | ||
182 | static void adp8860_led_work(struct work_struct *work) | ||
183 | { | ||
184 | struct adp8860_led *led = container_of(work, struct adp8860_led, work); | ||
185 | adp8860_write(led->client, ADP8860_ISC1 - led->id + 1, | ||
186 | led->new_brightness >> 1); | ||
187 | } | ||
188 | |||
189 | static void adp8860_led_set(struct led_classdev *led_cdev, | ||
190 | enum led_brightness value) | ||
191 | { | ||
192 | struct adp8860_led *led; | ||
193 | |||
194 | led = container_of(led_cdev, struct adp8860_led, cdev); | ||
195 | led->new_brightness = value; | ||
196 | schedule_work(&led->work); | ||
197 | } | ||
198 | |||
199 | static int adp8860_led_setup(struct adp8860_led *led) | ||
200 | { | ||
201 | struct i2c_client *client = led->client; | ||
202 | int ret = 0; | ||
203 | |||
204 | ret = adp8860_write(client, ADP8860_ISC1 - led->id + 1, 0); | ||
205 | ret |= adp8860_set_bits(client, ADP8860_ISCC, 1 << (led->id - 1)); | ||
206 | |||
207 | if (led->id > 4) | ||
208 | ret |= adp8860_set_bits(client, ADP8860_ISCT1, | ||
209 | (led->flags & 0x3) << ((led->id - 5) * 2)); | ||
210 | else | ||
211 | ret |= adp8860_set_bits(client, ADP8860_ISCT2, | ||
212 | (led->flags & 0x3) << ((led->id - 1) * 2)); | ||
213 | |||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | static int __devinit adp8860_led_probe(struct i2c_client *client) | ||
218 | { | ||
219 | struct adp8860_backlight_platform_data *pdata = | ||
220 | client->dev.platform_data; | ||
221 | struct adp8860_bl *data = i2c_get_clientdata(client); | ||
222 | struct adp8860_led *led, *led_dat; | ||
223 | struct led_info *cur_led; | ||
224 | int ret, i; | ||
225 | |||
226 | led = kzalloc(sizeof(*led) * pdata->num_leds, GFP_KERNEL); | ||
227 | if (led == NULL) { | ||
228 | dev_err(&client->dev, "failed to alloc memory\n"); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | |||
232 | ret = adp8860_write(client, ADP8860_ISCFR, pdata->led_fade_law); | ||
233 | ret = adp8860_write(client, ADP8860_ISCT1, | ||
234 | (pdata->led_on_time & 0x3) << 6); | ||
235 | ret |= adp8860_write(client, ADP8860_ISCF, | ||
236 | FADE_VAL(pdata->led_fade_in, pdata->led_fade_out)); | ||
237 | |||
238 | if (ret) { | ||
239 | dev_err(&client->dev, "failed to write\n"); | ||
240 | goto err_free; | ||
241 | } | ||
242 | |||
243 | for (i = 0; i < pdata->num_leds; ++i) { | ||
244 | cur_led = &pdata->leds[i]; | ||
245 | led_dat = &led[i]; | ||
246 | |||
247 | led_dat->id = cur_led->flags & ADP8860_FLAG_LED_MASK; | ||
248 | |||
249 | if (led_dat->id > 7 || led_dat->id < 1) { | ||
250 | dev_err(&client->dev, "Invalid LED ID %d\n", | ||
251 | led_dat->id); | ||
252 | goto err; | ||
253 | } | ||
254 | |||
255 | if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) { | ||
256 | dev_err(&client->dev, "LED %d used by Backlight\n", | ||
257 | led_dat->id); | ||
258 | goto err; | ||
259 | } | ||
260 | |||
261 | led_dat->cdev.name = cur_led->name; | ||
262 | led_dat->cdev.default_trigger = cur_led->default_trigger; | ||
263 | led_dat->cdev.brightness_set = adp8860_led_set; | ||
264 | led_dat->cdev.brightness = LED_OFF; | ||
265 | led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT; | ||
266 | led_dat->client = client; | ||
267 | led_dat->new_brightness = LED_OFF; | ||
268 | INIT_WORK(&led_dat->work, adp8860_led_work); | ||
269 | |||
270 | ret = led_classdev_register(&client->dev, &led_dat->cdev); | ||
271 | if (ret) { | ||
272 | dev_err(&client->dev, "failed to register LED %d\n", | ||
273 | led_dat->id); | ||
274 | goto err; | ||
275 | } | ||
276 | |||
277 | ret = adp8860_led_setup(led_dat); | ||
278 | if (ret) { | ||
279 | dev_err(&client->dev, "failed to write\n"); | ||
280 | i++; | ||
281 | goto err; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | data->led = led; | ||
286 | |||
287 | return 0; | ||
288 | |||
289 | err: | ||
290 | for (i = i - 1; i >= 0; --i) { | ||
291 | led_classdev_unregister(&led[i].cdev); | ||
292 | cancel_work_sync(&led[i].work); | ||
293 | } | ||
294 | |||
295 | err_free: | ||
296 | kfree(led); | ||
297 | |||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | static int __devexit adp8860_led_remove(struct i2c_client *client) | ||
302 | { | ||
303 | struct adp8860_backlight_platform_data *pdata = | ||
304 | client->dev.platform_data; | ||
305 | struct adp8860_bl *data = i2c_get_clientdata(client); | ||
306 | int i; | ||
307 | |||
308 | for (i = 0; i < pdata->num_leds; i++) { | ||
309 | led_classdev_unregister(&data->led[i].cdev); | ||
310 | cancel_work_sync(&data->led[i].work); | ||
311 | } | ||
312 | |||
313 | kfree(data->led); | ||
314 | return 0; | ||
315 | } | ||
316 | #else | ||
317 | static int __devinit adp8860_led_probe(struct i2c_client *client) | ||
318 | { | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static int __devexit adp8860_led_remove(struct i2c_client *client) | ||
323 | { | ||
324 | return 0; | ||
325 | } | ||
326 | #endif | ||
327 | |||
328 | static int adp8860_bl_set(struct backlight_device *bl, int brightness) | ||
329 | { | ||
330 | struct adp8860_bl *data = bl_get_data(bl); | ||
331 | struct i2c_client *client = data->client; | ||
332 | int ret = 0; | ||
333 | |||
334 | if (data->en_ambl_sens) { | ||
335 | if ((brightness > 0) && (brightness < ADP8860_MAX_BRIGHTNESS)) { | ||
336 | /* Disable Ambient Light auto adjust */ | ||
337 | ret |= adp8860_clr_bits(client, ADP8860_MDCR, | ||
338 | CMP_AUTOEN); | ||
339 | ret |= adp8860_write(client, ADP8860_BLMX1, brightness); | ||
340 | } else { | ||
341 | /* | ||
342 | * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust | ||
343 | * restore daylight l1 sysfs brightness | ||
344 | */ | ||
345 | ret |= adp8860_write(client, ADP8860_BLMX1, | ||
346 | data->cached_daylight_max); | ||
347 | ret |= adp8860_set_bits(client, ADP8860_MDCR, | ||
348 | CMP_AUTOEN); | ||
349 | } | ||
350 | } else | ||
351 | ret |= adp8860_write(client, ADP8860_BLMX1, brightness); | ||
352 | |||
353 | if (data->current_brightness && brightness == 0) | ||
354 | ret |= adp8860_set_bits(client, | ||
355 | ADP8860_MDCR, DIM_EN); | ||
356 | else if (data->current_brightness == 0 && brightness) | ||
357 | ret |= adp8860_clr_bits(client, | ||
358 | ADP8860_MDCR, DIM_EN); | ||
359 | |||
360 | if (!ret) | ||
361 | data->current_brightness = brightness; | ||
362 | |||
363 | return ret; | ||
364 | } | ||
365 | |||
366 | static int adp8860_bl_update_status(struct backlight_device *bl) | ||
367 | { | ||
368 | int brightness = bl->props.brightness; | ||
369 | if (bl->props.power != FB_BLANK_UNBLANK) | ||
370 | brightness = 0; | ||
371 | |||
372 | if (bl->props.fb_blank != FB_BLANK_UNBLANK) | ||
373 | brightness = 0; | ||
374 | |||
375 | return adp8860_bl_set(bl, brightness); | ||
376 | } | ||
377 | |||
378 | static int adp8860_bl_get_brightness(struct backlight_device *bl) | ||
379 | { | ||
380 | struct adp8860_bl *data = bl_get_data(bl); | ||
381 | |||
382 | return data->current_brightness; | ||
383 | } | ||
384 | |||
385 | static const struct backlight_ops adp8860_bl_ops = { | ||
386 | .update_status = adp8860_bl_update_status, | ||
387 | .get_brightness = adp8860_bl_get_brightness, | ||
388 | }; | ||
389 | |||
390 | static int adp8860_bl_setup(struct backlight_device *bl) | ||
391 | { | ||
392 | struct adp8860_bl *data = bl_get_data(bl); | ||
393 | struct i2c_client *client = data->client; | ||
394 | struct adp8860_backlight_platform_data *pdata = data->pdata; | ||
395 | int ret = 0; | ||
396 | |||
397 | ret |= adp8860_write(client, ADP8860_BLSEN, ~pdata->bl_led_assign); | ||
398 | ret |= adp8860_write(client, ADP8860_BLMX1, pdata->l1_daylight_max); | ||
399 | ret |= adp8860_write(client, ADP8860_BLDM1, pdata->l1_daylight_dim); | ||
400 | |||
401 | if (data->en_ambl_sens) { | ||
402 | data->cached_daylight_max = pdata->l1_daylight_max; | ||
403 | ret |= adp8860_write(client, ADP8860_BLMX2, | ||
404 | pdata->l2_office_max); | ||
405 | ret |= adp8860_write(client, ADP8860_BLDM2, | ||
406 | pdata->l2_office_dim); | ||
407 | ret |= adp8860_write(client, ADP8860_BLMX3, | ||
408 | pdata->l3_dark_max); | ||
409 | ret |= adp8860_write(client, ADP8860_BLDM3, | ||
410 | pdata->l3_dark_dim); | ||
411 | |||
412 | ret |= adp8860_write(client, ADP8860_L2_TRP, pdata->l2_trip); | ||
413 | ret |= adp8860_write(client, ADP8860_L2_HYS, pdata->l2_hyst); | ||
414 | ret |= adp8860_write(client, ADP8860_L3_TRP, pdata->l3_trip); | ||
415 | ret |= adp8860_write(client, ADP8860_L3_HYS, pdata->l3_hyst); | ||
416 | ret |= adp8860_write(client, ADP8860_CCFG, L2_EN | L3_EN | | ||
417 | ALS_CCFG_VAL(pdata->abml_filt)); | ||
418 | } | ||
419 | |||
420 | ret |= adp8860_write(client, ADP8860_CFGR, | ||
421 | BL_CFGR_VAL(pdata->bl_fade_law, 0)); | ||
422 | |||
423 | ret |= adp8860_write(client, ADP8860_BLFR, FADE_VAL(pdata->bl_fade_in, | ||
424 | pdata->bl_fade_out)); | ||
425 | |||
426 | ret |= adp8860_set_bits(client, ADP8860_MDCR, BLEN | DIM_EN | NSTBY | | ||
427 | (data->gdwn_dis ? GDWN_DIS : 0)); | ||
428 | |||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | static ssize_t adp8860_show(struct device *dev, char *buf, int reg) | ||
433 | { | ||
434 | struct adp8860_bl *data = dev_get_drvdata(dev); | ||
435 | int error; | ||
436 | uint8_t reg_val; | ||
437 | |||
438 | mutex_lock(&data->lock); | ||
439 | error = adp8860_read(data->client, reg, ®_val); | ||
440 | mutex_unlock(&data->lock); | ||
441 | |||
442 | if (error < 0) | ||
443 | return error; | ||
444 | |||
445 | return sprintf(buf, "%u\n", reg_val); | ||
446 | } | ||
447 | |||
448 | static ssize_t adp8860_store(struct device *dev, const char *buf, | ||
449 | size_t count, int reg) | ||
450 | { | ||
451 | struct adp8860_bl *data = dev_get_drvdata(dev); | ||
452 | unsigned long val; | ||
453 | int ret; | ||
454 | |||
455 | ret = strict_strtoul(buf, 10, &val); | ||
456 | if (ret) | ||
457 | return ret; | ||
458 | |||
459 | mutex_lock(&data->lock); | ||
460 | adp8860_write(data->client, reg, val); | ||
461 | mutex_unlock(&data->lock); | ||
462 | |||
463 | return count; | ||
464 | } | ||
465 | |||
466 | static ssize_t adp8860_bl_l3_dark_max_show(struct device *dev, | ||
467 | struct device_attribute *attr, char *buf) | ||
468 | { | ||
469 | return adp8860_show(dev, buf, ADP8860_BLMX3); | ||
470 | } | ||
471 | |||
472 | static ssize_t adp8860_bl_l3_dark_max_store(struct device *dev, | ||
473 | struct device_attribute *attr, const char *buf, size_t count) | ||
474 | { | ||
475 | return adp8860_store(dev, buf, count, ADP8860_BLMX3); | ||
476 | } | ||
477 | |||
478 | static DEVICE_ATTR(l3_dark_max, 0664, adp8860_bl_l3_dark_max_show, | ||
479 | adp8860_bl_l3_dark_max_store); | ||
480 | |||
481 | static ssize_t adp8860_bl_l2_office_max_show(struct device *dev, | ||
482 | struct device_attribute *attr, char *buf) | ||
483 | { | ||
484 | return adp8860_show(dev, buf, ADP8860_BLMX2); | ||
485 | } | ||
486 | |||
487 | static ssize_t adp8860_bl_l2_office_max_store(struct device *dev, | ||
488 | struct device_attribute *attr, const char *buf, size_t count) | ||
489 | { | ||
490 | return adp8860_store(dev, buf, count, ADP8860_BLMX2); | ||
491 | } | ||
492 | static DEVICE_ATTR(l2_office_max, 0664, adp8860_bl_l2_office_max_show, | ||
493 | adp8860_bl_l2_office_max_store); | ||
494 | |||
495 | static ssize_t adp8860_bl_l1_daylight_max_show(struct device *dev, | ||
496 | struct device_attribute *attr, char *buf) | ||
497 | { | ||
498 | return adp8860_show(dev, buf, ADP8860_BLMX1); | ||
499 | } | ||
500 | |||
501 | static ssize_t adp8860_bl_l1_daylight_max_store(struct device *dev, | ||
502 | struct device_attribute *attr, const char *buf, size_t count) | ||
503 | { | ||
504 | struct adp8860_bl *data = dev_get_drvdata(dev); | ||
505 | |||
506 | strict_strtoul(buf, 10, &data->cached_daylight_max); | ||
507 | return adp8860_store(dev, buf, count, ADP8860_BLMX1); | ||
508 | } | ||
509 | static DEVICE_ATTR(l1_daylight_max, 0664, adp8860_bl_l1_daylight_max_show, | ||
510 | adp8860_bl_l1_daylight_max_store); | ||
511 | |||
512 | static ssize_t adp8860_bl_l3_dark_dim_show(struct device *dev, | ||
513 | struct device_attribute *attr, char *buf) | ||
514 | { | ||
515 | return adp8860_show(dev, buf, ADP8860_BLDM3); | ||
516 | } | ||
517 | |||
518 | static ssize_t adp8860_bl_l3_dark_dim_store(struct device *dev, | ||
519 | struct device_attribute *attr, | ||
520 | const char *buf, size_t count) | ||
521 | { | ||
522 | return adp8860_store(dev, buf, count, ADP8860_BLDM3); | ||
523 | } | ||
524 | static DEVICE_ATTR(l3_dark_dim, 0664, adp8860_bl_l3_dark_dim_show, | ||
525 | adp8860_bl_l3_dark_dim_store); | ||
526 | |||
527 | static ssize_t adp8860_bl_l2_office_dim_show(struct device *dev, | ||
528 | struct device_attribute *attr, char *buf) | ||
529 | { | ||
530 | return adp8860_show(dev, buf, ADP8860_BLDM2); | ||
531 | } | ||
532 | |||
533 | static ssize_t adp8860_bl_l2_office_dim_store(struct device *dev, | ||
534 | struct device_attribute *attr, | ||
535 | const char *buf, size_t count) | ||
536 | { | ||
537 | return adp8860_store(dev, buf, count, ADP8860_BLDM2); | ||
538 | } | ||
539 | static DEVICE_ATTR(l2_office_dim, 0664, adp8860_bl_l2_office_dim_show, | ||
540 | adp8860_bl_l2_office_dim_store); | ||
541 | |||
542 | static ssize_t adp8860_bl_l1_daylight_dim_show(struct device *dev, | ||
543 | struct device_attribute *attr, char *buf) | ||
544 | { | ||
545 | return adp8860_show(dev, buf, ADP8860_BLDM1); | ||
546 | } | ||
547 | |||
548 | static ssize_t adp8860_bl_l1_daylight_dim_store(struct device *dev, | ||
549 | struct device_attribute *attr, | ||
550 | const char *buf, size_t count) | ||
551 | { | ||
552 | return adp8860_store(dev, buf, count, ADP8860_BLDM1); | ||
553 | } | ||
554 | static DEVICE_ATTR(l1_daylight_dim, 0664, adp8860_bl_l1_daylight_dim_show, | ||
555 | adp8860_bl_l1_daylight_dim_store); | ||
556 | |||
557 | #ifdef ADP8860_EXT_FEATURES | ||
558 | static ssize_t adp8860_bl_ambient_light_level_show(struct device *dev, | ||
559 | struct device_attribute *attr, char *buf) | ||
560 | { | ||
561 | struct adp8860_bl *data = dev_get_drvdata(dev); | ||
562 | int error; | ||
563 | uint8_t reg_val; | ||
564 | uint16_t ret_val; | ||
565 | |||
566 | mutex_lock(&data->lock); | ||
567 | error = adp8860_read(data->client, ADP8860_PH1LEVL, ®_val); | ||
568 | ret_val = reg_val; | ||
569 | error |= adp8860_read(data->client, ADP8860_PH1LEVH, ®_val); | ||
570 | mutex_unlock(&data->lock); | ||
571 | |||
572 | if (error < 0) | ||
573 | return error; | ||
574 | |||
575 | /* Return 13-bit conversion value for the first light sensor */ | ||
576 | ret_val += (reg_val & 0x1F) << 8; | ||
577 | |||
578 | return sprintf(buf, "%u\n", ret_val); | ||
579 | } | ||
580 | static DEVICE_ATTR(ambient_light_level, 0444, | ||
581 | adp8860_bl_ambient_light_level_show, NULL); | ||
582 | |||
583 | static ssize_t adp8860_bl_ambient_light_zone_show(struct device *dev, | ||
584 | struct device_attribute *attr, char *buf) | ||
585 | { | ||
586 | struct adp8860_bl *data = dev_get_drvdata(dev); | ||
587 | int error; | ||
588 | uint8_t reg_val; | ||
589 | |||
590 | mutex_lock(&data->lock); | ||
591 | error = adp8860_read(data->client, ADP8860_CFGR, ®_val); | ||
592 | mutex_unlock(&data->lock); | ||
593 | |||
594 | if (error < 0) | ||
595 | return error; | ||
596 | |||
597 | return sprintf(buf, "%u\n", | ||
598 | ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1); | ||
599 | } | ||
600 | |||
601 | static ssize_t adp8860_bl_ambient_light_zone_store(struct device *dev, | ||
602 | struct device_attribute *attr, | ||
603 | const char *buf, size_t count) | ||
604 | { | ||
605 | struct adp8860_bl *data = dev_get_drvdata(dev); | ||
606 | unsigned long val; | ||
607 | uint8_t reg_val; | ||
608 | int ret; | ||
609 | |||
610 | ret = strict_strtoul(buf, 10, &val); | ||
611 | if (ret) | ||
612 | return ret; | ||
613 | |||
614 | if (val == 0) { | ||
615 | /* Enable automatic ambient light sensing */ | ||
616 | adp8860_set_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); | ||
617 | } else if ((val > 0) && (val < 6)) { | ||
618 | /* Disable automatic ambient light sensing */ | ||
619 | adp8860_clr_bits(data->client, ADP8860_MDCR, CMP_AUTOEN); | ||
620 | |||
621 | /* Set user supplied ambient light zone */ | ||
622 | mutex_lock(&data->lock); | ||
623 | adp8860_read(data->client, ADP8860_CFGR, ®_val); | ||
624 | reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT); | ||
625 | reg_val |= val << CFGR_BLV_SHIFT; | ||
626 | adp8860_write(data->client, ADP8860_CFGR, reg_val); | ||
627 | mutex_unlock(&data->lock); | ||
628 | } | ||
629 | |||
630 | return count; | ||
631 | } | ||
632 | static DEVICE_ATTR(ambient_light_zone, 0664, | ||
633 | adp8860_bl_ambient_light_zone_show, | ||
634 | adp8860_bl_ambient_light_zone_store); | ||
635 | #endif | ||
636 | |||
637 | static struct attribute *adp8860_bl_attributes[] = { | ||
638 | &dev_attr_l3_dark_max.attr, | ||
639 | &dev_attr_l3_dark_dim.attr, | ||
640 | &dev_attr_l2_office_max.attr, | ||
641 | &dev_attr_l2_office_dim.attr, | ||
642 | &dev_attr_l1_daylight_max.attr, | ||
643 | &dev_attr_l1_daylight_dim.attr, | ||
644 | #ifdef ADP8860_EXT_FEATURES | ||
645 | &dev_attr_ambient_light_level.attr, | ||
646 | &dev_attr_ambient_light_zone.attr, | ||
647 | #endif | ||
648 | NULL | ||
649 | }; | ||
650 | |||
651 | static const struct attribute_group adp8860_bl_attr_group = { | ||
652 | .attrs = adp8860_bl_attributes, | ||
653 | }; | ||
654 | |||
655 | static int __devinit adp8860_probe(struct i2c_client *client, | ||
656 | const struct i2c_device_id *id) | ||
657 | { | ||
658 | struct backlight_device *bl; | ||
659 | struct adp8860_bl *data; | ||
660 | struct adp8860_backlight_platform_data *pdata = | ||
661 | client->dev.platform_data; | ||
662 | struct backlight_properties props; | ||
663 | uint8_t reg_val; | ||
664 | int ret; | ||
665 | |||
666 | if (!i2c_check_functionality(client->adapter, | ||
667 | I2C_FUNC_SMBUS_BYTE_DATA)) { | ||
668 | dev_err(&client->dev, "SMBUS Byte Data not Supported\n"); | ||
669 | return -EIO; | ||
670 | } | ||
671 | |||
672 | if (!pdata) { | ||
673 | dev_err(&client->dev, "no platform data?\n"); | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | |||
677 | data = kzalloc(sizeof(*data), GFP_KERNEL); | ||
678 | if (data == NULL) | ||
679 | return -ENOMEM; | ||
680 | |||
681 | ret = adp8860_read(client, ADP8860_MFDVID, ®_val); | ||
682 | if (ret < 0) | ||
683 | goto out2; | ||
684 | |||
685 | switch (ADP8860_MANID(reg_val)) { | ||
686 | case ADP8863_MANUFID: | ||
687 | data->gdwn_dis = !!pdata->gdwn_dis; | ||
688 | case ADP8860_MANUFID: | ||
689 | data->en_ambl_sens = !!pdata->en_ambl_sens; | ||
690 | break; | ||
691 | case ADP8861_MANUFID: | ||
692 | data->gdwn_dis = !!pdata->gdwn_dis; | ||
693 | break; | ||
694 | default: | ||
695 | dev_err(&client->dev, "failed to probe\n"); | ||
696 | ret = -ENODEV; | ||
697 | goto out2; | ||
698 | } | ||
699 | |||
700 | /* It's confirmed that the DEVID field is actually a REVID */ | ||
701 | |||
702 | data->revid = ADP8860_DEVID(reg_val); | ||
703 | data->client = client; | ||
704 | data->pdata = pdata; | ||
705 | data->id = id->driver_data; | ||
706 | data->current_brightness = 0; | ||
707 | i2c_set_clientdata(client, data); | ||
708 | |||
709 | memset(&props, 0, sizeof(props)); | ||
710 | props.max_brightness = ADP8860_MAX_BRIGHTNESS; | ||
711 | |||
712 | mutex_init(&data->lock); | ||
713 | |||
714 | bl = backlight_device_register(dev_driver_string(&client->dev), | ||
715 | &client->dev, data, &adp8860_bl_ops, &props); | ||
716 | if (IS_ERR(bl)) { | ||
717 | dev_err(&client->dev, "failed to register backlight\n"); | ||
718 | ret = PTR_ERR(bl); | ||
719 | goto out2; | ||
720 | } | ||
721 | |||
722 | bl->props.max_brightness = | ||
723 | bl->props.brightness = ADP8860_MAX_BRIGHTNESS; | ||
724 | |||
725 | data->bl = bl; | ||
726 | |||
727 | if (data->en_ambl_sens) | ||
728 | ret = sysfs_create_group(&bl->dev.kobj, | ||
729 | &adp8860_bl_attr_group); | ||
730 | |||
731 | if (ret) { | ||
732 | dev_err(&client->dev, "failed to register sysfs\n"); | ||
733 | goto out1; | ||
734 | } | ||
735 | |||
736 | ret = adp8860_bl_setup(bl); | ||
737 | if (ret) { | ||
738 | ret = -EIO; | ||
739 | goto out; | ||
740 | } | ||
741 | |||
742 | backlight_update_status(bl); | ||
743 | |||
744 | dev_info(&client->dev, "%s Rev.%d Backlight\n", | ||
745 | client->name, data->revid); | ||
746 | |||
747 | if (pdata->num_leds) | ||
748 | adp8860_led_probe(client); | ||
749 | |||
750 | return 0; | ||
751 | |||
752 | out: | ||
753 | if (data->en_ambl_sens) | ||
754 | sysfs_remove_group(&data->bl->dev.kobj, | ||
755 | &adp8860_bl_attr_group); | ||
756 | out1: | ||
757 | backlight_device_unregister(bl); | ||
758 | out2: | ||
759 | i2c_set_clientdata(client, NULL); | ||
760 | kfree(data); | ||
761 | |||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | static int __devexit adp8860_remove(struct i2c_client *client) | ||
766 | { | ||
767 | struct adp8860_bl *data = i2c_get_clientdata(client); | ||
768 | |||
769 | adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); | ||
770 | |||
771 | if (data->led) | ||
772 | adp8860_led_remove(client); | ||
773 | |||
774 | if (data->en_ambl_sens) | ||
775 | sysfs_remove_group(&data->bl->dev.kobj, | ||
776 | &adp8860_bl_attr_group); | ||
777 | |||
778 | backlight_device_unregister(data->bl); | ||
779 | i2c_set_clientdata(client, NULL); | ||
780 | kfree(data); | ||
781 | |||
782 | return 0; | ||
783 | } | ||
784 | |||
785 | #ifdef CONFIG_PM | ||
786 | static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) | ||
787 | { | ||
788 | adp8860_clr_bits(client, ADP8860_MDCR, NSTBY); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int adp8860_i2c_resume(struct i2c_client *client) | ||
794 | { | ||
795 | adp8860_set_bits(client, ADP8860_MDCR, NSTBY); | ||
796 | |||
797 | return 0; | ||
798 | } | ||
799 | #else | ||
800 | #define adp8860_i2c_suspend NULL | ||
801 | #define adp8860_i2c_resume NULL | ||
802 | #endif | ||
803 | |||
804 | static const struct i2c_device_id adp8860_id[] = { | ||
805 | { "adp8860", adp8860 }, | ||
806 | { "adp8861", adp8861 }, | ||
807 | { "adp8863", adp8863 }, | ||
808 | { } | ||
809 | }; | ||
810 | MODULE_DEVICE_TABLE(i2c, adp8860_id); | ||
811 | |||
812 | static struct i2c_driver adp8860_driver = { | ||
813 | .driver = { | ||
814 | .name = KBUILD_MODNAME, | ||
815 | }, | ||
816 | .probe = adp8860_probe, | ||
817 | .remove = __devexit_p(adp8860_remove), | ||
818 | .suspend = adp8860_i2c_suspend, | ||
819 | .resume = adp8860_i2c_resume, | ||
820 | .id_table = adp8860_id, | ||
821 | }; | ||
822 | |||
823 | static int __init adp8860_init(void) | ||
824 | { | ||
825 | return i2c_add_driver(&adp8860_driver); | ||
826 | } | ||
827 | module_init(adp8860_init); | ||
828 | |||
829 | static void __exit adp8860_exit(void) | ||
830 | { | ||
831 | i2c_del_driver(&adp8860_driver); | ||
832 | } | ||
833 | module_exit(adp8860_exit); | ||
834 | |||
835 | MODULE_LICENSE("GPL v2"); | ||
836 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); | ||
837 | MODULE_DESCRIPTION("ADP8860 Backlight driver"); | ||
838 | MODULE_ALIAS("i2c:adp8860-backlight"); | ||
diff --git a/drivers/video/backlight/adx_bl.c b/drivers/video/backlight/adx_bl.c index 7f4a7c30a98b..fe9af129c5dd 100644 --- a/drivers/video/backlight/adx_bl.c +++ b/drivers/video/backlight/adx_bl.c | |||
@@ -107,8 +107,8 @@ static int __devinit adx_backlight_probe(struct platform_device *pdev) | |||
107 | props.max_brightness = 0xff; | 107 | props.max_brightness = 0xff; |
108 | bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, | 108 | bldev = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, |
109 | bl, &adx_backlight_ops, &props); | 109 | bl, &adx_backlight_ops, &props); |
110 | if (!bldev) { | 110 | if (IS_ERR(bldev)) { |
111 | ret = -ENOMEM; | 111 | ret = PTR_ERR(bldev); |
112 | goto out; | 112 | goto out; |
113 | } | 113 | } |
114 | 114 | ||
diff --git a/drivers/video/backlight/ep93xx_bl.c b/drivers/video/backlight/ep93xx_bl.c new file mode 100644 index 000000000000..b0cc49184803 --- /dev/null +++ b/drivers/video/backlight/ep93xx_bl.c | |||
@@ -0,0 +1,160 @@ | |||
1 | /* | ||
2 | * Driver for the Cirrus EP93xx lcd backlight | ||
3 | * | ||
4 | * Copyright (c) 2010 H Hartley Sweeten <hsweeten@visionengravers.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This driver controls the pulse width modulated brightness control output, | ||
11 | * BRIGHT, on the Cirrus EP9307, EP9312, and EP9315 processors. | ||
12 | */ | ||
13 | |||
14 | |||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/fb.h> | ||
18 | #include <linux/backlight.h> | ||
19 | |||
20 | #include <mach/hardware.h> | ||
21 | |||
22 | #define EP93XX_RASTER_REG(x) (EP93XX_RASTER_BASE + (x)) | ||
23 | #define EP93XX_RASTER_BRIGHTNESS EP93XX_RASTER_REG(0x20) | ||
24 | |||
25 | #define EP93XX_MAX_COUNT 255 | ||
26 | #define EP93XX_MAX_BRIGHT 255 | ||
27 | #define EP93XX_DEF_BRIGHT 128 | ||
28 | |||
29 | struct ep93xxbl { | ||
30 | void __iomem *mmio; | ||
31 | int brightness; | ||
32 | }; | ||
33 | |||
34 | static int ep93xxbl_set(struct backlight_device *bl, int brightness) | ||
35 | { | ||
36 | struct ep93xxbl *ep93xxbl = bl_get_data(bl); | ||
37 | |||
38 | __raw_writel((brightness << 8) | EP93XX_MAX_COUNT, ep93xxbl->mmio); | ||
39 | |||
40 | ep93xxbl->brightness = brightness; | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int ep93xxbl_update_status(struct backlight_device *bl) | ||
46 | { | ||
47 | int brightness = bl->props.brightness; | ||
48 | |||
49 | if (bl->props.power != FB_BLANK_UNBLANK || | ||
50 | bl->props.fb_blank != FB_BLANK_UNBLANK) | ||
51 | brightness = 0; | ||
52 | |||
53 | return ep93xxbl_set(bl, brightness); | ||
54 | } | ||
55 | |||
56 | static int ep93xxbl_get_brightness(struct backlight_device *bl) | ||
57 | { | ||
58 | struct ep93xxbl *ep93xxbl = bl_get_data(bl); | ||
59 | |||
60 | return ep93xxbl->brightness; | ||
61 | } | ||
62 | |||
63 | static const struct backlight_ops ep93xxbl_ops = { | ||
64 | .update_status = ep93xxbl_update_status, | ||
65 | .get_brightness = ep93xxbl_get_brightness, | ||
66 | }; | ||
67 | |||
68 | static int __init ep93xxbl_probe(struct platform_device *dev) | ||
69 | { | ||
70 | struct ep93xxbl *ep93xxbl; | ||
71 | struct backlight_device *bl; | ||
72 | struct backlight_properties props; | ||
73 | |||
74 | ep93xxbl = devm_kzalloc(&dev->dev, sizeof(*ep93xxbl), GFP_KERNEL); | ||
75 | if (!ep93xxbl) | ||
76 | return -ENOMEM; | ||
77 | |||
78 | /* | ||
79 | * This register is located in the range already ioremap'ed by | ||
80 | * the framebuffer driver. A MFD driver seems a bit of overkill | ||
81 | * to handle this so use the static I/O mapping; this address | ||
82 | * is already virtual. | ||
83 | * | ||
84 | * NOTE: No locking is required; the framebuffer does not touch | ||
85 | * this register. | ||
86 | */ | ||
87 | ep93xxbl->mmio = EP93XX_RASTER_BRIGHTNESS; | ||
88 | |||
89 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
90 | props.max_brightness = EP93XX_MAX_BRIGHT; | ||
91 | bl = backlight_device_register(dev->name, &dev->dev, ep93xxbl, | ||
92 | &ep93xxbl_ops, &props); | ||
93 | if (IS_ERR(bl)) | ||
94 | return PTR_ERR(bl); | ||
95 | |||
96 | bl->props.brightness = EP93XX_DEF_BRIGHT; | ||
97 | |||
98 | platform_set_drvdata(dev, bl); | ||
99 | |||
100 | ep93xxbl_update_status(bl); | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int ep93xxbl_remove(struct platform_device *dev) | ||
106 | { | ||
107 | struct backlight_device *bl = platform_get_drvdata(dev); | ||
108 | |||
109 | backlight_device_unregister(bl); | ||
110 | platform_set_drvdata(dev, NULL); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | #ifdef CONFIG_PM | ||
115 | static int ep93xxbl_suspend(struct platform_device *dev, pm_message_t state) | ||
116 | { | ||
117 | struct backlight_device *bl = platform_get_drvdata(dev); | ||
118 | |||
119 | return ep93xxbl_set(bl, 0); | ||
120 | } | ||
121 | |||
122 | static int ep93xxbl_resume(struct platform_device *dev) | ||
123 | { | ||
124 | struct backlight_device *bl = platform_get_drvdata(dev); | ||
125 | |||
126 | backlight_update_status(bl); | ||
127 | return 0; | ||
128 | } | ||
129 | #else | ||
130 | #define ep93xxbl_suspend NULL | ||
131 | #define ep93xxbl_resume NULL | ||
132 | #endif | ||
133 | |||
134 | static struct platform_driver ep93xxbl_driver = { | ||
135 | .driver = { | ||
136 | .name = "ep93xx-bl", | ||
137 | .owner = THIS_MODULE, | ||
138 | }, | ||
139 | .probe = ep93xxbl_probe, | ||
140 | .remove = __devexit_p(ep93xxbl_remove), | ||
141 | .suspend = ep93xxbl_suspend, | ||
142 | .resume = ep93xxbl_resume, | ||
143 | }; | ||
144 | |||
145 | static int __init ep93xxbl_init(void) | ||
146 | { | ||
147 | return platform_driver_register(&ep93xxbl_driver); | ||
148 | } | ||
149 | module_init(ep93xxbl_init); | ||
150 | |||
151 | static void __exit ep93xxbl_exit(void) | ||
152 | { | ||
153 | platform_driver_unregister(&ep93xxbl_driver); | ||
154 | } | ||
155 | module_exit(ep93xxbl_exit); | ||
156 | |||
157 | MODULE_DESCRIPTION("EP93xx Backlight Driver"); | ||
158 | MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>"); | ||
159 | MODULE_LICENSE("GPL"); | ||
160 | MODULE_ALIAS("platform:ep93xx-bl"); | ||
diff --git a/drivers/video/backlight/l4f00242t03.c b/drivers/video/backlight/l4f00242t03.c index bcdb12c93efd..9093ef0fa869 100644 --- a/drivers/video/backlight/l4f00242t03.c +++ b/drivers/video/backlight/l4f00242t03.c | |||
@@ -125,8 +125,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) | |||
125 | 125 | ||
126 | if (priv == NULL) { | 126 | if (priv == NULL) { |
127 | dev_err(&spi->dev, "No memory for this device.\n"); | 127 | dev_err(&spi->dev, "No memory for this device.\n"); |
128 | ret = -ENOMEM; | 128 | return -ENOMEM; |
129 | goto err; | ||
130 | } | 129 | } |
131 | 130 | ||
132 | dev_set_drvdata(&spi->dev, priv); | 131 | dev_set_drvdata(&spi->dev, priv); |
@@ -139,7 +138,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) | |||
139 | if (ret) { | 138 | if (ret) { |
140 | dev_err(&spi->dev, | 139 | dev_err(&spi->dev, |
141 | "Unable to get the lcd l4f00242t03 reset gpio.\n"); | 140 | "Unable to get the lcd l4f00242t03 reset gpio.\n"); |
142 | return ret; | 141 | goto err; |
143 | } | 142 | } |
144 | 143 | ||
145 | ret = gpio_direction_output(pdata->reset_gpio, 1); | 144 | ret = gpio_direction_output(pdata->reset_gpio, 1); |
@@ -151,7 +150,7 @@ static int __devinit l4f00242t03_probe(struct spi_device *spi) | |||
151 | if (ret) { | 150 | if (ret) { |
152 | dev_err(&spi->dev, | 151 | dev_err(&spi->dev, |
153 | "Unable to get the lcd l4f00242t03 data en gpio.\n"); | 152 | "Unable to get the lcd l4f00242t03 data en gpio.\n"); |
154 | return ret; | 153 | goto err2; |
155 | } | 154 | } |
156 | 155 | ||
157 | ret = gpio_direction_output(pdata->data_enable_gpio, 0); | 156 | ret = gpio_direction_output(pdata->data_enable_gpio, 0); |
@@ -222,9 +221,9 @@ static int __devexit l4f00242t03_remove(struct spi_device *spi) | |||
222 | gpio_free(pdata->reset_gpio); | 221 | gpio_free(pdata->reset_gpio); |
223 | 222 | ||
224 | if (priv->io_reg) | 223 | if (priv->io_reg) |
225 | regulator_put(priv->core_reg); | ||
226 | if (priv->core_reg) | ||
227 | regulator_put(priv->io_reg); | 224 | regulator_put(priv->io_reg); |
225 | if (priv->core_reg) | ||
226 | regulator_put(priv->core_reg); | ||
228 | 227 | ||
229 | kfree(priv); | 228 | kfree(priv); |
230 | 229 | ||
diff --git a/drivers/video/backlight/max8925_bl.c b/drivers/video/backlight/max8925_bl.c index b5accc957ad3..b2b2c7ba1f63 100644 --- a/drivers/video/backlight/max8925_bl.c +++ b/drivers/video/backlight/max8925_bl.c | |||
@@ -162,6 +162,7 @@ static int __devinit max8925_backlight_probe(struct platform_device *pdev) | |||
162 | backlight_update_status(bl); | 162 | backlight_update_status(bl); |
163 | return 0; | 163 | return 0; |
164 | out: | 164 | out: |
165 | backlight_device_unregister(bl); | ||
165 | kfree(data); | 166 | kfree(data); |
166 | return ret; | 167 | return ret; |
167 | } | 168 | } |
diff --git a/drivers/video/backlight/mbp_nvidia_bl.c b/drivers/video/backlight/mbp_nvidia_bl.c index 1b5d3fe6bbbc..9fb533f6373e 100644 --- a/drivers/video/backlight/mbp_nvidia_bl.c +++ b/drivers/video/backlight/mbp_nvidia_bl.c | |||
@@ -141,7 +141,7 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { | |||
141 | .callback = mbp_dmi_match, | 141 | .callback = mbp_dmi_match, |
142 | .ident = "MacBook 1,1", | 142 | .ident = "MacBook 1,1", |
143 | .matches = { | 143 | .matches = { |
144 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 144 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), |
145 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), | 145 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), |
146 | }, | 146 | }, |
147 | .driver_data = (void *)&intel_chipset_data, | 147 | .driver_data = (void *)&intel_chipset_data, |
@@ -184,6 +184,42 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { | |||
184 | }, | 184 | }, |
185 | { | 185 | { |
186 | .callback = mbp_dmi_match, | 186 | .callback = mbp_dmi_match, |
187 | .ident = "MacBookPro 1,1", | ||
188 | .matches = { | ||
189 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
190 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,1"), | ||
191 | }, | ||
192 | .driver_data = (void *)&intel_chipset_data, | ||
193 | }, | ||
194 | { | ||
195 | .callback = mbp_dmi_match, | ||
196 | .ident = "MacBookPro 1,2", | ||
197 | .matches = { | ||
198 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
199 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro1,2"), | ||
200 | }, | ||
201 | .driver_data = (void *)&intel_chipset_data, | ||
202 | }, | ||
203 | { | ||
204 | .callback = mbp_dmi_match, | ||
205 | .ident = "MacBookPro 2,1", | ||
206 | .matches = { | ||
207 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
208 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,1"), | ||
209 | }, | ||
210 | .driver_data = (void *)&intel_chipset_data, | ||
211 | }, | ||
212 | { | ||
213 | .callback = mbp_dmi_match, | ||
214 | .ident = "MacBookPro 2,2", | ||
215 | .matches = { | ||
216 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
217 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro2,2"), | ||
218 | }, | ||
219 | .driver_data = (void *)&intel_chipset_data, | ||
220 | }, | ||
221 | { | ||
222 | .callback = mbp_dmi_match, | ||
187 | .ident = "MacBookPro 3,1", | 223 | .ident = "MacBookPro 3,1", |
188 | .matches = { | 224 | .matches = { |
189 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 225 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
@@ -238,6 +274,15 @@ static const struct dmi_system_id __initdata mbp_device_table[] = { | |||
238 | }, | 274 | }, |
239 | { | 275 | { |
240 | .callback = mbp_dmi_match, | 276 | .callback = mbp_dmi_match, |
277 | .ident = "MacBook 6,1", | ||
278 | .matches = { | ||
279 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | ||
280 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook6,1"), | ||
281 | }, | ||
282 | .driver_data = (void *)&nvidia_chipset_data, | ||
283 | }, | ||
284 | { | ||
285 | .callback = mbp_dmi_match, | ||
241 | .ident = "MacBookAir 2,1", | 286 | .ident = "MacBookAir 2,1", |
242 | .matches = { | 287 | .matches = { |
243 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), | 288 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."), |
diff --git a/drivers/video/backlight/pcf50633-backlight.c b/drivers/video/backlight/pcf50633-backlight.c new file mode 100644 index 000000000000..3c424f7efdcc --- /dev/null +++ b/drivers/video/backlight/pcf50633-backlight.c | |||
@@ -0,0 +1,190 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de> | ||
3 | * PCF50633 backlight device driver | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License as published by the | ||
7 | * Free Software Foundation; either version 2 of the License, or (at your | ||
8 | * option) any later version. | ||
9 | * | ||
10 | * You should have received a copy of the GNU General Public License along | ||
11 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
12 | * 675 Mass Ave, Cambridge, MA 02139, USA. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | |||
21 | #include <linux/backlight.h> | ||
22 | #include <linux/fb.h> | ||
23 | |||
24 | #include <linux/mfd/pcf50633/core.h> | ||
25 | #include <linux/mfd/pcf50633/backlight.h> | ||
26 | |||
27 | struct pcf50633_bl { | ||
28 | struct pcf50633 *pcf; | ||
29 | struct backlight_device *bl; | ||
30 | |||
31 | unsigned int brightness; | ||
32 | unsigned int brightness_limit; | ||
33 | }; | ||
34 | |||
35 | /* | ||
36 | * pcf50633_bl_set_brightness_limit | ||
37 | * | ||
38 | * Update the brightness limit for the pc50633 backlight. The actual brightness | ||
39 | * will not go above the limit. This is useful to limit power drain for example | ||
40 | * on low battery. | ||
41 | * | ||
42 | * @dev: Pointer to a pcf50633 device | ||
43 | * @limit: The brightness limit. Valid values are 0-63 | ||
44 | */ | ||
45 | int pcf50633_bl_set_brightness_limit(struct pcf50633 *pcf, unsigned int limit) | ||
46 | { | ||
47 | struct pcf50633_bl *pcf_bl = platform_get_drvdata(pcf->bl_pdev); | ||
48 | |||
49 | if (!pcf_bl) | ||
50 | return -ENODEV; | ||
51 | |||
52 | pcf_bl->brightness_limit = limit & 0x3f; | ||
53 | backlight_update_status(pcf_bl->bl); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int pcf50633_bl_update_status(struct backlight_device *bl) | ||
59 | { | ||
60 | struct pcf50633_bl *pcf_bl = bl_get_data(bl); | ||
61 | unsigned int new_brightness; | ||
62 | |||
63 | |||
64 | if (bl->props.state & (BL_CORE_SUSPENDED | BL_CORE_FBBLANK) || | ||
65 | bl->props.power != FB_BLANK_UNBLANK) | ||
66 | new_brightness = 0; | ||
67 | else if (bl->props.brightness < pcf_bl->brightness_limit) | ||
68 | new_brightness = bl->props.brightness; | ||
69 | else | ||
70 | new_brightness = pcf_bl->brightness_limit; | ||
71 | |||
72 | |||
73 | if (pcf_bl->brightness == new_brightness) | ||
74 | return 0; | ||
75 | |||
76 | if (new_brightness) { | ||
77 | pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDOUT, | ||
78 | new_brightness); | ||
79 | if (!pcf_bl->brightness) | ||
80 | pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 1); | ||
81 | } else { | ||
82 | pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDENA, 0); | ||
83 | } | ||
84 | |||
85 | pcf_bl->brightness = new_brightness; | ||
86 | |||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int pcf50633_bl_get_brightness(struct backlight_device *bl) | ||
91 | { | ||
92 | struct pcf50633_bl *pcf_bl = bl_get_data(bl); | ||
93 | return pcf_bl->brightness; | ||
94 | } | ||
95 | |||
96 | static const struct backlight_ops pcf50633_bl_ops = { | ||
97 | .get_brightness = pcf50633_bl_get_brightness, | ||
98 | .update_status = pcf50633_bl_update_status, | ||
99 | .options = BL_CORE_SUSPENDRESUME, | ||
100 | }; | ||
101 | |||
102 | static int __devinit pcf50633_bl_probe(struct platform_device *pdev) | ||
103 | { | ||
104 | int ret; | ||
105 | struct pcf50633_bl *pcf_bl; | ||
106 | struct device *parent = pdev->dev.parent; | ||
107 | struct pcf50633_platform_data *pcf50633_data = parent->platform_data; | ||
108 | struct pcf50633_bl_platform_data *pdata = pcf50633_data->backlight_data; | ||
109 | struct backlight_properties bl_props; | ||
110 | |||
111 | pcf_bl = kzalloc(sizeof(*pcf_bl), GFP_KERNEL); | ||
112 | if (!pcf_bl) | ||
113 | return -ENOMEM; | ||
114 | |||
115 | bl_props.max_brightness = 0x3f; | ||
116 | bl_props.power = FB_BLANK_UNBLANK; | ||
117 | |||
118 | if (pdata) { | ||
119 | bl_props.brightness = pdata->default_brightness; | ||
120 | pcf_bl->brightness_limit = pdata->default_brightness_limit; | ||
121 | } else { | ||
122 | bl_props.brightness = 0x3f; | ||
123 | pcf_bl->brightness_limit = 0x3f; | ||
124 | } | ||
125 | |||
126 | pcf_bl->pcf = dev_to_pcf50633(pdev->dev.parent); | ||
127 | |||
128 | pcf_bl->bl = backlight_device_register(pdev->name, &pdev->dev, pcf_bl, | ||
129 | &pcf50633_bl_ops, &bl_props); | ||
130 | |||
131 | if (IS_ERR(pcf_bl->bl)) { | ||
132 | ret = PTR_ERR(pcf_bl->bl); | ||
133 | goto err_free; | ||
134 | } | ||
135 | |||
136 | platform_set_drvdata(pdev, pcf_bl); | ||
137 | |||
138 | pcf50633_reg_write(pcf_bl->pcf, PCF50633_REG_LEDDIM, pdata->ramp_time); | ||
139 | |||
140 | /* Should be different from bl_props.brightness, so we do not exit | ||
141 | * update_status early the first time it's called */ | ||
142 | pcf_bl->brightness = pcf_bl->bl->props.brightness + 1; | ||
143 | |||
144 | backlight_update_status(pcf_bl->bl); | ||
145 | |||
146 | return 0; | ||
147 | |||
148 | err_free: | ||
149 | kfree(pcf_bl); | ||
150 | |||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | static int __devexit pcf50633_bl_remove(struct platform_device *pdev) | ||
155 | { | ||
156 | struct pcf50633_bl *pcf_bl = platform_get_drvdata(pdev); | ||
157 | |||
158 | backlight_device_unregister(pcf_bl->bl); | ||
159 | |||
160 | platform_set_drvdata(pdev, NULL); | ||
161 | |||
162 | kfree(pcf_bl); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | static struct platform_driver pcf50633_bl_driver = { | ||
168 | .probe = pcf50633_bl_probe, | ||
169 | .remove = __devexit_p(pcf50633_bl_remove), | ||
170 | .driver = { | ||
171 | .name = "pcf50633-backlight", | ||
172 | }, | ||
173 | }; | ||
174 | |||
175 | static int __init pcf50633_bl_init(void) | ||
176 | { | ||
177 | return platform_driver_register(&pcf50633_bl_driver); | ||
178 | } | ||
179 | module_init(pcf50633_bl_init); | ||
180 | |||
181 | static void __exit pcf50633_bl_exit(void) | ||
182 | { | ||
183 | platform_driver_unregister(&pcf50633_bl_driver); | ||
184 | } | ||
185 | module_exit(pcf50633_bl_exit); | ||
186 | |||
187 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
188 | MODULE_DESCRIPTION("PCF50633 backlight driver"); | ||
189 | MODULE_LICENSE("GPL"); | ||
190 | MODULE_ALIAS("platform:pcf50633-backlight"); | ||
diff --git a/drivers/video/backlight/s6e63m0.c b/drivers/video/backlight/s6e63m0.c new file mode 100644 index 000000000000..a3128c9cb7ad --- /dev/null +++ b/drivers/video/backlight/s6e63m0.c | |||
@@ -0,0 +1,920 @@ | |||
1 | /* | ||
2 | * S6E63M0 AMOLED LCD panel driver. | ||
3 | * | ||
4 | * Author: InKi Dae <inki.dae@samsung.com> | ||
5 | * | ||
6 | * Derived from drivers/video/omap/lcd-apollon.c | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License along | ||
19 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
20 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/wait.h> | ||
24 | #include <linux/fb.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/spi/spi.h> | ||
28 | #include <linux/irq.h> | ||
29 | #include <linux/interrupt.h> | ||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/lcd.h> | ||
32 | #include <linux/backlight.h> | ||
33 | |||
34 | #include "s6e63m0_gamma.h" | ||
35 | |||
36 | #define SLEEPMSEC 0x1000 | ||
37 | #define ENDDEF 0x2000 | ||
38 | #define DEFMASK 0xFF00 | ||
39 | #define COMMAND_ONLY 0xFE | ||
40 | #define DATA_ONLY 0xFF | ||
41 | |||
42 | #define MIN_BRIGHTNESS 0 | ||
43 | #define MAX_BRIGHTNESS 10 | ||
44 | |||
45 | #define POWER_IS_ON(pwr) ((pwr) <= FB_BLANK_NORMAL) | ||
46 | |||
47 | struct s6e63m0 { | ||
48 | struct device *dev; | ||
49 | struct spi_device *spi; | ||
50 | unsigned int power; | ||
51 | unsigned int current_brightness; | ||
52 | unsigned int gamma_mode; | ||
53 | unsigned int gamma_table_count; | ||
54 | struct lcd_device *ld; | ||
55 | struct backlight_device *bd; | ||
56 | struct lcd_platform_data *lcd_pd; | ||
57 | }; | ||
58 | |||
59 | static const unsigned short SEQ_PANEL_CONDITION_SET[] = { | ||
60 | 0xF8, 0x01, | ||
61 | DATA_ONLY, 0x27, | ||
62 | DATA_ONLY, 0x27, | ||
63 | DATA_ONLY, 0x07, | ||
64 | DATA_ONLY, 0x07, | ||
65 | DATA_ONLY, 0x54, | ||
66 | DATA_ONLY, 0x9f, | ||
67 | DATA_ONLY, 0x63, | ||
68 | DATA_ONLY, 0x86, | ||
69 | DATA_ONLY, 0x1a, | ||
70 | DATA_ONLY, 0x33, | ||
71 | DATA_ONLY, 0x0d, | ||
72 | DATA_ONLY, 0x00, | ||
73 | DATA_ONLY, 0x00, | ||
74 | |||
75 | ENDDEF, 0x0000 | ||
76 | }; | ||
77 | |||
78 | static const unsigned short SEQ_DISPLAY_CONDITION_SET[] = { | ||
79 | 0xf2, 0x02, | ||
80 | DATA_ONLY, 0x03, | ||
81 | DATA_ONLY, 0x1c, | ||
82 | DATA_ONLY, 0x10, | ||
83 | DATA_ONLY, 0x10, | ||
84 | |||
85 | 0xf7, 0x03, | ||
86 | DATA_ONLY, 0x00, | ||
87 | DATA_ONLY, 0x00, | ||
88 | |||
89 | ENDDEF, 0x0000 | ||
90 | }; | ||
91 | |||
92 | static const unsigned short SEQ_GAMMA_SETTING[] = { | ||
93 | 0xfa, 0x00, | ||
94 | DATA_ONLY, 0x18, | ||
95 | DATA_ONLY, 0x08, | ||
96 | DATA_ONLY, 0x24, | ||
97 | DATA_ONLY, 0x64, | ||
98 | DATA_ONLY, 0x56, | ||
99 | DATA_ONLY, 0x33, | ||
100 | DATA_ONLY, 0xb6, | ||
101 | DATA_ONLY, 0xba, | ||
102 | DATA_ONLY, 0xa8, | ||
103 | DATA_ONLY, 0xac, | ||
104 | DATA_ONLY, 0xb1, | ||
105 | DATA_ONLY, 0x9d, | ||
106 | DATA_ONLY, 0xc1, | ||
107 | DATA_ONLY, 0xc1, | ||
108 | DATA_ONLY, 0xb7, | ||
109 | DATA_ONLY, 0x00, | ||
110 | DATA_ONLY, 0x9c, | ||
111 | DATA_ONLY, 0x00, | ||
112 | DATA_ONLY, 0x9f, | ||
113 | DATA_ONLY, 0x00, | ||
114 | DATA_ONLY, 0xd6, | ||
115 | |||
116 | 0xfa, 0x01, | ||
117 | |||
118 | ENDDEF, 0x0000 | ||
119 | }; | ||
120 | |||
121 | static const unsigned short SEQ_ETC_CONDITION_SET[] = { | ||
122 | 0xf6, 0x00, | ||
123 | DATA_ONLY, 0x8c, | ||
124 | DATA_ONLY, 0x07, | ||
125 | |||
126 | 0xb3, 0xc, | ||
127 | |||
128 | 0xb5, 0x2c, | ||
129 | DATA_ONLY, 0x12, | ||
130 | DATA_ONLY, 0x0c, | ||
131 | DATA_ONLY, 0x0a, | ||
132 | DATA_ONLY, 0x10, | ||
133 | DATA_ONLY, 0x0e, | ||
134 | DATA_ONLY, 0x17, | ||
135 | DATA_ONLY, 0x13, | ||
136 | DATA_ONLY, 0x1f, | ||
137 | DATA_ONLY, 0x1a, | ||
138 | DATA_ONLY, 0x2a, | ||
139 | DATA_ONLY, 0x24, | ||
140 | DATA_ONLY, 0x1f, | ||
141 | DATA_ONLY, 0x1b, | ||
142 | DATA_ONLY, 0x1a, | ||
143 | DATA_ONLY, 0x17, | ||
144 | |||
145 | DATA_ONLY, 0x2b, | ||
146 | DATA_ONLY, 0x26, | ||
147 | DATA_ONLY, 0x22, | ||
148 | DATA_ONLY, 0x20, | ||
149 | DATA_ONLY, 0x3a, | ||
150 | DATA_ONLY, 0x34, | ||
151 | DATA_ONLY, 0x30, | ||
152 | DATA_ONLY, 0x2c, | ||
153 | DATA_ONLY, 0x29, | ||
154 | DATA_ONLY, 0x26, | ||
155 | DATA_ONLY, 0x25, | ||
156 | DATA_ONLY, 0x23, | ||
157 | DATA_ONLY, 0x21, | ||
158 | DATA_ONLY, 0x20, | ||
159 | DATA_ONLY, 0x1e, | ||
160 | DATA_ONLY, 0x1e, | ||
161 | |||
162 | 0xb6, 0x00, | ||
163 | DATA_ONLY, 0x00, | ||
164 | DATA_ONLY, 0x11, | ||
165 | DATA_ONLY, 0x22, | ||
166 | DATA_ONLY, 0x33, | ||
167 | DATA_ONLY, 0x44, | ||
168 | DATA_ONLY, 0x44, | ||
169 | DATA_ONLY, 0x44, | ||
170 | |||
171 | DATA_ONLY, 0x55, | ||
172 | DATA_ONLY, 0x55, | ||
173 | DATA_ONLY, 0x66, | ||
174 | DATA_ONLY, 0x66, | ||
175 | DATA_ONLY, 0x66, | ||
176 | DATA_ONLY, 0x66, | ||
177 | DATA_ONLY, 0x66, | ||
178 | DATA_ONLY, 0x66, | ||
179 | |||
180 | 0xb7, 0x2c, | ||
181 | DATA_ONLY, 0x12, | ||
182 | DATA_ONLY, 0x0c, | ||
183 | DATA_ONLY, 0x0a, | ||
184 | DATA_ONLY, 0x10, | ||
185 | DATA_ONLY, 0x0e, | ||
186 | DATA_ONLY, 0x17, | ||
187 | DATA_ONLY, 0x13, | ||
188 | DATA_ONLY, 0x1f, | ||
189 | DATA_ONLY, 0x1a, | ||
190 | DATA_ONLY, 0x2a, | ||
191 | DATA_ONLY, 0x24, | ||
192 | DATA_ONLY, 0x1f, | ||
193 | DATA_ONLY, 0x1b, | ||
194 | DATA_ONLY, 0x1a, | ||
195 | DATA_ONLY, 0x17, | ||
196 | |||
197 | DATA_ONLY, 0x2b, | ||
198 | DATA_ONLY, 0x26, | ||
199 | DATA_ONLY, 0x22, | ||
200 | DATA_ONLY, 0x20, | ||
201 | DATA_ONLY, 0x3a, | ||
202 | DATA_ONLY, 0x34, | ||
203 | DATA_ONLY, 0x30, | ||
204 | DATA_ONLY, 0x2c, | ||
205 | DATA_ONLY, 0x29, | ||
206 | DATA_ONLY, 0x26, | ||
207 | DATA_ONLY, 0x25, | ||
208 | DATA_ONLY, 0x23, | ||
209 | DATA_ONLY, 0x21, | ||
210 | DATA_ONLY, 0x20, | ||
211 | DATA_ONLY, 0x1e, | ||
212 | DATA_ONLY, 0x1e, | ||
213 | |||
214 | 0xb8, 0x00, | ||
215 | DATA_ONLY, 0x00, | ||
216 | DATA_ONLY, 0x11, | ||
217 | DATA_ONLY, 0x22, | ||
218 | DATA_ONLY, 0x33, | ||
219 | DATA_ONLY, 0x44, | ||
220 | DATA_ONLY, 0x44, | ||
221 | DATA_ONLY, 0x44, | ||
222 | |||
223 | DATA_ONLY, 0x55, | ||
224 | DATA_ONLY, 0x55, | ||
225 | DATA_ONLY, 0x66, | ||
226 | DATA_ONLY, 0x66, | ||
227 | DATA_ONLY, 0x66, | ||
228 | DATA_ONLY, 0x66, | ||
229 | DATA_ONLY, 0x66, | ||
230 | DATA_ONLY, 0x66, | ||
231 | |||
232 | 0xb9, 0x2c, | ||
233 | DATA_ONLY, 0x12, | ||
234 | DATA_ONLY, 0x0c, | ||
235 | DATA_ONLY, 0x0a, | ||
236 | DATA_ONLY, 0x10, | ||
237 | DATA_ONLY, 0x0e, | ||
238 | DATA_ONLY, 0x17, | ||
239 | DATA_ONLY, 0x13, | ||
240 | DATA_ONLY, 0x1f, | ||
241 | DATA_ONLY, 0x1a, | ||
242 | DATA_ONLY, 0x2a, | ||
243 | DATA_ONLY, 0x24, | ||
244 | DATA_ONLY, 0x1f, | ||
245 | DATA_ONLY, 0x1b, | ||
246 | DATA_ONLY, 0x1a, | ||
247 | DATA_ONLY, 0x17, | ||
248 | |||
249 | DATA_ONLY, 0x2b, | ||
250 | DATA_ONLY, 0x26, | ||
251 | DATA_ONLY, 0x22, | ||
252 | DATA_ONLY, 0x20, | ||
253 | DATA_ONLY, 0x3a, | ||
254 | DATA_ONLY, 0x34, | ||
255 | DATA_ONLY, 0x30, | ||
256 | DATA_ONLY, 0x2c, | ||
257 | DATA_ONLY, 0x29, | ||
258 | DATA_ONLY, 0x26, | ||
259 | DATA_ONLY, 0x25, | ||
260 | DATA_ONLY, 0x23, | ||
261 | DATA_ONLY, 0x21, | ||
262 | DATA_ONLY, 0x20, | ||
263 | DATA_ONLY, 0x1e, | ||
264 | DATA_ONLY, 0x1e, | ||
265 | |||
266 | 0xba, 0x00, | ||
267 | DATA_ONLY, 0x00, | ||
268 | DATA_ONLY, 0x11, | ||
269 | DATA_ONLY, 0x22, | ||
270 | DATA_ONLY, 0x33, | ||
271 | DATA_ONLY, 0x44, | ||
272 | DATA_ONLY, 0x44, | ||
273 | DATA_ONLY, 0x44, | ||
274 | |||
275 | DATA_ONLY, 0x55, | ||
276 | DATA_ONLY, 0x55, | ||
277 | DATA_ONLY, 0x66, | ||
278 | DATA_ONLY, 0x66, | ||
279 | DATA_ONLY, 0x66, | ||
280 | DATA_ONLY, 0x66, | ||
281 | DATA_ONLY, 0x66, | ||
282 | DATA_ONLY, 0x66, | ||
283 | |||
284 | 0xc1, 0x4d, | ||
285 | DATA_ONLY, 0x96, | ||
286 | DATA_ONLY, 0x1d, | ||
287 | DATA_ONLY, 0x00, | ||
288 | DATA_ONLY, 0x00, | ||
289 | DATA_ONLY, 0x01, | ||
290 | DATA_ONLY, 0xdf, | ||
291 | DATA_ONLY, 0x00, | ||
292 | DATA_ONLY, 0x00, | ||
293 | DATA_ONLY, 0x03, | ||
294 | DATA_ONLY, 0x1f, | ||
295 | DATA_ONLY, 0x00, | ||
296 | DATA_ONLY, 0x00, | ||
297 | DATA_ONLY, 0x00, | ||
298 | DATA_ONLY, 0x00, | ||
299 | DATA_ONLY, 0x00, | ||
300 | DATA_ONLY, 0x00, | ||
301 | DATA_ONLY, 0x00, | ||
302 | DATA_ONLY, 0x00, | ||
303 | DATA_ONLY, 0x03, | ||
304 | DATA_ONLY, 0x06, | ||
305 | DATA_ONLY, 0x09, | ||
306 | DATA_ONLY, 0x0d, | ||
307 | DATA_ONLY, 0x0f, | ||
308 | DATA_ONLY, 0x12, | ||
309 | DATA_ONLY, 0x15, | ||
310 | DATA_ONLY, 0x18, | ||
311 | |||
312 | 0xb2, 0x10, | ||
313 | DATA_ONLY, 0x10, | ||
314 | DATA_ONLY, 0x0b, | ||
315 | DATA_ONLY, 0x05, | ||
316 | |||
317 | ENDDEF, 0x0000 | ||
318 | }; | ||
319 | |||
320 | static const unsigned short SEQ_ACL_ON[] = { | ||
321 | /* ACL on */ | ||
322 | 0xc0, 0x01, | ||
323 | |||
324 | ENDDEF, 0x0000 | ||
325 | }; | ||
326 | |||
327 | static const unsigned short SEQ_ACL_OFF[] = { | ||
328 | /* ACL off */ | ||
329 | 0xc0, 0x00, | ||
330 | |||
331 | ENDDEF, 0x0000 | ||
332 | }; | ||
333 | |||
334 | static const unsigned short SEQ_ELVSS_ON[] = { | ||
335 | /* ELVSS on */ | ||
336 | 0xb1, 0x0b, | ||
337 | |||
338 | ENDDEF, 0x0000 | ||
339 | }; | ||
340 | |||
341 | static const unsigned short SEQ_ELVSS_OFF[] = { | ||
342 | /* ELVSS off */ | ||
343 | 0xb1, 0x0a, | ||
344 | |||
345 | ENDDEF, 0x0000 | ||
346 | }; | ||
347 | |||
348 | static const unsigned short SEQ_STAND_BY_OFF[] = { | ||
349 | 0x11, COMMAND_ONLY, | ||
350 | |||
351 | ENDDEF, 0x0000 | ||
352 | }; | ||
353 | |||
354 | static const unsigned short SEQ_STAND_BY_ON[] = { | ||
355 | 0x10, COMMAND_ONLY, | ||
356 | |||
357 | ENDDEF, 0x0000 | ||
358 | }; | ||
359 | |||
360 | static const unsigned short SEQ_DISPLAY_ON[] = { | ||
361 | 0x29, COMMAND_ONLY, | ||
362 | |||
363 | ENDDEF, 0x0000 | ||
364 | }; | ||
365 | |||
366 | |||
367 | static int s6e63m0_spi_write_byte(struct s6e63m0 *lcd, int addr, int data) | ||
368 | { | ||
369 | u16 buf[1]; | ||
370 | struct spi_message msg; | ||
371 | |||
372 | struct spi_transfer xfer = { | ||
373 | .len = 2, | ||
374 | .tx_buf = buf, | ||
375 | }; | ||
376 | |||
377 | buf[0] = (addr << 8) | data; | ||
378 | |||
379 | spi_message_init(&msg); | ||
380 | spi_message_add_tail(&xfer, &msg); | ||
381 | |||
382 | return spi_sync(lcd->spi, &msg); | ||
383 | } | ||
384 | |||
385 | static int s6e63m0_spi_write(struct s6e63m0 *lcd, unsigned char address, | ||
386 | unsigned char command) | ||
387 | { | ||
388 | int ret = 0; | ||
389 | |||
390 | if (address != DATA_ONLY) | ||
391 | ret = s6e63m0_spi_write_byte(lcd, 0x0, address); | ||
392 | if (command != COMMAND_ONLY) | ||
393 | ret = s6e63m0_spi_write_byte(lcd, 0x1, command); | ||
394 | |||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | static int s6e63m0_panel_send_sequence(struct s6e63m0 *lcd, | ||
399 | const unsigned short *wbuf) | ||
400 | { | ||
401 | int ret = 0, i = 0; | ||
402 | |||
403 | while ((wbuf[i] & DEFMASK) != ENDDEF) { | ||
404 | if ((wbuf[i] & DEFMASK) != SLEEPMSEC) { | ||
405 | ret = s6e63m0_spi_write(lcd, wbuf[i], wbuf[i+1]); | ||
406 | if (ret) | ||
407 | break; | ||
408 | } else | ||
409 | udelay(wbuf[i+1]*1000); | ||
410 | i += 2; | ||
411 | } | ||
412 | |||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | static int _s6e63m0_gamma_ctl(struct s6e63m0 *lcd, const unsigned int *gamma) | ||
417 | { | ||
418 | unsigned int i = 0; | ||
419 | int ret = 0; | ||
420 | |||
421 | /* disable gamma table updating. */ | ||
422 | ret = s6e63m0_spi_write(lcd, 0xfa, 0x00); | ||
423 | if (ret) { | ||
424 | dev_err(lcd->dev, "failed to disable gamma table updating.\n"); | ||
425 | goto gamma_err; | ||
426 | } | ||
427 | |||
428 | for (i = 0 ; i < GAMMA_TABLE_COUNT; i++) { | ||
429 | ret = s6e63m0_spi_write(lcd, DATA_ONLY, gamma[i]); | ||
430 | if (ret) { | ||
431 | dev_err(lcd->dev, "failed to set gamma table.\n"); | ||
432 | goto gamma_err; | ||
433 | } | ||
434 | } | ||
435 | |||
436 | /* update gamma table. */ | ||
437 | ret = s6e63m0_spi_write(lcd, 0xfa, 0x01); | ||
438 | if (ret) | ||
439 | dev_err(lcd->dev, "failed to update gamma table.\n"); | ||
440 | |||
441 | gamma_err: | ||
442 | return ret; | ||
443 | } | ||
444 | |||
445 | static int s6e63m0_gamma_ctl(struct s6e63m0 *lcd, int gamma) | ||
446 | { | ||
447 | int ret = 0; | ||
448 | |||
449 | ret = _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[gamma]); | ||
450 | |||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | |||
455 | static int s6e63m0_ldi_init(struct s6e63m0 *lcd) | ||
456 | { | ||
457 | int ret, i; | ||
458 | const unsigned short *init_seq[] = { | ||
459 | SEQ_PANEL_CONDITION_SET, | ||
460 | SEQ_DISPLAY_CONDITION_SET, | ||
461 | SEQ_GAMMA_SETTING, | ||
462 | SEQ_ETC_CONDITION_SET, | ||
463 | SEQ_ACL_ON, | ||
464 | SEQ_ELVSS_ON, | ||
465 | }; | ||
466 | |||
467 | for (i = 0; i < ARRAY_SIZE(init_seq); i++) { | ||
468 | ret = s6e63m0_panel_send_sequence(lcd, init_seq[i]); | ||
469 | if (ret) | ||
470 | break; | ||
471 | } | ||
472 | |||
473 | return ret; | ||
474 | } | ||
475 | |||
476 | static int s6e63m0_ldi_enable(struct s6e63m0 *lcd) | ||
477 | { | ||
478 | int ret = 0, i; | ||
479 | const unsigned short *enable_seq[] = { | ||
480 | SEQ_STAND_BY_OFF, | ||
481 | SEQ_DISPLAY_ON, | ||
482 | }; | ||
483 | |||
484 | for (i = 0; i < ARRAY_SIZE(enable_seq); i++) { | ||
485 | ret = s6e63m0_panel_send_sequence(lcd, enable_seq[i]); | ||
486 | if (ret) | ||
487 | break; | ||
488 | } | ||
489 | |||
490 | return ret; | ||
491 | } | ||
492 | |||
493 | static int s6e63m0_ldi_disable(struct s6e63m0 *lcd) | ||
494 | { | ||
495 | int ret; | ||
496 | |||
497 | ret = s6e63m0_panel_send_sequence(lcd, SEQ_STAND_BY_ON); | ||
498 | |||
499 | return ret; | ||
500 | } | ||
501 | |||
502 | static int s6e63m0_power_on(struct s6e63m0 *lcd) | ||
503 | { | ||
504 | int ret = 0; | ||
505 | struct lcd_platform_data *pd = NULL; | ||
506 | struct backlight_device *bd = NULL; | ||
507 | |||
508 | pd = lcd->lcd_pd; | ||
509 | if (!pd) { | ||
510 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
511 | return -EFAULT; | ||
512 | } | ||
513 | |||
514 | bd = lcd->bd; | ||
515 | if (!bd) { | ||
516 | dev_err(lcd->dev, "backlight device is NULL.\n"); | ||
517 | return -EFAULT; | ||
518 | } | ||
519 | |||
520 | if (!pd->power_on) { | ||
521 | dev_err(lcd->dev, "power_on is NULL.\n"); | ||
522 | return -EFAULT; | ||
523 | } else { | ||
524 | pd->power_on(lcd->ld, 1); | ||
525 | mdelay(pd->power_on_delay); | ||
526 | } | ||
527 | |||
528 | if (!pd->reset) { | ||
529 | dev_err(lcd->dev, "reset is NULL.\n"); | ||
530 | return -EFAULT; | ||
531 | } else { | ||
532 | pd->reset(lcd->ld); | ||
533 | mdelay(pd->reset_delay); | ||
534 | } | ||
535 | |||
536 | ret = s6e63m0_ldi_init(lcd); | ||
537 | if (ret) { | ||
538 | dev_err(lcd->dev, "failed to initialize ldi.\n"); | ||
539 | return ret; | ||
540 | } | ||
541 | |||
542 | ret = s6e63m0_ldi_enable(lcd); | ||
543 | if (ret) { | ||
544 | dev_err(lcd->dev, "failed to enable ldi.\n"); | ||
545 | return ret; | ||
546 | } | ||
547 | |||
548 | /* set brightness to current value after power on or resume. */ | ||
549 | ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness); | ||
550 | if (ret) { | ||
551 | dev_err(lcd->dev, "lcd gamma setting failed.\n"); | ||
552 | return ret; | ||
553 | } | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static int s6e63m0_power_off(struct s6e63m0 *lcd) | ||
559 | { | ||
560 | int ret = 0; | ||
561 | struct lcd_platform_data *pd = NULL; | ||
562 | |||
563 | pd = lcd->lcd_pd; | ||
564 | if (!pd) { | ||
565 | dev_err(lcd->dev, "platform data is NULL.\n"); | ||
566 | return -EFAULT; | ||
567 | } | ||
568 | |||
569 | ret = s6e63m0_ldi_disable(lcd); | ||
570 | if (ret) { | ||
571 | dev_err(lcd->dev, "lcd setting failed.\n"); | ||
572 | return -EIO; | ||
573 | } | ||
574 | |||
575 | mdelay(pd->power_off_delay); | ||
576 | |||
577 | if (!pd->power_on) { | ||
578 | dev_err(lcd->dev, "power_on is NULL.\n"); | ||
579 | return -EFAULT; | ||
580 | } else | ||
581 | pd->power_on(lcd->ld, 0); | ||
582 | |||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static int s6e63m0_power(struct s6e63m0 *lcd, int power) | ||
587 | { | ||
588 | int ret = 0; | ||
589 | |||
590 | if (POWER_IS_ON(power) && !POWER_IS_ON(lcd->power)) | ||
591 | ret = s6e63m0_power_on(lcd); | ||
592 | else if (!POWER_IS_ON(power) && POWER_IS_ON(lcd->power)) | ||
593 | ret = s6e63m0_power_off(lcd); | ||
594 | |||
595 | if (!ret) | ||
596 | lcd->power = power; | ||
597 | |||
598 | return ret; | ||
599 | } | ||
600 | |||
601 | static int s6e63m0_set_power(struct lcd_device *ld, int power) | ||
602 | { | ||
603 | struct s6e63m0 *lcd = lcd_get_data(ld); | ||
604 | |||
605 | if (power != FB_BLANK_UNBLANK && power != FB_BLANK_POWERDOWN && | ||
606 | power != FB_BLANK_NORMAL) { | ||
607 | dev_err(lcd->dev, "power value should be 0, 1 or 4.\n"); | ||
608 | return -EINVAL; | ||
609 | } | ||
610 | |||
611 | return s6e63m0_power(lcd, power); | ||
612 | } | ||
613 | |||
614 | static int s6e63m0_get_power(struct lcd_device *ld) | ||
615 | { | ||
616 | struct s6e63m0 *lcd = lcd_get_data(ld); | ||
617 | |||
618 | return lcd->power; | ||
619 | } | ||
620 | |||
621 | static int s6e63m0_get_brightness(struct backlight_device *bd) | ||
622 | { | ||
623 | return bd->props.brightness; | ||
624 | } | ||
625 | |||
626 | static int s6e63m0_set_brightness(struct backlight_device *bd) | ||
627 | { | ||
628 | int ret = 0, brightness = bd->props.brightness; | ||
629 | struct s6e63m0 *lcd = bl_get_data(bd); | ||
630 | |||
631 | if (brightness < MIN_BRIGHTNESS || | ||
632 | brightness > bd->props.max_brightness) { | ||
633 | dev_err(&bd->dev, "lcd brightness should be %d to %d.\n", | ||
634 | MIN_BRIGHTNESS, MAX_BRIGHTNESS); | ||
635 | return -EINVAL; | ||
636 | } | ||
637 | |||
638 | ret = s6e63m0_gamma_ctl(lcd, bd->props.brightness); | ||
639 | if (ret) { | ||
640 | dev_err(&bd->dev, "lcd brightness setting failed.\n"); | ||
641 | return -EIO; | ||
642 | } | ||
643 | |||
644 | return ret; | ||
645 | } | ||
646 | |||
647 | static struct lcd_ops s6e63m0_lcd_ops = { | ||
648 | .set_power = s6e63m0_set_power, | ||
649 | .get_power = s6e63m0_get_power, | ||
650 | }; | ||
651 | |||
652 | static const struct backlight_ops s6e63m0_backlight_ops = { | ||
653 | .get_brightness = s6e63m0_get_brightness, | ||
654 | .update_status = s6e63m0_set_brightness, | ||
655 | }; | ||
656 | |||
657 | static ssize_t s6e63m0_sysfs_show_gamma_mode(struct device *dev, | ||
658 | struct device_attribute *attr, char *buf) | ||
659 | { | ||
660 | struct s6e63m0 *lcd = dev_get_drvdata(dev); | ||
661 | char temp[10]; | ||
662 | |||
663 | switch (lcd->gamma_mode) { | ||
664 | case 0: | ||
665 | sprintf(temp, "2.2 mode\n"); | ||
666 | strcat(buf, temp); | ||
667 | break; | ||
668 | case 1: | ||
669 | sprintf(temp, "1.9 mode\n"); | ||
670 | strcat(buf, temp); | ||
671 | break; | ||
672 | case 2: | ||
673 | sprintf(temp, "1.7 mode\n"); | ||
674 | strcat(buf, temp); | ||
675 | break; | ||
676 | default: | ||
677 | dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7)n"); | ||
678 | break; | ||
679 | } | ||
680 | |||
681 | return strlen(buf); | ||
682 | } | ||
683 | |||
684 | static ssize_t s6e63m0_sysfs_store_gamma_mode(struct device *dev, | ||
685 | struct device_attribute *attr, | ||
686 | const char *buf, size_t len) | ||
687 | { | ||
688 | struct s6e63m0 *lcd = dev_get_drvdata(dev); | ||
689 | struct backlight_device *bd = NULL; | ||
690 | int brightness, rc; | ||
691 | |||
692 | rc = strict_strtoul(buf, 0, (unsigned long *)&lcd->gamma_mode); | ||
693 | if (rc < 0) | ||
694 | return rc; | ||
695 | |||
696 | bd = lcd->bd; | ||
697 | |||
698 | brightness = bd->props.brightness; | ||
699 | |||
700 | switch (lcd->gamma_mode) { | ||
701 | case 0: | ||
702 | _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]); | ||
703 | break; | ||
704 | case 1: | ||
705 | _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_19_table[brightness]); | ||
706 | break; | ||
707 | case 2: | ||
708 | _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_17_table[brightness]); | ||
709 | break; | ||
710 | default: | ||
711 | dev_info(dev, "gamma mode could be 0:2.2, 1:1.9 or 2:1.7\n"); | ||
712 | _s6e63m0_gamma_ctl(lcd, gamma_table.gamma_22_table[brightness]); | ||
713 | break; | ||
714 | } | ||
715 | return len; | ||
716 | } | ||
717 | |||
718 | static DEVICE_ATTR(gamma_mode, 0644, | ||
719 | s6e63m0_sysfs_show_gamma_mode, s6e63m0_sysfs_store_gamma_mode); | ||
720 | |||
721 | static ssize_t s6e63m0_sysfs_show_gamma_table(struct device *dev, | ||
722 | struct device_attribute *attr, char *buf) | ||
723 | { | ||
724 | struct s6e63m0 *lcd = dev_get_drvdata(dev); | ||
725 | char temp[3]; | ||
726 | |||
727 | sprintf(temp, "%d\n", lcd->gamma_table_count); | ||
728 | strcpy(buf, temp); | ||
729 | |||
730 | return strlen(buf); | ||
731 | } | ||
732 | static DEVICE_ATTR(gamma_table, 0644, | ||
733 | s6e63m0_sysfs_show_gamma_table, NULL); | ||
734 | |||
735 | static int __init s6e63m0_probe(struct spi_device *spi) | ||
736 | { | ||
737 | int ret = 0; | ||
738 | struct s6e63m0 *lcd = NULL; | ||
739 | struct lcd_device *ld = NULL; | ||
740 | struct backlight_device *bd = NULL; | ||
741 | |||
742 | lcd = kzalloc(sizeof(struct s6e63m0), GFP_KERNEL); | ||
743 | if (!lcd) | ||
744 | return -ENOMEM; | ||
745 | |||
746 | /* s6e63m0 lcd panel uses 3-wire 9bits SPI Mode. */ | ||
747 | spi->bits_per_word = 9; | ||
748 | |||
749 | ret = spi_setup(spi); | ||
750 | if (ret < 0) { | ||
751 | dev_err(&spi->dev, "spi setup failed.\n"); | ||
752 | goto out_free_lcd; | ||
753 | } | ||
754 | |||
755 | lcd->spi = spi; | ||
756 | lcd->dev = &spi->dev; | ||
757 | |||
758 | lcd->lcd_pd = (struct lcd_platform_data *)spi->dev.platform_data; | ||
759 | if (!lcd->lcd_pd) { | ||
760 | dev_err(&spi->dev, "platform data is NULL.\n"); | ||
761 | goto out_free_lcd; | ||
762 | } | ||
763 | |||
764 | ld = lcd_device_register("s6e63m0", &spi->dev, lcd, &s6e63m0_lcd_ops); | ||
765 | if (IS_ERR(ld)) { | ||
766 | ret = PTR_ERR(ld); | ||
767 | goto out_free_lcd; | ||
768 | } | ||
769 | |||
770 | lcd->ld = ld; | ||
771 | |||
772 | bd = backlight_device_register("s6e63m0bl-bl", &spi->dev, lcd, | ||
773 | &s6e63m0_backlight_ops, NULL); | ||
774 | if (IS_ERR(bd)) { | ||
775 | ret = PTR_ERR(bd); | ||
776 | goto out_lcd_unregister; | ||
777 | } | ||
778 | |||
779 | bd->props.max_brightness = MAX_BRIGHTNESS; | ||
780 | bd->props.brightness = MAX_BRIGHTNESS; | ||
781 | lcd->bd = bd; | ||
782 | |||
783 | /* | ||
784 | * it gets gamma table count available so it gets user | ||
785 | * know that. | ||
786 | */ | ||
787 | lcd->gamma_table_count = | ||
788 | sizeof(gamma_table) / (MAX_GAMMA_LEVEL * sizeof(int)); | ||
789 | |||
790 | ret = device_create_file(&(spi->dev), &dev_attr_gamma_mode); | ||
791 | if (ret < 0) | ||
792 | dev_err(&(spi->dev), "failed to add sysfs entries\n"); | ||
793 | |||
794 | ret = device_create_file(&(spi->dev), &dev_attr_gamma_table); | ||
795 | if (ret < 0) | ||
796 | dev_err(&(spi->dev), "failed to add sysfs entries\n"); | ||
797 | |||
798 | /* | ||
799 | * if lcd panel was on from bootloader like u-boot then | ||
800 | * do not lcd on. | ||
801 | */ | ||
802 | if (!lcd->lcd_pd->lcd_enabled) { | ||
803 | /* | ||
804 | * if lcd panel was off from bootloader then | ||
805 | * current lcd status is powerdown and then | ||
806 | * it enables lcd panel. | ||
807 | */ | ||
808 | lcd->power = FB_BLANK_POWERDOWN; | ||
809 | |||
810 | s6e63m0_power(lcd, FB_BLANK_UNBLANK); | ||
811 | } else | ||
812 | lcd->power = FB_BLANK_UNBLANK; | ||
813 | |||
814 | dev_set_drvdata(&spi->dev, lcd); | ||
815 | |||
816 | dev_info(&spi->dev, "s6e63m0 panel driver has been probed.\n"); | ||
817 | |||
818 | return 0; | ||
819 | |||
820 | out_lcd_unregister: | ||
821 | lcd_device_unregister(ld); | ||
822 | out_free_lcd: | ||
823 | kfree(lcd); | ||
824 | return ret; | ||
825 | } | ||
826 | |||
827 | static int __devexit s6e63m0_remove(struct spi_device *spi) | ||
828 | { | ||
829 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | ||
830 | |||
831 | s6e63m0_power(lcd, FB_BLANK_POWERDOWN); | ||
832 | lcd_device_unregister(lcd->ld); | ||
833 | kfree(lcd); | ||
834 | |||
835 | return 0; | ||
836 | } | ||
837 | |||
838 | #if defined(CONFIG_PM) | ||
839 | unsigned int before_power; | ||
840 | |||
841 | static int s6e63m0_suspend(struct spi_device *spi, pm_message_t mesg) | ||
842 | { | ||
843 | int ret = 0; | ||
844 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | ||
845 | |||
846 | dev_dbg(&spi->dev, "lcd->power = %d\n", lcd->power); | ||
847 | |||
848 | before_power = lcd->power; | ||
849 | |||
850 | /* | ||
851 | * when lcd panel is suspend, lcd panel becomes off | ||
852 | * regardless of status. | ||
853 | */ | ||
854 | ret = s6e63m0_power(lcd, FB_BLANK_POWERDOWN); | ||
855 | |||
856 | return ret; | ||
857 | } | ||
858 | |||
859 | static int s6e63m0_resume(struct spi_device *spi) | ||
860 | { | ||
861 | int ret = 0; | ||
862 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | ||
863 | |||
864 | /* | ||
865 | * after suspended, if lcd panel status is FB_BLANK_UNBLANK | ||
866 | * (at that time, before_power is FB_BLANK_UNBLANK) then | ||
867 | * it changes that status to FB_BLANK_POWERDOWN to get lcd on. | ||
868 | */ | ||
869 | if (before_power == FB_BLANK_UNBLANK) | ||
870 | lcd->power = FB_BLANK_POWERDOWN; | ||
871 | |||
872 | dev_dbg(&spi->dev, "before_power = %d\n", before_power); | ||
873 | |||
874 | ret = s6e63m0_power(lcd, before_power); | ||
875 | |||
876 | return ret; | ||
877 | } | ||
878 | #else | ||
879 | #define s6e63m0_suspend NULL | ||
880 | #define s6e63m0_resume NULL | ||
881 | #endif | ||
882 | |||
883 | /* Power down all displays on reboot, poweroff or halt. */ | ||
884 | static void s6e63m0_shutdown(struct spi_device *spi) | ||
885 | { | ||
886 | struct s6e63m0 *lcd = dev_get_drvdata(&spi->dev); | ||
887 | |||
888 | s6e63m0_power(lcd, FB_BLANK_POWERDOWN); | ||
889 | } | ||
890 | |||
891 | static struct spi_driver s6e63m0_driver = { | ||
892 | .driver = { | ||
893 | .name = "s6e63m0", | ||
894 | .bus = &spi_bus_type, | ||
895 | .owner = THIS_MODULE, | ||
896 | }, | ||
897 | .probe = s6e63m0_probe, | ||
898 | .remove = __devexit_p(s6e63m0_remove), | ||
899 | .shutdown = s6e63m0_shutdown, | ||
900 | .suspend = s6e63m0_suspend, | ||
901 | .resume = s6e63m0_resume, | ||
902 | }; | ||
903 | |||
904 | static int __init s6e63m0_init(void) | ||
905 | { | ||
906 | return spi_register_driver(&s6e63m0_driver); | ||
907 | } | ||
908 | |||
909 | static void __exit s6e63m0_exit(void) | ||
910 | { | ||
911 | spi_unregister_driver(&s6e63m0_driver); | ||
912 | } | ||
913 | |||
914 | module_init(s6e63m0_init); | ||
915 | module_exit(s6e63m0_exit); | ||
916 | |||
917 | MODULE_AUTHOR("InKi Dae <inki.dae@samsung.com>"); | ||
918 | MODULE_DESCRIPTION("S6E63M0 LCD Driver"); | ||
919 | MODULE_LICENSE("GPL"); | ||
920 | |||
diff --git a/drivers/video/backlight/s6e63m0_gamma.h b/drivers/video/backlight/s6e63m0_gamma.h new file mode 100644 index 000000000000..2c44bdb0696b --- /dev/null +++ b/drivers/video/backlight/s6e63m0_gamma.h | |||
@@ -0,0 +1,266 @@ | |||
1 | /* linux/drivers/video/samsung/s6e63m0_brightness.h | ||
2 | * | ||
3 | * Gamma level definitions. | ||
4 | * | ||
5 | * Copyright (c) 2009 Samsung Electronics | ||
6 | * InKi Dae <inki.dae@samsung.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _S6E63M0_BRIGHTNESS_H | ||
14 | #define _S6E63M0_BRIGHTNESS_H | ||
15 | |||
16 | #define MAX_GAMMA_LEVEL 11 | ||
17 | #define GAMMA_TABLE_COUNT 21 | ||
18 | |||
19 | /* gamma value: 2.2 */ | ||
20 | static const unsigned int s6e63m0_22_300[] = { | ||
21 | 0x18, 0x08, 0x24, 0x5f, 0x50, 0x2d, 0xB6, | ||
22 | 0xB9, 0xA7, 0xAd, 0xB1, 0x9f, 0xbe, 0xC0, | ||
23 | 0xB5, 0x00, 0xa0, 0x00, 0xa4, 0x00, 0xdb | ||
24 | }; | ||
25 | |||
26 | static const unsigned int s6e63m0_22_280[] = { | ||
27 | 0x18, 0x08, 0x24, 0x64, 0x56, 0x33, 0xB6, | ||
28 | 0xBA, 0xA8, 0xAC, 0xB1, 0x9D, 0xC1, 0xC1, | ||
29 | 0xB7, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6 | ||
30 | }; | ||
31 | |||
32 | static const unsigned int s6e63m0_22_260[] = { | ||
33 | 0x18, 0x08, 0x24, 0x66, 0x58, 0x34, 0xB6, | ||
34 | 0xBA, 0xA7, 0xAF, 0xB3, 0xA0, 0xC1, 0xC2, | ||
35 | 0xB7, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1 | ||
36 | |||
37 | }; | ||
38 | |||
39 | static const unsigned int s6e63m0_22_240[] = { | ||
40 | 0x18, 0x08, 0x24, 0x62, 0x54, 0x30, 0xB9, | ||
41 | 0xBB, 0xA9, 0xB0, 0xB3, 0xA1, 0xC1, 0xC3, | ||
42 | 0xB7, 0x00, 0x91, 0x00, 0x95, 0x00, 0xDA | ||
43 | |||
44 | }; | ||
45 | static const unsigned int s6e63m0_22_220[] = { | ||
46 | 0x18, 0x08, 0x24, 0x63, 0x53, 0x31, 0xB8, | ||
47 | 0xBC, 0xA9, 0xB0, 0xB5, 0xA2, 0xC4, 0xC4, | ||
48 | 0xB8, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2 | ||
49 | }; | ||
50 | |||
51 | static const unsigned int s6e63m0_22_200[] = { | ||
52 | 0x18, 0x08, 0x24, 0x66, 0x55, 0x34, 0xBA, | ||
53 | 0xBD, 0xAB, 0xB1, 0xB5, 0xA3, 0xC5, 0xC6, | ||
54 | 0xB9, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA | ||
55 | }; | ||
56 | |||
57 | static const unsigned int s6e63m0_22_170[] = { | ||
58 | 0x18, 0x08, 0x24, 0x69, 0x54, 0x37, 0xBB, | ||
59 | 0xBE, 0xAC, 0xB4, 0xB7, 0xA6, 0xC7, 0xC8, | ||
60 | 0xBC, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB | ||
61 | }; | ||
62 | |||
63 | static const unsigned int s6e63m0_22_140[] = { | ||
64 | 0x18, 0x08, 0x24, 0x6C, 0x54, 0x3A, 0xBC, | ||
65 | 0xBF, 0xAC, 0xB7, 0xBB, 0xA9, 0xC9, 0xC9, | ||
66 | 0xBE, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E | ||
67 | }; | ||
68 | |||
69 | static const unsigned int s6e63m0_22_110[] = { | ||
70 | 0x18, 0x08, 0x24, 0x70, 0x51, 0x3E, 0xBF, | ||
71 | 0xC1, 0xAF, 0xB9, 0xBC, 0xAB, 0xCC, 0xCC, | ||
72 | 0xC2, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D | ||
73 | }; | ||
74 | |||
75 | static const unsigned int s6e63m0_22_90[] = { | ||
76 | 0x18, 0x08, 0x24, 0x73, 0x4A, 0x3D, 0xC0, | ||
77 | 0xC2, 0xB1, 0xBB, 0xBE, 0xAC, 0xCE, 0xCF, | ||
78 | 0xC5, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82 | ||
79 | }; | ||
80 | |||
81 | static const unsigned int s6e63m0_22_30[] = { | ||
82 | 0x18, 0x08, 0x24, 0x78, 0xEC, 0x3D, 0xC8, | ||
83 | 0xC2, 0xB6, 0xC4, 0xC7, 0xB6, 0xD5, 0xD7, | ||
84 | 0xCC, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51 | ||
85 | }; | ||
86 | |||
87 | /* gamma value: 1.9 */ | ||
88 | static const unsigned int s6e63m0_19_300[] = { | ||
89 | 0x18, 0x08, 0x24, 0x61, 0x5F, 0x39, 0xBA, | ||
90 | 0xBD, 0xAD, 0xB1, 0xB6, 0xA5, 0xC4, 0xC5, | ||
91 | 0xBC, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB | ||
92 | }; | ||
93 | |||
94 | static const unsigned int s6e63m0_19_280[] = { | ||
95 | 0x18, 0x08, 0x24, 0x61, 0x60, 0x39, 0xBB, | ||
96 | 0xBE, 0xAD, 0xB2, 0xB6, 0xA6, 0xC5, 0xC7, | ||
97 | 0xBD, 0x00, 0x9B, 0x00, 0x9E, 0x00, 0xD5 | ||
98 | }; | ||
99 | |||
100 | static const unsigned int s6e63m0_19_260[] = { | ||
101 | 0x18, 0x08, 0x24, 0x63, 0x61, 0x3B, 0xBA, | ||
102 | 0xBE, 0xAC, 0xB3, 0xB8, 0xA7, 0xC6, 0xC8, | ||
103 | 0xBD, 0x00, 0x96, 0x00, 0x98, 0x00, 0xCF | ||
104 | }; | ||
105 | |||
106 | static const unsigned int s6e63m0_19_240[] = { | ||
107 | 0x18, 0x08, 0x24, 0x67, 0x64, 0x3F, 0xBB, | ||
108 | 0xBE, 0xAD, 0xB3, 0xB9, 0xA7, 0xC8, 0xC9, | ||
109 | 0xBE, 0x00, 0x90, 0x00, 0x92, 0x00, 0xC8 | ||
110 | }; | ||
111 | |||
112 | static const unsigned int s6e63m0_19_220[] = { | ||
113 | 0x18, 0x08, 0x24, 0x68, 0x64, 0x40, 0xBC, | ||
114 | 0xBF, 0xAF, 0xB4, 0xBA, 0xA9, 0xC8, 0xCA, | ||
115 | 0xBE, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0xC0 | ||
116 | }; | ||
117 | |||
118 | static const unsigned int s6e63m0_19_200[] = { | ||
119 | 0x18, 0x08, 0x24, 0x68, 0x64, 0x3F, 0xBE, | ||
120 | 0xC0, 0xB0, 0xB6, 0xBB, 0xAB, 0xC8, 0xCB, | ||
121 | 0xBF, 0x00, 0x85, 0x00, 0x86, 0x00, 0xB8 | ||
122 | }; | ||
123 | |||
124 | static const unsigned int s6e63m0_19_170[] = { | ||
125 | 0x18, 0x08, 0x24, 0x69, 0x64, 0x40, 0xBF, | ||
126 | 0xC1, 0xB0, 0xB9, 0xBE, 0xAD, 0xCB, 0xCD, | ||
127 | 0xC2, 0x00, 0x7A, 0x00, 0x7B, 0x00, 0xAA | ||
128 | }; | ||
129 | |||
130 | static const unsigned int s6e63m0_19_140[] = { | ||
131 | 0x18, 0x08, 0x24, 0x6E, 0x65, 0x45, 0xC0, | ||
132 | 0xC3, 0xB2, 0xBA, 0xBE, 0xAE, 0xCD, 0xD0, | ||
133 | 0xC4, 0x00, 0x70, 0x00, 0x70, 0x00, 0x9C | ||
134 | }; | ||
135 | |||
136 | static const unsigned int s6e63m0_19_110[] = { | ||
137 | 0x18, 0x08, 0x24, 0x6F, 0x65, 0x46, 0xC2, | ||
138 | 0xC4, 0xB3, 0xBF, 0xC2, 0xB2, 0xCF, 0xD1, | ||
139 | 0xC6, 0x00, 0x64, 0x00, 0x64, 0x00, 0x8D | ||
140 | }; | ||
141 | |||
142 | static const unsigned int s6e63m0_19_90[] = { | ||
143 | 0x18, 0x08, 0x24, 0x74, 0x60, 0x4A, 0xC3, | ||
144 | 0xC6, 0xB5, 0xBF, 0xC3, 0xB2, 0xD2, 0xD3, | ||
145 | 0xC8, 0x00, 0x5B, 0x00, 0x5B, 0x00, 0x81 | ||
146 | }; | ||
147 | |||
148 | static const unsigned int s6e63m0_19_30[] = { | ||
149 | 0x18, 0x08, 0x24, 0x84, 0x45, 0x4F, 0xCA, | ||
150 | 0xCB, 0xBC, 0xC9, 0xCB, 0xBC, 0xDA, 0xDA, | ||
151 | 0xD0, 0x00, 0x35, 0x00, 0x34, 0x00, 0x4E | ||
152 | }; | ||
153 | |||
154 | /* gamma value: 1.7 */ | ||
155 | static const unsigned int s6e63m0_17_300[] = { | ||
156 | 0x18, 0x08, 0x24, 0x70, 0x70, 0x4F, 0xBF, | ||
157 | 0xC2, 0xB2, 0xB8, 0xBC, 0xAC, 0xCB, 0xCD, | ||
158 | 0xC3, 0x00, 0xA0, 0x00, 0xA4, 0x00, 0xDB | ||
159 | }; | ||
160 | |||
161 | static const unsigned int s6e63m0_17_280[] = { | ||
162 | 0x18, 0x08, 0x24, 0x71, 0x71, 0x50, 0xBF, | ||
163 | 0xC2, 0xB2, 0xBA, 0xBE, 0xAE, 0xCB, 0xCD, | ||
164 | 0xC3, 0x00, 0x9C, 0x00, 0x9F, 0x00, 0xD6 | ||
165 | }; | ||
166 | |||
167 | static const unsigned int s6e63m0_17_260[] = { | ||
168 | 0x18, 0x08, 0x24, 0x72, 0x72, 0x50, 0xC0, | ||
169 | 0xC3, 0xB4, 0xB9, 0xBE, 0xAE, 0xCC, 0xCF, | ||
170 | 0xC4, 0x00, 0x97, 0x00, 0x9A, 0x00, 0xD1 | ||
171 | }; | ||
172 | |||
173 | static const unsigned int s6e63m0_17_240[] = { | ||
174 | 0x18, 0x08, 0x24, 0x71, 0x72, 0x4F, 0xC2, | ||
175 | 0xC4, 0xB5, 0xBB, 0xBF, 0xB0, 0xCC, 0xCF, | ||
176 | 0xC3, 0x00, 0x91, 0x00, 0x95, 0x00, 0xCA | ||
177 | }; | ||
178 | |||
179 | static const unsigned int s6e63m0_17_220[] = { | ||
180 | 0x18, 0x08, 0x24, 0x71, 0x73, 0x4F, 0xC2, | ||
181 | 0xC5, 0xB5, 0xBD, 0xC0, 0xB2, 0xCD, 0xD1, | ||
182 | 0xC5, 0x00, 0x8B, 0x00, 0x8E, 0x00, 0xC2 | ||
183 | }; | ||
184 | |||
185 | static const unsigned int s6e63m0_17_200[] = { | ||
186 | 0x18, 0x08, 0x24, 0x72, 0x75, 0x51, 0xC2, | ||
187 | 0xC6, 0xB5, 0xBF, 0xC1, 0xB3, 0xCE, 0xD1, | ||
188 | 0xC6, 0x00, 0x85, 0x00, 0x88, 0x00, 0xBA | ||
189 | }; | ||
190 | |||
191 | static const unsigned int s6e63m0_17_170[] = { | ||
192 | 0x18, 0x08, 0x24, 0x75, 0x77, 0x54, 0xC3, | ||
193 | 0xC7, 0xB7, 0xC0, 0xC3, 0xB4, 0xD1, 0xD3, | ||
194 | 0xC9, 0x00, 0x7B, 0x00, 0x7E, 0x00, 0xAB | ||
195 | }; | ||
196 | |||
197 | static const unsigned int s6e63m0_17_140[] = { | ||
198 | 0x18, 0x08, 0x24, 0x7B, 0x77, 0x58, 0xC3, | ||
199 | 0xC8, 0xB8, 0xC2, 0xC6, 0xB6, 0xD3, 0xD4, | ||
200 | 0xCA, 0x00, 0x71, 0x00, 0x73, 0x00, 0x9E | ||
201 | }; | ||
202 | |||
203 | static const unsigned int s6e63m0_17_110[] = { | ||
204 | 0x18, 0x08, 0x24, 0x81, 0x7B, 0x5D, 0xC6, | ||
205 | 0xCA, 0xBB, 0xC3, 0xC7, 0xB8, 0xD6, 0xD8, | ||
206 | 0xCD, 0x00, 0x65, 0x00, 0x67, 0x00, 0x8D | ||
207 | }; | ||
208 | |||
209 | static const unsigned int s6e63m0_17_90[] = { | ||
210 | 0x18, 0x08, 0x24, 0x82, 0x7A, 0x5B, 0xC8, | ||
211 | 0xCB, 0xBD, 0xC5, 0xCA, 0xBA, 0xD6, 0xD8, | ||
212 | 0xCE, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x82 | ||
213 | }; | ||
214 | |||
215 | static const unsigned int s6e63m0_17_30[] = { | ||
216 | 0x18, 0x08, 0x24, 0x8F, 0x73, 0x63, 0xD1, | ||
217 | 0xD0, 0xC5, 0xCC, 0xD1, 0xC2, 0xDE, 0xE0, | ||
218 | 0xD6, 0x00, 0x39, 0x00, 0x36, 0x00, 0x51 | ||
219 | }; | ||
220 | |||
221 | struct s6e63m0_gamma { | ||
222 | unsigned int *gamma_22_table[MAX_GAMMA_LEVEL]; | ||
223 | unsigned int *gamma_19_table[MAX_GAMMA_LEVEL]; | ||
224 | unsigned int *gamma_17_table[MAX_GAMMA_LEVEL]; | ||
225 | }; | ||
226 | |||
227 | static struct s6e63m0_gamma gamma_table = { | ||
228 | .gamma_22_table[0] = (unsigned int *)&s6e63m0_22_30, | ||
229 | .gamma_22_table[1] = (unsigned int *)&s6e63m0_22_90, | ||
230 | .gamma_22_table[2] = (unsigned int *)&s6e63m0_22_110, | ||
231 | .gamma_22_table[3] = (unsigned int *)&s6e63m0_22_140, | ||
232 | .gamma_22_table[4] = (unsigned int *)&s6e63m0_22_170, | ||
233 | .gamma_22_table[5] = (unsigned int *)&s6e63m0_22_200, | ||
234 | .gamma_22_table[6] = (unsigned int *)&s6e63m0_22_220, | ||
235 | .gamma_22_table[7] = (unsigned int *)&s6e63m0_22_240, | ||
236 | .gamma_22_table[8] = (unsigned int *)&s6e63m0_22_260, | ||
237 | .gamma_22_table[9] = (unsigned int *)&s6e63m0_22_280, | ||
238 | .gamma_22_table[10] = (unsigned int *)&s6e63m0_22_300, | ||
239 | |||
240 | .gamma_19_table[0] = (unsigned int *)&s6e63m0_19_30, | ||
241 | .gamma_19_table[1] = (unsigned int *)&s6e63m0_19_90, | ||
242 | .gamma_19_table[2] = (unsigned int *)&s6e63m0_19_110, | ||
243 | .gamma_19_table[3] = (unsigned int *)&s6e63m0_19_140, | ||
244 | .gamma_19_table[4] = (unsigned int *)&s6e63m0_19_170, | ||
245 | .gamma_19_table[5] = (unsigned int *)&s6e63m0_19_200, | ||
246 | .gamma_19_table[6] = (unsigned int *)&s6e63m0_19_220, | ||
247 | .gamma_19_table[7] = (unsigned int *)&s6e63m0_19_240, | ||
248 | .gamma_19_table[8] = (unsigned int *)&s6e63m0_19_260, | ||
249 | .gamma_19_table[9] = (unsigned int *)&s6e63m0_19_280, | ||
250 | .gamma_19_table[10] = (unsigned int *)&s6e63m0_19_300, | ||
251 | |||
252 | .gamma_17_table[0] = (unsigned int *)&s6e63m0_17_30, | ||
253 | .gamma_17_table[1] = (unsigned int *)&s6e63m0_17_90, | ||
254 | .gamma_17_table[2] = (unsigned int *)&s6e63m0_17_110, | ||
255 | .gamma_17_table[3] = (unsigned int *)&s6e63m0_17_140, | ||
256 | .gamma_17_table[4] = (unsigned int *)&s6e63m0_17_170, | ||
257 | .gamma_17_table[5] = (unsigned int *)&s6e63m0_17_200, | ||
258 | .gamma_17_table[6] = (unsigned int *)&s6e63m0_17_220, | ||
259 | .gamma_17_table[7] = (unsigned int *)&s6e63m0_17_240, | ||
260 | .gamma_17_table[8] = (unsigned int *)&s6e63m0_17_260, | ||
261 | .gamma_17_table[9] = (unsigned int *)&s6e63m0_17_280, | ||
262 | .gamma_17_table[10] = (unsigned int *)&s6e63m0_17_300, | ||
263 | }; | ||
264 | |||
265 | #endif | ||
266 | |||
diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 23b2a8c0dbfc..b020ba7f1cf2 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c | |||
@@ -501,7 +501,9 @@ static irqreturn_t bfin_bf54x_irq_error(int irq, void *dev_id) | |||
501 | 501 | ||
502 | static int __devinit bfin_bf54x_probe(struct platform_device *pdev) | 502 | static int __devinit bfin_bf54x_probe(struct platform_device *pdev) |
503 | { | 503 | { |
504 | #ifndef NO_BL_SUPPORT | ||
504 | struct backlight_properties props; | 505 | struct backlight_properties props; |
506 | #endif | ||
505 | struct bfin_bf54xfb_info *info; | 507 | struct bfin_bf54xfb_info *info; |
506 | struct fb_info *fbinfo; | 508 | struct fb_info *fbinfo; |
507 | int ret; | 509 | int ret; |
@@ -654,7 +656,8 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev) | |||
654 | printk(KERN_ERR DRIVER_NAME | 656 | printk(KERN_ERR DRIVER_NAME |
655 | ": unable to register backlight.\n"); | 657 | ": unable to register backlight.\n"); |
656 | ret = -EINVAL; | 658 | ret = -EINVAL; |
657 | goto out9; | 659 | unregister_framebuffer(fbinfo); |
660 | goto out8; | ||
658 | } | 661 | } |
659 | 662 | ||
660 | lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops); | 663 | lcd_dev = lcd_device_register(DRIVER_NAME, &pdev->dev, NULL, &bfin_lcd_ops); |
@@ -663,8 +666,6 @@ static int __devinit bfin_bf54x_probe(struct platform_device *pdev) | |||
663 | 666 | ||
664 | return 0; | 667 | return 0; |
665 | 668 | ||
666 | out9: | ||
667 | unregister_framebuffer(fbinfo); | ||
668 | out8: | 669 | out8: |
669 | free_irq(info->irq, info); | 670 | free_irq(info->irq, info); |
670 | out7: | 671 | out7: |
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index c2ec3dcd4e91..7a50272eaab9 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c | |||
@@ -420,7 +420,9 @@ static irqreturn_t bfin_t350mcqb_irq_error(int irq, void *dev_id) | |||
420 | 420 | ||
421 | static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) | 421 | static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) |
422 | { | 422 | { |
423 | #ifndef NO_BL_SUPPORT | ||
423 | struct backlight_properties props; | 424 | struct backlight_properties props; |
425 | #endif | ||
424 | struct bfin_t350mcqbfb_info *info; | 426 | struct bfin_t350mcqbfb_info *info; |
425 | struct fb_info *fbinfo; | 427 | struct fb_info *fbinfo; |
426 | int ret; | 428 | int ret; |
@@ -550,7 +552,8 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) | |||
550 | printk(KERN_ERR DRIVER_NAME | 552 | printk(KERN_ERR DRIVER_NAME |
551 | ": unable to register backlight.\n"); | 553 | ": unable to register backlight.\n"); |
552 | ret = -EINVAL; | 554 | ret = -EINVAL; |
553 | goto out9; | 555 | unregister_framebuffer(fbinfo); |
556 | goto out8; | ||
554 | } | 557 | } |
555 | 558 | ||
556 | lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); | 559 | lcd_dev = lcd_device_register(DRIVER_NAME, NULL, &bfin_lcd_ops); |
@@ -559,8 +562,6 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) | |||
559 | 562 | ||
560 | return 0; | 563 | return 0; |
561 | 564 | ||
562 | out9: | ||
563 | unregister_framebuffer(fbinfo); | ||
564 | out8: | 565 | out8: |
565 | free_irq(info->irq, info); | 566 | free_irq(info->irq, info); |
566 | out7: | 567 | out7: |
diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index d4471b4c0374..dce8c97b4333 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c | |||
@@ -71,7 +71,8 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
71 | "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", | 71 | "S3 Trio64UV+", "S3 Trio64V2/DX", "S3 Trio64V2/GX", |
72 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", | 72 | "S3 Plato/PX", "S3 Aurora64VP", "S3 Virge", |
73 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", | 73 | "S3 Virge/VX", "S3 Virge/DX", "S3 Virge/GX", |
74 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P"}; | 74 | "S3 Virge/GX2", "S3 Virge/GX2P", "S3 Virge/GX2P", |
75 | "S3 Trio3D/1X", "S3 Trio3D/2X", "S3 Trio3D/2X"}; | ||
75 | 76 | ||
76 | #define CHIP_UNKNOWN 0x00 | 77 | #define CHIP_UNKNOWN 0x00 |
77 | #define CHIP_732_TRIO32 0x01 | 78 | #define CHIP_732_TRIO32 0x01 |
@@ -89,10 +90,14 @@ static const char * const s3_names[] = {"S3 Unknown", "S3 Trio32", "S3 Trio64", | |||
89 | #define CHIP_356_VIRGE_GX2 0x0D | 90 | #define CHIP_356_VIRGE_GX2 0x0D |
90 | #define CHIP_357_VIRGE_GX2P 0x0E | 91 | #define CHIP_357_VIRGE_GX2P 0x0E |
91 | #define CHIP_359_VIRGE_GX2P 0x0F | 92 | #define CHIP_359_VIRGE_GX2P 0x0F |
93 | #define CHIP_360_TRIO3D_1X 0x10 | ||
94 | #define CHIP_362_TRIO3D_2X 0x11 | ||
95 | #define CHIP_368_TRIO3D_2X 0x12 | ||
92 | 96 | ||
93 | #define CHIP_XXX_TRIO 0x80 | 97 | #define CHIP_XXX_TRIO 0x80 |
94 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 | 98 | #define CHIP_XXX_TRIO64V2_DXGX 0x81 |
95 | #define CHIP_XXX_VIRGE_DXGX 0x82 | 99 | #define CHIP_XXX_VIRGE_DXGX 0x82 |
100 | #define CHIP_36X_TRIO3D_1X_2X 0x83 | ||
96 | 101 | ||
97 | #define CHIP_UNDECIDED_FLAG 0x80 | 102 | #define CHIP_UNDECIDED_FLAG 0x80 |
98 | #define CHIP_MASK 0xFF | 103 | #define CHIP_MASK 0xFF |
@@ -324,6 +329,7 @@ static void s3fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) | |||
324 | 329 | ||
325 | static void s3_set_pixclock(struct fb_info *info, u32 pixclock) | 330 | static void s3_set_pixclock(struct fb_info *info, u32 pixclock) |
326 | { | 331 | { |
332 | struct s3fb_info *par = info->par; | ||
327 | u16 m, n, r; | 333 | u16 m, n, r; |
328 | u8 regval; | 334 | u8 regval; |
329 | int rv; | 335 | int rv; |
@@ -339,7 +345,13 @@ static void s3_set_pixclock(struct fb_info *info, u32 pixclock) | |||
339 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); | 345 | vga_w(NULL, VGA_MIS_W, regval | VGA_MIS_ENB_PLL_LOAD); |
340 | 346 | ||
341 | /* Set S3 clock registers */ | 347 | /* Set S3 clock registers */ |
342 | vga_wseq(NULL, 0x12, ((n - 2) | (r << 5))); | 348 | if (par->chip == CHIP_360_TRIO3D_1X || |
349 | par->chip == CHIP_362_TRIO3D_2X || | ||
350 | par->chip == CHIP_368_TRIO3D_2X) { | ||
351 | vga_wseq(NULL, 0x12, (n - 2) | ((r & 3) << 6)); /* n and two bits of r */ | ||
352 | vga_wseq(NULL, 0x29, r >> 2); /* remaining highest bit of r */ | ||
353 | } else | ||
354 | vga_wseq(NULL, 0x12, (n - 2) | (r << 5)); | ||
343 | vga_wseq(NULL, 0x13, m - 2); | 355 | vga_wseq(NULL, 0x13, m - 2); |
344 | 356 | ||
345 | udelay(1000); | 357 | udelay(1000); |
@@ -456,7 +468,7 @@ static int s3fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | |||
456 | static int s3fb_set_par(struct fb_info *info) | 468 | static int s3fb_set_par(struct fb_info *info) |
457 | { | 469 | { |
458 | struct s3fb_info *par = info->par; | 470 | struct s3fb_info *par = info->par; |
459 | u32 value, mode, hmul, offset_value, screen_size, multiplex; | 471 | u32 value, mode, hmul, offset_value, screen_size, multiplex, dbytes; |
460 | u32 bpp = info->var.bits_per_pixel; | 472 | u32 bpp = info->var.bits_per_pixel; |
461 | 473 | ||
462 | if (bpp != 0) { | 474 | if (bpp != 0) { |
@@ -518,7 +530,7 @@ static int s3fb_set_par(struct fb_info *info) | |||
518 | svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ | 530 | svga_wcrt_mask(0x33, 0x00, 0x08); /* no DDR ? */ |
519 | svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ | 531 | svga_wcrt_mask(0x43, 0x00, 0x01); /* no DDR ? */ |
520 | 532 | ||
521 | svga_wcrt_mask(0x5D, 0x00, 0x28); // Clear strange HSlen bits | 533 | svga_wcrt_mask(0x5D, 0x00, 0x28); /* Clear strange HSlen bits */ |
522 | 534 | ||
523 | /* svga_wcrt_mask(0x58, 0x03, 0x03); */ | 535 | /* svga_wcrt_mask(0x58, 0x03, 0x03); */ |
524 | 536 | ||
@@ -530,10 +542,14 @@ static int s3fb_set_par(struct fb_info *info) | |||
530 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); | 542 | pr_debug("fb%d: offset register : %d\n", info->node, offset_value); |
531 | svga_wcrt_multi(s3_offset_regs, offset_value); | 543 | svga_wcrt_multi(s3_offset_regs, offset_value); |
532 | 544 | ||
533 | vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ | 545 | if (par->chip != CHIP_360_TRIO3D_1X && |
534 | vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ | 546 | par->chip != CHIP_362_TRIO3D_2X && |
535 | vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ | 547 | par->chip != CHIP_368_TRIO3D_2X) { |
536 | vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ | 548 | vga_wcrt(NULL, 0x54, 0x18); /* M parameter */ |
549 | vga_wcrt(NULL, 0x60, 0xff); /* N parameter */ | ||
550 | vga_wcrt(NULL, 0x61, 0xff); /* L parameter */ | ||
551 | vga_wcrt(NULL, 0x62, 0xff); /* L parameter */ | ||
552 | } | ||
537 | 553 | ||
538 | vga_wcrt(NULL, 0x3A, 0x35); | 554 | vga_wcrt(NULL, 0x3A, 0x35); |
539 | svga_wattr(0x33, 0x00); | 555 | svga_wattr(0x33, 0x00); |
@@ -570,6 +586,16 @@ static int s3fb_set_par(struct fb_info *info) | |||
570 | vga_wcrt(NULL, 0x66, 0x90); | 586 | vga_wcrt(NULL, 0x66, 0x90); |
571 | } | 587 | } |
572 | 588 | ||
589 | if (par->chip == CHIP_360_TRIO3D_1X || | ||
590 | par->chip == CHIP_362_TRIO3D_2X || | ||
591 | par->chip == CHIP_368_TRIO3D_2X) { | ||
592 | dbytes = info->var.xres * ((bpp+7)/8); | ||
593 | vga_wcrt(NULL, 0x91, (dbytes + 7) / 8); | ||
594 | vga_wcrt(NULL, 0x90, (((dbytes + 7) / 8) >> 8) | 0x80); | ||
595 | |||
596 | vga_wcrt(NULL, 0x66, 0x81); | ||
597 | } | ||
598 | |||
573 | svga_wcrt_mask(0x31, 0x00, 0x40); | 599 | svga_wcrt_mask(0x31, 0x00, 0x40); |
574 | multiplex = 0; | 600 | multiplex = 0; |
575 | hmul = 1; | 601 | hmul = 1; |
@@ -615,11 +641,13 @@ static int s3fb_set_par(struct fb_info *info) | |||
615 | break; | 641 | break; |
616 | case 3: | 642 | case 3: |
617 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); | 643 | pr_debug("fb%d: 8 bit pseudocolor\n", info->node); |
618 | if (info->var.pixclock > 20000) { | 644 | svga_wcrt_mask(0x50, 0x00, 0x30); |
619 | svga_wcrt_mask(0x50, 0x00, 0x30); | 645 | if (info->var.pixclock > 20000 || |
646 | par->chip == CHIP_360_TRIO3D_1X || | ||
647 | par->chip == CHIP_362_TRIO3D_2X || | ||
648 | par->chip == CHIP_368_TRIO3D_2X) | ||
620 | svga_wcrt_mask(0x67, 0x00, 0xF0); | 649 | svga_wcrt_mask(0x67, 0x00, 0xF0); |
621 | } else { | 650 | else { |
622 | svga_wcrt_mask(0x50, 0x00, 0x30); | ||
623 | svga_wcrt_mask(0x67, 0x10, 0xF0); | 651 | svga_wcrt_mask(0x67, 0x10, 0xF0); |
624 | multiplex = 1; | 652 | multiplex = 1; |
625 | } | 653 | } |
@@ -634,7 +662,10 @@ static int s3fb_set_par(struct fb_info *info) | |||
634 | } else { | 662 | } else { |
635 | svga_wcrt_mask(0x50, 0x10, 0x30); | 663 | svga_wcrt_mask(0x50, 0x10, 0x30); |
636 | svga_wcrt_mask(0x67, 0x30, 0xF0); | 664 | svga_wcrt_mask(0x67, 0x30, 0xF0); |
637 | hmul = 2; | 665 | if (par->chip != CHIP_360_TRIO3D_1X && |
666 | par->chip != CHIP_362_TRIO3D_2X && | ||
667 | par->chip != CHIP_368_TRIO3D_2X) | ||
668 | hmul = 2; | ||
638 | } | 669 | } |
639 | break; | 670 | break; |
640 | case 5: | 671 | case 5: |
@@ -647,7 +678,10 @@ static int s3fb_set_par(struct fb_info *info) | |||
647 | } else { | 678 | } else { |
648 | svga_wcrt_mask(0x50, 0x10, 0x30); | 679 | svga_wcrt_mask(0x50, 0x10, 0x30); |
649 | svga_wcrt_mask(0x67, 0x50, 0xF0); | 680 | svga_wcrt_mask(0x67, 0x50, 0xF0); |
650 | hmul = 2; | 681 | if (par->chip != CHIP_360_TRIO3D_1X && |
682 | par->chip != CHIP_362_TRIO3D_2X && | ||
683 | par->chip != CHIP_368_TRIO3D_2X) | ||
684 | hmul = 2; | ||
651 | } | 685 | } |
652 | break; | 686 | break; |
653 | case 6: | 687 | case 6: |
@@ -866,6 +900,17 @@ static int __devinit s3_identification(int chip) | |||
866 | return CHIP_385_VIRGE_GX; | 900 | return CHIP_385_VIRGE_GX; |
867 | } | 901 | } |
868 | 902 | ||
903 | if (chip == CHIP_36X_TRIO3D_1X_2X) { | ||
904 | switch (vga_rcrt(NULL, 0x2f)) { | ||
905 | case 0x00: | ||
906 | return CHIP_360_TRIO3D_1X; | ||
907 | case 0x01: | ||
908 | return CHIP_362_TRIO3D_2X; | ||
909 | case 0x02: | ||
910 | return CHIP_368_TRIO3D_2X; | ||
911 | } | ||
912 | } | ||
913 | |||
869 | return CHIP_UNKNOWN; | 914 | return CHIP_UNKNOWN; |
870 | } | 915 | } |
871 | 916 | ||
@@ -930,17 +975,32 @@ static int __devinit s3_pci_probe(struct pci_dev *dev, const struct pci_device_i | |||
930 | vga_wcrt(NULL, 0x38, 0x48); | 975 | vga_wcrt(NULL, 0x38, 0x48); |
931 | vga_wcrt(NULL, 0x39, 0xA5); | 976 | vga_wcrt(NULL, 0x39, 0xA5); |
932 | 977 | ||
933 | /* Find how many physical memory there is on card */ | 978 | /* Identify chip type */ |
934 | /* 0x36 register is accessible even if other registers are locked */ | ||
935 | regval = vga_rcrt(NULL, 0x36); | ||
936 | info->screen_size = s3_memsizes[regval >> 5] << 10; | ||
937 | info->fix.smem_len = info->screen_size; | ||
938 | |||
939 | par->chip = id->driver_data & CHIP_MASK; | 979 | par->chip = id->driver_data & CHIP_MASK; |
940 | par->rev = vga_rcrt(NULL, 0x2f); | 980 | par->rev = vga_rcrt(NULL, 0x2f); |
941 | if (par->chip & CHIP_UNDECIDED_FLAG) | 981 | if (par->chip & CHIP_UNDECIDED_FLAG) |
942 | par->chip = s3_identification(par->chip); | 982 | par->chip = s3_identification(par->chip); |
943 | 983 | ||
984 | /* Find how many physical memory there is on card */ | ||
985 | /* 0x36 register is accessible even if other registers are locked */ | ||
986 | regval = vga_rcrt(NULL, 0x36); | ||
987 | if (par->chip == CHIP_360_TRIO3D_1X || | ||
988 | par->chip == CHIP_362_TRIO3D_2X || | ||
989 | par->chip == CHIP_368_TRIO3D_2X) { | ||
990 | switch ((regval & 0xE0) >> 5) { | ||
991 | case 0: /* 8MB -- only 4MB usable for display */ | ||
992 | case 1: /* 4MB with 32-bit bus */ | ||
993 | case 2: /* 4MB */ | ||
994 | info->screen_size = 4 << 20; | ||
995 | break; | ||
996 | case 6: /* 2MB */ | ||
997 | info->screen_size = 2 << 20; | ||
998 | break; | ||
999 | } | ||
1000 | } else | ||
1001 | info->screen_size = s3_memsizes[regval >> 5] << 10; | ||
1002 | info->fix.smem_len = info->screen_size; | ||
1003 | |||
944 | /* Find MCLK frequency */ | 1004 | /* Find MCLK frequency */ |
945 | regval = vga_rseq(NULL, 0x10); | 1005 | regval = vga_rseq(NULL, 0x10); |
946 | par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); | 1006 | par->mclk_freq = ((vga_rseq(NULL, 0x11) + 2) * 14318) / ((regval & 0x1F) + 2); |
@@ -1131,6 +1191,7 @@ static struct pci_device_id s3_devices[] __devinitdata = { | |||
1131 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, | 1191 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A10), .driver_data = CHIP_356_VIRGE_GX2}, |
1132 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, | 1192 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A11), .driver_data = CHIP_357_VIRGE_GX2P}, |
1133 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, | 1193 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A12), .driver_data = CHIP_359_VIRGE_GX2P}, |
1194 | {PCI_DEVICE(PCI_VENDOR_ID_S3, 0x8A13), .driver_data = CHIP_36X_TRIO3D_1X_2X}, | ||
1134 | 1195 | ||
1135 | {0, 0, 0, 0, 0, 0, 0} | 1196 | {0, 0, 0, 0, 0, 0, 0} |
1136 | }; | 1197 | }; |
diff --git a/drivers/video/via/viafbdev.c b/drivers/video/via/viafbdev.c index 2bc40e682f95..1082541358f0 100644 --- a/drivers/video/via/viafbdev.c +++ b/drivers/video/via/viafbdev.c | |||
@@ -578,14 +578,9 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) | |||
578 | break; | 578 | break; |
579 | 579 | ||
580 | case VIAFB_SET_GAMMA_LUT: | 580 | case VIAFB_SET_GAMMA_LUT: |
581 | viafb_gamma_table = kmalloc(256 * sizeof(u32), GFP_KERNEL); | 581 | viafb_gamma_table = memdup_user(argp, 256 * sizeof(u32)); |
582 | if (!viafb_gamma_table) | 582 | if (IS_ERR(viafb_gamma_table)) |
583 | return -ENOMEM; | 583 | return PTR_ERR(viafb_gamma_table); |
584 | if (copy_from_user(viafb_gamma_table, argp, | ||
585 | 256 * sizeof(u32))) { | ||
586 | kfree(viafb_gamma_table); | ||
587 | return -EFAULT; | ||
588 | } | ||
589 | viafb_set_gamma_table(viafb_bpp, viafb_gamma_table); | 584 | viafb_set_gamma_table(viafb_bpp, viafb_gamma_table); |
590 | kfree(viafb_gamma_table); | 585 | kfree(viafb_gamma_table); |
591 | break; | 586 | break; |