diff options
author | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2010-06-30 06:16:24 -0400 |
---|---|---|
committer | Uwe Kleine-König <u.kleine-koenig@pengutronix.de> | 2010-07-26 08:27:25 -0400 |
commit | 2dcf78c0eeae3bd07082821557014f25f02ca2e9 (patch) | |
tree | 8ca5c4c7f35c9a9ab07fcd9732124c905e609aa1 /drivers | |
parent | 6b6322676add0fa2713d0ec89a28390fd4d907f5 (diff) | |
parent | 5109a4597f7e758b8d20694392d0361a0b4c43b1 (diff) |
Merge branch 'imx/for-2.6.36' of git://git.pengutronix.de/git/ukl/linux-2.6 into HEAD
There are some more conflicts than detected by git, namely support for
the newly added cpuimx machines needed to be converted to dynamic device
registration.
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Conflicts:
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/devices.c
arch/arm/mach-imx/devices.h
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
arch/arm/mach-mx2/Kconfig
arch/arm/mach-mx25/Makefile
arch/arm/mach-mx25/devices.c
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-mxc/include/mach/mxc_nand.h
Diffstat (limited to 'drivers')
359 files changed, 25345 insertions, 4965 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index f42a03029b7c..91874e048552 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_PCI) += pci/ | |||
10 | obj-$(CONFIG_PARISC) += parisc/ | 10 | obj-$(CONFIG_PARISC) += parisc/ |
11 | obj-$(CONFIG_RAPIDIO) += rapidio/ | 11 | obj-$(CONFIG_RAPIDIO) += rapidio/ |
12 | obj-y += video/ | 12 | obj-y += video/ |
13 | obj-y += idle/ | ||
13 | obj-$(CONFIG_ACPI) += acpi/ | 14 | obj-$(CONFIG_ACPI) += acpi/ |
14 | obj-$(CONFIG_SFI) += sfi/ | 15 | obj-$(CONFIG_SFI) += sfi/ |
15 | # PnP must come after ACPI since it will eventually need to check if acpi | 16 | # PnP must come after ACPI since it will eventually need to check if acpi |
@@ -91,7 +92,6 @@ obj-$(CONFIG_EISA) += eisa/ | |||
91 | obj-y += lguest/ | 92 | obj-y += lguest/ |
92 | obj-$(CONFIG_CPU_FREQ) += cpufreq/ | 93 | obj-$(CONFIG_CPU_FREQ) += cpufreq/ |
93 | obj-$(CONFIG_CPU_IDLE) += cpuidle/ | 94 | obj-$(CONFIG_CPU_IDLE) += cpuidle/ |
94 | obj-y += idle/ | ||
95 | obj-$(CONFIG_MMC) += mmc/ | 95 | obj-$(CONFIG_MMC) += mmc/ |
96 | obj-$(CONFIG_MEMSTICK) += memstick/ | 96 | obj-$(CONFIG_MEMSTICK) += memstick/ |
97 | obj-$(CONFIG_NEW_LEDS) += leds/ | 97 | obj-$(CONFIG_NEW_LEDS) += leds/ |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 93d2c7971df6..746411518802 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
@@ -360,4 +360,13 @@ config ACPI_SBS | |||
360 | To compile this driver as a module, choose M here: | 360 | To compile this driver as a module, choose M here: |
361 | the modules will be called sbs and sbshc. | 361 | the modules will be called sbs and sbshc. |
362 | 362 | ||
363 | config ACPI_HED | ||
364 | tristate "Hardware Error Device" | ||
365 | help | ||
366 | This driver supports the Hardware Error Device (PNP0C33), | ||
367 | which is used to report some hardware errors notified via | ||
368 | SCI, mainly the corrected errors. | ||
369 | |||
370 | source "drivers/acpi/apei/Kconfig" | ||
371 | |||
363 | endif # ACPI | 372 | endif # ACPI |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index a8d8998dd5c5..6ee33169e1dc 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
@@ -19,7 +19,7 @@ obj-y += acpi.o \ | |||
19 | 19 | ||
20 | # All the builtin files are in the "acpi." module_param namespace. | 20 | # All the builtin files are in the "acpi." module_param namespace. |
21 | acpi-y += osl.o utils.o reboot.o | 21 | acpi-y += osl.o utils.o reboot.o |
22 | acpi-y += hest.o | 22 | acpi-y += atomicio.o |
23 | 23 | ||
24 | # sleep related files | 24 | # sleep related files |
25 | acpi-y += wakeup.o | 25 | acpi-y += wakeup.o |
@@ -59,6 +59,7 @@ obj-$(CONFIG_ACPI_BATTERY) += battery.o | |||
59 | obj-$(CONFIG_ACPI_SBS) += sbshc.o | 59 | obj-$(CONFIG_ACPI_SBS) += sbshc.o |
60 | obj-$(CONFIG_ACPI_SBS) += sbs.o | 60 | obj-$(CONFIG_ACPI_SBS) += sbs.o |
61 | obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o | 61 | obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o |
62 | obj-$(CONFIG_ACPI_HED) += hed.o | ||
62 | 63 | ||
63 | # processor has its own "processor." module_param namespace | 64 | # processor has its own "processor." module_param namespace |
64 | processor-y := processor_driver.o processor_throttling.o | 65 | processor-y := processor_driver.o processor_throttling.o |
@@ -66,3 +67,5 @@ processor-y += processor_idle.o processor_thermal.o | |||
66 | processor-$(CONFIG_CPU_FREQ) += processor_perflib.o | 67 | processor-$(CONFIG_CPU_FREQ) += processor_perflib.o |
67 | 68 | ||
68 | obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o | 69 | obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o |
70 | |||
71 | obj-$(CONFIG_ACPI_APEI) += apei/ | ||
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 62122134693b..d269a8f3329c 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
@@ -43,6 +43,10 @@ static DEFINE_MUTEX(isolated_cpus_lock); | |||
43 | #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) | 43 | #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) |
44 | #define CPUID5_ECX_INTERRUPT_BREAK (0x2) | 44 | #define CPUID5_ECX_INTERRUPT_BREAK (0x2) |
45 | static unsigned long power_saving_mwait_eax; | 45 | static unsigned long power_saving_mwait_eax; |
46 | |||
47 | static unsigned char tsc_detected_unstable; | ||
48 | static unsigned char tsc_marked_unstable; | ||
49 | |||
46 | static void power_saving_mwait_init(void) | 50 | static void power_saving_mwait_init(void) |
47 | { | 51 | { |
48 | unsigned int eax, ebx, ecx, edx; | 52 | unsigned int eax, ebx, ecx, edx; |
@@ -87,8 +91,8 @@ static void power_saving_mwait_init(void) | |||
87 | 91 | ||
88 | /*FALL THROUGH*/ | 92 | /*FALL THROUGH*/ |
89 | default: | 93 | default: |
90 | /* TSC could halt in idle, so notify users */ | 94 | /* TSC could halt in idle */ |
91 | mark_tsc_unstable("TSC halts in idle"); | 95 | tsc_detected_unstable = 1; |
92 | } | 96 | } |
93 | #endif | 97 | #endif |
94 | } | 98 | } |
@@ -168,16 +172,14 @@ static int power_saving_thread(void *data) | |||
168 | 172 | ||
169 | do_sleep = 0; | 173 | do_sleep = 0; |
170 | 174 | ||
171 | current_thread_info()->status &= ~TS_POLLING; | ||
172 | /* | ||
173 | * TS_POLLING-cleared state must be visible before we test | ||
174 | * NEED_RESCHED: | ||
175 | */ | ||
176 | smp_mb(); | ||
177 | |||
178 | expire_time = jiffies + HZ * (100 - idle_pct) / 100; | 175 | expire_time = jiffies + HZ * (100 - idle_pct) / 100; |
179 | 176 | ||
180 | while (!need_resched()) { | 177 | while (!need_resched()) { |
178 | if (tsc_detected_unstable && !tsc_marked_unstable) { | ||
179 | /* TSC could halt in idle, so notify users */ | ||
180 | mark_tsc_unstable("TSC halts in idle"); | ||
181 | tsc_marked_unstable = 1; | ||
182 | } | ||
181 | local_irq_disable(); | 183 | local_irq_disable(); |
182 | cpu = smp_processor_id(); | 184 | cpu = smp_processor_id(); |
183 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, | 185 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, |
@@ -200,8 +202,6 @@ static int power_saving_thread(void *data) | |||
200 | } | 202 | } |
201 | } | 203 | } |
202 | 204 | ||
203 | current_thread_info()->status |= TS_POLLING; | ||
204 | |||
205 | /* | 205 | /* |
206 | * current sched_rt has threshold for rt task running time. | 206 | * current sched_rt has threshold for rt task running time. |
207 | * When a rt task uses 95% CPU time, the rt thread will be | 207 | * When a rt task uses 95% CPU time, the rt thread will be |
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 7c7bbb4d402c..d5a5efc043bf 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c | |||
@@ -69,7 +69,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
69 | 69 | ||
70 | acpi_status acpi_enable(void) | 70 | acpi_status acpi_enable(void) |
71 | { | 71 | { |
72 | acpi_status status = AE_OK; | 72 | acpi_status status; |
73 | 73 | ||
74 | ACPI_FUNCTION_TRACE(acpi_enable); | 74 | ACPI_FUNCTION_TRACE(acpi_enable); |
75 | 75 | ||
@@ -84,21 +84,30 @@ acpi_status acpi_enable(void) | |||
84 | if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { | 84 | if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) { |
85 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, | 85 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, |
86 | "System is already in ACPI mode\n")); | 86 | "System is already in ACPI mode\n")); |
87 | } else { | 87 | return_ACPI_STATUS(AE_OK); |
88 | /* Transition to ACPI mode */ | 88 | } |
89 | 89 | ||
90 | status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); | 90 | /* Transition to ACPI mode */ |
91 | if (ACPI_FAILURE(status)) { | ||
92 | ACPI_ERROR((AE_INFO, | ||
93 | "Could not transition to ACPI mode")); | ||
94 | return_ACPI_STATUS(status); | ||
95 | } | ||
96 | 91 | ||
97 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, | 92 | status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI); |
98 | "Transition to ACPI mode successful\n")); | 93 | if (ACPI_FAILURE(status)) { |
94 | ACPI_ERROR((AE_INFO, | ||
95 | "Could not transition to ACPI mode")); | ||
96 | return_ACPI_STATUS(status); | ||
99 | } | 97 | } |
100 | 98 | ||
101 | return_ACPI_STATUS(status); | 99 | /* Sanity check that transition succeeded */ |
100 | |||
101 | if (acpi_hw_get_mode() != ACPI_SYS_MODE_ACPI) { | ||
102 | ACPI_ERROR((AE_INFO, | ||
103 | "Hardware did not enter ACPI mode")); | ||
104 | return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); | ||
105 | } | ||
106 | |||
107 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, | ||
108 | "Transition to ACPI mode successful\n")); | ||
109 | |||
110 | return_ACPI_STATUS(AE_OK); | ||
102 | } | 111 | } |
103 | 112 | ||
104 | ACPI_EXPORT_SYMBOL(acpi_enable) | 113 | ACPI_EXPORT_SYMBOL(acpi_enable) |
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index 679a112a7d26..b44274a0b62c 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c | |||
@@ -63,7 +63,6 @@ acpi_status acpi_hw_set_mode(u32 mode) | |||
63 | { | 63 | { |
64 | 64 | ||
65 | acpi_status status; | 65 | acpi_status status; |
66 | u32 retry; | ||
67 | 66 | ||
68 | ACPI_FUNCTION_TRACE(hw_set_mode); | 67 | ACPI_FUNCTION_TRACE(hw_set_mode); |
69 | 68 | ||
@@ -125,24 +124,7 @@ acpi_status acpi_hw_set_mode(u32 mode) | |||
125 | return_ACPI_STATUS(status); | 124 | return_ACPI_STATUS(status); |
126 | } | 125 | } |
127 | 126 | ||
128 | /* | 127 | return_ACPI_STATUS(AE_OK); |
129 | * Some hardware takes a LONG time to switch modes. Give them 3 sec to | ||
130 | * do so, but allow faster systems to proceed more quickly. | ||
131 | */ | ||
132 | retry = 3000; | ||
133 | while (retry) { | ||
134 | if (acpi_hw_get_mode() == mode) { | ||
135 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
136 | "Mode %X successfully enabled\n", | ||
137 | mode)); | ||
138 | return_ACPI_STATUS(AE_OK); | ||
139 | } | ||
140 | acpi_os_stall(1000); | ||
141 | retry--; | ||
142 | } | ||
143 | |||
144 | ACPI_ERROR((AE_INFO, "Hardware did not change modes")); | ||
145 | return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE); | ||
146 | } | 128 | } |
147 | 129 | ||
148 | /******************************************************************************* | 130 | /******************************************************************************* |
diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig new file mode 100644 index 000000000000..f8c668f27b5a --- /dev/null +++ b/drivers/acpi/apei/Kconfig | |||
@@ -0,0 +1,30 @@ | |||
1 | config ACPI_APEI | ||
2 | bool "ACPI Platform Error Interface (APEI)" | ||
3 | depends on X86 | ||
4 | help | ||
5 | APEI allows to report errors (for example from the chipset) | ||
6 | to the operating system. This improves NMI handling | ||
7 | especially. In addition it supports error serialization and | ||
8 | error injection. | ||
9 | |||
10 | config ACPI_APEI_GHES | ||
11 | tristate "APEI Generic Hardware Error Source" | ||
12 | depends on ACPI_APEI && X86 | ||
13 | select ACPI_HED | ||
14 | help | ||
15 | Generic Hardware Error Source provides a way to report | ||
16 | platform hardware errors (such as that from chipset). It | ||
17 | works in so called "Firmware First" mode, that is, hardware | ||
18 | errors are reported to firmware firstly, then reported to | ||
19 | Linux by firmware. This way, some non-standard hardware | ||
20 | error registers or non-standard hardware link can be checked | ||
21 | by firmware to produce more valuable hardware error | ||
22 | information for Linux. | ||
23 | |||
24 | config ACPI_APEI_EINJ | ||
25 | tristate "APEI Error INJection (EINJ)" | ||
26 | depends on ACPI_APEI && DEBUG_FS | ||
27 | help | ||
28 | EINJ provides a hardware error injection mechanism, it is | ||
29 | mainly used for debugging and testing the other parts of | ||
30 | APEI and some other RAS features. | ||
diff --git a/drivers/acpi/apei/Makefile b/drivers/acpi/apei/Makefile new file mode 100644 index 000000000000..b13b03a17789 --- /dev/null +++ b/drivers/acpi/apei/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | obj-$(CONFIG_ACPI_APEI) += apei.o | ||
2 | obj-$(CONFIG_ACPI_APEI_GHES) += ghes.o | ||
3 | obj-$(CONFIG_ACPI_APEI_EINJ) += einj.o | ||
4 | |||
5 | apei-y := apei-base.o hest.o cper.o erst.o | ||
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c new file mode 100644 index 000000000000..db3946e9c66b --- /dev/null +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -0,0 +1,593 @@ | |||
1 | /* | ||
2 | * apei-base.c - ACPI Platform Error Interface (APEI) supporting | ||
3 | * infrastructure | ||
4 | * | ||
5 | * APEI allows to report errors (for example from the chipset) to the | ||
6 | * the operating system. This improves NMI handling especially. In | ||
7 | * addition it supports error serialization and error injection. | ||
8 | * | ||
9 | * For more information about APEI, please refer to ACPI Specification | ||
10 | * version 4.0, chapter 17. | ||
11 | * | ||
12 | * This file has Common functions used by more than one APEI table, | ||
13 | * including framework of interpreter for ERST and EINJ; resource | ||
14 | * management for APEI registers. | ||
15 | * | ||
16 | * Copyright (C) 2009, Intel Corp. | ||
17 | * Author: Huang Ying <ying.huang@intel.com> | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or | ||
20 | * modify it under the terms of the GNU General Public License version | ||
21 | * 2 as published by the Free Software Foundation. | ||
22 | * | ||
23 | * This program is distributed in the hope that it will be useful, | ||
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | * GNU General Public License for more details. | ||
27 | * | ||
28 | * You should have received a copy of the GNU General Public License | ||
29 | * along with this program; if not, write to the Free Software | ||
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
31 | */ | ||
32 | |||
33 | #include <linux/kernel.h> | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/acpi.h> | ||
37 | #include <linux/io.h> | ||
38 | #include <linux/kref.h> | ||
39 | #include <linux/rculist.h> | ||
40 | #include <linux/interrupt.h> | ||
41 | #include <linux/debugfs.h> | ||
42 | #include <acpi/atomicio.h> | ||
43 | |||
44 | #include "apei-internal.h" | ||
45 | |||
46 | #define APEI_PFX "APEI: " | ||
47 | |||
48 | /* | ||
49 | * APEI ERST (Error Record Serialization Table) and EINJ (Error | ||
50 | * INJection) interpreter framework. | ||
51 | */ | ||
52 | |||
53 | #define APEI_EXEC_PRESERVE_REGISTER 0x1 | ||
54 | |||
55 | void apei_exec_ctx_init(struct apei_exec_context *ctx, | ||
56 | struct apei_exec_ins_type *ins_table, | ||
57 | u32 instructions, | ||
58 | struct acpi_whea_header *action_table, | ||
59 | u32 entries) | ||
60 | { | ||
61 | ctx->ins_table = ins_table; | ||
62 | ctx->instructions = instructions; | ||
63 | ctx->action_table = action_table; | ||
64 | ctx->entries = entries; | ||
65 | } | ||
66 | EXPORT_SYMBOL_GPL(apei_exec_ctx_init); | ||
67 | |||
68 | int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val) | ||
69 | { | ||
70 | int rc; | ||
71 | |||
72 | rc = acpi_atomic_read(val, &entry->register_region); | ||
73 | if (rc) | ||
74 | return rc; | ||
75 | *val >>= entry->register_region.bit_offset; | ||
76 | *val &= entry->mask; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | int apei_exec_read_register(struct apei_exec_context *ctx, | ||
82 | struct acpi_whea_header *entry) | ||
83 | { | ||
84 | int rc; | ||
85 | u64 val = 0; | ||
86 | |||
87 | rc = __apei_exec_read_register(entry, &val); | ||
88 | if (rc) | ||
89 | return rc; | ||
90 | ctx->value = val; | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | EXPORT_SYMBOL_GPL(apei_exec_read_register); | ||
95 | |||
96 | int apei_exec_read_register_value(struct apei_exec_context *ctx, | ||
97 | struct acpi_whea_header *entry) | ||
98 | { | ||
99 | int rc; | ||
100 | |||
101 | rc = apei_exec_read_register(ctx, entry); | ||
102 | if (rc) | ||
103 | return rc; | ||
104 | ctx->value = (ctx->value == entry->value); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | EXPORT_SYMBOL_GPL(apei_exec_read_register_value); | ||
109 | |||
110 | int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val) | ||
111 | { | ||
112 | int rc; | ||
113 | |||
114 | val &= entry->mask; | ||
115 | val <<= entry->register_region.bit_offset; | ||
116 | if (entry->flags & APEI_EXEC_PRESERVE_REGISTER) { | ||
117 | u64 valr = 0; | ||
118 | rc = acpi_atomic_read(&valr, &entry->register_region); | ||
119 | if (rc) | ||
120 | return rc; | ||
121 | valr &= ~(entry->mask << entry->register_region.bit_offset); | ||
122 | val |= valr; | ||
123 | } | ||
124 | rc = acpi_atomic_write(val, &entry->register_region); | ||
125 | |||
126 | return rc; | ||
127 | } | ||
128 | |||
129 | int apei_exec_write_register(struct apei_exec_context *ctx, | ||
130 | struct acpi_whea_header *entry) | ||
131 | { | ||
132 | return __apei_exec_write_register(entry, ctx->value); | ||
133 | } | ||
134 | EXPORT_SYMBOL_GPL(apei_exec_write_register); | ||
135 | |||
136 | int apei_exec_write_register_value(struct apei_exec_context *ctx, | ||
137 | struct acpi_whea_header *entry) | ||
138 | { | ||
139 | int rc; | ||
140 | |||
141 | ctx->value = entry->value; | ||
142 | rc = apei_exec_write_register(ctx, entry); | ||
143 | |||
144 | return rc; | ||
145 | } | ||
146 | EXPORT_SYMBOL_GPL(apei_exec_write_register_value); | ||
147 | |||
148 | int apei_exec_noop(struct apei_exec_context *ctx, | ||
149 | struct acpi_whea_header *entry) | ||
150 | { | ||
151 | return 0; | ||
152 | } | ||
153 | EXPORT_SYMBOL_GPL(apei_exec_noop); | ||
154 | |||
155 | /* | ||
156 | * Interpret the specified action. Go through whole action table, | ||
157 | * execute all instructions belong to the action. | ||
158 | */ | ||
159 | int apei_exec_run(struct apei_exec_context *ctx, u8 action) | ||
160 | { | ||
161 | int rc; | ||
162 | u32 i, ip; | ||
163 | struct acpi_whea_header *entry; | ||
164 | apei_exec_ins_func_t run; | ||
165 | |||
166 | ctx->ip = 0; | ||
167 | |||
168 | /* | ||
169 | * "ip" is the instruction pointer of current instruction, | ||
170 | * "ctx->ip" specifies the next instruction to executed, | ||
171 | * instruction "run" function may change the "ctx->ip" to | ||
172 | * implement "goto" semantics. | ||
173 | */ | ||
174 | rewind: | ||
175 | ip = 0; | ||
176 | for (i = 0; i < ctx->entries; i++) { | ||
177 | entry = &ctx->action_table[i]; | ||
178 | if (entry->action != action) | ||
179 | continue; | ||
180 | if (ip == ctx->ip) { | ||
181 | if (entry->instruction >= ctx->instructions || | ||
182 | !ctx->ins_table[entry->instruction].run) { | ||
183 | pr_warning(FW_WARN APEI_PFX | ||
184 | "Invalid action table, unknown instruction type: %d\n", | ||
185 | entry->instruction); | ||
186 | return -EINVAL; | ||
187 | } | ||
188 | run = ctx->ins_table[entry->instruction].run; | ||
189 | rc = run(ctx, entry); | ||
190 | if (rc < 0) | ||
191 | return rc; | ||
192 | else if (rc != APEI_EXEC_SET_IP) | ||
193 | ctx->ip++; | ||
194 | } | ||
195 | ip++; | ||
196 | if (ctx->ip < ip) | ||
197 | goto rewind; | ||
198 | } | ||
199 | |||
200 | return 0; | ||
201 | } | ||
202 | EXPORT_SYMBOL_GPL(apei_exec_run); | ||
203 | |||
204 | typedef int (*apei_exec_entry_func_t)(struct apei_exec_context *ctx, | ||
205 | struct acpi_whea_header *entry, | ||
206 | void *data); | ||
207 | |||
208 | static int apei_exec_for_each_entry(struct apei_exec_context *ctx, | ||
209 | apei_exec_entry_func_t func, | ||
210 | void *data, | ||
211 | int *end) | ||
212 | { | ||
213 | u8 ins; | ||
214 | int i, rc; | ||
215 | struct acpi_whea_header *entry; | ||
216 | struct apei_exec_ins_type *ins_table = ctx->ins_table; | ||
217 | |||
218 | for (i = 0; i < ctx->entries; i++) { | ||
219 | entry = ctx->action_table + i; | ||
220 | ins = entry->instruction; | ||
221 | if (end) | ||
222 | *end = i; | ||
223 | if (ins >= ctx->instructions || !ins_table[ins].run) { | ||
224 | pr_warning(FW_WARN APEI_PFX | ||
225 | "Invalid action table, unknown instruction type: %d\n", | ||
226 | ins); | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | rc = func(ctx, entry, data); | ||
230 | if (rc) | ||
231 | return rc; | ||
232 | } | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static int pre_map_gar_callback(struct apei_exec_context *ctx, | ||
238 | struct acpi_whea_header *entry, | ||
239 | void *data) | ||
240 | { | ||
241 | u8 ins = entry->instruction; | ||
242 | |||
243 | if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) | ||
244 | return acpi_pre_map_gar(&entry->register_region); | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * Pre-map all GARs in action table to make it possible to access them | ||
251 | * in NMI handler. | ||
252 | */ | ||
253 | int apei_exec_pre_map_gars(struct apei_exec_context *ctx) | ||
254 | { | ||
255 | int rc, end; | ||
256 | |||
257 | rc = apei_exec_for_each_entry(ctx, pre_map_gar_callback, | ||
258 | NULL, &end); | ||
259 | if (rc) { | ||
260 | struct apei_exec_context ctx_unmap; | ||
261 | memcpy(&ctx_unmap, ctx, sizeof(*ctx)); | ||
262 | ctx_unmap.entries = end; | ||
263 | apei_exec_post_unmap_gars(&ctx_unmap); | ||
264 | } | ||
265 | |||
266 | return rc; | ||
267 | } | ||
268 | EXPORT_SYMBOL_GPL(apei_exec_pre_map_gars); | ||
269 | |||
270 | static int post_unmap_gar_callback(struct apei_exec_context *ctx, | ||
271 | struct acpi_whea_header *entry, | ||
272 | void *data) | ||
273 | { | ||
274 | u8 ins = entry->instruction; | ||
275 | |||
276 | if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) | ||
277 | acpi_post_unmap_gar(&entry->register_region); | ||
278 | |||
279 | return 0; | ||
280 | } | ||
281 | |||
282 | /* Post-unmap all GAR in action table. */ | ||
283 | int apei_exec_post_unmap_gars(struct apei_exec_context *ctx) | ||
284 | { | ||
285 | return apei_exec_for_each_entry(ctx, post_unmap_gar_callback, | ||
286 | NULL, NULL); | ||
287 | } | ||
288 | EXPORT_SYMBOL_GPL(apei_exec_post_unmap_gars); | ||
289 | |||
290 | /* | ||
291 | * Resource management for GARs in APEI | ||
292 | */ | ||
293 | struct apei_res { | ||
294 | struct list_head list; | ||
295 | unsigned long start; | ||
296 | unsigned long end; | ||
297 | }; | ||
298 | |||
299 | /* Collect all resources requested, to avoid conflict */ | ||
300 | struct apei_resources apei_resources_all = { | ||
301 | .iomem = LIST_HEAD_INIT(apei_resources_all.iomem), | ||
302 | .ioport = LIST_HEAD_INIT(apei_resources_all.ioport), | ||
303 | }; | ||
304 | |||
305 | static int apei_res_add(struct list_head *res_list, | ||
306 | unsigned long start, unsigned long size) | ||
307 | { | ||
308 | struct apei_res *res, *resn, *res_ins = NULL; | ||
309 | unsigned long end = start + size; | ||
310 | |||
311 | if (end <= start) | ||
312 | return 0; | ||
313 | repeat: | ||
314 | list_for_each_entry_safe(res, resn, res_list, list) { | ||
315 | if (res->start > end || res->end < start) | ||
316 | continue; | ||
317 | else if (end <= res->end && start >= res->start) { | ||
318 | kfree(res_ins); | ||
319 | return 0; | ||
320 | } | ||
321 | list_del(&res->list); | ||
322 | res->start = start = min(res->start, start); | ||
323 | res->end = end = max(res->end, end); | ||
324 | kfree(res_ins); | ||
325 | res_ins = res; | ||
326 | goto repeat; | ||
327 | } | ||
328 | |||
329 | if (res_ins) | ||
330 | list_add(&res_ins->list, res_list); | ||
331 | else { | ||
332 | res_ins = kmalloc(sizeof(*res), GFP_KERNEL); | ||
333 | if (!res_ins) | ||
334 | return -ENOMEM; | ||
335 | res_ins->start = start; | ||
336 | res_ins->end = end; | ||
337 | list_add(&res_ins->list, res_list); | ||
338 | } | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | static int apei_res_sub(struct list_head *res_list1, | ||
344 | struct list_head *res_list2) | ||
345 | { | ||
346 | struct apei_res *res1, *resn1, *res2, *res; | ||
347 | res1 = list_entry(res_list1->next, struct apei_res, list); | ||
348 | resn1 = list_entry(res1->list.next, struct apei_res, list); | ||
349 | while (&res1->list != res_list1) { | ||
350 | list_for_each_entry(res2, res_list2, list) { | ||
351 | if (res1->start >= res2->end || | ||
352 | res1->end <= res2->start) | ||
353 | continue; | ||
354 | else if (res1->end <= res2->end && | ||
355 | res1->start >= res2->start) { | ||
356 | list_del(&res1->list); | ||
357 | kfree(res1); | ||
358 | break; | ||
359 | } else if (res1->end > res2->end && | ||
360 | res1->start < res2->start) { | ||
361 | res = kmalloc(sizeof(*res), GFP_KERNEL); | ||
362 | if (!res) | ||
363 | return -ENOMEM; | ||
364 | res->start = res2->end; | ||
365 | res->end = res1->end; | ||
366 | res1->end = res2->start; | ||
367 | list_add(&res->list, &res1->list); | ||
368 | resn1 = res; | ||
369 | } else { | ||
370 | if (res1->start < res2->start) | ||
371 | res1->end = res2->start; | ||
372 | else | ||
373 | res1->start = res2->end; | ||
374 | } | ||
375 | } | ||
376 | res1 = resn1; | ||
377 | resn1 = list_entry(resn1->list.next, struct apei_res, list); | ||
378 | } | ||
379 | |||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static void apei_res_clean(struct list_head *res_list) | ||
384 | { | ||
385 | struct apei_res *res, *resn; | ||
386 | |||
387 | list_for_each_entry_safe(res, resn, res_list, list) { | ||
388 | list_del(&res->list); | ||
389 | kfree(res); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | void apei_resources_fini(struct apei_resources *resources) | ||
394 | { | ||
395 | apei_res_clean(&resources->iomem); | ||
396 | apei_res_clean(&resources->ioport); | ||
397 | } | ||
398 | EXPORT_SYMBOL_GPL(apei_resources_fini); | ||
399 | |||
400 | static int apei_resources_merge(struct apei_resources *resources1, | ||
401 | struct apei_resources *resources2) | ||
402 | { | ||
403 | int rc; | ||
404 | struct apei_res *res; | ||
405 | |||
406 | list_for_each_entry(res, &resources2->iomem, list) { | ||
407 | rc = apei_res_add(&resources1->iomem, res->start, | ||
408 | res->end - res->start); | ||
409 | if (rc) | ||
410 | return rc; | ||
411 | } | ||
412 | list_for_each_entry(res, &resources2->ioport, list) { | ||
413 | rc = apei_res_add(&resources1->ioport, res->start, | ||
414 | res->end - res->start); | ||
415 | if (rc) | ||
416 | return rc; | ||
417 | } | ||
418 | |||
419 | return 0; | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * EINJ has two groups of GARs (EINJ table entry and trigger table | ||
424 | * entry), so common resources are subtracted from the trigger table | ||
425 | * resources before the second requesting. | ||
426 | */ | ||
427 | int apei_resources_sub(struct apei_resources *resources1, | ||
428 | struct apei_resources *resources2) | ||
429 | { | ||
430 | int rc; | ||
431 | |||
432 | rc = apei_res_sub(&resources1->iomem, &resources2->iomem); | ||
433 | if (rc) | ||
434 | return rc; | ||
435 | return apei_res_sub(&resources1->ioport, &resources2->ioport); | ||
436 | } | ||
437 | EXPORT_SYMBOL_GPL(apei_resources_sub); | ||
438 | |||
439 | /* | ||
440 | * IO memory/port rersource management mechanism is used to check | ||
441 | * whether memory/port area used by GARs conflicts with normal memory | ||
442 | * or IO memory/port of devices. | ||
443 | */ | ||
444 | int apei_resources_request(struct apei_resources *resources, | ||
445 | const char *desc) | ||
446 | { | ||
447 | struct apei_res *res, *res_bak; | ||
448 | struct resource *r; | ||
449 | |||
450 | apei_resources_sub(resources, &apei_resources_all); | ||
451 | |||
452 | list_for_each_entry(res, &resources->iomem, list) { | ||
453 | r = request_mem_region(res->start, res->end - res->start, | ||
454 | desc); | ||
455 | if (!r) { | ||
456 | pr_err(APEI_PFX | ||
457 | "Can not request iomem region <%016llx-%016llx> for GARs.\n", | ||
458 | (unsigned long long)res->start, | ||
459 | (unsigned long long)res->end); | ||
460 | res_bak = res; | ||
461 | goto err_unmap_iomem; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | list_for_each_entry(res, &resources->ioport, list) { | ||
466 | r = request_region(res->start, res->end - res->start, desc); | ||
467 | if (!r) { | ||
468 | pr_err(APEI_PFX | ||
469 | "Can not request ioport region <%016llx-%016llx> for GARs.\n", | ||
470 | (unsigned long long)res->start, | ||
471 | (unsigned long long)res->end); | ||
472 | res_bak = res; | ||
473 | goto err_unmap_ioport; | ||
474 | } | ||
475 | } | ||
476 | |||
477 | apei_resources_merge(&apei_resources_all, resources); | ||
478 | |||
479 | return 0; | ||
480 | err_unmap_ioport: | ||
481 | list_for_each_entry(res, &resources->ioport, list) { | ||
482 | if (res == res_bak) | ||
483 | break; | ||
484 | release_mem_region(res->start, res->end - res->start); | ||
485 | } | ||
486 | res_bak = NULL; | ||
487 | err_unmap_iomem: | ||
488 | list_for_each_entry(res, &resources->iomem, list) { | ||
489 | if (res == res_bak) | ||
490 | break; | ||
491 | release_region(res->start, res->end - res->start); | ||
492 | } | ||
493 | return -EINVAL; | ||
494 | } | ||
495 | EXPORT_SYMBOL_GPL(apei_resources_request); | ||
496 | |||
497 | void apei_resources_release(struct apei_resources *resources) | ||
498 | { | ||
499 | struct apei_res *res; | ||
500 | |||
501 | list_for_each_entry(res, &resources->iomem, list) | ||
502 | release_mem_region(res->start, res->end - res->start); | ||
503 | list_for_each_entry(res, &resources->ioport, list) | ||
504 | release_region(res->start, res->end - res->start); | ||
505 | |||
506 | apei_resources_sub(&apei_resources_all, resources); | ||
507 | } | ||
508 | EXPORT_SYMBOL_GPL(apei_resources_release); | ||
509 | |||
510 | static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr) | ||
511 | { | ||
512 | u32 width, space_id; | ||
513 | |||
514 | width = reg->bit_width; | ||
515 | space_id = reg->space_id; | ||
516 | /* Handle possible alignment issues */ | ||
517 | memcpy(paddr, ®->address, sizeof(*paddr)); | ||
518 | if (!*paddr) { | ||
519 | pr_warning(FW_BUG APEI_PFX | ||
520 | "Invalid physical address in GAR [0x%llx/%u/%u]\n", | ||
521 | *paddr, width, space_id); | ||
522 | return -EINVAL; | ||
523 | } | ||
524 | |||
525 | if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) { | ||
526 | pr_warning(FW_BUG APEI_PFX | ||
527 | "Invalid bit width in GAR [0x%llx/%u/%u]\n", | ||
528 | *paddr, width, space_id); | ||
529 | return -EINVAL; | ||
530 | } | ||
531 | |||
532 | if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY && | ||
533 | space_id != ACPI_ADR_SPACE_SYSTEM_IO) { | ||
534 | pr_warning(FW_BUG APEI_PFX | ||
535 | "Invalid address space type in GAR [0x%llx/%u/%u]\n", | ||
536 | *paddr, width, space_id); | ||
537 | return -EINVAL; | ||
538 | } | ||
539 | |||
540 | return 0; | ||
541 | } | ||
542 | |||
543 | static int collect_res_callback(struct apei_exec_context *ctx, | ||
544 | struct acpi_whea_header *entry, | ||
545 | void *data) | ||
546 | { | ||
547 | struct apei_resources *resources = data; | ||
548 | struct acpi_generic_address *reg = &entry->register_region; | ||
549 | u8 ins = entry->instruction; | ||
550 | u64 paddr; | ||
551 | int rc; | ||
552 | |||
553 | if (!(ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER)) | ||
554 | return 0; | ||
555 | |||
556 | rc = apei_check_gar(reg, &paddr); | ||
557 | if (rc) | ||
558 | return rc; | ||
559 | |||
560 | switch (reg->space_id) { | ||
561 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | ||
562 | return apei_res_add(&resources->iomem, paddr, | ||
563 | reg->bit_width / 8); | ||
564 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
565 | return apei_res_add(&resources->ioport, paddr, | ||
566 | reg->bit_width / 8); | ||
567 | default: | ||
568 | return -EINVAL; | ||
569 | } | ||
570 | } | ||
571 | |||
572 | /* | ||
573 | * Same register may be used by multiple instructions in GARs, so | ||
574 | * resources are collected before requesting. | ||
575 | */ | ||
576 | int apei_exec_collect_resources(struct apei_exec_context *ctx, | ||
577 | struct apei_resources *resources) | ||
578 | { | ||
579 | return apei_exec_for_each_entry(ctx, collect_res_callback, | ||
580 | resources, NULL); | ||
581 | } | ||
582 | EXPORT_SYMBOL_GPL(apei_exec_collect_resources); | ||
583 | |||
584 | struct dentry *apei_get_debugfs_dir(void) | ||
585 | { | ||
586 | static struct dentry *dapei; | ||
587 | |||
588 | if (!dapei) | ||
589 | dapei = debugfs_create_dir("apei", NULL); | ||
590 | |||
591 | return dapei; | ||
592 | } | ||
593 | EXPORT_SYMBOL_GPL(apei_get_debugfs_dir); | ||
diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h new file mode 100644 index 000000000000..18df1e940276 --- /dev/null +++ b/drivers/acpi/apei/apei-internal.h | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * apei-internal.h - ACPI Platform Error Interface internal | ||
3 | * definations. | ||
4 | */ | ||
5 | |||
6 | #ifndef APEI_INTERNAL_H | ||
7 | #define APEI_INTERNAL_H | ||
8 | |||
9 | #include <linux/cper.h> | ||
10 | |||
11 | struct apei_exec_context; | ||
12 | |||
13 | typedef int (*apei_exec_ins_func_t)(struct apei_exec_context *ctx, | ||
14 | struct acpi_whea_header *entry); | ||
15 | |||
16 | #define APEI_EXEC_INS_ACCESS_REGISTER 0x0001 | ||
17 | |||
18 | struct apei_exec_ins_type { | ||
19 | u32 flags; | ||
20 | apei_exec_ins_func_t run; | ||
21 | }; | ||
22 | |||
23 | struct apei_exec_context { | ||
24 | u32 ip; | ||
25 | u64 value; | ||
26 | u64 var1; | ||
27 | u64 var2; | ||
28 | u64 src_base; | ||
29 | u64 dst_base; | ||
30 | struct apei_exec_ins_type *ins_table; | ||
31 | u32 instructions; | ||
32 | struct acpi_whea_header *action_table; | ||
33 | u32 entries; | ||
34 | }; | ||
35 | |||
36 | void apei_exec_ctx_init(struct apei_exec_context *ctx, | ||
37 | struct apei_exec_ins_type *ins_table, | ||
38 | u32 instructions, | ||
39 | struct acpi_whea_header *action_table, | ||
40 | u32 entries); | ||
41 | |||
42 | static inline void apei_exec_ctx_set_input(struct apei_exec_context *ctx, | ||
43 | u64 input) | ||
44 | { | ||
45 | ctx->value = input; | ||
46 | } | ||
47 | |||
48 | static inline u64 apei_exec_ctx_get_output(struct apei_exec_context *ctx) | ||
49 | { | ||
50 | return ctx->value; | ||
51 | } | ||
52 | |||
53 | int apei_exec_run(struct apei_exec_context *ctx, u8 action); | ||
54 | |||
55 | /* Common instruction implementation */ | ||
56 | |||
57 | /* IP has been set in instruction function */ | ||
58 | #define APEI_EXEC_SET_IP 1 | ||
59 | |||
60 | int __apei_exec_read_register(struct acpi_whea_header *entry, u64 *val); | ||
61 | int __apei_exec_write_register(struct acpi_whea_header *entry, u64 val); | ||
62 | int apei_exec_read_register(struct apei_exec_context *ctx, | ||
63 | struct acpi_whea_header *entry); | ||
64 | int apei_exec_read_register_value(struct apei_exec_context *ctx, | ||
65 | struct acpi_whea_header *entry); | ||
66 | int apei_exec_write_register(struct apei_exec_context *ctx, | ||
67 | struct acpi_whea_header *entry); | ||
68 | int apei_exec_write_register_value(struct apei_exec_context *ctx, | ||
69 | struct acpi_whea_header *entry); | ||
70 | int apei_exec_noop(struct apei_exec_context *ctx, | ||
71 | struct acpi_whea_header *entry); | ||
72 | int apei_exec_pre_map_gars(struct apei_exec_context *ctx); | ||
73 | int apei_exec_post_unmap_gars(struct apei_exec_context *ctx); | ||
74 | |||
75 | struct apei_resources { | ||
76 | struct list_head iomem; | ||
77 | struct list_head ioport; | ||
78 | }; | ||
79 | |||
80 | static inline void apei_resources_init(struct apei_resources *resources) | ||
81 | { | ||
82 | INIT_LIST_HEAD(&resources->iomem); | ||
83 | INIT_LIST_HEAD(&resources->ioport); | ||
84 | } | ||
85 | |||
86 | void apei_resources_fini(struct apei_resources *resources); | ||
87 | int apei_resources_sub(struct apei_resources *resources1, | ||
88 | struct apei_resources *resources2); | ||
89 | int apei_resources_request(struct apei_resources *resources, | ||
90 | const char *desc); | ||
91 | void apei_resources_release(struct apei_resources *resources); | ||
92 | int apei_exec_collect_resources(struct apei_exec_context *ctx, | ||
93 | struct apei_resources *resources); | ||
94 | |||
95 | struct dentry; | ||
96 | struct dentry *apei_get_debugfs_dir(void); | ||
97 | |||
98 | #define apei_estatus_for_each_section(estatus, section) \ | ||
99 | for (section = (struct acpi_hest_generic_data *)(estatus + 1); \ | ||
100 | (void *)section - (void *)estatus < estatus->data_length; \ | ||
101 | section = (void *)(section+1) + section->error_data_length) | ||
102 | |||
103 | static inline u32 apei_estatus_len(struct acpi_hest_generic_status *estatus) | ||
104 | { | ||
105 | if (estatus->raw_data_length) | ||
106 | return estatus->raw_data_offset + \ | ||
107 | estatus->raw_data_length; | ||
108 | else | ||
109 | return sizeof(*estatus) + estatus->data_length; | ||
110 | } | ||
111 | |||
112 | int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus); | ||
113 | int apei_estatus_check(const struct acpi_hest_generic_status *estatus); | ||
114 | #endif | ||
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c new file mode 100644 index 000000000000..f4cf2fc4c8c1 --- /dev/null +++ b/drivers/acpi/apei/cper.c | |||
@@ -0,0 +1,84 @@ | |||
1 | /* | ||
2 | * UEFI Common Platform Error Record (CPER) support | ||
3 | * | ||
4 | * Copyright (C) 2010, Intel Corp. | ||
5 | * Author: Huang Ying <ying.huang@intel.com> | ||
6 | * | ||
7 | * CPER is the format used to describe platform hardware error by | ||
8 | * various APEI tables, such as ERST, BERT and HEST etc. | ||
9 | * | ||
10 | * For more information about CPER, please refer to Appendix N of UEFI | ||
11 | * Specification version 2.3. | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License version | ||
15 | * 2 as published by the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/time.h> | ||
30 | #include <linux/cper.h> | ||
31 | #include <linux/acpi.h> | ||
32 | |||
33 | /* | ||
34 | * CPER record ID need to be unique even after reboot, because record | ||
35 | * ID is used as index for ERST storage, while CPER records from | ||
36 | * multiple boot may co-exist in ERST. | ||
37 | */ | ||
38 | u64 cper_next_record_id(void) | ||
39 | { | ||
40 | static atomic64_t seq; | ||
41 | |||
42 | if (!atomic64_read(&seq)) | ||
43 | atomic64_set(&seq, ((u64)get_seconds()) << 32); | ||
44 | |||
45 | return atomic64_inc_return(&seq); | ||
46 | } | ||
47 | EXPORT_SYMBOL_GPL(cper_next_record_id); | ||
48 | |||
49 | int apei_estatus_check_header(const struct acpi_hest_generic_status *estatus) | ||
50 | { | ||
51 | if (estatus->data_length && | ||
52 | estatus->data_length < sizeof(struct acpi_hest_generic_data)) | ||
53 | return -EINVAL; | ||
54 | if (estatus->raw_data_length && | ||
55 | estatus->raw_data_offset < sizeof(*estatus) + estatus->data_length) | ||
56 | return -EINVAL; | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | EXPORT_SYMBOL_GPL(apei_estatus_check_header); | ||
61 | |||
62 | int apei_estatus_check(const struct acpi_hest_generic_status *estatus) | ||
63 | { | ||
64 | struct acpi_hest_generic_data *gdata; | ||
65 | unsigned int data_len, gedata_len; | ||
66 | int rc; | ||
67 | |||
68 | rc = apei_estatus_check_header(estatus); | ||
69 | if (rc) | ||
70 | return rc; | ||
71 | data_len = estatus->data_length; | ||
72 | gdata = (struct acpi_hest_generic_data *)(estatus + 1); | ||
73 | while (data_len > sizeof(*gdata)) { | ||
74 | gedata_len = gdata->error_data_length; | ||
75 | if (gedata_len > data_len - sizeof(*gdata)) | ||
76 | return -EINVAL; | ||
77 | data_len -= gedata_len + sizeof(*gdata); | ||
78 | } | ||
79 | if (data_len) | ||
80 | return -EINVAL; | ||
81 | |||
82 | return 0; | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(apei_estatus_check); | ||
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c new file mode 100644 index 000000000000..465c885938ee --- /dev/null +++ b/drivers/acpi/apei/einj.c | |||
@@ -0,0 +1,548 @@ | |||
1 | /* | ||
2 | * APEI Error INJection support | ||
3 | * | ||
4 | * EINJ provides a hardware error injection mechanism, this is useful | ||
5 | * for debugging and testing of other APEI and RAS features. | ||
6 | * | ||
7 | * For more information about EINJ, please refer to ACPI Specification | ||
8 | * version 4.0, section 17.5. | ||
9 | * | ||
10 | * Copyright 2009-2010 Intel Corp. | ||
11 | * Author: Huang Ying <ying.huang@intel.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License version | ||
15 | * 2 as published by the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <linux/debugfs.h> | ||
32 | #include <linux/seq_file.h> | ||
33 | #include <linux/nmi.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <acpi/acpi.h> | ||
36 | |||
37 | #include "apei-internal.h" | ||
38 | |||
39 | #define EINJ_PFX "EINJ: " | ||
40 | |||
41 | #define SPIN_UNIT 100 /* 100ns */ | ||
42 | /* Firmware should respond within 1 miliseconds */ | ||
43 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) | ||
44 | |||
45 | /* | ||
46 | * Some BIOSes allow parameters to the SET_ERROR_TYPE entries in the | ||
47 | * EINJ table through an unpublished extension. Use with caution as | ||
48 | * most will ignore the parameter and make their own choice of address | ||
49 | * for error injection. | ||
50 | */ | ||
51 | struct einj_parameter { | ||
52 | u64 type; | ||
53 | u64 reserved1; | ||
54 | u64 reserved2; | ||
55 | u64 param1; | ||
56 | u64 param2; | ||
57 | }; | ||
58 | |||
59 | #define EINJ_OP_BUSY 0x1 | ||
60 | #define EINJ_STATUS_SUCCESS 0x0 | ||
61 | #define EINJ_STATUS_FAIL 0x1 | ||
62 | #define EINJ_STATUS_INVAL 0x2 | ||
63 | |||
64 | #define EINJ_TAB_ENTRY(tab) \ | ||
65 | ((struct acpi_whea_header *)((char *)(tab) + \ | ||
66 | sizeof(struct acpi_table_einj))) | ||
67 | |||
68 | static struct acpi_table_einj *einj_tab; | ||
69 | |||
70 | static struct apei_resources einj_resources; | ||
71 | |||
72 | static struct apei_exec_ins_type einj_ins_type[] = { | ||
73 | [ACPI_EINJ_READ_REGISTER] = { | ||
74 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
75 | .run = apei_exec_read_register, | ||
76 | }, | ||
77 | [ACPI_EINJ_READ_REGISTER_VALUE] = { | ||
78 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
79 | .run = apei_exec_read_register_value, | ||
80 | }, | ||
81 | [ACPI_EINJ_WRITE_REGISTER] = { | ||
82 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
83 | .run = apei_exec_write_register, | ||
84 | }, | ||
85 | [ACPI_EINJ_WRITE_REGISTER_VALUE] = { | ||
86 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
87 | .run = apei_exec_write_register_value, | ||
88 | }, | ||
89 | [ACPI_EINJ_NOOP] = { | ||
90 | .flags = 0, | ||
91 | .run = apei_exec_noop, | ||
92 | }, | ||
93 | }; | ||
94 | |||
95 | /* | ||
96 | * Prevent EINJ interpreter to run simultaneously, because the | ||
97 | * corresponding firmware implementation may not work properly when | ||
98 | * invoked simultaneously. | ||
99 | */ | ||
100 | static DEFINE_MUTEX(einj_mutex); | ||
101 | |||
102 | static struct einj_parameter *einj_param; | ||
103 | |||
104 | static void einj_exec_ctx_init(struct apei_exec_context *ctx) | ||
105 | { | ||
106 | apei_exec_ctx_init(ctx, einj_ins_type, ARRAY_SIZE(einj_ins_type), | ||
107 | EINJ_TAB_ENTRY(einj_tab), einj_tab->entries); | ||
108 | } | ||
109 | |||
110 | static int __einj_get_available_error_type(u32 *type) | ||
111 | { | ||
112 | struct apei_exec_context ctx; | ||
113 | int rc; | ||
114 | |||
115 | einj_exec_ctx_init(&ctx); | ||
116 | rc = apei_exec_run(&ctx, ACPI_EINJ_GET_ERROR_TYPE); | ||
117 | if (rc) | ||
118 | return rc; | ||
119 | *type = apei_exec_ctx_get_output(&ctx); | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | /* Get error injection capabilities of the platform */ | ||
125 | static int einj_get_available_error_type(u32 *type) | ||
126 | { | ||
127 | int rc; | ||
128 | |||
129 | mutex_lock(&einj_mutex); | ||
130 | rc = __einj_get_available_error_type(type); | ||
131 | mutex_unlock(&einj_mutex); | ||
132 | |||
133 | return rc; | ||
134 | } | ||
135 | |||
136 | static int einj_timedout(u64 *t) | ||
137 | { | ||
138 | if ((s64)*t < SPIN_UNIT) { | ||
139 | pr_warning(FW_WARN EINJ_PFX | ||
140 | "Firmware does not respond in time\n"); | ||
141 | return 1; | ||
142 | } | ||
143 | *t -= SPIN_UNIT; | ||
144 | ndelay(SPIN_UNIT); | ||
145 | touch_nmi_watchdog(); | ||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static u64 einj_get_parameter_address(void) | ||
150 | { | ||
151 | int i; | ||
152 | u64 paddr = 0; | ||
153 | struct acpi_whea_header *entry; | ||
154 | |||
155 | entry = EINJ_TAB_ENTRY(einj_tab); | ||
156 | for (i = 0; i < einj_tab->entries; i++) { | ||
157 | if (entry->action == ACPI_EINJ_SET_ERROR_TYPE && | ||
158 | entry->instruction == ACPI_EINJ_WRITE_REGISTER && | ||
159 | entry->register_region.space_id == | ||
160 | ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
161 | memcpy(&paddr, &entry->register_region.address, | ||
162 | sizeof(paddr)); | ||
163 | entry++; | ||
164 | } | ||
165 | |||
166 | return paddr; | ||
167 | } | ||
168 | |||
169 | /* do sanity check to trigger table */ | ||
170 | static int einj_check_trigger_header(struct acpi_einj_trigger *trigger_tab) | ||
171 | { | ||
172 | if (trigger_tab->header_size != sizeof(struct acpi_einj_trigger)) | ||
173 | return -EINVAL; | ||
174 | if (trigger_tab->table_size > PAGE_SIZE || | ||
175 | trigger_tab->table_size <= trigger_tab->header_size) | ||
176 | return -EINVAL; | ||
177 | if (trigger_tab->entry_count != | ||
178 | (trigger_tab->table_size - trigger_tab->header_size) / | ||
179 | sizeof(struct acpi_einj_entry)) | ||
180 | return -EINVAL; | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | /* Execute instructions in trigger error action table */ | ||
186 | static int __einj_error_trigger(u64 trigger_paddr) | ||
187 | { | ||
188 | struct acpi_einj_trigger *trigger_tab = NULL; | ||
189 | struct apei_exec_context trigger_ctx; | ||
190 | struct apei_resources trigger_resources; | ||
191 | struct acpi_whea_header *trigger_entry; | ||
192 | struct resource *r; | ||
193 | u32 table_size; | ||
194 | int rc = -EIO; | ||
195 | |||
196 | r = request_mem_region(trigger_paddr, sizeof(*trigger_tab), | ||
197 | "APEI EINJ Trigger Table"); | ||
198 | if (!r) { | ||
199 | pr_err(EINJ_PFX | ||
200 | "Can not request iomem region <%016llx-%016llx> for Trigger table.\n", | ||
201 | (unsigned long long)trigger_paddr, | ||
202 | (unsigned long long)trigger_paddr+sizeof(*trigger_tab)); | ||
203 | goto out; | ||
204 | } | ||
205 | trigger_tab = ioremap_cache(trigger_paddr, sizeof(*trigger_tab)); | ||
206 | if (!trigger_tab) { | ||
207 | pr_err(EINJ_PFX "Failed to map trigger table!\n"); | ||
208 | goto out_rel_header; | ||
209 | } | ||
210 | rc = einj_check_trigger_header(trigger_tab); | ||
211 | if (rc) { | ||
212 | pr_warning(FW_BUG EINJ_PFX | ||
213 | "The trigger error action table is invalid\n"); | ||
214 | goto out_rel_header; | ||
215 | } | ||
216 | rc = -EIO; | ||
217 | table_size = trigger_tab->table_size; | ||
218 | r = request_mem_region(trigger_paddr + sizeof(*trigger_tab), | ||
219 | table_size - sizeof(*trigger_tab), | ||
220 | "APEI EINJ Trigger Table"); | ||
221 | if (!r) { | ||
222 | pr_err(EINJ_PFX | ||
223 | "Can not request iomem region <%016llx-%016llx> for Trigger Table Entry.\n", | ||
224 | (unsigned long long)trigger_paddr+sizeof(*trigger_tab), | ||
225 | (unsigned long long)trigger_paddr + table_size); | ||
226 | goto out_rel_header; | ||
227 | } | ||
228 | iounmap(trigger_tab); | ||
229 | trigger_tab = ioremap_cache(trigger_paddr, table_size); | ||
230 | if (!trigger_tab) { | ||
231 | pr_err(EINJ_PFX "Failed to map trigger table!\n"); | ||
232 | goto out_rel_entry; | ||
233 | } | ||
234 | trigger_entry = (struct acpi_whea_header *) | ||
235 | ((char *)trigger_tab + sizeof(struct acpi_einj_trigger)); | ||
236 | apei_resources_init(&trigger_resources); | ||
237 | apei_exec_ctx_init(&trigger_ctx, einj_ins_type, | ||
238 | ARRAY_SIZE(einj_ins_type), | ||
239 | trigger_entry, trigger_tab->entry_count); | ||
240 | rc = apei_exec_collect_resources(&trigger_ctx, &trigger_resources); | ||
241 | if (rc) | ||
242 | goto out_fini; | ||
243 | rc = apei_resources_sub(&trigger_resources, &einj_resources); | ||
244 | if (rc) | ||
245 | goto out_fini; | ||
246 | rc = apei_resources_request(&trigger_resources, "APEI EINJ Trigger"); | ||
247 | if (rc) | ||
248 | goto out_fini; | ||
249 | rc = apei_exec_pre_map_gars(&trigger_ctx); | ||
250 | if (rc) | ||
251 | goto out_release; | ||
252 | |||
253 | rc = apei_exec_run(&trigger_ctx, ACPI_EINJ_TRIGGER_ERROR); | ||
254 | |||
255 | apei_exec_post_unmap_gars(&trigger_ctx); | ||
256 | out_release: | ||
257 | apei_resources_release(&trigger_resources); | ||
258 | out_fini: | ||
259 | apei_resources_fini(&trigger_resources); | ||
260 | out_rel_entry: | ||
261 | release_mem_region(trigger_paddr + sizeof(*trigger_tab), | ||
262 | table_size - sizeof(*trigger_tab)); | ||
263 | out_rel_header: | ||
264 | release_mem_region(trigger_paddr, sizeof(*trigger_tab)); | ||
265 | out: | ||
266 | if (trigger_tab) | ||
267 | iounmap(trigger_tab); | ||
268 | |||
269 | return rc; | ||
270 | } | ||
271 | |||
272 | static int __einj_error_inject(u32 type, u64 param1, u64 param2) | ||
273 | { | ||
274 | struct apei_exec_context ctx; | ||
275 | u64 val, trigger_paddr, timeout = FIRMWARE_TIMEOUT; | ||
276 | int rc; | ||
277 | |||
278 | einj_exec_ctx_init(&ctx); | ||
279 | |||
280 | rc = apei_exec_run(&ctx, ACPI_EINJ_BEGIN_OPERATION); | ||
281 | if (rc) | ||
282 | return rc; | ||
283 | apei_exec_ctx_set_input(&ctx, type); | ||
284 | rc = apei_exec_run(&ctx, ACPI_EINJ_SET_ERROR_TYPE); | ||
285 | if (rc) | ||
286 | return rc; | ||
287 | if (einj_param) { | ||
288 | writeq(param1, &einj_param->param1); | ||
289 | writeq(param2, &einj_param->param2); | ||
290 | } | ||
291 | rc = apei_exec_run(&ctx, ACPI_EINJ_EXECUTE_OPERATION); | ||
292 | if (rc) | ||
293 | return rc; | ||
294 | for (;;) { | ||
295 | rc = apei_exec_run(&ctx, ACPI_EINJ_CHECK_BUSY_STATUS); | ||
296 | if (rc) | ||
297 | return rc; | ||
298 | val = apei_exec_ctx_get_output(&ctx); | ||
299 | if (!(val & EINJ_OP_BUSY)) | ||
300 | break; | ||
301 | if (einj_timedout(&timeout)) | ||
302 | return -EIO; | ||
303 | } | ||
304 | rc = apei_exec_run(&ctx, ACPI_EINJ_GET_COMMAND_STATUS); | ||
305 | if (rc) | ||
306 | return rc; | ||
307 | val = apei_exec_ctx_get_output(&ctx); | ||
308 | if (val != EINJ_STATUS_SUCCESS) | ||
309 | return -EBUSY; | ||
310 | |||
311 | rc = apei_exec_run(&ctx, ACPI_EINJ_GET_TRIGGER_TABLE); | ||
312 | if (rc) | ||
313 | return rc; | ||
314 | trigger_paddr = apei_exec_ctx_get_output(&ctx); | ||
315 | rc = __einj_error_trigger(trigger_paddr); | ||
316 | if (rc) | ||
317 | return rc; | ||
318 | rc = apei_exec_run(&ctx, ACPI_EINJ_END_OPERATION); | ||
319 | |||
320 | return rc; | ||
321 | } | ||
322 | |||
323 | /* Inject the specified hardware error */ | ||
324 | static int einj_error_inject(u32 type, u64 param1, u64 param2) | ||
325 | { | ||
326 | int rc; | ||
327 | |||
328 | mutex_lock(&einj_mutex); | ||
329 | rc = __einj_error_inject(type, param1, param2); | ||
330 | mutex_unlock(&einj_mutex); | ||
331 | |||
332 | return rc; | ||
333 | } | ||
334 | |||
335 | static u32 error_type; | ||
336 | static u64 error_param1; | ||
337 | static u64 error_param2; | ||
338 | static struct dentry *einj_debug_dir; | ||
339 | |||
340 | static int available_error_type_show(struct seq_file *m, void *v) | ||
341 | { | ||
342 | int rc; | ||
343 | u32 available_error_type = 0; | ||
344 | |||
345 | rc = einj_get_available_error_type(&available_error_type); | ||
346 | if (rc) | ||
347 | return rc; | ||
348 | if (available_error_type & 0x0001) | ||
349 | seq_printf(m, "0x00000001\tProcessor Correctable\n"); | ||
350 | if (available_error_type & 0x0002) | ||
351 | seq_printf(m, "0x00000002\tProcessor Uncorrectable non-fatal\n"); | ||
352 | if (available_error_type & 0x0004) | ||
353 | seq_printf(m, "0x00000004\tProcessor Uncorrectable fatal\n"); | ||
354 | if (available_error_type & 0x0008) | ||
355 | seq_printf(m, "0x00000008\tMemory Correctable\n"); | ||
356 | if (available_error_type & 0x0010) | ||
357 | seq_printf(m, "0x00000010\tMemory Uncorrectable non-fatal\n"); | ||
358 | if (available_error_type & 0x0020) | ||
359 | seq_printf(m, "0x00000020\tMemory Uncorrectable fatal\n"); | ||
360 | if (available_error_type & 0x0040) | ||
361 | seq_printf(m, "0x00000040\tPCI Express Correctable\n"); | ||
362 | if (available_error_type & 0x0080) | ||
363 | seq_printf(m, "0x00000080\tPCI Express Uncorrectable non-fatal\n"); | ||
364 | if (available_error_type & 0x0100) | ||
365 | seq_printf(m, "0x00000100\tPCI Express Uncorrectable fatal\n"); | ||
366 | if (available_error_type & 0x0200) | ||
367 | seq_printf(m, "0x00000200\tPlatform Correctable\n"); | ||
368 | if (available_error_type & 0x0400) | ||
369 | seq_printf(m, "0x00000400\tPlatform Uncorrectable non-fatal\n"); | ||
370 | if (available_error_type & 0x0800) | ||
371 | seq_printf(m, "0x00000800\tPlatform Uncorrectable fatal\n"); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static int available_error_type_open(struct inode *inode, struct file *file) | ||
377 | { | ||
378 | return single_open(file, available_error_type_show, NULL); | ||
379 | } | ||
380 | |||
381 | static const struct file_operations available_error_type_fops = { | ||
382 | .open = available_error_type_open, | ||
383 | .read = seq_read, | ||
384 | .llseek = seq_lseek, | ||
385 | .release = single_release, | ||
386 | }; | ||
387 | |||
388 | static int error_type_get(void *data, u64 *val) | ||
389 | { | ||
390 | *val = error_type; | ||
391 | |||
392 | return 0; | ||
393 | } | ||
394 | |||
395 | static int error_type_set(void *data, u64 val) | ||
396 | { | ||
397 | int rc; | ||
398 | u32 available_error_type = 0; | ||
399 | |||
400 | /* Only one error type can be specified */ | ||
401 | if (val & (val - 1)) | ||
402 | return -EINVAL; | ||
403 | rc = einj_get_available_error_type(&available_error_type); | ||
404 | if (rc) | ||
405 | return rc; | ||
406 | if (!(val & available_error_type)) | ||
407 | return -EINVAL; | ||
408 | error_type = val; | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | DEFINE_SIMPLE_ATTRIBUTE(error_type_fops, error_type_get, | ||
414 | error_type_set, "0x%llx\n"); | ||
415 | |||
416 | static int error_inject_set(void *data, u64 val) | ||
417 | { | ||
418 | if (!error_type) | ||
419 | return -EINVAL; | ||
420 | |||
421 | return einj_error_inject(error_type, error_param1, error_param2); | ||
422 | } | ||
423 | |||
424 | DEFINE_SIMPLE_ATTRIBUTE(error_inject_fops, NULL, | ||
425 | error_inject_set, "%llu\n"); | ||
426 | |||
427 | static int einj_check_table(struct acpi_table_einj *einj_tab) | ||
428 | { | ||
429 | if (einj_tab->header_length != sizeof(struct acpi_table_einj)) | ||
430 | return -EINVAL; | ||
431 | if (einj_tab->header.length < sizeof(struct acpi_table_einj)) | ||
432 | return -EINVAL; | ||
433 | if (einj_tab->entries != | ||
434 | (einj_tab->header.length - sizeof(struct acpi_table_einj)) / | ||
435 | sizeof(struct acpi_einj_entry)) | ||
436 | return -EINVAL; | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | static int __init einj_init(void) | ||
442 | { | ||
443 | int rc; | ||
444 | u64 param_paddr; | ||
445 | acpi_status status; | ||
446 | struct dentry *fentry; | ||
447 | struct apei_exec_context ctx; | ||
448 | |||
449 | if (acpi_disabled) | ||
450 | return -ENODEV; | ||
451 | |||
452 | status = acpi_get_table(ACPI_SIG_EINJ, 0, | ||
453 | (struct acpi_table_header **)&einj_tab); | ||
454 | if (status == AE_NOT_FOUND) { | ||
455 | pr_info(EINJ_PFX "Table is not found!\n"); | ||
456 | return -ENODEV; | ||
457 | } else if (ACPI_FAILURE(status)) { | ||
458 | const char *msg = acpi_format_exception(status); | ||
459 | pr_err(EINJ_PFX "Failed to get table, %s\n", msg); | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | |||
463 | rc = einj_check_table(einj_tab); | ||
464 | if (rc) { | ||
465 | pr_warning(FW_BUG EINJ_PFX "EINJ table is invalid\n"); | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | |||
469 | rc = -ENOMEM; | ||
470 | einj_debug_dir = debugfs_create_dir("einj", apei_get_debugfs_dir()); | ||
471 | if (!einj_debug_dir) | ||
472 | goto err_cleanup; | ||
473 | fentry = debugfs_create_file("available_error_type", S_IRUSR, | ||
474 | einj_debug_dir, NULL, | ||
475 | &available_error_type_fops); | ||
476 | if (!fentry) | ||
477 | goto err_cleanup; | ||
478 | fentry = debugfs_create_file("error_type", S_IRUSR | S_IWUSR, | ||
479 | einj_debug_dir, NULL, &error_type_fops); | ||
480 | if (!fentry) | ||
481 | goto err_cleanup; | ||
482 | fentry = debugfs_create_x64("param1", S_IRUSR | S_IWUSR, | ||
483 | einj_debug_dir, &error_param1); | ||
484 | if (!fentry) | ||
485 | goto err_cleanup; | ||
486 | fentry = debugfs_create_x64("param2", S_IRUSR | S_IWUSR, | ||
487 | einj_debug_dir, &error_param2); | ||
488 | if (!fentry) | ||
489 | goto err_cleanup; | ||
490 | fentry = debugfs_create_file("error_inject", S_IWUSR, | ||
491 | einj_debug_dir, NULL, &error_inject_fops); | ||
492 | if (!fentry) | ||
493 | goto err_cleanup; | ||
494 | |||
495 | apei_resources_init(&einj_resources); | ||
496 | einj_exec_ctx_init(&ctx); | ||
497 | rc = apei_exec_collect_resources(&ctx, &einj_resources); | ||
498 | if (rc) | ||
499 | goto err_fini; | ||
500 | rc = apei_resources_request(&einj_resources, "APEI EINJ"); | ||
501 | if (rc) | ||
502 | goto err_fini; | ||
503 | rc = apei_exec_pre_map_gars(&ctx); | ||
504 | if (rc) | ||
505 | goto err_release; | ||
506 | param_paddr = einj_get_parameter_address(); | ||
507 | if (param_paddr) { | ||
508 | einj_param = ioremap(param_paddr, sizeof(*einj_param)); | ||
509 | rc = -ENOMEM; | ||
510 | if (!einj_param) | ||
511 | goto err_unmap; | ||
512 | } | ||
513 | |||
514 | pr_info(EINJ_PFX "Error INJection is initialized.\n"); | ||
515 | |||
516 | return 0; | ||
517 | |||
518 | err_unmap: | ||
519 | apei_exec_post_unmap_gars(&ctx); | ||
520 | err_release: | ||
521 | apei_resources_release(&einj_resources); | ||
522 | err_fini: | ||
523 | apei_resources_fini(&einj_resources); | ||
524 | err_cleanup: | ||
525 | debugfs_remove_recursive(einj_debug_dir); | ||
526 | |||
527 | return rc; | ||
528 | } | ||
529 | |||
530 | static void __exit einj_exit(void) | ||
531 | { | ||
532 | struct apei_exec_context ctx; | ||
533 | |||
534 | if (einj_param) | ||
535 | iounmap(einj_param); | ||
536 | einj_exec_ctx_init(&ctx); | ||
537 | apei_exec_post_unmap_gars(&ctx); | ||
538 | apei_resources_release(&einj_resources); | ||
539 | apei_resources_fini(&einj_resources); | ||
540 | debugfs_remove_recursive(einj_debug_dir); | ||
541 | } | ||
542 | |||
543 | module_init(einj_init); | ||
544 | module_exit(einj_exit); | ||
545 | |||
546 | MODULE_AUTHOR("Huang Ying"); | ||
547 | MODULE_DESCRIPTION("APEI Error INJection support"); | ||
548 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c new file mode 100644 index 000000000000..2ebc39115507 --- /dev/null +++ b/drivers/acpi/apei/erst.c | |||
@@ -0,0 +1,855 @@ | |||
1 | /* | ||
2 | * APEI Error Record Serialization Table support | ||
3 | * | ||
4 | * ERST is a way provided by APEI to save and retrieve hardware error | ||
5 | * infomation to and from a persistent store. | ||
6 | * | ||
7 | * For more information about ERST, please refer to ACPI Specification | ||
8 | * version 4.0, section 17.4. | ||
9 | * | ||
10 | * Copyright 2010 Intel Corp. | ||
11 | * Author: Huang Ying <ying.huang@intel.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or | ||
14 | * modify it under the terms of the GNU General Public License version | ||
15 | * 2 as published by the Free Software Foundation. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
25 | */ | ||
26 | |||
27 | #include <linux/kernel.h> | ||
28 | #include <linux/module.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/io.h> | ||
32 | #include <linux/acpi.h> | ||
33 | #include <linux/uaccess.h> | ||
34 | #include <linux/cper.h> | ||
35 | #include <linux/nmi.h> | ||
36 | #include <acpi/apei.h> | ||
37 | |||
38 | #include "apei-internal.h" | ||
39 | |||
40 | #define ERST_PFX "ERST: " | ||
41 | |||
42 | /* ERST command status */ | ||
43 | #define ERST_STATUS_SUCCESS 0x0 | ||
44 | #define ERST_STATUS_NOT_ENOUGH_SPACE 0x1 | ||
45 | #define ERST_STATUS_HARDWARE_NOT_AVAILABLE 0x2 | ||
46 | #define ERST_STATUS_FAILED 0x3 | ||
47 | #define ERST_STATUS_RECORD_STORE_EMPTY 0x4 | ||
48 | #define ERST_STATUS_RECORD_NOT_FOUND 0x5 | ||
49 | |||
50 | #define ERST_TAB_ENTRY(tab) \ | ||
51 | ((struct acpi_whea_header *)((char *)(tab) + \ | ||
52 | sizeof(struct acpi_table_erst))) | ||
53 | |||
54 | #define SPIN_UNIT 100 /* 100ns */ | ||
55 | /* Firmware should respond within 1 miliseconds */ | ||
56 | #define FIRMWARE_TIMEOUT (1 * NSEC_PER_MSEC) | ||
57 | #define FIRMWARE_MAX_STALL 50 /* 50us */ | ||
58 | |||
59 | int erst_disable; | ||
60 | EXPORT_SYMBOL_GPL(erst_disable); | ||
61 | |||
62 | static struct acpi_table_erst *erst_tab; | ||
63 | |||
64 | /* ERST Error Log Address Range atrributes */ | ||
65 | #define ERST_RANGE_RESERVED 0x0001 | ||
66 | #define ERST_RANGE_NVRAM 0x0002 | ||
67 | #define ERST_RANGE_SLOW 0x0004 | ||
68 | |||
69 | /* | ||
70 | * ERST Error Log Address Range, used as buffer for reading/writing | ||
71 | * error records. | ||
72 | */ | ||
73 | static struct erst_erange { | ||
74 | u64 base; | ||
75 | u64 size; | ||
76 | void __iomem *vaddr; | ||
77 | u32 attr; | ||
78 | } erst_erange; | ||
79 | |||
80 | /* | ||
81 | * Prevent ERST interpreter to run simultaneously, because the | ||
82 | * corresponding firmware implementation may not work properly when | ||
83 | * invoked simultaneously. | ||
84 | * | ||
85 | * It is used to provide exclusive accessing for ERST Error Log | ||
86 | * Address Range too. | ||
87 | */ | ||
88 | static DEFINE_SPINLOCK(erst_lock); | ||
89 | |||
90 | static inline int erst_errno(int command_status) | ||
91 | { | ||
92 | switch (command_status) { | ||
93 | case ERST_STATUS_SUCCESS: | ||
94 | return 0; | ||
95 | case ERST_STATUS_HARDWARE_NOT_AVAILABLE: | ||
96 | return -ENODEV; | ||
97 | case ERST_STATUS_NOT_ENOUGH_SPACE: | ||
98 | return -ENOSPC; | ||
99 | case ERST_STATUS_RECORD_STORE_EMPTY: | ||
100 | case ERST_STATUS_RECORD_NOT_FOUND: | ||
101 | return -ENOENT; | ||
102 | default: | ||
103 | return -EINVAL; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static int erst_timedout(u64 *t, u64 spin_unit) | ||
108 | { | ||
109 | if ((s64)*t < spin_unit) { | ||
110 | pr_warning(FW_WARN ERST_PFX | ||
111 | "Firmware does not respond in time\n"); | ||
112 | return 1; | ||
113 | } | ||
114 | *t -= spin_unit; | ||
115 | ndelay(spin_unit); | ||
116 | touch_nmi_watchdog(); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static int erst_exec_load_var1(struct apei_exec_context *ctx, | ||
121 | struct acpi_whea_header *entry) | ||
122 | { | ||
123 | return __apei_exec_read_register(entry, &ctx->var1); | ||
124 | } | ||
125 | |||
126 | static int erst_exec_load_var2(struct apei_exec_context *ctx, | ||
127 | struct acpi_whea_header *entry) | ||
128 | { | ||
129 | return __apei_exec_read_register(entry, &ctx->var2); | ||
130 | } | ||
131 | |||
132 | static int erst_exec_store_var1(struct apei_exec_context *ctx, | ||
133 | struct acpi_whea_header *entry) | ||
134 | { | ||
135 | return __apei_exec_write_register(entry, ctx->var1); | ||
136 | } | ||
137 | |||
138 | static int erst_exec_add(struct apei_exec_context *ctx, | ||
139 | struct acpi_whea_header *entry) | ||
140 | { | ||
141 | ctx->var1 += ctx->var2; | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static int erst_exec_subtract(struct apei_exec_context *ctx, | ||
146 | struct acpi_whea_header *entry) | ||
147 | { | ||
148 | ctx->var1 -= ctx->var2; | ||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | static int erst_exec_add_value(struct apei_exec_context *ctx, | ||
153 | struct acpi_whea_header *entry) | ||
154 | { | ||
155 | int rc; | ||
156 | u64 val; | ||
157 | |||
158 | rc = __apei_exec_read_register(entry, &val); | ||
159 | if (rc) | ||
160 | return rc; | ||
161 | val += ctx->value; | ||
162 | rc = __apei_exec_write_register(entry, val); | ||
163 | return rc; | ||
164 | } | ||
165 | |||
166 | static int erst_exec_subtract_value(struct apei_exec_context *ctx, | ||
167 | struct acpi_whea_header *entry) | ||
168 | { | ||
169 | int rc; | ||
170 | u64 val; | ||
171 | |||
172 | rc = __apei_exec_read_register(entry, &val); | ||
173 | if (rc) | ||
174 | return rc; | ||
175 | val -= ctx->value; | ||
176 | rc = __apei_exec_write_register(entry, val); | ||
177 | return rc; | ||
178 | } | ||
179 | |||
180 | static int erst_exec_stall(struct apei_exec_context *ctx, | ||
181 | struct acpi_whea_header *entry) | ||
182 | { | ||
183 | u64 stall_time; | ||
184 | |||
185 | if (ctx->value > FIRMWARE_MAX_STALL) { | ||
186 | if (!in_nmi()) | ||
187 | pr_warning(FW_WARN ERST_PFX | ||
188 | "Too long stall time for stall instruction: %llx.\n", | ||
189 | ctx->value); | ||
190 | stall_time = FIRMWARE_MAX_STALL; | ||
191 | } else | ||
192 | stall_time = ctx->value; | ||
193 | udelay(stall_time); | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int erst_exec_stall_while_true(struct apei_exec_context *ctx, | ||
198 | struct acpi_whea_header *entry) | ||
199 | { | ||
200 | int rc; | ||
201 | u64 val; | ||
202 | u64 timeout = FIRMWARE_TIMEOUT; | ||
203 | u64 stall_time; | ||
204 | |||
205 | if (ctx->var1 > FIRMWARE_MAX_STALL) { | ||
206 | if (!in_nmi()) | ||
207 | pr_warning(FW_WARN ERST_PFX | ||
208 | "Too long stall time for stall while true instruction: %llx.\n", | ||
209 | ctx->var1); | ||
210 | stall_time = FIRMWARE_MAX_STALL; | ||
211 | } else | ||
212 | stall_time = ctx->var1; | ||
213 | |||
214 | for (;;) { | ||
215 | rc = __apei_exec_read_register(entry, &val); | ||
216 | if (rc) | ||
217 | return rc; | ||
218 | if (val != ctx->value) | ||
219 | break; | ||
220 | if (erst_timedout(&timeout, stall_time * NSEC_PER_USEC)) | ||
221 | return -EIO; | ||
222 | } | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int erst_exec_skip_next_instruction_if_true( | ||
227 | struct apei_exec_context *ctx, | ||
228 | struct acpi_whea_header *entry) | ||
229 | { | ||
230 | int rc; | ||
231 | u64 val; | ||
232 | |||
233 | rc = __apei_exec_read_register(entry, &val); | ||
234 | if (rc) | ||
235 | return rc; | ||
236 | if (val == ctx->value) { | ||
237 | ctx->ip += 2; | ||
238 | return APEI_EXEC_SET_IP; | ||
239 | } | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int erst_exec_goto(struct apei_exec_context *ctx, | ||
245 | struct acpi_whea_header *entry) | ||
246 | { | ||
247 | ctx->ip = ctx->value; | ||
248 | return APEI_EXEC_SET_IP; | ||
249 | } | ||
250 | |||
251 | static int erst_exec_set_src_address_base(struct apei_exec_context *ctx, | ||
252 | struct acpi_whea_header *entry) | ||
253 | { | ||
254 | return __apei_exec_read_register(entry, &ctx->src_base); | ||
255 | } | ||
256 | |||
257 | static int erst_exec_set_dst_address_base(struct apei_exec_context *ctx, | ||
258 | struct acpi_whea_header *entry) | ||
259 | { | ||
260 | return __apei_exec_read_register(entry, &ctx->dst_base); | ||
261 | } | ||
262 | |||
263 | static int erst_exec_move_data(struct apei_exec_context *ctx, | ||
264 | struct acpi_whea_header *entry) | ||
265 | { | ||
266 | int rc; | ||
267 | u64 offset; | ||
268 | |||
269 | rc = __apei_exec_read_register(entry, &offset); | ||
270 | if (rc) | ||
271 | return rc; | ||
272 | memmove((void *)ctx->dst_base + offset, | ||
273 | (void *)ctx->src_base + offset, | ||
274 | ctx->var2); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static struct apei_exec_ins_type erst_ins_type[] = { | ||
280 | [ACPI_ERST_READ_REGISTER] = { | ||
281 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
282 | .run = apei_exec_read_register, | ||
283 | }, | ||
284 | [ACPI_ERST_READ_REGISTER_VALUE] = { | ||
285 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
286 | .run = apei_exec_read_register_value, | ||
287 | }, | ||
288 | [ACPI_ERST_WRITE_REGISTER] = { | ||
289 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
290 | .run = apei_exec_write_register, | ||
291 | }, | ||
292 | [ACPI_ERST_WRITE_REGISTER_VALUE] = { | ||
293 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
294 | .run = apei_exec_write_register_value, | ||
295 | }, | ||
296 | [ACPI_ERST_NOOP] = { | ||
297 | .flags = 0, | ||
298 | .run = apei_exec_noop, | ||
299 | }, | ||
300 | [ACPI_ERST_LOAD_VAR1] = { | ||
301 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
302 | .run = erst_exec_load_var1, | ||
303 | }, | ||
304 | [ACPI_ERST_LOAD_VAR2] = { | ||
305 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
306 | .run = erst_exec_load_var2, | ||
307 | }, | ||
308 | [ACPI_ERST_STORE_VAR1] = { | ||
309 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
310 | .run = erst_exec_store_var1, | ||
311 | }, | ||
312 | [ACPI_ERST_ADD] = { | ||
313 | .flags = 0, | ||
314 | .run = erst_exec_add, | ||
315 | }, | ||
316 | [ACPI_ERST_SUBTRACT] = { | ||
317 | .flags = 0, | ||
318 | .run = erst_exec_subtract, | ||
319 | }, | ||
320 | [ACPI_ERST_ADD_VALUE] = { | ||
321 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
322 | .run = erst_exec_add_value, | ||
323 | }, | ||
324 | [ACPI_ERST_SUBTRACT_VALUE] = { | ||
325 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
326 | .run = erst_exec_subtract_value, | ||
327 | }, | ||
328 | [ACPI_ERST_STALL] = { | ||
329 | .flags = 0, | ||
330 | .run = erst_exec_stall, | ||
331 | }, | ||
332 | [ACPI_ERST_STALL_WHILE_TRUE] = { | ||
333 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
334 | .run = erst_exec_stall_while_true, | ||
335 | }, | ||
336 | [ACPI_ERST_SKIP_NEXT_IF_TRUE] = { | ||
337 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
338 | .run = erst_exec_skip_next_instruction_if_true, | ||
339 | }, | ||
340 | [ACPI_ERST_GOTO] = { | ||
341 | .flags = 0, | ||
342 | .run = erst_exec_goto, | ||
343 | }, | ||
344 | [ACPI_ERST_SET_SRC_ADDRESS_BASE] = { | ||
345 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
346 | .run = erst_exec_set_src_address_base, | ||
347 | }, | ||
348 | [ACPI_ERST_SET_DST_ADDRESS_BASE] = { | ||
349 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
350 | .run = erst_exec_set_dst_address_base, | ||
351 | }, | ||
352 | [ACPI_ERST_MOVE_DATA] = { | ||
353 | .flags = APEI_EXEC_INS_ACCESS_REGISTER, | ||
354 | .run = erst_exec_move_data, | ||
355 | }, | ||
356 | }; | ||
357 | |||
358 | static inline void erst_exec_ctx_init(struct apei_exec_context *ctx) | ||
359 | { | ||
360 | apei_exec_ctx_init(ctx, erst_ins_type, ARRAY_SIZE(erst_ins_type), | ||
361 | ERST_TAB_ENTRY(erst_tab), erst_tab->entries); | ||
362 | } | ||
363 | |||
364 | static int erst_get_erange(struct erst_erange *range) | ||
365 | { | ||
366 | struct apei_exec_context ctx; | ||
367 | int rc; | ||
368 | |||
369 | erst_exec_ctx_init(&ctx); | ||
370 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_RANGE); | ||
371 | if (rc) | ||
372 | return rc; | ||
373 | range->base = apei_exec_ctx_get_output(&ctx); | ||
374 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_LENGTH); | ||
375 | if (rc) | ||
376 | return rc; | ||
377 | range->size = apei_exec_ctx_get_output(&ctx); | ||
378 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_ERROR_ATTRIBUTES); | ||
379 | if (rc) | ||
380 | return rc; | ||
381 | range->attr = apei_exec_ctx_get_output(&ctx); | ||
382 | |||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static ssize_t __erst_get_record_count(void) | ||
387 | { | ||
388 | struct apei_exec_context ctx; | ||
389 | int rc; | ||
390 | |||
391 | erst_exec_ctx_init(&ctx); | ||
392 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_COUNT); | ||
393 | if (rc) | ||
394 | return rc; | ||
395 | return apei_exec_ctx_get_output(&ctx); | ||
396 | } | ||
397 | |||
398 | ssize_t erst_get_record_count(void) | ||
399 | { | ||
400 | ssize_t count; | ||
401 | unsigned long flags; | ||
402 | |||
403 | if (erst_disable) | ||
404 | return -ENODEV; | ||
405 | |||
406 | spin_lock_irqsave(&erst_lock, flags); | ||
407 | count = __erst_get_record_count(); | ||
408 | spin_unlock_irqrestore(&erst_lock, flags); | ||
409 | |||
410 | return count; | ||
411 | } | ||
412 | EXPORT_SYMBOL_GPL(erst_get_record_count); | ||
413 | |||
414 | static int __erst_get_next_record_id(u64 *record_id) | ||
415 | { | ||
416 | struct apei_exec_context ctx; | ||
417 | int rc; | ||
418 | |||
419 | erst_exec_ctx_init(&ctx); | ||
420 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_RECORD_ID); | ||
421 | if (rc) | ||
422 | return rc; | ||
423 | *record_id = apei_exec_ctx_get_output(&ctx); | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * Get the record ID of an existing error record on the persistent | ||
430 | * storage. If there is no error record on the persistent storage, the | ||
431 | * returned record_id is APEI_ERST_INVALID_RECORD_ID. | ||
432 | */ | ||
433 | int erst_get_next_record_id(u64 *record_id) | ||
434 | { | ||
435 | int rc; | ||
436 | unsigned long flags; | ||
437 | |||
438 | if (erst_disable) | ||
439 | return -ENODEV; | ||
440 | |||
441 | spin_lock_irqsave(&erst_lock, flags); | ||
442 | rc = __erst_get_next_record_id(record_id); | ||
443 | spin_unlock_irqrestore(&erst_lock, flags); | ||
444 | |||
445 | return rc; | ||
446 | } | ||
447 | EXPORT_SYMBOL_GPL(erst_get_next_record_id); | ||
448 | |||
449 | static int __erst_write_to_storage(u64 offset) | ||
450 | { | ||
451 | struct apei_exec_context ctx; | ||
452 | u64 timeout = FIRMWARE_TIMEOUT; | ||
453 | u64 val; | ||
454 | int rc; | ||
455 | |||
456 | erst_exec_ctx_init(&ctx); | ||
457 | rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_WRITE); | ||
458 | if (rc) | ||
459 | return rc; | ||
460 | apei_exec_ctx_set_input(&ctx, offset); | ||
461 | rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_OFFSET); | ||
462 | if (rc) | ||
463 | return rc; | ||
464 | rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION); | ||
465 | if (rc) | ||
466 | return rc; | ||
467 | for (;;) { | ||
468 | rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS); | ||
469 | if (rc) | ||
470 | return rc; | ||
471 | val = apei_exec_ctx_get_output(&ctx); | ||
472 | if (!val) | ||
473 | break; | ||
474 | if (erst_timedout(&timeout, SPIN_UNIT)) | ||
475 | return -EIO; | ||
476 | } | ||
477 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS); | ||
478 | if (rc) | ||
479 | return rc; | ||
480 | val = apei_exec_ctx_get_output(&ctx); | ||
481 | rc = apei_exec_run(&ctx, ACPI_ERST_END); | ||
482 | if (rc) | ||
483 | return rc; | ||
484 | |||
485 | return erst_errno(val); | ||
486 | } | ||
487 | |||
488 | static int __erst_read_from_storage(u64 record_id, u64 offset) | ||
489 | { | ||
490 | struct apei_exec_context ctx; | ||
491 | u64 timeout = FIRMWARE_TIMEOUT; | ||
492 | u64 val; | ||
493 | int rc; | ||
494 | |||
495 | erst_exec_ctx_init(&ctx); | ||
496 | rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_READ); | ||
497 | if (rc) | ||
498 | return rc; | ||
499 | apei_exec_ctx_set_input(&ctx, offset); | ||
500 | rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_OFFSET); | ||
501 | if (rc) | ||
502 | return rc; | ||
503 | apei_exec_ctx_set_input(&ctx, record_id); | ||
504 | rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_ID); | ||
505 | if (rc) | ||
506 | return rc; | ||
507 | rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION); | ||
508 | if (rc) | ||
509 | return rc; | ||
510 | for (;;) { | ||
511 | rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS); | ||
512 | if (rc) | ||
513 | return rc; | ||
514 | val = apei_exec_ctx_get_output(&ctx); | ||
515 | if (!val) | ||
516 | break; | ||
517 | if (erst_timedout(&timeout, SPIN_UNIT)) | ||
518 | return -EIO; | ||
519 | }; | ||
520 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS); | ||
521 | if (rc) | ||
522 | return rc; | ||
523 | val = apei_exec_ctx_get_output(&ctx); | ||
524 | rc = apei_exec_run(&ctx, ACPI_ERST_END); | ||
525 | if (rc) | ||
526 | return rc; | ||
527 | |||
528 | return erst_errno(val); | ||
529 | } | ||
530 | |||
531 | static int __erst_clear_from_storage(u64 record_id) | ||
532 | { | ||
533 | struct apei_exec_context ctx; | ||
534 | u64 timeout = FIRMWARE_TIMEOUT; | ||
535 | u64 val; | ||
536 | int rc; | ||
537 | |||
538 | erst_exec_ctx_init(&ctx); | ||
539 | rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_CLEAR); | ||
540 | if (rc) | ||
541 | return rc; | ||
542 | apei_exec_ctx_set_input(&ctx, record_id); | ||
543 | rc = apei_exec_run(&ctx, ACPI_ERST_SET_RECORD_ID); | ||
544 | if (rc) | ||
545 | return rc; | ||
546 | rc = apei_exec_run(&ctx, ACPI_ERST_EXECUTE_OPERATION); | ||
547 | if (rc) | ||
548 | return rc; | ||
549 | for (;;) { | ||
550 | rc = apei_exec_run(&ctx, ACPI_ERST_CHECK_BUSY_STATUS); | ||
551 | if (rc) | ||
552 | return rc; | ||
553 | val = apei_exec_ctx_get_output(&ctx); | ||
554 | if (!val) | ||
555 | break; | ||
556 | if (erst_timedout(&timeout, SPIN_UNIT)) | ||
557 | return -EIO; | ||
558 | } | ||
559 | rc = apei_exec_run(&ctx, ACPI_ERST_GET_COMMAND_STATUS); | ||
560 | if (rc) | ||
561 | return rc; | ||
562 | val = apei_exec_ctx_get_output(&ctx); | ||
563 | rc = apei_exec_run(&ctx, ACPI_ERST_END); | ||
564 | if (rc) | ||
565 | return rc; | ||
566 | |||
567 | return erst_errno(val); | ||
568 | } | ||
569 | |||
570 | /* NVRAM ERST Error Log Address Range is not supported yet */ | ||
571 | static void pr_unimpl_nvram(void) | ||
572 | { | ||
573 | if (printk_ratelimit()) | ||
574 | pr_warning(ERST_PFX | ||
575 | "NVRAM ERST Log Address Range is not implemented yet\n"); | ||
576 | } | ||
577 | |||
578 | static int __erst_write_to_nvram(const struct cper_record_header *record) | ||
579 | { | ||
580 | /* do not print message, because printk is not safe for NMI */ | ||
581 | return -ENOSYS; | ||
582 | } | ||
583 | |||
584 | static int __erst_read_to_erange_from_nvram(u64 record_id, u64 *offset) | ||
585 | { | ||
586 | pr_unimpl_nvram(); | ||
587 | return -ENOSYS; | ||
588 | } | ||
589 | |||
590 | static int __erst_clear_from_nvram(u64 record_id) | ||
591 | { | ||
592 | pr_unimpl_nvram(); | ||
593 | return -ENOSYS; | ||
594 | } | ||
595 | |||
596 | int erst_write(const struct cper_record_header *record) | ||
597 | { | ||
598 | int rc; | ||
599 | unsigned long flags; | ||
600 | struct cper_record_header *rcd_erange; | ||
601 | |||
602 | if (erst_disable) | ||
603 | return -ENODEV; | ||
604 | |||
605 | if (memcmp(record->signature, CPER_SIG_RECORD, CPER_SIG_SIZE)) | ||
606 | return -EINVAL; | ||
607 | |||
608 | if (erst_erange.attr & ERST_RANGE_NVRAM) { | ||
609 | if (!spin_trylock_irqsave(&erst_lock, flags)) | ||
610 | return -EBUSY; | ||
611 | rc = __erst_write_to_nvram(record); | ||
612 | spin_unlock_irqrestore(&erst_lock, flags); | ||
613 | return rc; | ||
614 | } | ||
615 | |||
616 | if (record->record_length > erst_erange.size) | ||
617 | return -EINVAL; | ||
618 | |||
619 | if (!spin_trylock_irqsave(&erst_lock, flags)) | ||
620 | return -EBUSY; | ||
621 | memcpy(erst_erange.vaddr, record, record->record_length); | ||
622 | rcd_erange = erst_erange.vaddr; | ||
623 | /* signature for serialization system */ | ||
624 | memcpy(&rcd_erange->persistence_information, "ER", 2); | ||
625 | |||
626 | rc = __erst_write_to_storage(0); | ||
627 | spin_unlock_irqrestore(&erst_lock, flags); | ||
628 | |||
629 | return rc; | ||
630 | } | ||
631 | EXPORT_SYMBOL_GPL(erst_write); | ||
632 | |||
633 | static int __erst_read_to_erange(u64 record_id, u64 *offset) | ||
634 | { | ||
635 | int rc; | ||
636 | |||
637 | if (erst_erange.attr & ERST_RANGE_NVRAM) | ||
638 | return __erst_read_to_erange_from_nvram( | ||
639 | record_id, offset); | ||
640 | |||
641 | rc = __erst_read_from_storage(record_id, 0); | ||
642 | if (rc) | ||
643 | return rc; | ||
644 | *offset = 0; | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static ssize_t __erst_read(u64 record_id, struct cper_record_header *record, | ||
650 | size_t buflen) | ||
651 | { | ||
652 | int rc; | ||
653 | u64 offset, len = 0; | ||
654 | struct cper_record_header *rcd_tmp; | ||
655 | |||
656 | rc = __erst_read_to_erange(record_id, &offset); | ||
657 | if (rc) | ||
658 | return rc; | ||
659 | rcd_tmp = erst_erange.vaddr + offset; | ||
660 | len = rcd_tmp->record_length; | ||
661 | if (len <= buflen) | ||
662 | memcpy(record, rcd_tmp, len); | ||
663 | |||
664 | return len; | ||
665 | } | ||
666 | |||
667 | /* | ||
668 | * If return value > buflen, the buffer size is not big enough, | ||
669 | * else if return value < 0, something goes wrong, | ||
670 | * else everything is OK, and return value is record length | ||
671 | */ | ||
672 | ssize_t erst_read(u64 record_id, struct cper_record_header *record, | ||
673 | size_t buflen) | ||
674 | { | ||
675 | ssize_t len; | ||
676 | unsigned long flags; | ||
677 | |||
678 | if (erst_disable) | ||
679 | return -ENODEV; | ||
680 | |||
681 | spin_lock_irqsave(&erst_lock, flags); | ||
682 | len = __erst_read(record_id, record, buflen); | ||
683 | spin_unlock_irqrestore(&erst_lock, flags); | ||
684 | return len; | ||
685 | } | ||
686 | EXPORT_SYMBOL_GPL(erst_read); | ||
687 | |||
688 | /* | ||
689 | * If return value > buflen, the buffer size is not big enough, | ||
690 | * else if return value = 0, there is no more record to read, | ||
691 | * else if return value < 0, something goes wrong, | ||
692 | * else everything is OK, and return value is record length | ||
693 | */ | ||
694 | ssize_t erst_read_next(struct cper_record_header *record, size_t buflen) | ||
695 | { | ||
696 | int rc; | ||
697 | ssize_t len; | ||
698 | unsigned long flags; | ||
699 | u64 record_id; | ||
700 | |||
701 | if (erst_disable) | ||
702 | return -ENODEV; | ||
703 | |||
704 | spin_lock_irqsave(&erst_lock, flags); | ||
705 | rc = __erst_get_next_record_id(&record_id); | ||
706 | if (rc) { | ||
707 | spin_unlock_irqrestore(&erst_lock, flags); | ||
708 | return rc; | ||
709 | } | ||
710 | /* no more record */ | ||
711 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { | ||
712 | spin_unlock_irqrestore(&erst_lock, flags); | ||
713 | return 0; | ||
714 | } | ||
715 | |||
716 | len = __erst_read(record_id, record, buflen); | ||
717 | spin_unlock_irqrestore(&erst_lock, flags); | ||
718 | |||
719 | return len; | ||
720 | } | ||
721 | EXPORT_SYMBOL_GPL(erst_read_next); | ||
722 | |||
723 | int erst_clear(u64 record_id) | ||
724 | { | ||
725 | int rc; | ||
726 | unsigned long flags; | ||
727 | |||
728 | if (erst_disable) | ||
729 | return -ENODEV; | ||
730 | |||
731 | spin_lock_irqsave(&erst_lock, flags); | ||
732 | if (erst_erange.attr & ERST_RANGE_NVRAM) | ||
733 | rc = __erst_clear_from_nvram(record_id); | ||
734 | else | ||
735 | rc = __erst_clear_from_storage(record_id); | ||
736 | spin_unlock_irqrestore(&erst_lock, flags); | ||
737 | |||
738 | return rc; | ||
739 | } | ||
740 | EXPORT_SYMBOL_GPL(erst_clear); | ||
741 | |||
742 | static int __init setup_erst_disable(char *str) | ||
743 | { | ||
744 | erst_disable = 1; | ||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | __setup("erst_disable", setup_erst_disable); | ||
749 | |||
750 | static int erst_check_table(struct acpi_table_erst *erst_tab) | ||
751 | { | ||
752 | if (erst_tab->header_length != sizeof(struct acpi_table_erst)) | ||
753 | return -EINVAL; | ||
754 | if (erst_tab->header.length < sizeof(struct acpi_table_erst)) | ||
755 | return -EINVAL; | ||
756 | if (erst_tab->entries != | ||
757 | (erst_tab->header.length - sizeof(struct acpi_table_erst)) / | ||
758 | sizeof(struct acpi_erst_entry)) | ||
759 | return -EINVAL; | ||
760 | |||
761 | return 0; | ||
762 | } | ||
763 | |||
764 | static int __init erst_init(void) | ||
765 | { | ||
766 | int rc = 0; | ||
767 | acpi_status status; | ||
768 | struct apei_exec_context ctx; | ||
769 | struct apei_resources erst_resources; | ||
770 | struct resource *r; | ||
771 | |||
772 | if (acpi_disabled) | ||
773 | goto err; | ||
774 | |||
775 | if (erst_disable) { | ||
776 | pr_info(ERST_PFX | ||
777 | "Error Record Serialization Table (ERST) support is disabled.\n"); | ||
778 | goto err; | ||
779 | } | ||
780 | |||
781 | status = acpi_get_table(ACPI_SIG_ERST, 0, | ||
782 | (struct acpi_table_header **)&erst_tab); | ||
783 | if (status == AE_NOT_FOUND) { | ||
784 | pr_err(ERST_PFX "Table is not found!\n"); | ||
785 | goto err; | ||
786 | } else if (ACPI_FAILURE(status)) { | ||
787 | const char *msg = acpi_format_exception(status); | ||
788 | pr_err(ERST_PFX "Failed to get table, %s\n", msg); | ||
789 | rc = -EINVAL; | ||
790 | goto err; | ||
791 | } | ||
792 | |||
793 | rc = erst_check_table(erst_tab); | ||
794 | if (rc) { | ||
795 | pr_err(FW_BUG ERST_PFX "ERST table is invalid\n"); | ||
796 | goto err; | ||
797 | } | ||
798 | |||
799 | apei_resources_init(&erst_resources); | ||
800 | erst_exec_ctx_init(&ctx); | ||
801 | rc = apei_exec_collect_resources(&ctx, &erst_resources); | ||
802 | if (rc) | ||
803 | goto err_fini; | ||
804 | rc = apei_resources_request(&erst_resources, "APEI ERST"); | ||
805 | if (rc) | ||
806 | goto err_fini; | ||
807 | rc = apei_exec_pre_map_gars(&ctx); | ||
808 | if (rc) | ||
809 | goto err_release; | ||
810 | rc = erst_get_erange(&erst_erange); | ||
811 | if (rc) { | ||
812 | if (rc == -ENODEV) | ||
813 | pr_info(ERST_PFX | ||
814 | "The corresponding hardware device or firmware implementation " | ||
815 | "is not available.\n"); | ||
816 | else | ||
817 | pr_err(ERST_PFX | ||
818 | "Failed to get Error Log Address Range.\n"); | ||
819 | goto err_unmap_reg; | ||
820 | } | ||
821 | |||
822 | r = request_mem_region(erst_erange.base, erst_erange.size, "APEI ERST"); | ||
823 | if (!r) { | ||
824 | pr_err(ERST_PFX | ||
825 | "Can not request iomem region <0x%16llx-0x%16llx> for ERST.\n", | ||
826 | (unsigned long long)erst_erange.base, | ||
827 | (unsigned long long)erst_erange.base + erst_erange.size); | ||
828 | rc = -EIO; | ||
829 | goto err_unmap_reg; | ||
830 | } | ||
831 | rc = -ENOMEM; | ||
832 | erst_erange.vaddr = ioremap_cache(erst_erange.base, | ||
833 | erst_erange.size); | ||
834 | if (!erst_erange.vaddr) | ||
835 | goto err_release_erange; | ||
836 | |||
837 | pr_info(ERST_PFX | ||
838 | "Error Record Serialization Table (ERST) support is initialized.\n"); | ||
839 | |||
840 | return 0; | ||
841 | |||
842 | err_release_erange: | ||
843 | release_mem_region(erst_erange.base, erst_erange.size); | ||
844 | err_unmap_reg: | ||
845 | apei_exec_post_unmap_gars(&ctx); | ||
846 | err_release: | ||
847 | apei_resources_release(&erst_resources); | ||
848 | err_fini: | ||
849 | apei_resources_fini(&erst_resources); | ||
850 | err: | ||
851 | erst_disable = 1; | ||
852 | return rc; | ||
853 | } | ||
854 | |||
855 | device_initcall(erst_init); | ||
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c new file mode 100644 index 000000000000..fd0cc016a099 --- /dev/null +++ b/drivers/acpi/apei/ghes.c | |||
@@ -0,0 +1,427 @@ | |||
1 | /* | ||
2 | * APEI Generic Hardware Error Source support | ||
3 | * | ||
4 | * Generic Hardware Error Source provides a way to report platform | ||
5 | * hardware errors (such as that from chipset). It works in so called | ||
6 | * "Firmware First" mode, that is, hardware errors are reported to | ||
7 | * firmware firstly, then reported to Linux by firmware. This way, | ||
8 | * some non-standard hardware error registers or non-standard hardware | ||
9 | * link can be checked by firmware to produce more hardware error | ||
10 | * information for Linux. | ||
11 | * | ||
12 | * For more information about Generic Hardware Error Source, please | ||
13 | * refer to ACPI Specification version 4.0, section 17.3.2.6 | ||
14 | * | ||
15 | * Now, only SCI notification type and memory errors are | ||
16 | * supported. More notification type and hardware error type will be | ||
17 | * added later. | ||
18 | * | ||
19 | * Copyright 2010 Intel Corp. | ||
20 | * Author: Huang Ying <ying.huang@intel.com> | ||
21 | * | ||
22 | * This program is free software; you can redistribute it and/or | ||
23 | * modify it under the terms of the GNU General Public License version | ||
24 | * 2 as published by the Free Software Foundation; | ||
25 | * | ||
26 | * This program is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with this program; if not, write to the Free Software | ||
33 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/module.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/acpi.h> | ||
40 | #include <linux/io.h> | ||
41 | #include <linux/interrupt.h> | ||
42 | #include <linux/cper.h> | ||
43 | #include <linux/kdebug.h> | ||
44 | #include <acpi/apei.h> | ||
45 | #include <acpi/atomicio.h> | ||
46 | #include <acpi/hed.h> | ||
47 | #include <asm/mce.h> | ||
48 | |||
49 | #include "apei-internal.h" | ||
50 | |||
51 | #define GHES_PFX "GHES: " | ||
52 | |||
53 | #define GHES_ESTATUS_MAX_SIZE 65536 | ||
54 | |||
55 | /* | ||
56 | * One struct ghes is created for each generic hardware error | ||
57 | * source. | ||
58 | * | ||
59 | * It provides the context for APEI hardware error timer/IRQ/SCI/NMI | ||
60 | * handler. Handler for one generic hardware error source is only | ||
61 | * triggered after the previous one is done. So handler can uses | ||
62 | * struct ghes without locking. | ||
63 | * | ||
64 | * estatus: memory buffer for error status block, allocated during | ||
65 | * HEST parsing. | ||
66 | */ | ||
67 | #define GHES_TO_CLEAR 0x0001 | ||
68 | |||
69 | struct ghes { | ||
70 | struct acpi_hest_generic *generic; | ||
71 | struct acpi_hest_generic_status *estatus; | ||
72 | struct list_head list; | ||
73 | u64 buffer_paddr; | ||
74 | unsigned long flags; | ||
75 | }; | ||
76 | |||
77 | /* | ||
78 | * Error source lists, one list for each notification method. The | ||
79 | * members in lists are struct ghes. | ||
80 | * | ||
81 | * The list members are only added in HEST parsing and deleted during | ||
82 | * module_exit, that is, single-threaded. So no lock is needed for | ||
83 | * that. | ||
84 | * | ||
85 | * But the mutual exclusion is needed between members adding/deleting | ||
86 | * and timer/IRQ/SCI/NMI handler, which may traverse the list. RCU is | ||
87 | * used for that. | ||
88 | */ | ||
89 | static LIST_HEAD(ghes_sci); | ||
90 | |||
91 | static struct ghes *ghes_new(struct acpi_hest_generic *generic) | ||
92 | { | ||
93 | struct ghes *ghes; | ||
94 | unsigned int error_block_length; | ||
95 | int rc; | ||
96 | |||
97 | ghes = kzalloc(sizeof(*ghes), GFP_KERNEL); | ||
98 | if (!ghes) | ||
99 | return ERR_PTR(-ENOMEM); | ||
100 | ghes->generic = generic; | ||
101 | INIT_LIST_HEAD(&ghes->list); | ||
102 | rc = acpi_pre_map_gar(&generic->error_status_address); | ||
103 | if (rc) | ||
104 | goto err_free; | ||
105 | error_block_length = generic->error_block_length; | ||
106 | if (error_block_length > GHES_ESTATUS_MAX_SIZE) { | ||
107 | pr_warning(FW_WARN GHES_PFX | ||
108 | "Error status block length is too long: %u for " | ||
109 | "generic hardware error source: %d.\n", | ||
110 | error_block_length, generic->header.source_id); | ||
111 | error_block_length = GHES_ESTATUS_MAX_SIZE; | ||
112 | } | ||
113 | ghes->estatus = kmalloc(error_block_length, GFP_KERNEL); | ||
114 | if (!ghes->estatus) { | ||
115 | rc = -ENOMEM; | ||
116 | goto err_unmap; | ||
117 | } | ||
118 | |||
119 | return ghes; | ||
120 | |||
121 | err_unmap: | ||
122 | acpi_post_unmap_gar(&generic->error_status_address); | ||
123 | err_free: | ||
124 | kfree(ghes); | ||
125 | return ERR_PTR(rc); | ||
126 | } | ||
127 | |||
128 | static void ghes_fini(struct ghes *ghes) | ||
129 | { | ||
130 | kfree(ghes->estatus); | ||
131 | acpi_post_unmap_gar(&ghes->generic->error_status_address); | ||
132 | } | ||
133 | |||
134 | enum { | ||
135 | GHES_SER_NO = 0x0, | ||
136 | GHES_SER_CORRECTED = 0x1, | ||
137 | GHES_SER_RECOVERABLE = 0x2, | ||
138 | GHES_SER_PANIC = 0x3, | ||
139 | }; | ||
140 | |||
141 | static inline int ghes_severity(int severity) | ||
142 | { | ||
143 | switch (severity) { | ||
144 | case CPER_SER_INFORMATIONAL: | ||
145 | return GHES_SER_NO; | ||
146 | case CPER_SER_CORRECTED: | ||
147 | return GHES_SER_CORRECTED; | ||
148 | case CPER_SER_RECOVERABLE: | ||
149 | return GHES_SER_RECOVERABLE; | ||
150 | case CPER_SER_FATAL: | ||
151 | return GHES_SER_PANIC; | ||
152 | default: | ||
153 | /* Unkown, go panic */ | ||
154 | return GHES_SER_PANIC; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | /* SCI handler run in work queue, so ioremap can be used here */ | ||
159 | static int ghes_copy_tofrom_phys(void *buffer, u64 paddr, u32 len, | ||
160 | int from_phys) | ||
161 | { | ||
162 | void *vaddr; | ||
163 | |||
164 | vaddr = ioremap_cache(paddr, len); | ||
165 | if (!vaddr) | ||
166 | return -ENOMEM; | ||
167 | if (from_phys) | ||
168 | memcpy(buffer, vaddr, len); | ||
169 | else | ||
170 | memcpy(vaddr, buffer, len); | ||
171 | iounmap(vaddr); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static int ghes_read_estatus(struct ghes *ghes, int silent) | ||
177 | { | ||
178 | struct acpi_hest_generic *g = ghes->generic; | ||
179 | u64 buf_paddr; | ||
180 | u32 len; | ||
181 | int rc; | ||
182 | |||
183 | rc = acpi_atomic_read(&buf_paddr, &g->error_status_address); | ||
184 | if (rc) { | ||
185 | if (!silent && printk_ratelimit()) | ||
186 | pr_warning(FW_WARN GHES_PFX | ||
187 | "Failed to read error status block address for hardware error source: %d.\n", | ||
188 | g->header.source_id); | ||
189 | return -EIO; | ||
190 | } | ||
191 | if (!buf_paddr) | ||
192 | return -ENOENT; | ||
193 | |||
194 | rc = ghes_copy_tofrom_phys(ghes->estatus, buf_paddr, | ||
195 | sizeof(*ghes->estatus), 1); | ||
196 | if (rc) | ||
197 | return rc; | ||
198 | if (!ghes->estatus->block_status) | ||
199 | return -ENOENT; | ||
200 | |||
201 | ghes->buffer_paddr = buf_paddr; | ||
202 | ghes->flags |= GHES_TO_CLEAR; | ||
203 | |||
204 | rc = -EIO; | ||
205 | len = apei_estatus_len(ghes->estatus); | ||
206 | if (len < sizeof(*ghes->estatus)) | ||
207 | goto err_read_block; | ||
208 | if (len > ghes->generic->error_block_length) | ||
209 | goto err_read_block; | ||
210 | if (apei_estatus_check_header(ghes->estatus)) | ||
211 | goto err_read_block; | ||
212 | rc = ghes_copy_tofrom_phys(ghes->estatus + 1, | ||
213 | buf_paddr + sizeof(*ghes->estatus), | ||
214 | len - sizeof(*ghes->estatus), 1); | ||
215 | if (rc) | ||
216 | return rc; | ||
217 | if (apei_estatus_check(ghes->estatus)) | ||
218 | goto err_read_block; | ||
219 | rc = 0; | ||
220 | |||
221 | err_read_block: | ||
222 | if (rc && !silent) | ||
223 | pr_warning(FW_WARN GHES_PFX | ||
224 | "Failed to read error status block!\n"); | ||
225 | return rc; | ||
226 | } | ||
227 | |||
228 | static void ghes_clear_estatus(struct ghes *ghes) | ||
229 | { | ||
230 | ghes->estatus->block_status = 0; | ||
231 | if (!(ghes->flags & GHES_TO_CLEAR)) | ||
232 | return; | ||
233 | ghes_copy_tofrom_phys(ghes->estatus, ghes->buffer_paddr, | ||
234 | sizeof(ghes->estatus->block_status), 0); | ||
235 | ghes->flags &= ~GHES_TO_CLEAR; | ||
236 | } | ||
237 | |||
238 | static void ghes_do_proc(struct ghes *ghes) | ||
239 | { | ||
240 | int ser, processed = 0; | ||
241 | struct acpi_hest_generic_data *gdata; | ||
242 | |||
243 | ser = ghes_severity(ghes->estatus->error_severity); | ||
244 | apei_estatus_for_each_section(ghes->estatus, gdata) { | ||
245 | #ifdef CONFIG_X86_MCE | ||
246 | if (!uuid_le_cmp(*(uuid_le *)gdata->section_type, | ||
247 | CPER_SEC_PLATFORM_MEM)) { | ||
248 | apei_mce_report_mem_error( | ||
249 | ser == GHES_SER_CORRECTED, | ||
250 | (struct cper_sec_mem_err *)(gdata+1)); | ||
251 | processed = 1; | ||
252 | } | ||
253 | #endif | ||
254 | } | ||
255 | |||
256 | if (!processed && printk_ratelimit()) | ||
257 | pr_warning(GHES_PFX | ||
258 | "Unknown error record from generic hardware error source: %d\n", | ||
259 | ghes->generic->header.source_id); | ||
260 | } | ||
261 | |||
262 | static int ghes_proc(struct ghes *ghes) | ||
263 | { | ||
264 | int rc; | ||
265 | |||
266 | rc = ghes_read_estatus(ghes, 0); | ||
267 | if (rc) | ||
268 | goto out; | ||
269 | ghes_do_proc(ghes); | ||
270 | |||
271 | out: | ||
272 | ghes_clear_estatus(ghes); | ||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int ghes_notify_sci(struct notifier_block *this, | ||
277 | unsigned long event, void *data) | ||
278 | { | ||
279 | struct ghes *ghes; | ||
280 | int ret = NOTIFY_DONE; | ||
281 | |||
282 | rcu_read_lock(); | ||
283 | list_for_each_entry_rcu(ghes, &ghes_sci, list) { | ||
284 | if (!ghes_proc(ghes)) | ||
285 | ret = NOTIFY_OK; | ||
286 | } | ||
287 | rcu_read_unlock(); | ||
288 | |||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | static struct notifier_block ghes_notifier_sci = { | ||
293 | .notifier_call = ghes_notify_sci, | ||
294 | }; | ||
295 | |||
296 | static int hest_ghes_parse(struct acpi_hest_header *hest_hdr, void *data) | ||
297 | { | ||
298 | struct acpi_hest_generic *generic; | ||
299 | struct ghes *ghes = NULL; | ||
300 | int rc = 0; | ||
301 | |||
302 | if (hest_hdr->type != ACPI_HEST_TYPE_GENERIC_ERROR) | ||
303 | return 0; | ||
304 | |||
305 | generic = (struct acpi_hest_generic *)hest_hdr; | ||
306 | if (!generic->enabled) | ||
307 | return 0; | ||
308 | |||
309 | if (generic->error_block_length < | ||
310 | sizeof(struct acpi_hest_generic_status)) { | ||
311 | pr_warning(FW_BUG GHES_PFX | ||
312 | "Invalid error block length: %u for generic hardware error source: %d\n", | ||
313 | generic->error_block_length, | ||
314 | generic->header.source_id); | ||
315 | goto err; | ||
316 | } | ||
317 | if (generic->records_to_preallocate == 0) { | ||
318 | pr_warning(FW_BUG GHES_PFX | ||
319 | "Invalid records to preallocate: %u for generic hardware error source: %d\n", | ||
320 | generic->records_to_preallocate, | ||
321 | generic->header.source_id); | ||
322 | goto err; | ||
323 | } | ||
324 | ghes = ghes_new(generic); | ||
325 | if (IS_ERR(ghes)) { | ||
326 | rc = PTR_ERR(ghes); | ||
327 | ghes = NULL; | ||
328 | goto err; | ||
329 | } | ||
330 | switch (generic->notify.type) { | ||
331 | case ACPI_HEST_NOTIFY_POLLED: | ||
332 | pr_warning(GHES_PFX | ||
333 | "Generic hardware error source: %d notified via POLL is not supported!\n", | ||
334 | generic->header.source_id); | ||
335 | break; | ||
336 | case ACPI_HEST_NOTIFY_EXTERNAL: | ||
337 | case ACPI_HEST_NOTIFY_LOCAL: | ||
338 | pr_warning(GHES_PFX | ||
339 | "Generic hardware error source: %d notified via IRQ is not supported!\n", | ||
340 | generic->header.source_id); | ||
341 | break; | ||
342 | case ACPI_HEST_NOTIFY_SCI: | ||
343 | if (list_empty(&ghes_sci)) | ||
344 | register_acpi_hed_notifier(&ghes_notifier_sci); | ||
345 | list_add_rcu(&ghes->list, &ghes_sci); | ||
346 | break; | ||
347 | case ACPI_HEST_NOTIFY_NMI: | ||
348 | pr_warning(GHES_PFX | ||
349 | "Generic hardware error source: %d notified via NMI is not supported!\n", | ||
350 | generic->header.source_id); | ||
351 | break; | ||
352 | default: | ||
353 | pr_warning(FW_WARN GHES_PFX | ||
354 | "Unknown notification type: %u for generic hardware error source: %d\n", | ||
355 | generic->notify.type, generic->header.source_id); | ||
356 | break; | ||
357 | } | ||
358 | |||
359 | return 0; | ||
360 | err: | ||
361 | if (ghes) | ||
362 | ghes_fini(ghes); | ||
363 | return rc; | ||
364 | } | ||
365 | |||
366 | static void ghes_cleanup(void) | ||
367 | { | ||
368 | struct ghes *ghes, *nghes; | ||
369 | |||
370 | if (!list_empty(&ghes_sci)) | ||
371 | unregister_acpi_hed_notifier(&ghes_notifier_sci); | ||
372 | |||
373 | synchronize_rcu(); | ||
374 | |||
375 | list_for_each_entry_safe(ghes, nghes, &ghes_sci, list) { | ||
376 | list_del(&ghes->list); | ||
377 | ghes_fini(ghes); | ||
378 | kfree(ghes); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | static int __init ghes_init(void) | ||
383 | { | ||
384 | int rc; | ||
385 | |||
386 | if (acpi_disabled) | ||
387 | return -ENODEV; | ||
388 | |||
389 | if (hest_disable) { | ||
390 | pr_info(GHES_PFX "HEST is not enabled!\n"); | ||
391 | return -EINVAL; | ||
392 | } | ||
393 | |||
394 | rc = apei_hest_parse(hest_ghes_parse, NULL); | ||
395 | if (rc) { | ||
396 | pr_err(GHES_PFX | ||
397 | "Error during parsing HEST generic hardware error sources.\n"); | ||
398 | goto err_cleanup; | ||
399 | } | ||
400 | |||
401 | if (list_empty(&ghes_sci)) { | ||
402 | pr_info(GHES_PFX | ||
403 | "No functional generic hardware error sources.\n"); | ||
404 | rc = -ENODEV; | ||
405 | goto err_cleanup; | ||
406 | } | ||
407 | |||
408 | pr_info(GHES_PFX | ||
409 | "Generic Hardware Error Source support is initialized.\n"); | ||
410 | |||
411 | return 0; | ||
412 | err_cleanup: | ||
413 | ghes_cleanup(); | ||
414 | return rc; | ||
415 | } | ||
416 | |||
417 | static void __exit ghes_exit(void) | ||
418 | { | ||
419 | ghes_cleanup(); | ||
420 | } | ||
421 | |||
422 | module_init(ghes_init); | ||
423 | module_exit(ghes_exit); | ||
424 | |||
425 | MODULE_AUTHOR("Huang Ying"); | ||
426 | MODULE_DESCRIPTION("APEI Generic Hardware Error Source support"); | ||
427 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/apei/hest.c b/drivers/acpi/apei/hest.c new file mode 100644 index 000000000000..e7f40d362cb3 --- /dev/null +++ b/drivers/acpi/apei/hest.c | |||
@@ -0,0 +1,173 @@ | |||
1 | /* | ||
2 | * APEI Hardware Error Souce Table support | ||
3 | * | ||
4 | * HEST describes error sources in detail; communicates operational | ||
5 | * parameters (i.e. severity levels, masking bits, and threshold | ||
6 | * values) to Linux as necessary. It also allows the BIOS to report | ||
7 | * non-standard error sources to Linux (for example, chipset-specific | ||
8 | * error registers). | ||
9 | * | ||
10 | * For more information about HEST, please refer to ACPI Specification | ||
11 | * version 4.0, section 17.3.2. | ||
12 | * | ||
13 | * Copyright 2009 Intel Corp. | ||
14 | * Author: Huang Ying <ying.huang@intel.com> | ||
15 | * | ||
16 | * This program is free software; you can redistribute it and/or | ||
17 | * modify it under the terms of the GNU General Public License version | ||
18 | * 2 as published by the Free Software Foundation; | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/acpi.h> | ||
34 | #include <linux/kdebug.h> | ||
35 | #include <linux/highmem.h> | ||
36 | #include <linux/io.h> | ||
37 | #include <acpi/apei.h> | ||
38 | |||
39 | #include "apei-internal.h" | ||
40 | |||
41 | #define HEST_PFX "HEST: " | ||
42 | |||
43 | int hest_disable; | ||
44 | EXPORT_SYMBOL_GPL(hest_disable); | ||
45 | |||
46 | /* HEST table parsing */ | ||
47 | |||
48 | static struct acpi_table_hest *hest_tab; | ||
49 | |||
50 | static int hest_void_parse(struct acpi_hest_header *hest_hdr, void *data) | ||
51 | { | ||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int hest_esrc_len_tab[ACPI_HEST_TYPE_RESERVED] = { | ||
56 | [ACPI_HEST_TYPE_IA32_CHECK] = -1, /* need further calculation */ | ||
57 | [ACPI_HEST_TYPE_IA32_CORRECTED_CHECK] = -1, | ||
58 | [ACPI_HEST_TYPE_IA32_NMI] = sizeof(struct acpi_hest_ia_nmi), | ||
59 | [ACPI_HEST_TYPE_AER_ROOT_PORT] = sizeof(struct acpi_hest_aer_root), | ||
60 | [ACPI_HEST_TYPE_AER_ENDPOINT] = sizeof(struct acpi_hest_aer), | ||
61 | [ACPI_HEST_TYPE_AER_BRIDGE] = sizeof(struct acpi_hest_aer_bridge), | ||
62 | [ACPI_HEST_TYPE_GENERIC_ERROR] = sizeof(struct acpi_hest_generic), | ||
63 | }; | ||
64 | |||
65 | static int hest_esrc_len(struct acpi_hest_header *hest_hdr) | ||
66 | { | ||
67 | u16 hest_type = hest_hdr->type; | ||
68 | int len; | ||
69 | |||
70 | if (hest_type >= ACPI_HEST_TYPE_RESERVED) | ||
71 | return 0; | ||
72 | |||
73 | len = hest_esrc_len_tab[hest_type]; | ||
74 | |||
75 | if (hest_type == ACPI_HEST_TYPE_IA32_CORRECTED_CHECK) { | ||
76 | struct acpi_hest_ia_corrected *cmc; | ||
77 | cmc = (struct acpi_hest_ia_corrected *)hest_hdr; | ||
78 | len = sizeof(*cmc) + cmc->num_hardware_banks * | ||
79 | sizeof(struct acpi_hest_ia_error_bank); | ||
80 | } else if (hest_type == ACPI_HEST_TYPE_IA32_CHECK) { | ||
81 | struct acpi_hest_ia_machine_check *mc; | ||
82 | mc = (struct acpi_hest_ia_machine_check *)hest_hdr; | ||
83 | len = sizeof(*mc) + mc->num_hardware_banks * | ||
84 | sizeof(struct acpi_hest_ia_error_bank); | ||
85 | } | ||
86 | BUG_ON(len == -1); | ||
87 | |||
88 | return len; | ||
89 | }; | ||
90 | |||
91 | int apei_hest_parse(apei_hest_func_t func, void *data) | ||
92 | { | ||
93 | struct acpi_hest_header *hest_hdr; | ||
94 | int i, rc, len; | ||
95 | |||
96 | if (hest_disable) | ||
97 | return -EINVAL; | ||
98 | |||
99 | hest_hdr = (struct acpi_hest_header *)(hest_tab + 1); | ||
100 | for (i = 0; i < hest_tab->error_source_count; i++) { | ||
101 | len = hest_esrc_len(hest_hdr); | ||
102 | if (!len) { | ||
103 | pr_warning(FW_WARN HEST_PFX | ||
104 | "Unknown or unused hardware error source " | ||
105 | "type: %d for hardware error source: %d.\n", | ||
106 | hest_hdr->type, hest_hdr->source_id); | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | if ((void *)hest_hdr + len > | ||
110 | (void *)hest_tab + hest_tab->header.length) { | ||
111 | pr_warning(FW_BUG HEST_PFX | ||
112 | "Table contents overflow for hardware error source: %d.\n", | ||
113 | hest_hdr->source_id); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | |||
117 | rc = func(hest_hdr, data); | ||
118 | if (rc) | ||
119 | return rc; | ||
120 | |||
121 | hest_hdr = (void *)hest_hdr + len; | ||
122 | } | ||
123 | |||
124 | return 0; | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(apei_hest_parse); | ||
127 | |||
128 | static int __init setup_hest_disable(char *str) | ||
129 | { | ||
130 | hest_disable = 1; | ||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | __setup("hest_disable", setup_hest_disable); | ||
135 | |||
136 | static int __init hest_init(void) | ||
137 | { | ||
138 | acpi_status status; | ||
139 | int rc = -ENODEV; | ||
140 | |||
141 | if (acpi_disabled) | ||
142 | goto err; | ||
143 | |||
144 | if (hest_disable) { | ||
145 | pr_info(HEST_PFX "HEST tabling parsing is disabled.\n"); | ||
146 | goto err; | ||
147 | } | ||
148 | |||
149 | status = acpi_get_table(ACPI_SIG_HEST, 0, | ||
150 | (struct acpi_table_header **)&hest_tab); | ||
151 | if (status == AE_NOT_FOUND) { | ||
152 | pr_info(HEST_PFX "Table is not found!\n"); | ||
153 | goto err; | ||
154 | } else if (ACPI_FAILURE(status)) { | ||
155 | const char *msg = acpi_format_exception(status); | ||
156 | pr_err(HEST_PFX "Failed to get table, %s\n", msg); | ||
157 | rc = -EINVAL; | ||
158 | goto err; | ||
159 | } | ||
160 | |||
161 | rc = apei_hest_parse(hest_void_parse, NULL); | ||
162 | if (rc) | ||
163 | goto err; | ||
164 | |||
165 | pr_info(HEST_PFX "HEST table parsing is initialized.\n"); | ||
166 | |||
167 | return 0; | ||
168 | err: | ||
169 | hest_disable = 1; | ||
170 | return rc; | ||
171 | } | ||
172 | |||
173 | subsys_initcall(hest_init); | ||
diff --git a/drivers/acpi/atomicio.c b/drivers/acpi/atomicio.c new file mode 100644 index 000000000000..814b19249616 --- /dev/null +++ b/drivers/acpi/atomicio.c | |||
@@ -0,0 +1,360 @@ | |||
1 | /* | ||
2 | * atomicio.c - ACPI IO memory pre-mapping/post-unmapping, then | ||
3 | * accessing in atomic context. | ||
4 | * | ||
5 | * This is used for NMI handler to access IO memory area, because | ||
6 | * ioremap/iounmap can not be used in NMI handler. The IO memory area | ||
7 | * is pre-mapped in process context and accessed in NMI handler. | ||
8 | * | ||
9 | * Copyright (C) 2009-2010, Intel Corp. | ||
10 | * Author: Huang Ying <ying.huang@intel.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License version | ||
14 | * 2 as published by the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/module.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/acpi.h> | ||
30 | #include <linux/io.h> | ||
31 | #include <linux/kref.h> | ||
32 | #include <linux/rculist.h> | ||
33 | #include <linux/interrupt.h> | ||
34 | #include <acpi/atomicio.h> | ||
35 | |||
36 | #define ACPI_PFX "ACPI: " | ||
37 | |||
38 | static LIST_HEAD(acpi_iomaps); | ||
39 | /* | ||
40 | * Used for mutual exclusion between writers of acpi_iomaps list, for | ||
41 | * synchronization between readers and writer, RCU is used. | ||
42 | */ | ||
43 | static DEFINE_SPINLOCK(acpi_iomaps_lock); | ||
44 | |||
45 | struct acpi_iomap { | ||
46 | struct list_head list; | ||
47 | void __iomem *vaddr; | ||
48 | unsigned long size; | ||
49 | phys_addr_t paddr; | ||
50 | struct kref ref; | ||
51 | }; | ||
52 | |||
53 | /* acpi_iomaps_lock or RCU read lock must be held before calling */ | ||
54 | static struct acpi_iomap *__acpi_find_iomap(phys_addr_t paddr, | ||
55 | unsigned long size) | ||
56 | { | ||
57 | struct acpi_iomap *map; | ||
58 | |||
59 | list_for_each_entry_rcu(map, &acpi_iomaps, list) { | ||
60 | if (map->paddr + map->size >= paddr + size && | ||
61 | map->paddr <= paddr) | ||
62 | return map; | ||
63 | } | ||
64 | return NULL; | ||
65 | } | ||
66 | |||
67 | /* | ||
68 | * Atomic "ioremap" used by NMI handler, if the specified IO memory | ||
69 | * area is not pre-mapped, NULL will be returned. | ||
70 | * | ||
71 | * acpi_iomaps_lock or RCU read lock must be held before calling | ||
72 | */ | ||
73 | static void __iomem *__acpi_ioremap_fast(phys_addr_t paddr, | ||
74 | unsigned long size) | ||
75 | { | ||
76 | struct acpi_iomap *map; | ||
77 | |||
78 | map = __acpi_find_iomap(paddr, size); | ||
79 | if (map) | ||
80 | return map->vaddr + (paddr - map->paddr); | ||
81 | else | ||
82 | return NULL; | ||
83 | } | ||
84 | |||
85 | /* acpi_iomaps_lock must be held before calling */ | ||
86 | static void __iomem *__acpi_try_ioremap(phys_addr_t paddr, | ||
87 | unsigned long size) | ||
88 | { | ||
89 | struct acpi_iomap *map; | ||
90 | |||
91 | map = __acpi_find_iomap(paddr, size); | ||
92 | if (map) { | ||
93 | kref_get(&map->ref); | ||
94 | return map->vaddr + (paddr - map->paddr); | ||
95 | } else | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | /* | ||
100 | * Used to pre-map the specified IO memory area. First try to find | ||
101 | * whether the area is already pre-mapped, if it is, increase the | ||
102 | * reference count (in __acpi_try_ioremap) and return; otherwise, do | ||
103 | * the real ioremap, and add the mapping into acpi_iomaps list. | ||
104 | */ | ||
105 | static void __iomem *acpi_pre_map(phys_addr_t paddr, | ||
106 | unsigned long size) | ||
107 | { | ||
108 | void __iomem *vaddr; | ||
109 | struct acpi_iomap *map; | ||
110 | unsigned long pg_sz, flags; | ||
111 | phys_addr_t pg_off; | ||
112 | |||
113 | spin_lock_irqsave(&acpi_iomaps_lock, flags); | ||
114 | vaddr = __acpi_try_ioremap(paddr, size); | ||
115 | spin_unlock_irqrestore(&acpi_iomaps_lock, flags); | ||
116 | if (vaddr) | ||
117 | return vaddr; | ||
118 | |||
119 | pg_off = paddr & PAGE_MASK; | ||
120 | pg_sz = ((paddr + size + PAGE_SIZE - 1) & PAGE_MASK) - pg_off; | ||
121 | vaddr = ioremap(pg_off, pg_sz); | ||
122 | if (!vaddr) | ||
123 | return NULL; | ||
124 | map = kmalloc(sizeof(*map), GFP_KERNEL); | ||
125 | if (!map) | ||
126 | goto err_unmap; | ||
127 | INIT_LIST_HEAD(&map->list); | ||
128 | map->paddr = pg_off; | ||
129 | map->size = pg_sz; | ||
130 | map->vaddr = vaddr; | ||
131 | kref_init(&map->ref); | ||
132 | |||
133 | spin_lock_irqsave(&acpi_iomaps_lock, flags); | ||
134 | vaddr = __acpi_try_ioremap(paddr, size); | ||
135 | if (vaddr) { | ||
136 | spin_unlock_irqrestore(&acpi_iomaps_lock, flags); | ||
137 | iounmap(map->vaddr); | ||
138 | kfree(map); | ||
139 | return vaddr; | ||
140 | } | ||
141 | list_add_tail_rcu(&map->list, &acpi_iomaps); | ||
142 | spin_unlock_irqrestore(&acpi_iomaps_lock, flags); | ||
143 | |||
144 | return vaddr + (paddr - pg_off); | ||
145 | err_unmap: | ||
146 | iounmap(vaddr); | ||
147 | return NULL; | ||
148 | } | ||
149 | |||
150 | /* acpi_iomaps_lock must be held before calling */ | ||
151 | static void __acpi_kref_del_iomap(struct kref *ref) | ||
152 | { | ||
153 | struct acpi_iomap *map; | ||
154 | |||
155 | map = container_of(ref, struct acpi_iomap, ref); | ||
156 | list_del_rcu(&map->list); | ||
157 | } | ||
158 | |||
159 | /* | ||
160 | * Used to post-unmap the specified IO memory area. The iounmap is | ||
161 | * done only if the reference count goes zero. | ||
162 | */ | ||
163 | static void acpi_post_unmap(phys_addr_t paddr, unsigned long size) | ||
164 | { | ||
165 | struct acpi_iomap *map; | ||
166 | unsigned long flags; | ||
167 | int del; | ||
168 | |||
169 | spin_lock_irqsave(&acpi_iomaps_lock, flags); | ||
170 | map = __acpi_find_iomap(paddr, size); | ||
171 | BUG_ON(!map); | ||
172 | del = kref_put(&map->ref, __acpi_kref_del_iomap); | ||
173 | spin_unlock_irqrestore(&acpi_iomaps_lock, flags); | ||
174 | |||
175 | if (!del) | ||
176 | return; | ||
177 | |||
178 | synchronize_rcu(); | ||
179 | iounmap(map->vaddr); | ||
180 | kfree(map); | ||
181 | } | ||
182 | |||
183 | /* In NMI handler, should set silent = 1 */ | ||
184 | static int acpi_check_gar(struct acpi_generic_address *reg, | ||
185 | u64 *paddr, int silent) | ||
186 | { | ||
187 | u32 width, space_id; | ||
188 | |||
189 | width = reg->bit_width; | ||
190 | space_id = reg->space_id; | ||
191 | /* Handle possible alignment issues */ | ||
192 | memcpy(paddr, ®->address, sizeof(*paddr)); | ||
193 | if (!*paddr) { | ||
194 | if (!silent) | ||
195 | pr_warning(FW_BUG ACPI_PFX | ||
196 | "Invalid physical address in GAR [0x%llx/%u/%u]\n", | ||
197 | *paddr, width, space_id); | ||
198 | return -EINVAL; | ||
199 | } | ||
200 | |||
201 | if ((width != 8) && (width != 16) && (width != 32) && (width != 64)) { | ||
202 | if (!silent) | ||
203 | pr_warning(FW_BUG ACPI_PFX | ||
204 | "Invalid bit width in GAR [0x%llx/%u/%u]\n", | ||
205 | *paddr, width, space_id); | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | if (space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY && | ||
210 | space_id != ACPI_ADR_SPACE_SYSTEM_IO) { | ||
211 | if (!silent) | ||
212 | pr_warning(FW_BUG ACPI_PFX | ||
213 | "Invalid address space type in GAR [0x%llx/%u/%u]\n", | ||
214 | *paddr, width, space_id); | ||
215 | return -EINVAL; | ||
216 | } | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | /* Pre-map, working on GAR */ | ||
222 | int acpi_pre_map_gar(struct acpi_generic_address *reg) | ||
223 | { | ||
224 | u64 paddr; | ||
225 | void __iomem *vaddr; | ||
226 | int rc; | ||
227 | |||
228 | if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
229 | return 0; | ||
230 | |||
231 | rc = acpi_check_gar(reg, &paddr, 0); | ||
232 | if (rc) | ||
233 | return rc; | ||
234 | |||
235 | vaddr = acpi_pre_map(paddr, reg->bit_width / 8); | ||
236 | if (!vaddr) | ||
237 | return -EIO; | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | EXPORT_SYMBOL_GPL(acpi_pre_map_gar); | ||
242 | |||
243 | /* Post-unmap, working on GAR */ | ||
244 | int acpi_post_unmap_gar(struct acpi_generic_address *reg) | ||
245 | { | ||
246 | u64 paddr; | ||
247 | int rc; | ||
248 | |||
249 | if (reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) | ||
250 | return 0; | ||
251 | |||
252 | rc = acpi_check_gar(reg, &paddr, 0); | ||
253 | if (rc) | ||
254 | return rc; | ||
255 | |||
256 | acpi_post_unmap(paddr, reg->bit_width / 8); | ||
257 | |||
258 | return 0; | ||
259 | } | ||
260 | EXPORT_SYMBOL_GPL(acpi_post_unmap_gar); | ||
261 | |||
262 | /* | ||
263 | * Can be used in atomic (including NMI) or process context. RCU read | ||
264 | * lock can only be released after the IO memory area accessing. | ||
265 | */ | ||
266 | static int acpi_atomic_read_mem(u64 paddr, u64 *val, u32 width) | ||
267 | { | ||
268 | void __iomem *addr; | ||
269 | |||
270 | rcu_read_lock(); | ||
271 | addr = __acpi_ioremap_fast(paddr, width); | ||
272 | switch (width) { | ||
273 | case 8: | ||
274 | *val = readb(addr); | ||
275 | break; | ||
276 | case 16: | ||
277 | *val = readw(addr); | ||
278 | break; | ||
279 | case 32: | ||
280 | *val = readl(addr); | ||
281 | break; | ||
282 | case 64: | ||
283 | *val = readq(addr); | ||
284 | break; | ||
285 | default: | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | rcu_read_unlock(); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int acpi_atomic_write_mem(u64 paddr, u64 val, u32 width) | ||
294 | { | ||
295 | void __iomem *addr; | ||
296 | |||
297 | rcu_read_lock(); | ||
298 | addr = __acpi_ioremap_fast(paddr, width); | ||
299 | switch (width) { | ||
300 | case 8: | ||
301 | writeb(val, addr); | ||
302 | break; | ||
303 | case 16: | ||
304 | writew(val, addr); | ||
305 | break; | ||
306 | case 32: | ||
307 | writel(val, addr); | ||
308 | break; | ||
309 | case 64: | ||
310 | writeq(val, addr); | ||
311 | break; | ||
312 | default: | ||
313 | return -EINVAL; | ||
314 | } | ||
315 | rcu_read_unlock(); | ||
316 | |||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | /* GAR accessing in atomic (including NMI) or process context */ | ||
321 | int acpi_atomic_read(u64 *val, struct acpi_generic_address *reg) | ||
322 | { | ||
323 | u64 paddr; | ||
324 | int rc; | ||
325 | |||
326 | rc = acpi_check_gar(reg, &paddr, 1); | ||
327 | if (rc) | ||
328 | return rc; | ||
329 | |||
330 | *val = 0; | ||
331 | switch (reg->space_id) { | ||
332 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | ||
333 | return acpi_atomic_read_mem(paddr, val, reg->bit_width); | ||
334 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
335 | return acpi_os_read_port(paddr, (u32 *)val, reg->bit_width); | ||
336 | default: | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | } | ||
340 | EXPORT_SYMBOL_GPL(acpi_atomic_read); | ||
341 | |||
342 | int acpi_atomic_write(u64 val, struct acpi_generic_address *reg) | ||
343 | { | ||
344 | u64 paddr; | ||
345 | int rc; | ||
346 | |||
347 | rc = acpi_check_gar(reg, &paddr, 1); | ||
348 | if (rc) | ||
349 | return rc; | ||
350 | |||
351 | switch (reg->space_id) { | ||
352 | case ACPI_ADR_SPACE_SYSTEM_MEMORY: | ||
353 | return acpi_atomic_write_mem(paddr, val, reg->bit_width); | ||
354 | case ACPI_ADR_SPACE_SYSTEM_IO: | ||
355 | return acpi_os_write_port(paddr, val, reg->bit_width); | ||
356 | default: | ||
357 | return -EINVAL; | ||
358 | } | ||
359 | } | ||
360 | EXPORT_SYMBOL_GPL(acpi_atomic_write); | ||
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index f2234db85da0..e61d4f8e62a5 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
@@ -1027,10 +1027,9 @@ int __init acpi_ec_ecdt_probe(void) | |||
1027 | /* Don't trust ECDT, which comes from ASUSTek */ | 1027 | /* Don't trust ECDT, which comes from ASUSTek */ |
1028 | if (!EC_FLAGS_VALIDATE_ECDT) | 1028 | if (!EC_FLAGS_VALIDATE_ECDT) |
1029 | goto install; | 1029 | goto install; |
1030 | saved_ec = kmalloc(sizeof(struct acpi_ec), GFP_KERNEL); | 1030 | saved_ec = kmemdup(boot_ec, sizeof(struct acpi_ec), GFP_KERNEL); |
1031 | if (!saved_ec) | 1031 | if (!saved_ec) |
1032 | return -ENOMEM; | 1032 | return -ENOMEM; |
1033 | memcpy(saved_ec, boot_ec, sizeof(struct acpi_ec)); | ||
1034 | /* fall through */ | 1033 | /* fall through */ |
1035 | } | 1034 | } |
1036 | 1035 | ||
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c new file mode 100644 index 000000000000..d0c1967f7597 --- /dev/null +++ b/drivers/acpi/hed.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * ACPI Hardware Error Device (PNP0C33) Driver | ||
3 | * | ||
4 | * Copyright (C) 2010, Intel Corp. | ||
5 | * Author: Huang Ying <ying.huang@intel.com> | ||
6 | * | ||
7 | * ACPI Hardware Error Device is used to report some hardware errors | ||
8 | * notified via SCI, mainly the corrected errors. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License version | ||
12 | * 2 as published by the Free Software Foundation; | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
22 | */ | ||
23 | |||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/acpi.h> | ||
28 | #include <acpi/acpi_bus.h> | ||
29 | #include <acpi/acpi_drivers.h> | ||
30 | #include <acpi/hed.h> | ||
31 | |||
32 | static struct acpi_device_id acpi_hed_ids[] = { | ||
33 | {"PNP0C33", 0}, | ||
34 | {"", 0}, | ||
35 | }; | ||
36 | MODULE_DEVICE_TABLE(acpi, acpi_hed_ids); | ||
37 | |||
38 | static acpi_handle hed_handle; | ||
39 | |||
40 | static BLOCKING_NOTIFIER_HEAD(acpi_hed_notify_list); | ||
41 | |||
42 | int register_acpi_hed_notifier(struct notifier_block *nb) | ||
43 | { | ||
44 | return blocking_notifier_chain_register(&acpi_hed_notify_list, nb); | ||
45 | } | ||
46 | EXPORT_SYMBOL_GPL(register_acpi_hed_notifier); | ||
47 | |||
48 | void unregister_acpi_hed_notifier(struct notifier_block *nb) | ||
49 | { | ||
50 | blocking_notifier_chain_unregister(&acpi_hed_notify_list, nb); | ||
51 | } | ||
52 | EXPORT_SYMBOL_GPL(unregister_acpi_hed_notifier); | ||
53 | |||
54 | /* | ||
55 | * SCI to report hardware error is forwarded to the listeners of HED, | ||
56 | * it is used by HEST Generic Hardware Error Source with notify type | ||
57 | * SCI. | ||
58 | */ | ||
59 | static void acpi_hed_notify(struct acpi_device *device, u32 event) | ||
60 | { | ||
61 | blocking_notifier_call_chain(&acpi_hed_notify_list, 0, NULL); | ||
62 | } | ||
63 | |||
64 | static int __devinit acpi_hed_add(struct acpi_device *device) | ||
65 | { | ||
66 | /* Only one hardware error device */ | ||
67 | if (hed_handle) | ||
68 | return -EINVAL; | ||
69 | hed_handle = device->handle; | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int __devexit acpi_hed_remove(struct acpi_device *device, int type) | ||
74 | { | ||
75 | hed_handle = NULL; | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static struct acpi_driver acpi_hed_driver = { | ||
80 | .name = "hardware_error_device", | ||
81 | .class = "hardware_error", | ||
82 | .ids = acpi_hed_ids, | ||
83 | .ops = { | ||
84 | .add = acpi_hed_add, | ||
85 | .remove = acpi_hed_remove, | ||
86 | .notify = acpi_hed_notify, | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | static int __init acpi_hed_init(void) | ||
91 | { | ||
92 | if (acpi_disabled) | ||
93 | return -ENODEV; | ||
94 | |||
95 | if (acpi_bus_register_driver(&acpi_hed_driver) < 0) | ||
96 | return -ENODEV; | ||
97 | |||
98 | return 0; | ||
99 | } | ||
100 | |||
101 | static void __exit acpi_hed_exit(void) | ||
102 | { | ||
103 | acpi_bus_unregister_driver(&acpi_hed_driver); | ||
104 | } | ||
105 | |||
106 | module_init(acpi_hed_init); | ||
107 | module_exit(acpi_hed_exit); | ||
108 | |||
109 | ACPI_MODULE_NAME("hed"); | ||
110 | MODULE_AUTHOR("Huang Ying"); | ||
111 | MODULE_DESCRIPTION("ACPI Hardware Error Device Driver"); | ||
112 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/acpi/hest.c b/drivers/acpi/hest.c deleted file mode 100644 index 1c527a192872..000000000000 --- a/drivers/acpi/hest.c +++ /dev/null | |||
@@ -1,139 +0,0 @@ | |||
1 | #include <linux/acpi.h> | ||
2 | #include <linux/pci.h> | ||
3 | |||
4 | #define PREFIX "ACPI: " | ||
5 | |||
6 | static inline unsigned long parse_acpi_hest_ia_machine_check(struct acpi_hest_ia_machine_check *p) | ||
7 | { | ||
8 | return sizeof(*p) + | ||
9 | (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks); | ||
10 | } | ||
11 | |||
12 | static inline unsigned long parse_acpi_hest_ia_corrected(struct acpi_hest_ia_corrected *p) | ||
13 | { | ||
14 | return sizeof(*p) + | ||
15 | (sizeof(struct acpi_hest_ia_error_bank) * p->num_hardware_banks); | ||
16 | } | ||
17 | |||
18 | static inline unsigned long parse_acpi_hest_ia_nmi(struct acpi_hest_ia_nmi *p) | ||
19 | { | ||
20 | return sizeof(*p); | ||
21 | } | ||
22 | |||
23 | static inline unsigned long parse_acpi_hest_generic(struct acpi_hest_generic *p) | ||
24 | { | ||
25 | return sizeof(*p); | ||
26 | } | ||
27 | |||
28 | static inline unsigned int hest_match_pci(struct acpi_hest_aer_common *p, struct pci_dev *pci) | ||
29 | { | ||
30 | return (0 == pci_domain_nr(pci->bus) && | ||
31 | p->bus == pci->bus->number && | ||
32 | p->device == PCI_SLOT(pci->devfn) && | ||
33 | p->function == PCI_FUNC(pci->devfn)); | ||
34 | } | ||
35 | |||
36 | static unsigned long parse_acpi_hest_aer(void *hdr, int type, struct pci_dev *pci, int *firmware_first) | ||
37 | { | ||
38 | struct acpi_hest_aer_common *p = hdr + sizeof(struct acpi_hest_header); | ||
39 | unsigned long rc=0; | ||
40 | u8 pcie_type = 0; | ||
41 | u8 bridge = 0; | ||
42 | switch (type) { | ||
43 | case ACPI_HEST_TYPE_AER_ROOT_PORT: | ||
44 | rc = sizeof(struct acpi_hest_aer_root); | ||
45 | pcie_type = PCI_EXP_TYPE_ROOT_PORT; | ||
46 | break; | ||
47 | case ACPI_HEST_TYPE_AER_ENDPOINT: | ||
48 | rc = sizeof(struct acpi_hest_aer); | ||
49 | pcie_type = PCI_EXP_TYPE_ENDPOINT; | ||
50 | break; | ||
51 | case ACPI_HEST_TYPE_AER_BRIDGE: | ||
52 | rc = sizeof(struct acpi_hest_aer_bridge); | ||
53 | if ((pci->class >> 16) == PCI_BASE_CLASS_BRIDGE) | ||
54 | bridge = 1; | ||
55 | break; | ||
56 | } | ||
57 | |||
58 | if (p->flags & ACPI_HEST_GLOBAL) { | ||
59 | if ((pci->is_pcie && (pci->pcie_type == pcie_type)) || bridge) | ||
60 | *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
61 | } | ||
62 | else | ||
63 | if (hest_match_pci(p, pci)) | ||
64 | *firmware_first = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
65 | return rc; | ||
66 | } | ||
67 | |||
68 | static int acpi_hest_firmware_first(struct acpi_table_header *stdheader, struct pci_dev *pci) | ||
69 | { | ||
70 | struct acpi_table_hest *hest = (struct acpi_table_hest *)stdheader; | ||
71 | void *p = (void *)hest + sizeof(*hest); /* defined by the ACPI 4.0 spec */ | ||
72 | struct acpi_hest_header *hdr = p; | ||
73 | |||
74 | int i; | ||
75 | int firmware_first = 0; | ||
76 | static unsigned char printed_unused = 0; | ||
77 | static unsigned char printed_reserved = 0; | ||
78 | |||
79 | for (i=0, hdr=p; p < (((void *)hest) + hest->header.length) && i < hest->error_source_count; i++) { | ||
80 | switch (hdr->type) { | ||
81 | case ACPI_HEST_TYPE_IA32_CHECK: | ||
82 | p += parse_acpi_hest_ia_machine_check(p); | ||
83 | break; | ||
84 | case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: | ||
85 | p += parse_acpi_hest_ia_corrected(p); | ||
86 | break; | ||
87 | case ACPI_HEST_TYPE_IA32_NMI: | ||
88 | p += parse_acpi_hest_ia_nmi(p); | ||
89 | break; | ||
90 | /* These three should never appear */ | ||
91 | case ACPI_HEST_TYPE_NOT_USED3: | ||
92 | case ACPI_HEST_TYPE_NOT_USED4: | ||
93 | case ACPI_HEST_TYPE_NOT_USED5: | ||
94 | if (!printed_unused) { | ||
95 | printk(KERN_DEBUG PREFIX | ||
96 | "HEST Error Source list contains an obsolete type (%d).\n", hdr->type); | ||
97 | printed_unused = 1; | ||
98 | } | ||
99 | break; | ||
100 | case ACPI_HEST_TYPE_AER_ROOT_PORT: | ||
101 | case ACPI_HEST_TYPE_AER_ENDPOINT: | ||
102 | case ACPI_HEST_TYPE_AER_BRIDGE: | ||
103 | p += parse_acpi_hest_aer(p, hdr->type, pci, &firmware_first); | ||
104 | break; | ||
105 | case ACPI_HEST_TYPE_GENERIC_ERROR: | ||
106 | p += parse_acpi_hest_generic(p); | ||
107 | break; | ||
108 | /* These should never appear either */ | ||
109 | case ACPI_HEST_TYPE_RESERVED: | ||
110 | default: | ||
111 | if (!printed_reserved) { | ||
112 | printk(KERN_DEBUG PREFIX | ||
113 | "HEST Error Source list contains a reserved type (%d).\n", hdr->type); | ||
114 | printed_reserved = 1; | ||
115 | } | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | return firmware_first; | ||
120 | } | ||
121 | |||
122 | int acpi_hest_firmware_first_pci(struct pci_dev *pci) | ||
123 | { | ||
124 | acpi_status status = AE_NOT_FOUND; | ||
125 | struct acpi_table_header *hest = NULL; | ||
126 | |||
127 | if (acpi_disabled) | ||
128 | return 0; | ||
129 | |||
130 | status = acpi_get_table(ACPI_SIG_HEST, 1, &hest); | ||
131 | |||
132 | if (ACPI_SUCCESS(status)) { | ||
133 | if (acpi_hest_firmware_first(hest, pci)) { | ||
134 | return 1; | ||
135 | } | ||
136 | } | ||
137 | return 0; | ||
138 | } | ||
139 | EXPORT_SYMBOL_GPL(acpi_hest_firmware_first_pci); | ||
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/acpi/pci_root.c b/drivers/acpi/pci_root.c index aefce33f2a09..4eac59393edc 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -120,7 +120,8 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus) | |||
120 | struct acpi_pci_root *root; | 120 | struct acpi_pci_root *root; |
121 | 121 | ||
122 | list_for_each_entry(root, &acpi_pci_roots, node) | 122 | list_for_each_entry(root, &acpi_pci_roots, node) |
123 | if ((root->segment == (u16) seg) && (root->bus_nr == (u16) bus)) | 123 | if ((root->segment == (u16) seg) && |
124 | (root->secondary.start == (u16) bus)) | ||
124 | return root->device->handle; | 125 | return root->device->handle; |
125 | return NULL; | 126 | return NULL; |
126 | } | 127 | } |
@@ -154,7 +155,7 @@ EXPORT_SYMBOL_GPL(acpi_is_root_bridge); | |||
154 | static acpi_status | 155 | static acpi_status |
155 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | 156 | get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) |
156 | { | 157 | { |
157 | int *busnr = data; | 158 | struct resource *res = data; |
158 | struct acpi_resource_address64 address; | 159 | struct acpi_resource_address64 address; |
159 | 160 | ||
160 | if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && | 161 | if (resource->type != ACPI_RESOURCE_TYPE_ADDRESS16 && |
@@ -164,28 +165,27 @@ get_root_bridge_busnr_callback(struct acpi_resource *resource, void *data) | |||
164 | 165 | ||
165 | acpi_resource_to_address64(resource, &address); | 166 | acpi_resource_to_address64(resource, &address); |
166 | if ((address.address_length > 0) && | 167 | if ((address.address_length > 0) && |
167 | (address.resource_type == ACPI_BUS_NUMBER_RANGE)) | 168 | (address.resource_type == ACPI_BUS_NUMBER_RANGE)) { |
168 | *busnr = address.minimum; | 169 | res->start = address.minimum; |
170 | res->end = address.minimum + address.address_length - 1; | ||
171 | } | ||
169 | 172 | ||
170 | return AE_OK; | 173 | return AE_OK; |
171 | } | 174 | } |
172 | 175 | ||
173 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, | 176 | static acpi_status try_get_root_bridge_busnr(acpi_handle handle, |
174 | unsigned long long *bus) | 177 | struct resource *res) |
175 | { | 178 | { |
176 | acpi_status status; | 179 | acpi_status status; |
177 | int busnum; | ||
178 | 180 | ||
179 | busnum = -1; | 181 | res->start = -1; |
180 | status = | 182 | status = |
181 | acpi_walk_resources(handle, METHOD_NAME__CRS, | 183 | acpi_walk_resources(handle, METHOD_NAME__CRS, |
182 | get_root_bridge_busnr_callback, &busnum); | 184 | get_root_bridge_busnr_callback, res); |
183 | if (ACPI_FAILURE(status)) | 185 | if (ACPI_FAILURE(status)) |
184 | return status; | 186 | return status; |
185 | /* Check if we really get a bus number from _CRS */ | 187 | if (res->start == -1) |
186 | if (busnum == -1) | ||
187 | return AE_ERROR; | 188 | return AE_ERROR; |
188 | *bus = busnum; | ||
189 | return AE_OK; | 189 | return AE_OK; |
190 | } | 190 | } |
191 | 191 | ||
@@ -429,34 +429,47 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
429 | struct acpi_device *child; | 429 | struct acpi_device *child; |
430 | u32 flags, base_flags; | 430 | u32 flags, base_flags; |
431 | 431 | ||
432 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | ||
433 | if (!root) | ||
434 | return -ENOMEM; | ||
435 | |||
432 | segment = 0; | 436 | segment = 0; |
433 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, | 437 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__SEG, NULL, |
434 | &segment); | 438 | &segment); |
435 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 439 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
436 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); | 440 | printk(KERN_ERR PREFIX "can't evaluate _SEG\n"); |
437 | return -ENODEV; | 441 | result = -ENODEV; |
442 | goto end; | ||
438 | } | 443 | } |
439 | 444 | ||
440 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ | 445 | /* Check _CRS first, then _BBN. If no _BBN, default to zero. */ |
441 | bus = 0; | 446 | root->secondary.flags = IORESOURCE_BUS; |
442 | status = try_get_root_bridge_busnr(device->handle, &bus); | 447 | status = try_get_root_bridge_busnr(device->handle, &root->secondary); |
443 | if (ACPI_FAILURE(status)) { | 448 | if (ACPI_FAILURE(status)) { |
449 | /* | ||
450 | * We need both the start and end of the downstream bus range | ||
451 | * to interpret _CBA (MMCONFIG base address), so it really is | ||
452 | * supposed to be in _CRS. If we don't find it there, all we | ||
453 | * can do is assume [_BBN-0xFF] or [0-0xFF]. | ||
454 | */ | ||
455 | root->secondary.end = 0xFF; | ||
456 | printk(KERN_WARNING FW_BUG PREFIX | ||
457 | "no secondary bus range in _CRS\n"); | ||
444 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); | 458 | status = acpi_evaluate_integer(device->handle, METHOD_NAME__BBN, NULL, &bus); |
445 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { | 459 | if (ACPI_SUCCESS(status)) |
446 | printk(KERN_ERR PREFIX | 460 | root->secondary.start = bus; |
447 | "no bus number in _CRS and can't evaluate _BBN\n"); | 461 | else if (status == AE_NOT_FOUND) |
448 | return -ENODEV; | 462 | root->secondary.start = 0; |
463 | else { | ||
464 | printk(KERN_ERR PREFIX "can't evaluate _BBN\n"); | ||
465 | result = -ENODEV; | ||
466 | goto end; | ||
449 | } | 467 | } |
450 | } | 468 | } |
451 | 469 | ||
452 | root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL); | ||
453 | if (!root) | ||
454 | return -ENOMEM; | ||
455 | |||
456 | INIT_LIST_HEAD(&root->node); | 470 | INIT_LIST_HEAD(&root->node); |
457 | root->device = device; | 471 | root->device = device; |
458 | root->segment = segment & 0xFFFF; | 472 | root->segment = segment & 0xFFFF; |
459 | root->bus_nr = bus & 0xFF; | ||
460 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); | 473 | strcpy(acpi_device_name(device), ACPI_PCI_ROOT_DEVICE_NAME); |
461 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); | 474 | strcpy(acpi_device_class(device), ACPI_PCI_ROOT_CLASS); |
462 | device->driver_data = root; | 475 | device->driver_data = root; |
@@ -475,9 +488,9 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
475 | /* TBD: Locking */ | 488 | /* TBD: Locking */ |
476 | list_add_tail(&root->node, &acpi_pci_roots); | 489 | list_add_tail(&root->node, &acpi_pci_roots); |
477 | 490 | ||
478 | printk(KERN_INFO PREFIX "%s [%s] (%04x:%02x)\n", | 491 | printk(KERN_INFO PREFIX "%s [%s] (domain %04x %pR)\n", |
479 | acpi_device_name(device), acpi_device_bid(device), | 492 | acpi_device_name(device), acpi_device_bid(device), |
480 | root->segment, root->bus_nr); | 493 | root->segment, &root->secondary); |
481 | 494 | ||
482 | /* | 495 | /* |
483 | * Scan the Root Bridge | 496 | * Scan the Root Bridge |
@@ -486,11 +499,11 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
486 | * PCI namespace does not get created until this call is made (and | 499 | * PCI namespace does not get created until this call is made (and |
487 | * thus the root bridge's pci_dev does not exist). | 500 | * thus the root bridge's pci_dev does not exist). |
488 | */ | 501 | */ |
489 | root->bus = pci_acpi_scan_root(device, segment, bus); | 502 | root->bus = pci_acpi_scan_root(root); |
490 | if (!root->bus) { | 503 | if (!root->bus) { |
491 | printk(KERN_ERR PREFIX | 504 | printk(KERN_ERR PREFIX |
492 | "Bus %04x:%02x not present in PCI namespace\n", | 505 | "Bus %04x:%02x not present in PCI namespace\n", |
493 | root->segment, root->bus_nr); | 506 | root->segment, (unsigned int)root->secondary.start); |
494 | result = -ENODEV; | 507 | result = -ENODEV; |
495 | goto end; | 508 | goto end; |
496 | } | 509 | } |
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 5675d9747e87..b1034a9ada4e 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -616,7 +616,8 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) | |||
616 | acpi_processor_get_limit_info(pr); | 616 | acpi_processor_get_limit_info(pr); |
617 | 617 | ||
618 | 618 | ||
619 | acpi_processor_power_init(pr, device); | 619 | if (cpuidle_get_driver() == &acpi_idle_driver) |
620 | acpi_processor_power_init(pr, device); | ||
620 | 621 | ||
621 | pr->cdev = thermal_cooling_device_register("Processor", device, | 622 | pr->cdev = thermal_cooling_device_register("Processor", device, |
622 | &processor_cooling_ops); | 623 | &processor_cooling_ops); |
@@ -920,9 +921,14 @@ static int __init acpi_processor_init(void) | |||
920 | if (!acpi_processor_dir) | 921 | if (!acpi_processor_dir) |
921 | return -ENOMEM; | 922 | return -ENOMEM; |
922 | #endif | 923 | #endif |
923 | result = cpuidle_register_driver(&acpi_idle_driver); | 924 | |
924 | if (result < 0) | 925 | if (!cpuidle_register_driver(&acpi_idle_driver)) { |
925 | goto out_proc; | 926 | printk(KERN_DEBUG "ACPI: %s registered with cpuidle\n", |
927 | acpi_idle_driver.name); | ||
928 | } else { | ||
929 | printk(KERN_DEBUG "ACPI: acpi_idle yielding to %s", | ||
930 | cpuidle_get_driver()->name); | ||
931 | } | ||
926 | 932 | ||
927 | result = acpi_bus_register_driver(&acpi_processor_driver); | 933 | result = acpi_bus_register_driver(&acpi_processor_driver); |
928 | if (result < 0) | 934 | if (result < 0) |
@@ -941,7 +947,6 @@ static int __init acpi_processor_init(void) | |||
941 | out_cpuidle: | 947 | out_cpuidle: |
942 | cpuidle_unregister_driver(&acpi_idle_driver); | 948 | cpuidle_unregister_driver(&acpi_idle_driver); |
943 | 949 | ||
944 | out_proc: | ||
945 | #ifdef CONFIG_ACPI_PROCFS | 950 | #ifdef CONFIG_ACPI_PROCFS |
946 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); | 951 | remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); |
947 | #endif | 952 | #endif |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index c3817e1f32c7..2e8c27d48f2b 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -727,19 +727,9 @@ static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) | |||
727 | break; | 727 | break; |
728 | } | 728 | } |
729 | 729 | ||
730 | if (pr->power.states[i].promotion.state) | 730 | seq_puts(seq, "promotion[--] "); |
731 | seq_printf(seq, "promotion[C%zd] ", | 731 | |
732 | (pr->power.states[i].promotion.state - | 732 | seq_puts(seq, "demotion[--] "); |
733 | pr->power.states)); | ||
734 | else | ||
735 | seq_puts(seq, "promotion[--] "); | ||
736 | |||
737 | if (pr->power.states[i].demotion.state) | ||
738 | seq_printf(seq, "demotion[C%zd] ", | ||
739 | (pr->power.states[i].demotion.state - | ||
740 | pr->power.states)); | ||
741 | else | ||
742 | seq_puts(seq, "demotion[--] "); | ||
743 | 733 | ||
744 | seq_printf(seq, "latency[%03d] usage[%08d] duration[%020llu]\n", | 734 | seq_printf(seq, "latency[%03d] usage[%08d] duration[%020llu]\n", |
745 | pr->power.states[i].latency, | 735 | pr->power.states[i].latency, |
@@ -869,6 +859,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
869 | struct acpi_processor *pr; | 859 | struct acpi_processor *pr; |
870 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 860 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
871 | ktime_t kt1, kt2; | 861 | ktime_t kt1, kt2; |
862 | s64 idle_time_ns; | ||
872 | s64 idle_time; | 863 | s64 idle_time; |
873 | s64 sleep_ticks = 0; | 864 | s64 sleep_ticks = 0; |
874 | 865 | ||
@@ -881,6 +872,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
881 | return(acpi_idle_enter_c1(dev, state)); | 872 | return(acpi_idle_enter_c1(dev, state)); |
882 | 873 | ||
883 | local_irq_disable(); | 874 | local_irq_disable(); |
875 | |||
884 | if (cx->entry_method != ACPI_CSTATE_FFH) { | 876 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
885 | current_thread_info()->status &= ~TS_POLLING; | 877 | current_thread_info()->status &= ~TS_POLLING; |
886 | /* | 878 | /* |
@@ -888,12 +880,12 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
888 | * NEED_RESCHED: | 880 | * NEED_RESCHED: |
889 | */ | 881 | */ |
890 | smp_mb(); | 882 | smp_mb(); |
891 | } | ||
892 | 883 | ||
893 | if (unlikely(need_resched())) { | 884 | if (unlikely(need_resched())) { |
894 | current_thread_info()->status |= TS_POLLING; | 885 | current_thread_info()->status |= TS_POLLING; |
895 | local_irq_enable(); | 886 | local_irq_enable(); |
896 | return 0; | 887 | return 0; |
888 | } | ||
897 | } | 889 | } |
898 | 890 | ||
899 | /* | 891 | /* |
@@ -910,15 +902,18 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev, | |||
910 | sched_clock_idle_sleep_event(); | 902 | sched_clock_idle_sleep_event(); |
911 | acpi_idle_do_entry(cx); | 903 | acpi_idle_do_entry(cx); |
912 | kt2 = ktime_get_real(); | 904 | kt2 = ktime_get_real(); |
913 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | 905 | idle_time_ns = ktime_to_ns(ktime_sub(kt2, kt1)); |
906 | idle_time = idle_time_ns; | ||
907 | do_div(idle_time, NSEC_PER_USEC); | ||
914 | 908 | ||
915 | sleep_ticks = us_to_pm_timer_ticks(idle_time); | 909 | sleep_ticks = us_to_pm_timer_ticks(idle_time); |
916 | 910 | ||
917 | /* Tell the scheduler how much we idled: */ | 911 | /* Tell the scheduler how much we idled: */ |
918 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | 912 | sched_clock_idle_wakeup_event(idle_time_ns); |
919 | 913 | ||
920 | local_irq_enable(); | 914 | local_irq_enable(); |
921 | current_thread_info()->status |= TS_POLLING; | 915 | if (cx->entry_method != ACPI_CSTATE_FFH) |
916 | current_thread_info()->status |= TS_POLLING; | ||
922 | 917 | ||
923 | cx->usage++; | 918 | cx->usage++; |
924 | 919 | ||
@@ -943,6 +938,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
943 | struct acpi_processor *pr; | 938 | struct acpi_processor *pr; |
944 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); | 939 | struct acpi_processor_cx *cx = cpuidle_get_statedata(state); |
945 | ktime_t kt1, kt2; | 940 | ktime_t kt1, kt2; |
941 | s64 idle_time_ns; | ||
946 | s64 idle_time; | 942 | s64 idle_time; |
947 | s64 sleep_ticks = 0; | 943 | s64 sleep_ticks = 0; |
948 | 944 | ||
@@ -968,6 +964,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
968 | } | 964 | } |
969 | 965 | ||
970 | local_irq_disable(); | 966 | local_irq_disable(); |
967 | |||
971 | if (cx->entry_method != ACPI_CSTATE_FFH) { | 968 | if (cx->entry_method != ACPI_CSTATE_FFH) { |
972 | current_thread_info()->status &= ~TS_POLLING; | 969 | current_thread_info()->status &= ~TS_POLLING; |
973 | /* | 970 | /* |
@@ -975,12 +972,12 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
975 | * NEED_RESCHED: | 972 | * NEED_RESCHED: |
976 | */ | 973 | */ |
977 | smp_mb(); | 974 | smp_mb(); |
978 | } | ||
979 | 975 | ||
980 | if (unlikely(need_resched())) { | 976 | if (unlikely(need_resched())) { |
981 | current_thread_info()->status |= TS_POLLING; | 977 | current_thread_info()->status |= TS_POLLING; |
982 | local_irq_enable(); | 978 | local_irq_enable(); |
983 | return 0; | 979 | return 0; |
980 | } | ||
984 | } | 981 | } |
985 | 982 | ||
986 | acpi_unlazy_tlb(smp_processor_id()); | 983 | acpi_unlazy_tlb(smp_processor_id()); |
@@ -1025,14 +1022,17 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev, | |||
1025 | spin_unlock(&c3_lock); | 1022 | spin_unlock(&c3_lock); |
1026 | } | 1023 | } |
1027 | kt2 = ktime_get_real(); | 1024 | kt2 = ktime_get_real(); |
1028 | idle_time = ktime_to_us(ktime_sub(kt2, kt1)); | 1025 | idle_time_ns = ktime_to_us(ktime_sub(kt2, kt1)); |
1026 | idle_time = idle_time_ns; | ||
1027 | do_div(idle_time, NSEC_PER_USEC); | ||
1029 | 1028 | ||
1030 | sleep_ticks = us_to_pm_timer_ticks(idle_time); | 1029 | sleep_ticks = us_to_pm_timer_ticks(idle_time); |
1031 | /* Tell the scheduler how much we idled: */ | 1030 | /* Tell the scheduler how much we idled: */ |
1032 | sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); | 1031 | sched_clock_idle_wakeup_event(idle_time_ns); |
1033 | 1032 | ||
1034 | local_irq_enable(); | 1033 | local_irq_enable(); |
1035 | current_thread_info()->status |= TS_POLLING; | 1034 | if (cx->entry_method != ACPI_CSTATE_FFH) |
1035 | current_thread_info()->status |= TS_POLLING; | ||
1036 | 1036 | ||
1037 | cx->usage++; | 1037 | cx->usage++; |
1038 | 1038 | ||
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index baa76bbf244a..4ab2275b4461 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -80,22 +80,6 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
80 | 80 | ||
81 | #ifdef CONFIG_ACPI_SLEEP | 81 | #ifdef CONFIG_ACPI_SLEEP |
82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | 82 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
83 | /* | ||
84 | * According to the ACPI specification the BIOS should make sure that ACPI is | ||
85 | * enabled and SCI_EN bit is set on wake-up from S1 - S3 sleep states. Still, | ||
86 | * some BIOSes don't do that and therefore we use acpi_enable() to enable ACPI | ||
87 | * on such systems during resume. Unfortunately that doesn't help in | ||
88 | * particularly pathological cases in which SCI_EN has to be set directly on | ||
89 | * resume, although the specification states very clearly that this flag is | ||
90 | * owned by the hardware. The set_sci_en_on_resume variable will be set in such | ||
91 | * cases. | ||
92 | */ | ||
93 | static bool set_sci_en_on_resume; | ||
94 | |||
95 | void __init acpi_set_sci_en_on_resume(void) | ||
96 | { | ||
97 | set_sci_en_on_resume = true; | ||
98 | } | ||
99 | 83 | ||
100 | /* | 84 | /* |
101 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | 85 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the |
@@ -253,11 +237,8 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
253 | break; | 237 | break; |
254 | } | 238 | } |
255 | 239 | ||
256 | /* If ACPI is not enabled by the BIOS, we need to enable it here. */ | 240 | /* This violates the spec but is required for bug compatibility. */ |
257 | if (set_sci_en_on_resume) | 241 | acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); |
258 | acpi_write_bit_register(ACPI_BITREG_SCI_ENABLE, 1); | ||
259 | else | ||
260 | acpi_enable(); | ||
261 | 242 | ||
262 | /* Reprogram control registers and execute _BFS */ | 243 | /* Reprogram control registers and execute _BFS */ |
263 | acpi_leave_sleep_state_prep(acpi_state); | 244 | acpi_leave_sleep_state_prep(acpi_state); |
@@ -346,12 +327,6 @@ static int __init init_old_suspend_ordering(const struct dmi_system_id *d) | |||
346 | return 0; | 327 | return 0; |
347 | } | 328 | } |
348 | 329 | ||
349 | static int __init init_set_sci_en_on_resume(const struct dmi_system_id *d) | ||
350 | { | ||
351 | set_sci_en_on_resume = true; | ||
352 | return 0; | ||
353 | } | ||
354 | |||
355 | static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | 330 | static struct dmi_system_id __initdata acpisleep_dmi_table[] = { |
356 | { | 331 | { |
357 | .callback = init_old_suspend_ordering, | 332 | .callback = init_old_suspend_ordering, |
@@ -370,22 +345,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
370 | }, | 345 | }, |
371 | }, | 346 | }, |
372 | { | 347 | { |
373 | .callback = init_set_sci_en_on_resume, | ||
374 | .ident = "Apple MacBook 1,1", | ||
375 | .matches = { | ||
376 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), | ||
377 | DMI_MATCH(DMI_PRODUCT_NAME, "MacBook1,1"), | ||
378 | }, | ||
379 | }, | ||
380 | { | ||
381 | .callback = init_set_sci_en_on_resume, | ||
382 | .ident = "Apple MacMini 1,1", | ||
383 | .matches = { | ||
384 | DMI_MATCH(DMI_SYS_VENDOR, "Apple Computer, Inc."), | ||
385 | DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), | ||
386 | }, | ||
387 | }, | ||
388 | { | ||
389 | .callback = init_old_suspend_ordering, | 348 | .callback = init_old_suspend_ordering, |
390 | .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", | 349 | .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", |
391 | .matches = { | 350 | .matches = { |
@@ -394,94 +353,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
394 | }, | 353 | }, |
395 | }, | 354 | }, |
396 | { | 355 | { |
397 | .callback = init_set_sci_en_on_resume, | ||
398 | .ident = "Toshiba Satellite L300", | ||
399 | .matches = { | ||
400 | DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), | ||
401 | DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), | ||
402 | }, | ||
403 | }, | ||
404 | { | ||
405 | .callback = init_set_sci_en_on_resume, | ||
406 | .ident = "Hewlett-Packard HP G7000 Notebook PC", | ||
407 | .matches = { | ||
408 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
409 | DMI_MATCH(DMI_PRODUCT_NAME, "HP G7000 Notebook PC"), | ||
410 | }, | ||
411 | }, | ||
412 | { | ||
413 | .callback = init_set_sci_en_on_resume, | ||
414 | .ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC", | ||
415 | .matches = { | ||
416 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
417 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"), | ||
418 | }, | ||
419 | }, | ||
420 | { | ||
421 | .callback = init_set_sci_en_on_resume, | ||
422 | .ident = "Hewlett-Packard Pavilion dv4", | ||
423 | .matches = { | ||
424 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
425 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv4"), | ||
426 | }, | ||
427 | }, | ||
428 | { | ||
429 | .callback = init_set_sci_en_on_resume, | ||
430 | .ident = "Hewlett-Packard Pavilion dv7", | ||
431 | .matches = { | ||
432 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
433 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv7"), | ||
434 | }, | ||
435 | }, | ||
436 | { | ||
437 | .callback = init_set_sci_en_on_resume, | ||
438 | .ident = "Hewlett-Packard Compaq Presario C700 Notebook PC", | ||
439 | .matches = { | ||
440 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
441 | DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario C700 Notebook PC"), | ||
442 | }, | ||
443 | }, | ||
444 | { | ||
445 | .callback = init_set_sci_en_on_resume, | ||
446 | .ident = "Hewlett-Packard Compaq Presario CQ40 Notebook PC", | ||
447 | .matches = { | ||
448 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
449 | DMI_MATCH(DMI_PRODUCT_NAME, "Compaq Presario CQ40 Notebook PC"), | ||
450 | }, | ||
451 | }, | ||
452 | { | ||
453 | .callback = init_set_sci_en_on_resume, | ||
454 | .ident = "Lenovo ThinkPad T410", | ||
455 | .matches = { | ||
456 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
457 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), | ||
458 | }, | ||
459 | }, | ||
460 | { | ||
461 | .callback = init_set_sci_en_on_resume, | ||
462 | .ident = "Lenovo ThinkPad T510", | ||
463 | .matches = { | ||
464 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
465 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), | ||
466 | }, | ||
467 | }, | ||
468 | { | ||
469 | .callback = init_set_sci_en_on_resume, | ||
470 | .ident = "Lenovo ThinkPad W510", | ||
471 | .matches = { | ||
472 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
473 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), | ||
474 | }, | ||
475 | }, | ||
476 | { | ||
477 | .callback = init_set_sci_en_on_resume, | ||
478 | .ident = "Lenovo ThinkPad X201[s]", | ||
479 | .matches = { | ||
480 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
481 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), | ||
482 | }, | ||
483 | }, | ||
484 | { | ||
485 | .callback = init_old_suspend_ordering, | 356 | .callback = init_old_suspend_ordering, |
486 | .ident = "Panasonic CF51-2L", | 357 | .ident = "Panasonic CF51-2L", |
487 | .matches = { | 358 | .matches = { |
@@ -490,30 +361,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
490 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), | 361 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), |
491 | }, | 362 | }, |
492 | }, | 363 | }, |
493 | { | ||
494 | .callback = init_set_sci_en_on_resume, | ||
495 | .ident = "Dell Studio 1558", | ||
496 | .matches = { | ||
497 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
498 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"), | ||
499 | }, | ||
500 | }, | ||
501 | { | ||
502 | .callback = init_set_sci_en_on_resume, | ||
503 | .ident = "Dell Studio 1557", | ||
504 | .matches = { | ||
505 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
506 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), | ||
507 | }, | ||
508 | }, | ||
509 | { | ||
510 | .callback = init_set_sci_en_on_resume, | ||
511 | .ident = "Dell Studio 1555", | ||
512 | .matches = { | ||
513 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
514 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"), | ||
515 | }, | ||
516 | }, | ||
517 | {}, | 364 | {}, |
518 | }; | 365 | }; |
519 | #endif /* CONFIG_SUSPEND */ | 366 | #endif /* CONFIG_SUSPEND */ |
diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index 8a8f3b3382a6..25b8bd149284 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h | |||
@@ -1,6 +1,6 @@ | |||
1 | 1 | ||
2 | extern u8 sleep_states[]; | 2 | extern u8 sleep_states[]; |
3 | extern int acpi_suspend (u32 state); | 3 | extern int acpi_suspend(u32 state); |
4 | 4 | ||
5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); | 5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); |
6 | extern void acpi_enable_wakeup_device(u8 sleep_state); | 6 | extern void acpi_enable_wakeup_device(u8 sleep_state); |
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 8a0ed2800e63..f336bca7c450 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
@@ -213,7 +213,7 @@ acpi_table_parse_entries(char *id, | |||
213 | unsigned long table_end; | 213 | unsigned long table_end; |
214 | acpi_size tbl_size; | 214 | acpi_size tbl_size; |
215 | 215 | ||
216 | if (acpi_disabled && !acpi_ht) | 216 | if (acpi_disabled) |
217 | return -ENODEV; | 217 | return -ENODEV; |
218 | 218 | ||
219 | if (!handler) | 219 | if (!handler) |
@@ -280,7 +280,7 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) | |||
280 | struct acpi_table_header *table = NULL; | 280 | struct acpi_table_header *table = NULL; |
281 | acpi_size tbl_size; | 281 | acpi_size tbl_size; |
282 | 282 | ||
283 | if (acpi_disabled && !acpi_ht) | 283 | if (acpi_disabled) |
284 | return -ENODEV; | 284 | return -ENODEV; |
285 | 285 | ||
286 | if (!handler) | 286 | if (!handler) |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index a0c93b321482..9865d46f49a8 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <acpi/acpi_bus.h> | 45 | #include <acpi/acpi_bus.h> |
46 | #include <acpi/acpi_drivers.h> | 46 | #include <acpi/acpi_drivers.h> |
47 | #include <linux/suspend.h> | 47 | #include <linux/suspend.h> |
48 | #include <acpi/video.h> | ||
48 | 49 | ||
49 | #define PREFIX "ACPI: " | 50 | #define PREFIX "ACPI: " |
50 | 51 | ||
@@ -65,11 +66,6 @@ | |||
65 | 66 | ||
66 | #define MAX_NAME_LEN 20 | 67 | #define MAX_NAME_LEN 20 |
67 | 68 | ||
68 | #define ACPI_VIDEO_DISPLAY_CRT 1 | ||
69 | #define ACPI_VIDEO_DISPLAY_TV 2 | ||
70 | #define ACPI_VIDEO_DISPLAY_DVI 3 | ||
71 | #define ACPI_VIDEO_DISPLAY_LCD 4 | ||
72 | |||
73 | #define _COMPONENT ACPI_VIDEO_COMPONENT | 69 | #define _COMPONENT ACPI_VIDEO_COMPONENT |
74 | ACPI_MODULE_NAME("video"); | 70 | ACPI_MODULE_NAME("video"); |
75 | 71 | ||
@@ -1007,11 +1003,11 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
1007 | result = acpi_video_init_brightness(device); | 1003 | result = acpi_video_init_brightness(device); |
1008 | if (result) | 1004 | if (result) |
1009 | return; | 1005 | return; |
1010 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 1006 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); |
1011 | if (!name) | 1007 | if (!name) |
1012 | return; | 1008 | return; |
1009 | count++; | ||
1013 | 1010 | ||
1014 | sprintf(name, "acpi_video%d", count++); | ||
1015 | memset(&props, 0, sizeof(struct backlight_properties)); | 1011 | memset(&props, 0, sizeof(struct backlight_properties)); |
1016 | props.max_brightness = device->brightness->count - 3; | 1012 | props.max_brightness = device->brightness->count - 3; |
1017 | device->backlight = backlight_device_register(name, NULL, device, | 1013 | device->backlight = backlight_device_register(name, NULL, device, |
@@ -1067,10 +1063,10 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) | |||
1067 | if (device->cap._DCS && device->cap._DSS) { | 1063 | if (device->cap._DCS && device->cap._DSS) { |
1068 | static int count; | 1064 | static int count; |
1069 | char *name; | 1065 | char *name; |
1070 | name = kzalloc(MAX_NAME_LEN, GFP_KERNEL); | 1066 | name = kasprintf(GFP_KERNEL, "acpi_video%d", count); |
1071 | if (!name) | 1067 | if (!name) |
1072 | return; | 1068 | return; |
1073 | sprintf(name, "acpi_video%d", count++); | 1069 | count++; |
1074 | device->output_dev = video_output_register(name, | 1070 | device->output_dev = video_output_register(name, |
1075 | NULL, device, &acpi_output_properties); | 1071 | NULL, device, &acpi_output_properties); |
1076 | kfree(name); | 1072 | kfree(name); |
@@ -1748,11 +1744,27 @@ acpi_video_get_device_attr(struct acpi_video_bus *video, unsigned long device_id | |||
1748 | } | 1744 | } |
1749 | 1745 | ||
1750 | static int | 1746 | static int |
1747 | acpi_video_get_device_type(struct acpi_video_bus *video, | ||
1748 | unsigned long device_id) | ||
1749 | { | ||
1750 | struct acpi_video_enumerated_device *ids; | ||
1751 | int i; | ||
1752 | |||
1753 | for (i = 0; i < video->attached_count; i++) { | ||
1754 | ids = &video->attached_array[i]; | ||
1755 | if ((ids->value.int_val & 0xffff) == device_id) | ||
1756 | return ids->value.int_val; | ||
1757 | } | ||
1758 | |||
1759 | return 0; | ||
1760 | } | ||
1761 | |||
1762 | static int | ||
1751 | acpi_video_bus_get_one_device(struct acpi_device *device, | 1763 | acpi_video_bus_get_one_device(struct acpi_device *device, |
1752 | struct acpi_video_bus *video) | 1764 | struct acpi_video_bus *video) |
1753 | { | 1765 | { |
1754 | unsigned long long device_id; | 1766 | unsigned long long device_id; |
1755 | int status; | 1767 | int status, device_type; |
1756 | struct acpi_video_device *data; | 1768 | struct acpi_video_device *data; |
1757 | struct acpi_video_device_attrib* attribute; | 1769 | struct acpi_video_device_attrib* attribute; |
1758 | 1770 | ||
@@ -1797,8 +1809,25 @@ acpi_video_bus_get_one_device(struct acpi_device *device, | |||
1797 | } | 1809 | } |
1798 | if(attribute->bios_can_detect) | 1810 | if(attribute->bios_can_detect) |
1799 | data->flags.bios = 1; | 1811 | data->flags.bios = 1; |
1800 | } else | 1812 | } else { |
1801 | data->flags.unknown = 1; | 1813 | /* Check for legacy IDs */ |
1814 | device_type = acpi_video_get_device_type(video, | ||
1815 | device_id); | ||
1816 | /* Ignore bits 16 and 18-20 */ | ||
1817 | switch (device_type & 0xffe2ffff) { | ||
1818 | case ACPI_VIDEO_DISPLAY_LEGACY_MONITOR: | ||
1819 | data->flags.crt = 1; | ||
1820 | break; | ||
1821 | case ACPI_VIDEO_DISPLAY_LEGACY_PANEL: | ||
1822 | data->flags.lcd = 1; | ||
1823 | break; | ||
1824 | case ACPI_VIDEO_DISPLAY_LEGACY_TV: | ||
1825 | data->flags.tvout = 1; | ||
1826 | break; | ||
1827 | default: | ||
1828 | data->flags.unknown = 1; | ||
1829 | } | ||
1830 | } | ||
1802 | 1831 | ||
1803 | acpi_video_device_bind(video, data); | 1832 | acpi_video_device_bind(video, data); |
1804 | acpi_video_device_find_cap(data); | 1833 | acpi_video_device_find_cap(data); |
@@ -2032,6 +2061,71 @@ out: | |||
2032 | return result; | 2061 | return result; |
2033 | } | 2062 | } |
2034 | 2063 | ||
2064 | int acpi_video_get_edid(struct acpi_device *device, int type, int device_id, | ||
2065 | void **edid) | ||
2066 | { | ||
2067 | struct acpi_video_bus *video; | ||
2068 | struct acpi_video_device *video_device; | ||
2069 | union acpi_object *buffer = NULL; | ||
2070 | acpi_status status; | ||
2071 | int i, length; | ||
2072 | |||
2073 | if (!device || !acpi_driver_data(device)) | ||
2074 | return -EINVAL; | ||
2075 | |||
2076 | video = acpi_driver_data(device); | ||
2077 | |||
2078 | for (i = 0; i < video->attached_count; i++) { | ||
2079 | video_device = video->attached_array[i].bind_info; | ||
2080 | length = 256; | ||
2081 | |||
2082 | if (!video_device) | ||
2083 | continue; | ||
2084 | |||
2085 | if (type) { | ||
2086 | switch (type) { | ||
2087 | case ACPI_VIDEO_DISPLAY_CRT: | ||
2088 | if (!video_device->flags.crt) | ||
2089 | continue; | ||
2090 | break; | ||
2091 | case ACPI_VIDEO_DISPLAY_TV: | ||
2092 | if (!video_device->flags.tvout) | ||
2093 | continue; | ||
2094 | break; | ||
2095 | case ACPI_VIDEO_DISPLAY_DVI: | ||
2096 | if (!video_device->flags.dvi) | ||
2097 | continue; | ||
2098 | break; | ||
2099 | case ACPI_VIDEO_DISPLAY_LCD: | ||
2100 | if (!video_device->flags.lcd) | ||
2101 | continue; | ||
2102 | break; | ||
2103 | } | ||
2104 | } else if (video_device->device_id != device_id) { | ||
2105 | continue; | ||
2106 | } | ||
2107 | |||
2108 | status = acpi_video_device_EDID(video_device, &buffer, length); | ||
2109 | |||
2110 | if (ACPI_FAILURE(status) || !buffer || | ||
2111 | buffer->type != ACPI_TYPE_BUFFER) { | ||
2112 | length = 128; | ||
2113 | status = acpi_video_device_EDID(video_device, &buffer, | ||
2114 | length); | ||
2115 | if (ACPI_FAILURE(status) || !buffer || | ||
2116 | buffer->type != ACPI_TYPE_BUFFER) { | ||
2117 | continue; | ||
2118 | } | ||
2119 | } | ||
2120 | |||
2121 | *edid = buffer->buffer.pointer; | ||
2122 | return length; | ||
2123 | } | ||
2124 | |||
2125 | return -ENODEV; | ||
2126 | } | ||
2127 | EXPORT_SYMBOL(acpi_video_get_edid); | ||
2128 | |||
2035 | static int | 2129 | static int |
2036 | acpi_video_bus_get_devices(struct acpi_video_bus *video, | 2130 | acpi_video_bus_get_devices(struct acpi_video_bus *video, |
2037 | struct acpi_device *device) | 2131 | struct acpi_device *device) |
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index fc2f26b9b407..c5fef01b3c95 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c | |||
@@ -250,7 +250,7 @@ static int __init acpi_backlight(char *str) | |||
250 | ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; | 250 | ACPI_VIDEO_BACKLIGHT_FORCE_VENDOR; |
251 | if (!strcmp("video", str)) | 251 | if (!strcmp("video", str)) |
252 | acpi_video_support |= | 252 | acpi_video_support |= |
253 | ACPI_VIDEO_OUTPUT_SWITCHING_FORCE_VIDEO; | 253 | ACPI_VIDEO_BACKLIGHT_FORCE_VIDEO; |
254 | } | 254 | } |
255 | return 1; | 255 | return 1; |
256 | } | 256 | } |
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index e68541f662b9..73f883333a0d 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -57,6 +57,8 @@ config SATA_PMP | |||
57 | This option adds support for SATA Port Multipliers | 57 | This option adds support for SATA Port Multipliers |
58 | (the SATA version of an ethernet hub, or SAS expander). | 58 | (the SATA version of an ethernet hub, or SAS expander). |
59 | 59 | ||
60 | comment "Controllers with non-SFF native interface" | ||
61 | |||
60 | config SATA_AHCI | 62 | config SATA_AHCI |
61 | tristate "AHCI SATA support" | 63 | tristate "AHCI SATA support" |
62 | depends on PCI | 64 | depends on PCI |
@@ -73,11 +75,12 @@ config SATA_AHCI_PLATFORM | |||
73 | 75 | ||
74 | If unsure, say N. | 76 | If unsure, say N. |
75 | 77 | ||
76 | config SATA_SIL24 | 78 | config SATA_FSL |
77 | tristate "Silicon Image 3124/3132 SATA support" | 79 | tristate "Freescale 3.0Gbps SATA support" |
78 | depends on PCI | 80 | depends on FSL_SOC |
79 | help | 81 | help |
80 | This option enables support for Silicon Image 3124/3132 Serial ATA. | 82 | This option enables support for Freescale 3.0Gbps SATA controller. |
83 | It can be found on MPC837x and MPC8315. | ||
81 | 84 | ||
82 | If unsure, say N. | 85 | If unsure, say N. |
83 | 86 | ||
@@ -87,12 +90,11 @@ config SATA_INIC162X | |||
87 | help | 90 | help |
88 | This option enables support for Initio 162x Serial ATA. | 91 | This option enables support for Initio 162x Serial ATA. |
89 | 92 | ||
90 | config SATA_FSL | 93 | config SATA_SIL24 |
91 | tristate "Freescale 3.0Gbps SATA support" | 94 | tristate "Silicon Image 3124/3132 SATA support" |
92 | depends on FSL_SOC | 95 | depends on PCI |
93 | help | 96 | help |
94 | This option enables support for Freescale 3.0Gbps SATA controller. | 97 | This option enables support for Silicon Image 3124/3132 Serial ATA. |
95 | It can be found on MPC837x and MPC8315. | ||
96 | 98 | ||
97 | If unsure, say N. | 99 | If unsure, say N. |
98 | 100 | ||
@@ -116,15 +118,65 @@ config ATA_SFF | |||
116 | 118 | ||
117 | if ATA_SFF | 119 | if ATA_SFF |
118 | 120 | ||
119 | config SATA_SVW | 121 | comment "SFF controllers with custom DMA interface" |
120 | tristate "ServerWorks Frodo / Apple K2 SATA support" | 122 | |
123 | config PDC_ADMA | ||
124 | tristate "Pacific Digital ADMA support" | ||
121 | depends on PCI | 125 | depends on PCI |
122 | help | 126 | help |
123 | This option enables support for Broadcom/Serverworks/Apple K2 | 127 | This option enables support for Pacific Digital ADMA controllers |
124 | SATA support. | 128 | |
129 | If unsure, say N. | ||
130 | |||
131 | config PATA_MPC52xx | ||
132 | tristate "Freescale MPC52xx SoC internal IDE" | ||
133 | depends on PPC_MPC52xx && PPC_BESTCOMM | ||
134 | select PPC_BESTCOMM_ATA | ||
135 | help | ||
136 | This option enables support for integrated IDE controller | ||
137 | of the Freescale MPC52xx SoC. | ||
138 | |||
139 | If unsure, say N. | ||
140 | |||
141 | config PATA_OCTEON_CF | ||
142 | tristate "OCTEON Boot Bus Compact Flash support" | ||
143 | depends on CPU_CAVIUM_OCTEON | ||
144 | help | ||
145 | This option enables a polled compact flash driver for use with | ||
146 | compact flash cards attached to the OCTEON boot bus. | ||
147 | |||
148 | If unsure, say N. | ||
149 | |||
150 | config SATA_QSTOR | ||
151 | tristate "Pacific Digital SATA QStor support" | ||
152 | depends on PCI | ||
153 | help | ||
154 | This option enables support for Pacific Digital Serial ATA QStor. | ||
155 | |||
156 | If unsure, say N. | ||
157 | |||
158 | config SATA_SX4 | ||
159 | tristate "Promise SATA SX4 support (Experimental)" | ||
160 | depends on PCI && EXPERIMENTAL | ||
161 | help | ||
162 | This option enables support for Promise Serial ATA SX4. | ||
125 | 163 | ||
126 | If unsure, say N. | 164 | If unsure, say N. |
127 | 165 | ||
166 | config ATA_BMDMA | ||
167 | bool "ATA BMDMA support" | ||
168 | default y | ||
169 | help | ||
170 | This option adds support for SFF ATA controllers with BMDMA | ||
171 | capability. BMDMA stands for bus-master DMA and the | ||
172 | de-facto DMA interface for SFF controllers. | ||
173 | |||
174 | If unuser, say Y. | ||
175 | |||
176 | if ATA_BMDMA | ||
177 | |||
178 | comment "SATA SFF controllers with BMDMA" | ||
179 | |||
128 | config ATA_PIIX | 180 | config ATA_PIIX |
129 | tristate "Intel ESB, ICH, PIIX3, PIIX4 PATA/SATA support" | 181 | tristate "Intel ESB, ICH, PIIX3, PIIX4 PATA/SATA support" |
130 | depends on PCI | 182 | depends on PCI |
@@ -152,22 +204,6 @@ config SATA_NV | |||
152 | 204 | ||
153 | If unsure, say N. | 205 | If unsure, say N. |
154 | 206 | ||
155 | config PDC_ADMA | ||
156 | tristate "Pacific Digital ADMA support" | ||
157 | depends on PCI | ||
158 | help | ||
159 | This option enables support for Pacific Digital ADMA controllers | ||
160 | |||
161 | If unsure, say N. | ||
162 | |||
163 | config SATA_QSTOR | ||
164 | tristate "Pacific Digital SATA QStor support" | ||
165 | depends on PCI | ||
166 | help | ||
167 | This option enables support for Pacific Digital Serial ATA QStor. | ||
168 | |||
169 | If unsure, say N. | ||
170 | |||
171 | config SATA_PROMISE | 207 | config SATA_PROMISE |
172 | tristate "Promise SATA TX2/TX4 support" | 208 | tristate "Promise SATA TX2/TX4 support" |
173 | depends on PCI | 209 | depends on PCI |
@@ -176,14 +212,6 @@ config SATA_PROMISE | |||
176 | 212 | ||
177 | If unsure, say N. | 213 | If unsure, say N. |
178 | 214 | ||
179 | config SATA_SX4 | ||
180 | tristate "Promise SATA SX4 support (Experimental)" | ||
181 | depends on PCI && EXPERIMENTAL | ||
182 | help | ||
183 | This option enables support for Promise Serial ATA SX4. | ||
184 | |||
185 | If unsure, say N. | ||
186 | |||
187 | config SATA_SIL | 215 | config SATA_SIL |
188 | tristate "Silicon Image SATA support" | 216 | tristate "Silicon Image SATA support" |
189 | depends on PCI | 217 | depends on PCI |
@@ -203,6 +231,15 @@ config SATA_SIS | |||
203 | enable the PATA_SIS driver in the config. | 231 | enable the PATA_SIS driver in the config. |
204 | If unsure, say N. | 232 | If unsure, say N. |
205 | 233 | ||
234 | config SATA_SVW | ||
235 | tristate "ServerWorks Frodo / Apple K2 SATA support" | ||
236 | depends on PCI | ||
237 | help | ||
238 | This option enables support for Broadcom/Serverworks/Apple K2 | ||
239 | SATA support. | ||
240 | |||
241 | If unsure, say N. | ||
242 | |||
206 | config SATA_ULI | 243 | config SATA_ULI |
207 | tristate "ULi Electronics SATA support" | 244 | tristate "ULi Electronics SATA support" |
208 | depends on PCI | 245 | depends on PCI |
@@ -227,14 +264,7 @@ config SATA_VITESSE | |||
227 | 264 | ||
228 | If unsure, say N. | 265 | If unsure, say N. |
229 | 266 | ||
230 | config PATA_ACPI | 267 | comment "PATA SFF controllers with BMDMA" |
231 | tristate "ACPI firmware driver for PATA" | ||
232 | depends on ATA_ACPI | ||
233 | help | ||
234 | This option enables an ACPI method driver which drives | ||
235 | motherboard PATA controller interfaces through the ACPI | ||
236 | firmware in the BIOS. This driver can sometimes handle | ||
237 | otherwise unsupported hardware. | ||
238 | 268 | ||
239 | config PATA_ALI | 269 | config PATA_ALI |
240 | tristate "ALi PATA support" | 270 | tristate "ALi PATA support" |
@@ -262,40 +292,30 @@ config PATA_ARTOP | |||
262 | 292 | ||
263 | If unsure, say N. | 293 | If unsure, say N. |
264 | 294 | ||
265 | config PATA_ATP867X | 295 | config PATA_ATIIXP |
266 | tristate "ARTOP/Acard ATP867X PATA support" | 296 | tristate "ATI PATA support" |
267 | depends on PCI | 297 | depends on PCI |
268 | help | 298 | help |
269 | This option enables support for ARTOP/Acard ATP867X PATA | 299 | This option enables support for the ATI ATA interfaces |
270 | controllers. | 300 | found on the many ATI chipsets. |
271 | |||
272 | If unsure, say N. | ||
273 | |||
274 | config PATA_AT32 | ||
275 | tristate "Atmel AVR32 PATA support (Experimental)" | ||
276 | depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL | ||
277 | help | ||
278 | This option enables support for the IDE devices on the | ||
279 | Atmel AT32AP platform. | ||
280 | 301 | ||
281 | If unsure, say N. | 302 | If unsure, say N. |
282 | 303 | ||
283 | config PATA_ATIIXP | 304 | config PATA_ATP867X |
284 | tristate "ATI PATA support" | 305 | tristate "ARTOP/Acard ATP867X PATA support" |
285 | depends on PCI | 306 | depends on PCI |
286 | help | 307 | help |
287 | This option enables support for the ATI ATA interfaces | 308 | This option enables support for ARTOP/Acard ATP867X PATA |
288 | found on the many ATI chipsets. | 309 | controllers. |
289 | 310 | ||
290 | If unsure, say N. | 311 | If unsure, say N. |
291 | 312 | ||
292 | config PATA_CMD640_PCI | 313 | config PATA_BF54X |
293 | tristate "CMD640 PCI PATA support (Experimental)" | 314 | tristate "Blackfin 54x ATAPI support" |
294 | depends on PCI && EXPERIMENTAL | 315 | depends on BF542 || BF548 || BF549 |
295 | help | 316 | help |
296 | This option enables support for the CMD640 PCI IDE | 317 | This option enables support for the built-in ATAPI controller on |
297 | interface chip. Only the primary channel is currently | 318 | Blackfin 54x family chips. |
298 | supported. | ||
299 | 319 | ||
300 | If unsure, say N. | 320 | If unsure, say N. |
301 | 321 | ||
@@ -362,15 +382,6 @@ config PATA_EFAR | |||
362 | 382 | ||
363 | If unsure, say N. | 383 | If unsure, say N. |
364 | 384 | ||
365 | config ATA_GENERIC | ||
366 | tristate "Generic ATA support" | ||
367 | depends on PCI | ||
368 | help | ||
369 | This option enables support for generic BIOS configured | ||
370 | ATA controllers via the new ATA layer | ||
371 | |||
372 | If unsure, say N. | ||
373 | |||
374 | config PATA_HPT366 | 385 | config PATA_HPT366 |
375 | tristate "HPT 366/368 PATA support" | 386 | tristate "HPT 366/368 PATA support" |
376 | depends on PCI | 387 | depends on PCI |
@@ -415,12 +426,20 @@ config PATA_HPT3X3_DMA | |||
415 | controllers. Enable with care as there are still some | 426 | controllers. Enable with care as there are still some |
416 | problems with DMA on this chipset. | 427 | problems with DMA on this chipset. |
417 | 428 | ||
418 | config PATA_ISAPNP | 429 | config PATA_ICSIDE |
419 | tristate "ISA Plug and Play PATA support" | 430 | tristate "Acorn ICS PATA support" |
420 | depends on ISAPNP | 431 | depends on ARM && ARCH_ACORN |
421 | help | 432 | help |
422 | This option enables support for ISA plug & play ATA | 433 | On Acorn systems, say Y here if you wish to use the ICS PATA |
423 | controllers such as those found on old soundcards. | 434 | interface card. This is not required for ICS partition support. |
435 | If you are unsure, say N to this. | ||
436 | |||
437 | config PATA_IT8213 | ||
438 | tristate "IT8213 PATA support (Experimental)" | ||
439 | depends on PCI && EXPERIMENTAL | ||
440 | help | ||
441 | This option enables support for the ITE 821 PATA | ||
442 | controllers via the new ATA layer. | ||
424 | 443 | ||
425 | If unsure, say N. | 444 | If unsure, say N. |
426 | 445 | ||
@@ -434,15 +453,6 @@ config PATA_IT821X | |||
434 | 453 | ||
435 | If unsure, say N. | 454 | If unsure, say N. |
436 | 455 | ||
437 | config PATA_IT8213 | ||
438 | tristate "IT8213 PATA support (Experimental)" | ||
439 | depends on PCI && EXPERIMENTAL | ||
440 | help | ||
441 | This option enables support for the ITE 821 PATA | ||
442 | controllers via the new ATA layer. | ||
443 | |||
444 | If unsure, say N. | ||
445 | |||
446 | config PATA_JMICRON | 456 | config PATA_JMICRON |
447 | tristate "JMicron PATA support" | 457 | tristate "JMicron PATA support" |
448 | depends on PCI | 458 | depends on PCI |
@@ -452,23 +462,14 @@ config PATA_JMICRON | |||
452 | 462 | ||
453 | If unsure, say N. | 463 | If unsure, say N. |
454 | 464 | ||
455 | config PATA_LEGACY | 465 | config PATA_MACIO |
456 | tristate "Legacy ISA PATA support (Experimental)" | 466 | tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE" |
457 | depends on (ISA || PCI) && EXPERIMENTAL | 467 | depends on PPC_PMAC |
458 | help | ||
459 | This option enables support for ISA/VLB/PCI bus legacy PATA | ||
460 | ports and allows them to be accessed via the new ATA layer. | ||
461 | |||
462 | If unsure, say N. | ||
463 | |||
464 | config PATA_TRIFLEX | ||
465 | tristate "Compaq Triflex PATA support" | ||
466 | depends on PCI | ||
467 | help | 468 | help |
468 | Enable support for the Compaq 'Triflex' IDE controller as found | 469 | Most IDE capable PowerMacs have IDE busses driven by a variant |
469 | on many Compaq Pentium-Pro systems, via the new ATA layer. | 470 | of this controller which is part of the Apple chipset used on |
470 | 471 | most PowerMac models. Some models have multiple busses using | |
471 | If unsure, say N. | 472 | different chipsets, though generally, MacIO is one of them. |
472 | 473 | ||
473 | config PATA_MARVELL | 474 | config PATA_MARVELL |
474 | tristate "Marvell PATA support via legacy mode" | 475 | tristate "Marvell PATA support via legacy mode" |
@@ -481,32 +482,6 @@ config PATA_MARVELL | |||
481 | 482 | ||
482 | If unsure, say N. | 483 | If unsure, say N. |
483 | 484 | ||
484 | config PATA_MPC52xx | ||
485 | tristate "Freescale MPC52xx SoC internal IDE" | ||
486 | depends on PPC_MPC52xx && PPC_BESTCOMM | ||
487 | select PPC_BESTCOMM_ATA | ||
488 | help | ||
489 | This option enables support for integrated IDE controller | ||
490 | of the Freescale MPC52xx SoC. | ||
491 | |||
492 | If unsure, say N. | ||
493 | |||
494 | config PATA_MPIIX | ||
495 | tristate "Intel PATA MPIIX support" | ||
496 | depends on PCI | ||
497 | help | ||
498 | This option enables support for MPIIX PATA support. | ||
499 | |||
500 | If unsure, say N. | ||
501 | |||
502 | config PATA_OLDPIIX | ||
503 | tristate "Intel PATA old PIIX support" | ||
504 | depends on PCI | ||
505 | help | ||
506 | This option enables support for early PIIX PATA support. | ||
507 | |||
508 | If unsure, say N. | ||
509 | |||
510 | config PATA_NETCELL | 485 | config PATA_NETCELL |
511 | tristate "NETCELL Revolution RAID support" | 486 | tristate "NETCELL Revolution RAID support" |
512 | depends on PCI | 487 | depends on PCI |
@@ -525,15 +500,6 @@ config PATA_NINJA32 | |||
525 | 500 | ||
526 | If unsure, say N. | 501 | If unsure, say N. |
527 | 502 | ||
528 | config PATA_NS87410 | ||
529 | tristate "Nat Semi NS87410 PATA support" | ||
530 | depends on PCI | ||
531 | help | ||
532 | This option enables support for the National Semiconductor | ||
533 | NS87410 PCI-IDE controller. | ||
534 | |||
535 | If unsure, say N. | ||
536 | |||
537 | config PATA_NS87415 | 503 | config PATA_NS87415 |
538 | tristate "Nat Semi NS87415 PATA support" | 504 | tristate "Nat Semi NS87415 PATA support" |
539 | depends on PCI | 505 | depends on PCI |
@@ -543,12 +509,11 @@ config PATA_NS87415 | |||
543 | 509 | ||
544 | If unsure, say N. | 510 | If unsure, say N. |
545 | 511 | ||
546 | config PATA_OPTI | 512 | config PATA_OLDPIIX |
547 | tristate "OPTI621/6215 PATA support (Very Experimental)" | 513 | tristate "Intel PATA old PIIX support" |
548 | depends on PCI && EXPERIMENTAL | 514 | depends on PCI |
549 | help | 515 | help |
550 | This option enables full PIO support for the early Opti ATA | 516 | This option enables support for early PIIX PATA support. |
551 | controllers found on some old motherboards. | ||
552 | 517 | ||
553 | If unsure, say N. | 518 | If unsure, say N. |
554 | 519 | ||
@@ -562,24 +527,6 @@ config PATA_OPTIDMA | |||
562 | 527 | ||
563 | If unsure, say N. | 528 | If unsure, say N. |
564 | 529 | ||
565 | config PATA_PALMLD | ||
566 | tristate "Palm LifeDrive PATA support" | ||
567 | depends on MACH_PALMLD | ||
568 | help | ||
569 | This option enables support for Palm LifeDrive's internal ATA | ||
570 | port via the new ATA layer. | ||
571 | |||
572 | If unsure, say N. | ||
573 | |||
574 | config PATA_PCMCIA | ||
575 | tristate "PCMCIA PATA support" | ||
576 | depends on PCMCIA | ||
577 | help | ||
578 | This option enables support for PCMCIA ATA interfaces, including | ||
579 | compact flash card adapters via the new ATA layer. | ||
580 | |||
581 | If unsure, say N. | ||
582 | |||
583 | config PATA_PDC2027X | 530 | config PATA_PDC2027X |
584 | tristate "Promise PATA 2027x support" | 531 | tristate "Promise PATA 2027x support" |
585 | depends on PCI | 532 | depends on PCI |
@@ -597,12 +544,6 @@ config PATA_PDC_OLD | |||
597 | 544 | ||
598 | If unsure, say N. | 545 | If unsure, say N. |
599 | 546 | ||
600 | config PATA_QDI | ||
601 | tristate "QDI VLB PATA support" | ||
602 | depends on ISA | ||
603 | help | ||
604 | Support for QDI 6500 and 6580 PATA controllers on VESA local bus. | ||
605 | |||
606 | config PATA_RADISYS | 547 | config PATA_RADISYS |
607 | tristate "RADISYS 82600 PATA support (Experimental)" | 548 | tristate "RADISYS 82600 PATA support (Experimental)" |
608 | depends on PCI && EXPERIMENTAL | 549 | depends on PCI && EXPERIMENTAL |
@@ -612,15 +553,6 @@ config PATA_RADISYS | |||
612 | 553 | ||
613 | If unsure, say N. | 554 | If unsure, say N. |
614 | 555 | ||
615 | config PATA_RB532 | ||
616 | tristate "RouterBoard 532 PATA CompactFlash support" | ||
617 | depends on MIKROTIK_RB532 | ||
618 | help | ||
619 | This option enables support for the RouterBoard 532 | ||
620 | PATA CompactFlash controller. | ||
621 | |||
622 | If unsure, say N. | ||
623 | |||
624 | config PATA_RDC | 556 | config PATA_RDC |
625 | tristate "RDC PATA support" | 557 | tristate "RDC PATA support" |
626 | depends on PCI | 558 | depends on PCI |
@@ -631,21 +563,30 @@ config PATA_RDC | |||
631 | 563 | ||
632 | If unsure, say N. | 564 | If unsure, say N. |
633 | 565 | ||
634 | config PATA_RZ1000 | 566 | config PATA_SC1200 |
635 | tristate "PC Tech RZ1000 PATA support" | 567 | tristate "SC1200 PATA support" |
636 | depends on PCI | 568 | depends on PCI |
637 | help | 569 | help |
638 | This option enables basic support for the PC Tech RZ1000/1 | 570 | This option enables support for the NatSemi/AMD SC1200 SoC |
639 | PATA controllers via the new ATA layer | 571 | companion chip used with the Geode processor family. |
640 | 572 | ||
641 | If unsure, say N. | 573 | If unsure, say N. |
642 | 574 | ||
643 | config PATA_SC1200 | 575 | config PATA_SCC |
644 | tristate "SC1200 PATA support" | 576 | tristate "Toshiba's Cell Reference Set IDE support" |
577 | depends on PCI && PPC_CELLEB | ||
578 | help | ||
579 | This option enables support for the built-in IDE controller on | ||
580 | Toshiba Cell Reference Board. | ||
581 | |||
582 | If unsure, say N. | ||
583 | |||
584 | config PATA_SCH | ||
585 | tristate "Intel SCH PATA support" | ||
645 | depends on PCI | 586 | depends on PCI |
646 | help | 587 | help |
647 | This option enables support for the NatSemi/AMD SC1200 SoC | 588 | This option enables support for Intel SCH PATA on the Intel |
648 | companion chip used with the Geode processor family. | 589 | SCH (US15W, US15L, UL11L) series host controllers. |
649 | 590 | ||
650 | If unsure, say N. | 591 | If unsure, say N. |
651 | 592 | ||
@@ -683,6 +624,15 @@ config PATA_TOSHIBA | |||
683 | 624 | ||
684 | If unsure, say N. | 625 | If unsure, say N. |
685 | 626 | ||
627 | config PATA_TRIFLEX | ||
628 | tristate "Compaq Triflex PATA support" | ||
629 | depends on PCI | ||
630 | help | ||
631 | Enable support for the Compaq 'Triflex' IDE controller as found | ||
632 | on many Compaq Pentium-Pro systems, via the new ATA layer. | ||
633 | |||
634 | If unsure, say N. | ||
635 | |||
686 | config PATA_VIA | 636 | config PATA_VIA |
687 | tristate "VIA PATA support" | 637 | tristate "VIA PATA support" |
688 | depends on PCI | 638 | depends on PCI |
@@ -701,12 +651,99 @@ config PATA_WINBOND | |||
701 | 651 | ||
702 | If unsure, say N. | 652 | If unsure, say N. |
703 | 653 | ||
704 | config PATA_WINBOND_VLB | 654 | endif # ATA_BMDMA |
705 | tristate "Winbond W83759A VLB PATA support (Experimental)" | 655 | |
706 | depends on ISA && EXPERIMENTAL | 656 | comment "PIO-only SFF controllers" |
657 | |||
658 | config PATA_AT32 | ||
659 | tristate "Atmel AVR32 PATA support (Experimental)" | ||
660 | depends on AVR32 && PLATFORM_AT32AP && EXPERIMENTAL | ||
707 | help | 661 | help |
708 | Support for the Winbond W83759A controller on Vesa Local Bus | 662 | This option enables support for the IDE devices on the |
709 | systems. | 663 | Atmel AT32AP platform. |
664 | |||
665 | If unsure, say N. | ||
666 | |||
667 | config PATA_AT91 | ||
668 | tristate "PATA support for AT91SAM9260" | ||
669 | depends on ARM && ARCH_AT91 | ||
670 | help | ||
671 | This option enables support for IDE devices on the Atmel AT91SAM9260 SoC. | ||
672 | |||
673 | If unsure, say N. | ||
674 | |||
675 | config PATA_CMD640_PCI | ||
676 | tristate "CMD640 PCI PATA support (Experimental)" | ||
677 | depends on PCI && EXPERIMENTAL | ||
678 | help | ||
679 | This option enables support for the CMD640 PCI IDE | ||
680 | interface chip. Only the primary channel is currently | ||
681 | supported. | ||
682 | |||
683 | If unsure, say N. | ||
684 | |||
685 | config PATA_ISAPNP | ||
686 | tristate "ISA Plug and Play PATA support" | ||
687 | depends on ISAPNP | ||
688 | help | ||
689 | This option enables support for ISA plug & play ATA | ||
690 | controllers such as those found on old soundcards. | ||
691 | |||
692 | If unsure, say N. | ||
693 | |||
694 | config PATA_IXP4XX_CF | ||
695 | tristate "IXP4XX Compact Flash support" | ||
696 | depends on ARCH_IXP4XX | ||
697 | help | ||
698 | This option enables support for a Compact Flash connected on | ||
699 | the ixp4xx expansion bus. This driver had been written for | ||
700 | Loft/Avila boards in mind but can work with others. | ||
701 | |||
702 | If unsure, say N. | ||
703 | |||
704 | config PATA_MPIIX | ||
705 | tristate "Intel PATA MPIIX support" | ||
706 | depends on PCI | ||
707 | help | ||
708 | This option enables support for MPIIX PATA support. | ||
709 | |||
710 | If unsure, say N. | ||
711 | |||
712 | config PATA_NS87410 | ||
713 | tristate "Nat Semi NS87410 PATA support" | ||
714 | depends on PCI | ||
715 | help | ||
716 | This option enables support for the National Semiconductor | ||
717 | NS87410 PCI-IDE controller. | ||
718 | |||
719 | If unsure, say N. | ||
720 | |||
721 | config PATA_OPTI | ||
722 | tristate "OPTI621/6215 PATA support (Very Experimental)" | ||
723 | depends on PCI && EXPERIMENTAL | ||
724 | help | ||
725 | This option enables full PIO support for the early Opti ATA | ||
726 | controllers found on some old motherboards. | ||
727 | |||
728 | If unsure, say N. | ||
729 | |||
730 | config PATA_PALMLD | ||
731 | tristate "Palm LifeDrive PATA support" | ||
732 | depends on MACH_PALMLD | ||
733 | help | ||
734 | This option enables support for Palm LifeDrive's internal ATA | ||
735 | port via the new ATA layer. | ||
736 | |||
737 | If unsure, say N. | ||
738 | |||
739 | config PATA_PCMCIA | ||
740 | tristate "PCMCIA PATA support" | ||
741 | depends on PCMCIA | ||
742 | help | ||
743 | This option enables support for PCMCIA ATA interfaces, including | ||
744 | compact flash card adapters via the new ATA layer. | ||
745 | |||
746 | If unsure, say N. | ||
710 | 747 | ||
711 | config HAVE_PATA_PLATFORM | 748 | config HAVE_PATA_PLATFORM |
712 | bool | 749 | bool |
@@ -725,14 +762,6 @@ config PATA_PLATFORM | |||
725 | 762 | ||
726 | If unsure, say N. | 763 | If unsure, say N. |
727 | 764 | ||
728 | config PATA_AT91 | ||
729 | tristate "PATA support for AT91SAM9260" | ||
730 | depends on ARM && ARCH_AT91 | ||
731 | help | ||
732 | This option enables support for IDE devices on the Atmel AT91SAM9260 SoC. | ||
733 | |||
734 | If unsure, say N. | ||
735 | |||
736 | config PATA_OF_PLATFORM | 765 | config PATA_OF_PLATFORM |
737 | tristate "OpenFirmware platform device PATA support" | 766 | tristate "OpenFirmware platform device PATA support" |
738 | depends on PATA_PLATFORM && PPC_OF | 767 | depends on PATA_PLATFORM && PPC_OF |
@@ -743,69 +772,65 @@ config PATA_OF_PLATFORM | |||
743 | 772 | ||
744 | If unsure, say N. | 773 | If unsure, say N. |
745 | 774 | ||
746 | config PATA_ICSIDE | 775 | config PATA_QDI |
747 | tristate "Acorn ICS PATA support" | 776 | tristate "QDI VLB PATA support" |
748 | depends on ARM && ARCH_ACORN | 777 | depends on ISA |
749 | help | 778 | help |
750 | On Acorn systems, say Y here if you wish to use the ICS PATA | 779 | Support for QDI 6500 and 6580 PATA controllers on VESA local bus. |
751 | interface card. This is not required for ICS partition support. | ||
752 | If you are unsure, say N to this. | ||
753 | 780 | ||
754 | config PATA_IXP4XX_CF | 781 | config PATA_RB532 |
755 | tristate "IXP4XX Compact Flash support" | 782 | tristate "RouterBoard 532 PATA CompactFlash support" |
756 | depends on ARCH_IXP4XX | 783 | depends on MIKROTIK_RB532 |
757 | help | 784 | help |
758 | This option enables support for a Compact Flash connected on | 785 | This option enables support for the RouterBoard 532 |
759 | the ixp4xx expansion bus. This driver had been written for | 786 | PATA CompactFlash controller. |
760 | Loft/Avila boards in mind but can work with others. | ||
761 | 787 | ||
762 | If unsure, say N. | 788 | If unsure, say N. |
763 | 789 | ||
764 | config PATA_OCTEON_CF | 790 | config PATA_RZ1000 |
765 | tristate "OCTEON Boot Bus Compact Flash support" | 791 | tristate "PC Tech RZ1000 PATA support" |
766 | depends on CPU_CAVIUM_OCTEON | 792 | depends on PCI |
767 | help | 793 | help |
768 | This option enables a polled compact flash driver for use with | 794 | This option enables basic support for the PC Tech RZ1000/1 |
769 | compact flash cards attached to the OCTEON boot bus. | 795 | PATA controllers via the new ATA layer |
770 | 796 | ||
771 | If unsure, say N. | 797 | If unsure, say N. |
772 | 798 | ||
773 | config PATA_SCC | 799 | config PATA_WINBOND_VLB |
774 | tristate "Toshiba's Cell Reference Set IDE support" | 800 | tristate "Winbond W83759A VLB PATA support (Experimental)" |
775 | depends on PCI && PPC_CELLEB | 801 | depends on ISA && EXPERIMENTAL |
776 | help | 802 | help |
777 | This option enables support for the built-in IDE controller on | 803 | Support for the Winbond W83759A controller on Vesa Local Bus |
778 | Toshiba Cell Reference Board. | 804 | systems. |
779 | 805 | ||
780 | If unsure, say N. | 806 | comment "Generic fallback / legacy drivers" |
781 | 807 | ||
782 | config PATA_SCH | 808 | config PATA_ACPI |
783 | tristate "Intel SCH PATA support" | 809 | tristate "ACPI firmware driver for PATA" |
784 | depends on PCI | 810 | depends on ATA_ACPI && ATA_BMDMA |
785 | help | 811 | help |
786 | This option enables support for Intel SCH PATA on the Intel | 812 | This option enables an ACPI method driver which drives |
787 | SCH (US15W, US15L, UL11L) series host controllers. | 813 | motherboard PATA controller interfaces through the ACPI |
788 | 814 | firmware in the BIOS. This driver can sometimes handle | |
789 | If unsure, say N. | 815 | otherwise unsupported hardware. |
790 | 816 | ||
791 | config PATA_BF54X | 817 | config ATA_GENERIC |
792 | tristate "Blackfin 54x ATAPI support" | 818 | tristate "Generic ATA support" |
793 | depends on BF542 || BF548 || BF549 | 819 | depends on PCI && ATA_BMDMA |
794 | help | 820 | help |
795 | This option enables support for the built-in ATAPI controller on | 821 | This option enables support for generic BIOS configured |
796 | Blackfin 54x family chips. | 822 | ATA controllers via the new ATA layer |
797 | 823 | ||
798 | If unsure, say N. | 824 | If unsure, say N. |
799 | 825 | ||
800 | config PATA_MACIO | 826 | config PATA_LEGACY |
801 | tristate "Apple PowerMac/PowerBook internal 'MacIO' IDE" | 827 | tristate "Legacy ISA PATA support (Experimental)" |
802 | depends on PPC_PMAC | 828 | depends on (ISA || PCI) && EXPERIMENTAL |
803 | help | 829 | help |
804 | Most IDE capable PowerMacs have IDE busses driven by a variant | 830 | This option enables support for ISA/VLB/PCI bus legacy PATA |
805 | of this controller which is part of the Apple chipset used on | 831 | ports and allows them to be accessed via the new ATA layer. |
806 | most PowerMac models. Some models have multiple busses using | ||
807 | different chipsets, though generally, MacIO is one of them. | ||
808 | 832 | ||
833 | If unsure, say N. | ||
809 | 834 | ||
810 | endif # ATA_SFF | 835 | endif # ATA_SFF |
811 | endif # ATA | 836 | endif # ATA |
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index d0a93c4ad3ec..7ef89d73df63 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile | |||
@@ -1,33 +1,39 @@ | |||
1 | 1 | ||
2 | obj-$(CONFIG_ATA) += libata.o | 2 | obj-$(CONFIG_ATA) += libata.o |
3 | 3 | ||
4 | # non-SFF interface | ||
4 | obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o | 5 | obj-$(CONFIG_SATA_AHCI) += ahci.o libahci.o |
5 | obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o | 6 | obj-$(CONFIG_SATA_AHCI_PLATFORM) += ahci_platform.o libahci.o |
6 | obj-$(CONFIG_SATA_SVW) += sata_svw.o | 7 | obj-$(CONFIG_SATA_FSL) += sata_fsl.o |
8 | obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o | ||
9 | obj-$(CONFIG_SATA_SIL24) += sata_sil24.o | ||
10 | |||
11 | # SFF w/ custom DMA | ||
12 | obj-$(CONFIG_PDC_ADMA) += pdc_adma.o | ||
13 | obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o | ||
14 | obj-$(CONFIG_PATA_OCTEON_CF) += pata_octeon_cf.o | ||
15 | obj-$(CONFIG_SATA_QSTOR) += sata_qstor.o | ||
16 | obj-$(CONFIG_SATA_SX4) += sata_sx4.o | ||
17 | |||
18 | # SFF SATA w/ BMDMA | ||
7 | obj-$(CONFIG_ATA_PIIX) += ata_piix.o | 19 | obj-$(CONFIG_ATA_PIIX) += ata_piix.o |
20 | obj-$(CONFIG_SATA_MV) += sata_mv.o | ||
21 | obj-$(CONFIG_SATA_NV) += sata_nv.o | ||
8 | obj-$(CONFIG_SATA_PROMISE) += sata_promise.o | 22 | obj-$(CONFIG_SATA_PROMISE) += sata_promise.o |
9 | obj-$(CONFIG_SATA_QSTOR) += sata_qstor.o | ||
10 | obj-$(CONFIG_SATA_SIL) += sata_sil.o | 23 | obj-$(CONFIG_SATA_SIL) += sata_sil.o |
11 | obj-$(CONFIG_SATA_SIL24) += sata_sil24.o | ||
12 | obj-$(CONFIG_SATA_VIA) += sata_via.o | ||
13 | obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o | ||
14 | obj-$(CONFIG_SATA_SIS) += sata_sis.o | 24 | obj-$(CONFIG_SATA_SIS) += sata_sis.o |
15 | obj-$(CONFIG_SATA_SX4) += sata_sx4.o | 25 | obj-$(CONFIG_SATA_SVW) += sata_svw.o |
16 | obj-$(CONFIG_SATA_NV) += sata_nv.o | ||
17 | obj-$(CONFIG_SATA_ULI) += sata_uli.o | 26 | obj-$(CONFIG_SATA_ULI) += sata_uli.o |
18 | obj-$(CONFIG_SATA_MV) += sata_mv.o | 27 | obj-$(CONFIG_SATA_VIA) += sata_via.o |
19 | obj-$(CONFIG_SATA_INIC162X) += sata_inic162x.o | 28 | obj-$(CONFIG_SATA_VITESSE) += sata_vsc.o |
20 | obj-$(CONFIG_PDC_ADMA) += pdc_adma.o | ||
21 | obj-$(CONFIG_SATA_FSL) += sata_fsl.o | ||
22 | obj-$(CONFIG_PATA_MACIO) += pata_macio.o | ||
23 | 29 | ||
30 | # SFF PATA w/ BMDMA | ||
24 | obj-$(CONFIG_PATA_ALI) += pata_ali.o | 31 | obj-$(CONFIG_PATA_ALI) += pata_ali.o |
25 | obj-$(CONFIG_PATA_AMD) += pata_amd.o | 32 | obj-$(CONFIG_PATA_AMD) += pata_amd.o |
26 | obj-$(CONFIG_PATA_ARTOP) += pata_artop.o | 33 | obj-$(CONFIG_PATA_ARTOP) += pata_artop.o |
27 | obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o | ||
28 | obj-$(CONFIG_PATA_AT32) += pata_at32.o | ||
29 | obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o | 34 | obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o |
30 | obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o | 35 | obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o |
36 | obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o | ||
31 | obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o | 37 | obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o |
32 | obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o | 38 | obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o |
33 | obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o | 39 | obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o |
@@ -39,47 +45,50 @@ obj-$(CONFIG_PATA_HPT366) += pata_hpt366.o | |||
39 | obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o | 45 | obj-$(CONFIG_PATA_HPT37X) += pata_hpt37x.o |
40 | obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o | 46 | obj-$(CONFIG_PATA_HPT3X2N) += pata_hpt3x2n.o |
41 | obj-$(CONFIG_PATA_HPT3X3) += pata_hpt3x3.o | 47 | obj-$(CONFIG_PATA_HPT3X3) += pata_hpt3x3.o |
42 | obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o | 48 | obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o |
43 | obj-$(CONFIG_PATA_IT821X) += pata_it821x.o | ||
44 | obj-$(CONFIG_PATA_IT8213) += pata_it8213.o | 49 | obj-$(CONFIG_PATA_IT8213) += pata_it8213.o |
50 | obj-$(CONFIG_PATA_IT821X) += pata_it821x.o | ||
45 | obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o | 51 | obj-$(CONFIG_PATA_JMICRON) += pata_jmicron.o |
52 | obj-$(CONFIG_PATA_MACIO) += pata_macio.o | ||
53 | obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o | ||
46 | obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o | 54 | obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o |
47 | obj-$(CONFIG_PATA_NINJA32) += pata_ninja32.o | 55 | obj-$(CONFIG_PATA_NINJA32) += pata_ninja32.o |
48 | obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o | ||
49 | obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o | 56 | obj-$(CONFIG_PATA_NS87415) += pata_ns87415.o |
50 | obj-$(CONFIG_PATA_OPTI) += pata_opti.o | ||
51 | obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o | ||
52 | obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o | ||
53 | obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o | ||
54 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o | ||
55 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o | 57 | obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o |
56 | obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o | 58 | obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o |
57 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o | ||
58 | obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o | 59 | obj-$(CONFIG_PATA_PDC2027X) += pata_pdc2027x.o |
59 | obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o | 60 | obj-$(CONFIG_PATA_PDC_OLD) += pata_pdc202xx_old.o |
60 | obj-$(CONFIG_PATA_QDI) += pata_qdi.o | ||
61 | obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o | 61 | obj-$(CONFIG_PATA_RADISYS) += pata_radisys.o |
62 | obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o | ||
63 | obj-$(CONFIG_PATA_RDC) += pata_rdc.o | 62 | obj-$(CONFIG_PATA_RDC) += pata_rdc.o |
64 | obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o | ||
65 | obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o | 63 | obj-$(CONFIG_PATA_SC1200) += pata_sc1200.o |
64 | obj-$(CONFIG_PATA_SCC) += pata_scc.o | ||
65 | obj-$(CONFIG_PATA_SCH) += pata_sch.o | ||
66 | obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o | 66 | obj-$(CONFIG_PATA_SERVERWORKS) += pata_serverworks.o |
67 | obj-$(CONFIG_PATA_SIL680) += pata_sil680.o | 67 | obj-$(CONFIG_PATA_SIL680) += pata_sil680.o |
68 | obj-$(CONFIG_PATA_SIS) += pata_sis.o | ||
68 | obj-$(CONFIG_PATA_TOSHIBA) += pata_piccolo.o | 69 | obj-$(CONFIG_PATA_TOSHIBA) += pata_piccolo.o |
70 | obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o | ||
69 | obj-$(CONFIG_PATA_VIA) += pata_via.o | 71 | obj-$(CONFIG_PATA_VIA) += pata_via.o |
70 | obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o | 72 | obj-$(CONFIG_PATA_WINBOND) += pata_sl82c105.o |
71 | obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o | 73 | |
72 | obj-$(CONFIG_PATA_SIS) += pata_sis.o | 74 | # SFF PIO only |
73 | obj-$(CONFIG_PATA_TRIFLEX) += pata_triflex.o | 75 | obj-$(CONFIG_PATA_AT32) += pata_at32.o |
76 | obj-$(CONFIG_PATA_AT91) += pata_at91.o | ||
77 | obj-$(CONFIG_PATA_CMD640_PCI) += pata_cmd640.o | ||
78 | obj-$(CONFIG_PATA_ISAPNP) += pata_isapnp.o | ||
74 | obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o | 79 | obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o |
75 | obj-$(CONFIG_PATA_SCC) += pata_scc.o | 80 | obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o |
76 | obj-$(CONFIG_PATA_SCH) += pata_sch.o | 81 | obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o |
77 | obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o | 82 | obj-$(CONFIG_PATA_OPTI) += pata_opti.o |
78 | obj-$(CONFIG_PATA_OCTEON_CF) += pata_octeon_cf.o | 83 | obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o |
84 | obj-$(CONFIG_PATA_PALMLD) += pata_palmld.o | ||
79 | obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o | 85 | obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o |
80 | obj-$(CONFIG_PATA_AT91) += pata_at91.o | ||
81 | obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o | 86 | obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o |
82 | obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o | 87 | obj-$(CONFIG_PATA_QDI) += pata_qdi.o |
88 | obj-$(CONFIG_PATA_RB532) += pata_rb532_cf.o | ||
89 | obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o | ||
90 | obj-$(CONFIG_PATA_WINBOND_VLB) += pata_winbond.o | ||
91 | |||
83 | # Should be last but two libata driver | 92 | # Should be last but two libata driver |
84 | obj-$(CONFIG_PATA_ACPI) += pata_acpi.o | 93 | obj-$(CONFIG_PATA_ACPI) += pata_acpi.o |
85 | # Should be last but one libata driver | 94 | # Should be last but one libata driver |
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 33fb614f9784..573158a9668d 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c | |||
@@ -155,7 +155,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id | |||
155 | return rc; | 155 | return rc; |
156 | pcim_pin_device(dev); | 156 | pcim_pin_device(dev); |
157 | } | 157 | } |
158 | return ata_pci_sff_init_one(dev, ppi, &generic_sht, NULL, 0); | 158 | return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, NULL, 0); |
159 | } | 159 | } |
160 | 160 | ||
161 | static struct pci_device_id ata_generic[] = { | 161 | static struct pci_device_id ata_generic[] = { |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index ec52fc618763..7409f98d2ae6 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -1589,7 +1589,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
1589 | hpriv->map = piix_init_sata_map(pdev, port_info, | 1589 | hpriv->map = piix_init_sata_map(pdev, port_info, |
1590 | piix_map_db_table[ent->driver_data]); | 1590 | piix_map_db_table[ent->driver_data]); |
1591 | 1591 | ||
1592 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | 1592 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); |
1593 | if (rc) | 1593 | if (rc) |
1594 | return rc; | 1594 | return rc; |
1595 | host->private_data = hpriv; | 1595 | host->private_data = hpriv; |
@@ -1626,7 +1626,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
1626 | host->flags |= ATA_HOST_PARALLEL_SCAN; | 1626 | host->flags |= ATA_HOST_PARALLEL_SCAN; |
1627 | 1627 | ||
1628 | pci_set_master(pdev); | 1628 | pci_set_master(pdev); |
1629 | return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht); | 1629 | return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &piix_sht); |
1630 | } | 1630 | } |
1631 | 1631 | ||
1632 | static void piix_remove_one(struct pci_dev *pdev) | 1632 | static void piix_remove_one(struct pci_dev *pdev) |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c47373f01f89..06b7e49e039c 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -160,6 +160,10 @@ int libata_allow_tpm = 0; | |||
160 | module_param_named(allow_tpm, libata_allow_tpm, int, 0444); | 160 | module_param_named(allow_tpm, libata_allow_tpm, int, 0444); |
161 | MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)"); | 161 | MODULE_PARM_DESC(allow_tpm, "Permit the use of TPM commands (0=off [default], 1=on)"); |
162 | 162 | ||
163 | static int atapi_an; | ||
164 | module_param(atapi_an, int, 0444); | ||
165 | MODULE_PARM_DESC(atapi_an, "Enable ATAPI AN media presence notification (0=0ff [default], 1=on)"); | ||
166 | |||
163 | MODULE_AUTHOR("Jeff Garzik"); | 167 | MODULE_AUTHOR("Jeff Garzik"); |
164 | MODULE_DESCRIPTION("Library module for ATA devices"); | 168 | MODULE_DESCRIPTION("Library module for ATA devices"); |
165 | MODULE_LICENSE("GPL"); | 169 | MODULE_LICENSE("GPL"); |
@@ -2122,6 +2126,14 @@ retry: | |||
2122 | goto err_out; | 2126 | goto err_out; |
2123 | } | 2127 | } |
2124 | 2128 | ||
2129 | if (dev->horkage & ATA_HORKAGE_DUMP_ID) { | ||
2130 | ata_dev_printk(dev, KERN_DEBUG, "dumping IDENTIFY data, " | ||
2131 | "class=%d may_fallback=%d tried_spinup=%d\n", | ||
2132 | class, may_fallback, tried_spinup); | ||
2133 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, | ||
2134 | 16, 2, id, ATA_ID_WORDS * sizeof(*id), true); | ||
2135 | } | ||
2136 | |||
2125 | /* Falling back doesn't make sense if ID data was read | 2137 | /* Falling back doesn't make sense if ID data was read |
2126 | * successfully at least once. | 2138 | * successfully at least once. |
2127 | */ | 2139 | */ |
@@ -2510,7 +2522,8 @@ int ata_dev_configure(struct ata_device *dev) | |||
2510 | * to enable ATAPI AN to discern between PHY status | 2522 | * to enable ATAPI AN to discern between PHY status |
2511 | * changed notifications and ATAPI ANs. | 2523 | * changed notifications and ATAPI ANs. |
2512 | */ | 2524 | */ |
2513 | if ((ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) && | 2525 | if (atapi_an && |
2526 | (ap->flags & ATA_FLAG_AN) && ata_id_has_atapi_AN(id) && | ||
2514 | (!sata_pmp_attached(ap) || | 2527 | (!sata_pmp_attached(ap) || |
2515 | sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) { | 2528 | sata_scr_read(&ap->link, SCR_NOTIFICATION, &sntf) == 0)) { |
2516 | unsigned int err_mask; | 2529 | unsigned int err_mask; |
@@ -6372,6 +6385,7 @@ static int __init ata_parse_force_one(char **cur, | |||
6372 | { "3.0Gbps", .spd_limit = 2 }, | 6385 | { "3.0Gbps", .spd_limit = 2 }, |
6373 | { "noncq", .horkage_on = ATA_HORKAGE_NONCQ }, | 6386 | { "noncq", .horkage_on = ATA_HORKAGE_NONCQ }, |
6374 | { "ncq", .horkage_off = ATA_HORKAGE_NONCQ }, | 6387 | { "ncq", .horkage_off = ATA_HORKAGE_NONCQ }, |
6388 | { "dump_id", .horkage_on = ATA_HORKAGE_DUMP_ID }, | ||
6375 | { "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) }, | 6389 | { "pio0", .xfer_mask = 1 << (ATA_SHIFT_PIO + 0) }, |
6376 | { "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) }, | 6390 | { "pio1", .xfer_mask = 1 << (ATA_SHIFT_PIO + 1) }, |
6377 | { "pio2", .xfer_mask = 1 << (ATA_SHIFT_PIO + 2) }, | 6391 | { "pio2", .xfer_mask = 1 << (ATA_SHIFT_PIO + 2) }, |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 19ddf924944f..efa4a18cfb9d 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
@@ -63,7 +63,6 @@ const struct ata_port_operations ata_sff_port_ops = { | |||
63 | .sff_tf_read = ata_sff_tf_read, | 63 | .sff_tf_read = ata_sff_tf_read, |
64 | .sff_exec_command = ata_sff_exec_command, | 64 | .sff_exec_command = ata_sff_exec_command, |
65 | .sff_data_xfer = ata_sff_data_xfer, | 65 | .sff_data_xfer = ata_sff_data_xfer, |
66 | .sff_irq_clear = ata_sff_irq_clear, | ||
67 | .sff_drain_fifo = ata_sff_drain_fifo, | 66 | .sff_drain_fifo = ata_sff_drain_fifo, |
68 | 67 | ||
69 | .lost_interrupt = ata_sff_lost_interrupt, | 68 | .lost_interrupt = ata_sff_lost_interrupt, |
@@ -395,33 +394,12 @@ void ata_sff_irq_on(struct ata_port *ap) | |||
395 | ata_sff_set_devctl(ap, ap->ctl); | 394 | ata_sff_set_devctl(ap, ap->ctl); |
396 | ata_wait_idle(ap); | 395 | ata_wait_idle(ap); |
397 | 396 | ||
398 | ap->ops->sff_irq_clear(ap); | 397 | if (ap->ops->sff_irq_clear) |
398 | ap->ops->sff_irq_clear(ap); | ||
399 | } | 399 | } |
400 | EXPORT_SYMBOL_GPL(ata_sff_irq_on); | 400 | EXPORT_SYMBOL_GPL(ata_sff_irq_on); |
401 | 401 | ||
402 | /** | 402 | /** |
403 | * ata_sff_irq_clear - Clear PCI IDE BMDMA interrupt. | ||
404 | * @ap: Port associated with this ATA transaction. | ||
405 | * | ||
406 | * Clear interrupt and error flags in DMA status register. | ||
407 | * | ||
408 | * May be used as the irq_clear() entry in ata_port_operations. | ||
409 | * | ||
410 | * LOCKING: | ||
411 | * spin_lock_irqsave(host lock) | ||
412 | */ | ||
413 | void ata_sff_irq_clear(struct ata_port *ap) | ||
414 | { | ||
415 | void __iomem *mmio = ap->ioaddr.bmdma_addr; | ||
416 | |||
417 | if (!mmio) | ||
418 | return; | ||
419 | |||
420 | iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS); | ||
421 | } | ||
422 | EXPORT_SYMBOL_GPL(ata_sff_irq_clear); | ||
423 | |||
424 | /** | ||
425 | * ata_sff_tf_load - send taskfile registers to host controller | 403 | * ata_sff_tf_load - send taskfile registers to host controller |
426 | * @ap: Port to which output is sent | 404 | * @ap: Port to which output is sent |
427 | * @tf: ATA taskfile register set | 405 | * @tf: ATA taskfile register set |
@@ -820,11 +798,15 @@ static void atapi_send_cdb(struct ata_port *ap, struct ata_queued_cmd *qc) | |||
820 | case ATAPI_PROT_NODATA: | 798 | case ATAPI_PROT_NODATA: |
821 | ap->hsm_task_state = HSM_ST_LAST; | 799 | ap->hsm_task_state = HSM_ST_LAST; |
822 | break; | 800 | break; |
801 | #ifdef CONFIG_ATA_BMDMA | ||
823 | case ATAPI_PROT_DMA: | 802 | case ATAPI_PROT_DMA: |
824 | ap->hsm_task_state = HSM_ST_LAST; | 803 | ap->hsm_task_state = HSM_ST_LAST; |
825 | /* initiate bmdma */ | 804 | /* initiate bmdma */ |
826 | ap->ops->bmdma_start(qc); | 805 | ap->ops->bmdma_start(qc); |
827 | break; | 806 | break; |
807 | #endif /* CONFIG_ATA_BMDMA */ | ||
808 | default: | ||
809 | BUG(); | ||
828 | } | 810 | } |
829 | } | 811 | } |
830 | 812 | ||
@@ -1491,27 +1473,27 @@ bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc) | |||
1491 | } | 1473 | } |
1492 | EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); | 1474 | EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); |
1493 | 1475 | ||
1494 | /** | 1476 | static unsigned int ata_sff_idle_irq(struct ata_port *ap) |
1495 | * ata_sff_host_intr - Handle host interrupt for given (port, task) | ||
1496 | * @ap: Port on which interrupt arrived (possibly...) | ||
1497 | * @qc: Taskfile currently active in engine | ||
1498 | * | ||
1499 | * Handle host interrupt for given queued command. Currently, | ||
1500 | * only DMA interrupts are handled. All other commands are | ||
1501 | * handled via polling with interrupts disabled (nIEN bit). | ||
1502 | * | ||
1503 | * LOCKING: | ||
1504 | * spin_lock_irqsave(host lock) | ||
1505 | * | ||
1506 | * RETURNS: | ||
1507 | * One if interrupt was handled, zero if not (shared irq). | ||
1508 | */ | ||
1509 | unsigned int ata_sff_host_intr(struct ata_port *ap, | ||
1510 | struct ata_queued_cmd *qc) | ||
1511 | { | 1477 | { |
1512 | struct ata_eh_info *ehi = &ap->link.eh_info; | 1478 | ap->stats.idle_irq++; |
1513 | u8 status, host_stat = 0; | 1479 | |
1514 | bool bmdma_stopped = false; | 1480 | #ifdef ATA_IRQ_TRAP |
1481 | if ((ap->stats.idle_irq % 1000) == 0) { | ||
1482 | ap->ops->sff_check_status(ap); | ||
1483 | if (ap->ops->sff_irq_clear) | ||
1484 | ap->ops->sff_irq_clear(ap); | ||
1485 | ata_port_printk(ap, KERN_WARNING, "irq trap\n"); | ||
1486 | return 1; | ||
1487 | } | ||
1488 | #endif | ||
1489 | return 0; /* irq not handled */ | ||
1490 | } | ||
1491 | |||
1492 | static unsigned int __ata_sff_port_intr(struct ata_port *ap, | ||
1493 | struct ata_queued_cmd *qc, | ||
1494 | bool hsmv_on_idle) | ||
1495 | { | ||
1496 | u8 status; | ||
1515 | 1497 | ||
1516 | VPRINTK("ata%u: protocol %d task_state %d\n", | 1498 | VPRINTK("ata%u: protocol %d task_state %d\n", |
1517 | ap->print_id, qc->tf.protocol, ap->hsm_task_state); | 1499 | ap->print_id, qc->tf.protocol, ap->hsm_task_state); |
@@ -1528,90 +1510,56 @@ unsigned int ata_sff_host_intr(struct ata_port *ap, | |||
1528 | * need to check ata_is_atapi(qc->tf.protocol) again. | 1510 | * need to check ata_is_atapi(qc->tf.protocol) again. |
1529 | */ | 1511 | */ |
1530 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) | 1512 | if (!(qc->dev->flags & ATA_DFLAG_CDB_INTR)) |
1531 | goto idle_irq; | 1513 | return ata_sff_idle_irq(ap); |
1532 | break; | ||
1533 | case HSM_ST_LAST: | ||
1534 | if (qc->tf.protocol == ATA_PROT_DMA || | ||
1535 | qc->tf.protocol == ATAPI_PROT_DMA) { | ||
1536 | /* check status of DMA engine */ | ||
1537 | host_stat = ap->ops->bmdma_status(ap); | ||
1538 | VPRINTK("ata%u: host_stat 0x%X\n", | ||
1539 | ap->print_id, host_stat); | ||
1540 | |||
1541 | /* if it's not our irq... */ | ||
1542 | if (!(host_stat & ATA_DMA_INTR)) | ||
1543 | goto idle_irq; | ||
1544 | |||
1545 | /* before we do anything else, clear DMA-Start bit */ | ||
1546 | ap->ops->bmdma_stop(qc); | ||
1547 | bmdma_stopped = true; | ||
1548 | |||
1549 | if (unlikely(host_stat & ATA_DMA_ERR)) { | ||
1550 | /* error when transfering data to/from memory */ | ||
1551 | qc->err_mask |= AC_ERR_HOST_BUS; | ||
1552 | ap->hsm_task_state = HSM_ST_ERR; | ||
1553 | } | ||
1554 | } | ||
1555 | break; | 1514 | break; |
1556 | case HSM_ST: | 1515 | case HSM_ST: |
1516 | case HSM_ST_LAST: | ||
1557 | break; | 1517 | break; |
1558 | default: | 1518 | default: |
1559 | goto idle_irq; | 1519 | return ata_sff_idle_irq(ap); |
1560 | } | 1520 | } |
1561 | 1521 | ||
1562 | |||
1563 | /* check main status, clearing INTRQ if needed */ | 1522 | /* check main status, clearing INTRQ if needed */ |
1564 | status = ata_sff_irq_status(ap); | 1523 | status = ata_sff_irq_status(ap); |
1565 | if (status & ATA_BUSY) { | 1524 | if (status & ATA_BUSY) { |
1566 | if (bmdma_stopped) { | 1525 | if (hsmv_on_idle) { |
1567 | /* BMDMA engine is already stopped, we're screwed */ | 1526 | /* BMDMA engine is already stopped, we're screwed */ |
1568 | qc->err_mask |= AC_ERR_HSM; | 1527 | qc->err_mask |= AC_ERR_HSM; |
1569 | ap->hsm_task_state = HSM_ST_ERR; | 1528 | ap->hsm_task_state = HSM_ST_ERR; |
1570 | } else | 1529 | } else |
1571 | goto idle_irq; | 1530 | return ata_sff_idle_irq(ap); |
1572 | } | 1531 | } |
1573 | 1532 | ||
1574 | /* clear irq events */ | 1533 | /* clear irq events */ |
1575 | ap->ops->sff_irq_clear(ap); | 1534 | if (ap->ops->sff_irq_clear) |
1535 | ap->ops->sff_irq_clear(ap); | ||
1576 | 1536 | ||
1577 | ata_sff_hsm_move(ap, qc, status, 0); | 1537 | ata_sff_hsm_move(ap, qc, status, 0); |
1578 | 1538 | ||
1579 | if (unlikely(qc->err_mask) && (qc->tf.protocol == ATA_PROT_DMA || | ||
1580 | qc->tf.protocol == ATAPI_PROT_DMA)) | ||
1581 | ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); | ||
1582 | |||
1583 | return 1; /* irq handled */ | 1539 | return 1; /* irq handled */ |
1584 | |||
1585 | idle_irq: | ||
1586 | ap->stats.idle_irq++; | ||
1587 | |||
1588 | #ifdef ATA_IRQ_TRAP | ||
1589 | if ((ap->stats.idle_irq % 1000) == 0) { | ||
1590 | ap->ops->sff_check_status(ap); | ||
1591 | ap->ops->sff_irq_clear(ap); | ||
1592 | ata_port_printk(ap, KERN_WARNING, "irq trap\n"); | ||
1593 | return 1; | ||
1594 | } | ||
1595 | #endif | ||
1596 | return 0; /* irq not handled */ | ||
1597 | } | 1540 | } |
1598 | EXPORT_SYMBOL_GPL(ata_sff_host_intr); | ||
1599 | 1541 | ||
1600 | /** | 1542 | /** |
1601 | * ata_sff_interrupt - Default ATA host interrupt handler | 1543 | * ata_sff_port_intr - Handle SFF port interrupt |
1602 | * @irq: irq line (unused) | 1544 | * @ap: Port on which interrupt arrived (possibly...) |
1603 | * @dev_instance: pointer to our ata_host information structure | 1545 | * @qc: Taskfile currently active in engine |
1604 | * | 1546 | * |
1605 | * Default interrupt handler for PCI IDE devices. Calls | 1547 | * Handle port interrupt for given queued command. |
1606 | * ata_sff_host_intr() for each port that is not disabled. | ||
1607 | * | 1548 | * |
1608 | * LOCKING: | 1549 | * LOCKING: |
1609 | * Obtains host lock during operation. | 1550 | * spin_lock_irqsave(host lock) |
1610 | * | 1551 | * |
1611 | * RETURNS: | 1552 | * RETURNS: |
1612 | * IRQ_NONE or IRQ_HANDLED. | 1553 | * One if interrupt was handled, zero if not (shared irq). |
1613 | */ | 1554 | */ |
1614 | irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) | 1555 | unsigned int ata_sff_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc) |
1556 | { | ||
1557 | return __ata_sff_port_intr(ap, qc, false); | ||
1558 | } | ||
1559 | EXPORT_SYMBOL_GPL(ata_sff_port_intr); | ||
1560 | |||
1561 | static inline irqreturn_t __ata_sff_interrupt(int irq, void *dev_instance, | ||
1562 | unsigned int (*port_intr)(struct ata_port *, struct ata_queued_cmd *)) | ||
1615 | { | 1563 | { |
1616 | struct ata_host *host = dev_instance; | 1564 | struct ata_host *host = dev_instance; |
1617 | bool retried = false; | 1565 | bool retried = false; |
@@ -1631,7 +1579,7 @@ retry: | |||
1631 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | 1579 | qc = ata_qc_from_tag(ap, ap->link.active_tag); |
1632 | if (qc) { | 1580 | if (qc) { |
1633 | if (!(qc->tf.flags & ATA_TFLAG_POLLING)) | 1581 | if (!(qc->tf.flags & ATA_TFLAG_POLLING)) |
1634 | handled |= ata_sff_host_intr(ap, qc); | 1582 | handled |= port_intr(ap, qc); |
1635 | else | 1583 | else |
1636 | polling |= 1 << i; | 1584 | polling |= 1 << i; |
1637 | } else | 1585 | } else |
@@ -1658,7 +1606,8 @@ retry: | |||
1658 | 1606 | ||
1659 | if (idle & (1 << i)) { | 1607 | if (idle & (1 << i)) { |
1660 | ap->ops->sff_check_status(ap); | 1608 | ap->ops->sff_check_status(ap); |
1661 | ap->ops->sff_irq_clear(ap); | 1609 | if (ap->ops->sff_irq_clear) |
1610 | ap->ops->sff_irq_clear(ap); | ||
1662 | } else { | 1611 | } else { |
1663 | /* clear INTRQ and check if BUSY cleared */ | 1612 | /* clear INTRQ and check if BUSY cleared */ |
1664 | if (!(ap->ops->sff_check_status(ap) & ATA_BUSY)) | 1613 | if (!(ap->ops->sff_check_status(ap) & ATA_BUSY)) |
@@ -1680,6 +1629,25 @@ retry: | |||
1680 | 1629 | ||
1681 | return IRQ_RETVAL(handled); | 1630 | return IRQ_RETVAL(handled); |
1682 | } | 1631 | } |
1632 | |||
1633 | /** | ||
1634 | * ata_sff_interrupt - Default SFF ATA host interrupt handler | ||
1635 | * @irq: irq line (unused) | ||
1636 | * @dev_instance: pointer to our ata_host information structure | ||
1637 | * | ||
1638 | * Default interrupt handler for PCI IDE devices. Calls | ||
1639 | * ata_sff_port_intr() for each port that is not disabled. | ||
1640 | * | ||
1641 | * LOCKING: | ||
1642 | * Obtains host lock during operation. | ||
1643 | * | ||
1644 | * RETURNS: | ||
1645 | * IRQ_NONE or IRQ_HANDLED. | ||
1646 | */ | ||
1647 | irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) | ||
1648 | { | ||
1649 | return __ata_sff_interrupt(irq, dev_instance, ata_sff_port_intr); | ||
1650 | } | ||
1683 | EXPORT_SYMBOL_GPL(ata_sff_interrupt); | 1651 | EXPORT_SYMBOL_GPL(ata_sff_interrupt); |
1684 | 1652 | ||
1685 | /** | 1653 | /** |
@@ -1717,7 +1685,7 @@ void ata_sff_lost_interrupt(struct ata_port *ap) | |||
1717 | status); | 1685 | status); |
1718 | /* Run the host interrupt logic as if the interrupt had not been | 1686 | /* Run the host interrupt logic as if the interrupt had not been |
1719 | lost */ | 1687 | lost */ |
1720 | ata_sff_host_intr(ap, qc); | 1688 | ata_sff_port_intr(ap, qc); |
1721 | } | 1689 | } |
1722 | EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); | 1690 | EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); |
1723 | 1691 | ||
@@ -1744,7 +1712,8 @@ void ata_sff_freeze(struct ata_port *ap) | |||
1744 | */ | 1712 | */ |
1745 | ap->ops->sff_check_status(ap); | 1713 | ap->ops->sff_check_status(ap); |
1746 | 1714 | ||
1747 | ap->ops->sff_irq_clear(ap); | 1715 | if (ap->ops->sff_irq_clear) |
1716 | ap->ops->sff_irq_clear(ap); | ||
1748 | } | 1717 | } |
1749 | EXPORT_SYMBOL_GPL(ata_sff_freeze); | 1718 | EXPORT_SYMBOL_GPL(ata_sff_freeze); |
1750 | 1719 | ||
@@ -1761,7 +1730,8 @@ void ata_sff_thaw(struct ata_port *ap) | |||
1761 | { | 1730 | { |
1762 | /* clear & re-enable interrupts */ | 1731 | /* clear & re-enable interrupts */ |
1763 | ap->ops->sff_check_status(ap); | 1732 | ap->ops->sff_check_status(ap); |
1764 | ap->ops->sff_irq_clear(ap); | 1733 | if (ap->ops->sff_irq_clear) |
1734 | ap->ops->sff_irq_clear(ap); | ||
1765 | ata_sff_irq_on(ap); | 1735 | ata_sff_irq_on(ap); |
1766 | } | 1736 | } |
1767 | EXPORT_SYMBOL_GPL(ata_sff_thaw); | 1737 | EXPORT_SYMBOL_GPL(ata_sff_thaw); |
@@ -2349,13 +2319,13 @@ int ata_pci_sff_init_host(struct ata_host *host) | |||
2349 | EXPORT_SYMBOL_GPL(ata_pci_sff_init_host); | 2319 | EXPORT_SYMBOL_GPL(ata_pci_sff_init_host); |
2350 | 2320 | ||
2351 | /** | 2321 | /** |
2352 | * ata_pci_sff_prepare_host - helper to prepare native PCI ATA host | 2322 | * ata_pci_sff_prepare_host - helper to prepare PCI PIO-only SFF ATA host |
2353 | * @pdev: target PCI device | 2323 | * @pdev: target PCI device |
2354 | * @ppi: array of port_info, must be enough for two ports | 2324 | * @ppi: array of port_info, must be enough for two ports |
2355 | * @r_host: out argument for the initialized ATA host | 2325 | * @r_host: out argument for the initialized ATA host |
2356 | * | 2326 | * |
2357 | * Helper to allocate ATA host for @pdev, acquire all native PCI | 2327 | * Helper to allocate PIO-only SFF ATA host for @pdev, acquire |
2358 | * resources and initialize it accordingly in one go. | 2328 | * all PCI resources and initialize it accordingly in one go. |
2359 | * | 2329 | * |
2360 | * LOCKING: | 2330 | * LOCKING: |
2361 | * Inherited from calling layer (may sleep). | 2331 | * Inherited from calling layer (may sleep). |
@@ -2385,9 +2355,6 @@ int ata_pci_sff_prepare_host(struct pci_dev *pdev, | |||
2385 | if (rc) | 2355 | if (rc) |
2386 | goto err_out; | 2356 | goto err_out; |
2387 | 2357 | ||
2388 | /* init DMA related stuff */ | ||
2389 | ata_pci_bmdma_init(host); | ||
2390 | |||
2391 | devres_remove_group(&pdev->dev, NULL); | 2358 | devres_remove_group(&pdev->dev, NULL); |
2392 | *r_host = host; | 2359 | *r_host = host; |
2393 | return 0; | 2360 | return 0; |
@@ -2492,8 +2459,21 @@ out: | |||
2492 | } | 2459 | } |
2493 | EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host); | 2460 | EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host); |
2494 | 2461 | ||
2462 | static const struct ata_port_info *ata_sff_find_valid_pi( | ||
2463 | const struct ata_port_info * const *ppi) | ||
2464 | { | ||
2465 | int i; | ||
2466 | |||
2467 | /* look up the first valid port_info */ | ||
2468 | for (i = 0; i < 2 && ppi[i]; i++) | ||
2469 | if (ppi[i]->port_ops != &ata_dummy_port_ops) | ||
2470 | return ppi[i]; | ||
2471 | |||
2472 | return NULL; | ||
2473 | } | ||
2474 | |||
2495 | /** | 2475 | /** |
2496 | * ata_pci_sff_init_one - Initialize/register PCI IDE host controller | 2476 | * ata_pci_sff_init_one - Initialize/register PIO-only PCI IDE controller |
2497 | * @pdev: Controller to be initialized | 2477 | * @pdev: Controller to be initialized |
2498 | * @ppi: array of port_info, must be enough for two ports | 2478 | * @ppi: array of port_info, must be enough for two ports |
2499 | * @sht: scsi_host_template to use when registering the host | 2479 | * @sht: scsi_host_template to use when registering the host |
@@ -2502,11 +2482,7 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_activate_host); | |||
2502 | * | 2482 | * |
2503 | * This is a helper function which can be called from a driver's | 2483 | * This is a helper function which can be called from a driver's |
2504 | * xxx_init_one() probe function if the hardware uses traditional | 2484 | * xxx_init_one() probe function if the hardware uses traditional |
2505 | * IDE taskfile registers. | 2485 | * IDE taskfile registers and is PIO only. |
2506 | * | ||
2507 | * This function calls pci_enable_device(), reserves its register | ||
2508 | * regions, sets the dma mask, enables bus master mode, and calls | ||
2509 | * ata_device_add() | ||
2510 | * | 2486 | * |
2511 | * ASSUMPTION: | 2487 | * ASSUMPTION: |
2512 | * Nobody makes a single channel controller that appears solely as | 2488 | * Nobody makes a single channel controller that appears solely as |
@@ -2523,20 +2499,13 @@ int ata_pci_sff_init_one(struct pci_dev *pdev, | |||
2523 | struct scsi_host_template *sht, void *host_priv, int hflag) | 2499 | struct scsi_host_template *sht, void *host_priv, int hflag) |
2524 | { | 2500 | { |
2525 | struct device *dev = &pdev->dev; | 2501 | struct device *dev = &pdev->dev; |
2526 | const struct ata_port_info *pi = NULL; | 2502 | const struct ata_port_info *pi; |
2527 | struct ata_host *host = NULL; | 2503 | struct ata_host *host = NULL; |
2528 | int i, rc; | 2504 | int rc; |
2529 | 2505 | ||
2530 | DPRINTK("ENTER\n"); | 2506 | DPRINTK("ENTER\n"); |
2531 | 2507 | ||
2532 | /* look up the first valid port_info */ | 2508 | pi = ata_sff_find_valid_pi(ppi); |
2533 | for (i = 0; i < 2 && ppi[i]; i++) { | ||
2534 | if (ppi[i]->port_ops != &ata_dummy_port_ops) { | ||
2535 | pi = ppi[i]; | ||
2536 | break; | ||
2537 | } | ||
2538 | } | ||
2539 | |||
2540 | if (!pi) { | 2509 | if (!pi) { |
2541 | dev_printk(KERN_ERR, &pdev->dev, | 2510 | dev_printk(KERN_ERR, &pdev->dev, |
2542 | "no valid port_info specified\n"); | 2511 | "no valid port_info specified\n"); |
@@ -2557,7 +2526,6 @@ int ata_pci_sff_init_one(struct pci_dev *pdev, | |||
2557 | host->private_data = host_priv; | 2526 | host->private_data = host_priv; |
2558 | host->flags |= hflag; | 2527 | host->flags |= hflag; |
2559 | 2528 | ||
2560 | pci_set_master(pdev); | ||
2561 | rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); | 2529 | rc = ata_pci_sff_activate_host(host, ata_sff_interrupt, sht); |
2562 | out: | 2530 | out: |
2563 | if (rc == 0) | 2531 | if (rc == 0) |
@@ -2571,6 +2539,12 @@ EXPORT_SYMBOL_GPL(ata_pci_sff_init_one); | |||
2571 | 2539 | ||
2572 | #endif /* CONFIG_PCI */ | 2540 | #endif /* CONFIG_PCI */ |
2573 | 2541 | ||
2542 | /* | ||
2543 | * BMDMA support | ||
2544 | */ | ||
2545 | |||
2546 | #ifdef CONFIG_ATA_BMDMA | ||
2547 | |||
2574 | const struct ata_port_operations ata_bmdma_port_ops = { | 2548 | const struct ata_port_operations ata_bmdma_port_ops = { |
2575 | .inherits = &ata_sff_port_ops, | 2549 | .inherits = &ata_sff_port_ops, |
2576 | 2550 | ||
@@ -2580,6 +2554,7 @@ const struct ata_port_operations ata_bmdma_port_ops = { | |||
2580 | .qc_prep = ata_bmdma_qc_prep, | 2554 | .qc_prep = ata_bmdma_qc_prep, |
2581 | .qc_issue = ata_bmdma_qc_issue, | 2555 | .qc_issue = ata_bmdma_qc_issue, |
2582 | 2556 | ||
2557 | .sff_irq_clear = ata_bmdma_irq_clear, | ||
2583 | .bmdma_setup = ata_bmdma_setup, | 2558 | .bmdma_setup = ata_bmdma_setup, |
2584 | .bmdma_start = ata_bmdma_start, | 2559 | .bmdma_start = ata_bmdma_start, |
2585 | .bmdma_stop = ata_bmdma_stop, | 2560 | .bmdma_stop = ata_bmdma_stop, |
@@ -2804,6 +2779,75 @@ unsigned int ata_bmdma_qc_issue(struct ata_queued_cmd *qc) | |||
2804 | EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue); | 2779 | EXPORT_SYMBOL_GPL(ata_bmdma_qc_issue); |
2805 | 2780 | ||
2806 | /** | 2781 | /** |
2782 | * ata_bmdma_port_intr - Handle BMDMA port interrupt | ||
2783 | * @ap: Port on which interrupt arrived (possibly...) | ||
2784 | * @qc: Taskfile currently active in engine | ||
2785 | * | ||
2786 | * Handle port interrupt for given queued command. | ||
2787 | * | ||
2788 | * LOCKING: | ||
2789 | * spin_lock_irqsave(host lock) | ||
2790 | * | ||
2791 | * RETURNS: | ||
2792 | * One if interrupt was handled, zero if not (shared irq). | ||
2793 | */ | ||
2794 | unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc) | ||
2795 | { | ||
2796 | struct ata_eh_info *ehi = &ap->link.eh_info; | ||
2797 | u8 host_stat = 0; | ||
2798 | bool bmdma_stopped = false; | ||
2799 | unsigned int handled; | ||
2800 | |||
2801 | if (ap->hsm_task_state == HSM_ST_LAST && ata_is_dma(qc->tf.protocol)) { | ||
2802 | /* check status of DMA engine */ | ||
2803 | host_stat = ap->ops->bmdma_status(ap); | ||
2804 | VPRINTK("ata%u: host_stat 0x%X\n", ap->print_id, host_stat); | ||
2805 | |||
2806 | /* if it's not our irq... */ | ||
2807 | if (!(host_stat & ATA_DMA_INTR)) | ||
2808 | return ata_sff_idle_irq(ap); | ||
2809 | |||
2810 | /* before we do anything else, clear DMA-Start bit */ | ||
2811 | ap->ops->bmdma_stop(qc); | ||
2812 | bmdma_stopped = true; | ||
2813 | |||
2814 | if (unlikely(host_stat & ATA_DMA_ERR)) { | ||
2815 | /* error when transfering data to/from memory */ | ||
2816 | qc->err_mask |= AC_ERR_HOST_BUS; | ||
2817 | ap->hsm_task_state = HSM_ST_ERR; | ||
2818 | } | ||
2819 | } | ||
2820 | |||
2821 | handled = __ata_sff_port_intr(ap, qc, bmdma_stopped); | ||
2822 | |||
2823 | if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol)) | ||
2824 | ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat); | ||
2825 | |||
2826 | return handled; | ||
2827 | } | ||
2828 | EXPORT_SYMBOL_GPL(ata_bmdma_port_intr); | ||
2829 | |||
2830 | /** | ||
2831 | * ata_bmdma_interrupt - Default BMDMA ATA host interrupt handler | ||
2832 | * @irq: irq line (unused) | ||
2833 | * @dev_instance: pointer to our ata_host information structure | ||
2834 | * | ||
2835 | * Default interrupt handler for PCI IDE devices. Calls | ||
2836 | * ata_bmdma_port_intr() for each port that is not disabled. | ||
2837 | * | ||
2838 | * LOCKING: | ||
2839 | * Obtains host lock during operation. | ||
2840 | * | ||
2841 | * RETURNS: | ||
2842 | * IRQ_NONE or IRQ_HANDLED. | ||
2843 | */ | ||
2844 | irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance) | ||
2845 | { | ||
2846 | return __ata_sff_interrupt(irq, dev_instance, ata_bmdma_port_intr); | ||
2847 | } | ||
2848 | EXPORT_SYMBOL_GPL(ata_bmdma_interrupt); | ||
2849 | |||
2850 | /** | ||
2807 | * ata_bmdma_error_handler - Stock error handler for BMDMA controller | 2851 | * ata_bmdma_error_handler - Stock error handler for BMDMA controller |
2808 | * @ap: port to handle error for | 2852 | * @ap: port to handle error for |
2809 | * | 2853 | * |
@@ -2848,7 +2892,8 @@ void ata_bmdma_error_handler(struct ata_port *ap) | |||
2848 | /* if we're gonna thaw, make sure IRQ is clear */ | 2892 | /* if we're gonna thaw, make sure IRQ is clear */ |
2849 | if (thaw) { | 2893 | if (thaw) { |
2850 | ap->ops->sff_check_status(ap); | 2894 | ap->ops->sff_check_status(ap); |
2851 | ap->ops->sff_irq_clear(ap); | 2895 | if (ap->ops->sff_irq_clear) |
2896 | ap->ops->sff_irq_clear(ap); | ||
2852 | } | 2897 | } |
2853 | } | 2898 | } |
2854 | 2899 | ||
@@ -2882,6 +2927,28 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc) | |||
2882 | EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd); | 2927 | EXPORT_SYMBOL_GPL(ata_bmdma_post_internal_cmd); |
2883 | 2928 | ||
2884 | /** | 2929 | /** |
2930 | * ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt. | ||
2931 | * @ap: Port associated with this ATA transaction. | ||
2932 | * | ||
2933 | * Clear interrupt and error flags in DMA status register. | ||
2934 | * | ||
2935 | * May be used as the irq_clear() entry in ata_port_operations. | ||
2936 | * | ||
2937 | * LOCKING: | ||
2938 | * spin_lock_irqsave(host lock) | ||
2939 | */ | ||
2940 | void ata_bmdma_irq_clear(struct ata_port *ap) | ||
2941 | { | ||
2942 | void __iomem *mmio = ap->ioaddr.bmdma_addr; | ||
2943 | |||
2944 | if (!mmio) | ||
2945 | return; | ||
2946 | |||
2947 | iowrite8(ioread8(mmio + ATA_DMA_STATUS), mmio + ATA_DMA_STATUS); | ||
2948 | } | ||
2949 | EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); | ||
2950 | |||
2951 | /** | ||
2885 | * ata_bmdma_setup - Set up PCI IDE BMDMA transaction | 2952 | * ata_bmdma_setup - Set up PCI IDE BMDMA transaction |
2886 | * @qc: Info associated with this ATA transaction. | 2953 | * @qc: Info associated with this ATA transaction. |
2887 | * | 2954 | * |
@@ -3137,7 +3204,100 @@ void ata_pci_bmdma_init(struct ata_host *host) | |||
3137 | } | 3204 | } |
3138 | EXPORT_SYMBOL_GPL(ata_pci_bmdma_init); | 3205 | EXPORT_SYMBOL_GPL(ata_pci_bmdma_init); |
3139 | 3206 | ||
3207 | /** | ||
3208 | * ata_pci_bmdma_prepare_host - helper to prepare PCI BMDMA ATA host | ||
3209 | * @pdev: target PCI device | ||
3210 | * @ppi: array of port_info, must be enough for two ports | ||
3211 | * @r_host: out argument for the initialized ATA host | ||
3212 | * | ||
3213 | * Helper to allocate BMDMA ATA host for @pdev, acquire all PCI | ||
3214 | * resources and initialize it accordingly in one go. | ||
3215 | * | ||
3216 | * LOCKING: | ||
3217 | * Inherited from calling layer (may sleep). | ||
3218 | * | ||
3219 | * RETURNS: | ||
3220 | * 0 on success, -errno otherwise. | ||
3221 | */ | ||
3222 | int ata_pci_bmdma_prepare_host(struct pci_dev *pdev, | ||
3223 | const struct ata_port_info * const * ppi, | ||
3224 | struct ata_host **r_host) | ||
3225 | { | ||
3226 | int rc; | ||
3227 | |||
3228 | rc = ata_pci_sff_prepare_host(pdev, ppi, r_host); | ||
3229 | if (rc) | ||
3230 | return rc; | ||
3231 | |||
3232 | ata_pci_bmdma_init(*r_host); | ||
3233 | return 0; | ||
3234 | } | ||
3235 | EXPORT_SYMBOL_GPL(ata_pci_bmdma_prepare_host); | ||
3236 | |||
3237 | /** | ||
3238 | * ata_pci_bmdma_init_one - Initialize/register BMDMA PCI IDE controller | ||
3239 | * @pdev: Controller to be initialized | ||
3240 | * @ppi: array of port_info, must be enough for two ports | ||
3241 | * @sht: scsi_host_template to use when registering the host | ||
3242 | * @host_priv: host private_data | ||
3243 | * @hflags: host flags | ||
3244 | * | ||
3245 | * This function is similar to ata_pci_sff_init_one() but also | ||
3246 | * takes care of BMDMA initialization. | ||
3247 | * | ||
3248 | * LOCKING: | ||
3249 | * Inherited from PCI layer (may sleep). | ||
3250 | * | ||
3251 | * RETURNS: | ||
3252 | * Zero on success, negative on errno-based value on error. | ||
3253 | */ | ||
3254 | int ata_pci_bmdma_init_one(struct pci_dev *pdev, | ||
3255 | const struct ata_port_info * const * ppi, | ||
3256 | struct scsi_host_template *sht, void *host_priv, | ||
3257 | int hflags) | ||
3258 | { | ||
3259 | struct device *dev = &pdev->dev; | ||
3260 | const struct ata_port_info *pi; | ||
3261 | struct ata_host *host = NULL; | ||
3262 | int rc; | ||
3263 | |||
3264 | DPRINTK("ENTER\n"); | ||
3265 | |||
3266 | pi = ata_sff_find_valid_pi(ppi); | ||
3267 | if (!pi) { | ||
3268 | dev_printk(KERN_ERR, &pdev->dev, | ||
3269 | "no valid port_info specified\n"); | ||
3270 | return -EINVAL; | ||
3271 | } | ||
3272 | |||
3273 | if (!devres_open_group(dev, NULL, GFP_KERNEL)) | ||
3274 | return -ENOMEM; | ||
3275 | |||
3276 | rc = pcim_enable_device(pdev); | ||
3277 | if (rc) | ||
3278 | goto out; | ||
3279 | |||
3280 | /* prepare and activate BMDMA host */ | ||
3281 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); | ||
3282 | if (rc) | ||
3283 | goto out; | ||
3284 | host->private_data = host_priv; | ||
3285 | host->flags |= hflags; | ||
3286 | |||
3287 | pci_set_master(pdev); | ||
3288 | rc = ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); | ||
3289 | out: | ||
3290 | if (rc == 0) | ||
3291 | devres_remove_group(&pdev->dev, NULL); | ||
3292 | else | ||
3293 | devres_release_group(&pdev->dev, NULL); | ||
3294 | |||
3295 | return rc; | ||
3296 | } | ||
3297 | EXPORT_SYMBOL_GPL(ata_pci_bmdma_init_one); | ||
3298 | |||
3140 | #endif /* CONFIG_PCI */ | 3299 | #endif /* CONFIG_PCI */ |
3300 | #endif /* CONFIG_ATA_BMDMA */ | ||
3141 | 3301 | ||
3142 | /** | 3302 | /** |
3143 | * ata_sff_port_init - Initialize SFF/BMDMA ATA port | 3303 | * ata_sff_port_init - Initialize SFF/BMDMA ATA port |
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 066b9f301ed5..c8d47034d5e9 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c | |||
@@ -260,7 +260,7 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id) | |||
260 | return rc; | 260 | return rc; |
261 | pcim_pin_device(pdev); | 261 | pcim_pin_device(pdev); |
262 | } | 262 | } |
263 | return ata_pci_sff_init_one(pdev, ppi, &pacpi_sht, NULL, 0); | 263 | return ata_pci_bmdma_init_one(pdev, ppi, &pacpi_sht, NULL, 0); |
264 | } | 264 | } |
265 | 265 | ||
266 | static const struct pci_device_id pacpi_pci_tbl[] = { | 266 | static const struct pci_device_id pacpi_pci_tbl[] = { |
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index f306e10c748d..794ec6e3275d 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c | |||
@@ -583,7 +583,10 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
583 | ppi[0] = &info_20_udma; | 583 | ppi[0] = &info_20_udma; |
584 | } | 584 | } |
585 | 585 | ||
586 | return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0); | 586 | if (!ppi[0]->mwdma_mask && !ppi[0]->udma_mask) |
587 | return ata_pci_sff_init_one(pdev, ppi, &ali_sht, NULL, 0); | ||
588 | else | ||
589 | return ata_pci_bmdma_init_one(pdev, ppi, &ali_sht, NULL, 0); | ||
587 | } | 590 | } |
588 | 591 | ||
589 | #ifdef CONFIG_PM | 592 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index d95eca9c547e..620a07cabe31 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c | |||
@@ -574,7 +574,7 @@ static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
574 | } | 574 | } |
575 | 575 | ||
576 | /* And fire it up */ | 576 | /* And fire it up */ |
577 | return ata_pci_sff_init_one(pdev, ppi, &amd_sht, hpriv, 0); | 577 | return ata_pci_bmdma_init_one(pdev, ppi, &amd_sht, hpriv, 0); |
578 | } | 578 | } |
579 | 579 | ||
580 | #ifdef CONFIG_PM | 580 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 4d066d6c30fa..ba43f0f8c880 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c | |||
@@ -421,7 +421,7 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) | |||
421 | 421 | ||
422 | BUG_ON(ppi[0] == NULL); | 422 | BUG_ON(ppi[0] == NULL); |
423 | 423 | ||
424 | return ata_pci_sff_init_one(pdev, ppi, &artop_sht, NULL, 0); | 424 | return ata_pci_bmdma_init_one(pdev, ppi, &artop_sht, NULL, 0); |
425 | } | 425 | } |
426 | 426 | ||
427 | static const struct pci_device_id artop_pci_tbl[] = { | 427 | static const struct pci_device_id artop_pci_tbl[] = { |
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 44d88b380ddd..43755616dc5a 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c | |||
@@ -246,8 +246,8 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
246 | if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i])) | 246 | if (!pci_test_config_bits(pdev, &atiixp_enable_bits[i])) |
247 | ppi[i] = &ata_dummy_port_info; | 247 | ppi[i] = &ata_dummy_port_info; |
248 | 248 | ||
249 | return ata_pci_sff_init_one(pdev, ppi, &atiixp_sht, NULL, | 249 | return ata_pci_bmdma_init_one(pdev, ppi, &atiixp_sht, NULL, |
250 | ATA_HOST_PARALLEL_SCAN); | 250 | ATA_HOST_PARALLEL_SCAN); |
251 | } | 251 | } |
252 | 252 | ||
253 | static const struct pci_device_id atiixp[] = { | 253 | static const struct pci_device_id atiixp[] = { |
diff --git a/drivers/ata/pata_atp867x.c b/drivers/ata/pata_atp867x.c index bb6e0746e07d..95295935dd95 100644 --- a/drivers/ata/pata_atp867x.c +++ b/drivers/ata/pata_atp867x.c | |||
@@ -525,7 +525,7 @@ static int atp867x_init_one(struct pci_dev *pdev, | |||
525 | 525 | ||
526 | pci_set_master(pdev); | 526 | pci_set_master(pdev); |
527 | 527 | ||
528 | rc = ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 528 | rc = ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
529 | IRQF_SHARED, &atp867x_sht); | 529 | IRQF_SHARED, &atp867x_sht); |
530 | if (rc) | 530 | if (rc) |
531 | dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n"); | 531 | dev_printk(KERN_ERR, &pdev->dev, "failed to activate host\n"); |
diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 6422cfd13d0d..9cae65de750e 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c | |||
@@ -1214,7 +1214,7 @@ static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf, | |||
1214 | * bfin_irq_clear - Clear ATAPI interrupt. | 1214 | * bfin_irq_clear - Clear ATAPI interrupt. |
1215 | * @ap: Port associated with this ATA transaction. | 1215 | * @ap: Port associated with this ATA transaction. |
1216 | * | 1216 | * |
1217 | * Note: Original code is ata_sff_irq_clear(). | 1217 | * Note: Original code is ata_bmdma_irq_clear(). |
1218 | */ | 1218 | */ |
1219 | 1219 | ||
1220 | static void bfin_irq_clear(struct ata_port *ap) | 1220 | static void bfin_irq_clear(struct ata_port *ap) |
diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 4c81a71b8877..9f5da1c7454b 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c | |||
@@ -367,7 +367,7 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
367 | pci_write_config_byte(pdev, UDIDETCR0, 0xF0); | 367 | pci_write_config_byte(pdev, UDIDETCR0, 0xF0); |
368 | #endif | 368 | #endif |
369 | 369 | ||
370 | return ata_pci_sff_init_one(pdev, ppi, &cmd64x_sht, NULL, 0); | 370 | return ata_pci_bmdma_init_one(pdev, ppi, &cmd64x_sht, NULL, 0); |
371 | } | 371 | } |
372 | 372 | ||
373 | #ifdef CONFIG_PM | 373 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 17c5f346ff01..030952f1f97c 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c | |||
@@ -221,7 +221,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi | |||
221 | continue; | 221 | continue; |
222 | 222 | ||
223 | rc = devm_request_irq(&pdev->dev, irq[ap->port_no], | 223 | rc = devm_request_irq(&pdev->dev, irq[ap->port_no], |
224 | ata_sff_interrupt, 0, DRV_NAME, host); | 224 | ata_bmdma_interrupt, 0, DRV_NAME, host); |
225 | if (rc) | 225 | if (rc) |
226 | return rc; | 226 | return rc; |
227 | 227 | ||
diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index e809a4233a81..f792330f0d8e 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c | |||
@@ -324,7 +324,7 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
324 | ppi[1] = &info_palmax_secondary; | 324 | ppi[1] = &info_palmax_secondary; |
325 | 325 | ||
326 | /* Now kick off ATA set up */ | 326 | /* Now kick off ATA set up */ |
327 | return ata_pci_sff_init_one(pdev, ppi, &cs5530_sht, NULL, 0); | 327 | return ata_pci_bmdma_init_one(pdev, ppi, &cs5530_sht, NULL, 0); |
328 | } | 328 | } |
329 | 329 | ||
330 | #ifdef CONFIG_PM | 330 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index a02e6459fdcc..03a93186aa19 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c | |||
@@ -198,7 +198,7 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
198 | rdmsr(ATAC_CH0D1_PIO, timings, dummy); | 198 | rdmsr(ATAC_CH0D1_PIO, timings, dummy); |
199 | if (CS5535_BAD_PIO(timings)) | 199 | if (CS5535_BAD_PIO(timings)) |
200 | wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0); | 200 | wrmsr(ATAC_CH0D1_PIO, 0xF7F4F7F4UL, 0); |
201 | return ata_pci_sff_init_one(dev, ppi, &cs5535_sht, NULL, 0); | 201 | return ata_pci_bmdma_init_one(dev, ppi, &cs5535_sht, NULL, 0); |
202 | } | 202 | } |
203 | 203 | ||
204 | static const struct pci_device_id cs5535[] = { | 204 | static const struct pci_device_id cs5535[] = { |
diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index 914ae3506ff5..21ee23f89e88 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c | |||
@@ -260,7 +260,7 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
260 | return -ENODEV; | 260 | return -ENODEV; |
261 | } | 261 | } |
262 | 262 | ||
263 | return ata_pci_sff_init_one(dev, ppi, &cs5536_sht, NULL, 0); | 263 | return ata_pci_bmdma_init_one(dev, ppi, &cs5536_sht, NULL, 0); |
264 | } | 264 | } |
265 | 265 | ||
266 | static const struct pci_device_id cs5536[] = { | 266 | static const struct pci_device_id cs5536[] = { |
diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index 0fcc096b8dac..6d915b063d93 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c | |||
@@ -138,7 +138,7 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i | |||
138 | if (PCI_FUNC(pdev->devfn) != 1) | 138 | if (PCI_FUNC(pdev->devfn) != 1) |
139 | return -ENODEV; | 139 | return -ENODEV; |
140 | 140 | ||
141 | return ata_pci_sff_init_one(pdev, ppi, &cy82c693_sht, NULL, 0); | 141 | return ata_pci_bmdma_init_one(pdev, ppi, &cy82c693_sht, NULL, 0); |
142 | } | 142 | } |
143 | 143 | ||
144 | static const struct pci_device_id cy82c693[] = { | 144 | static const struct pci_device_id cy82c693[] = { |
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index 3bac0e079691..a08834758ea2 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c | |||
@@ -277,8 +277,8 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
277 | dev_printk(KERN_DEBUG, &pdev->dev, | 277 | dev_printk(KERN_DEBUG, &pdev->dev, |
278 | "version " DRV_VERSION "\n"); | 278 | "version " DRV_VERSION "\n"); |
279 | 279 | ||
280 | return ata_pci_sff_init_one(pdev, ppi, &efar_sht, NULL, | 280 | return ata_pci_bmdma_init_one(pdev, ppi, &efar_sht, NULL, |
281 | ATA_HOST_PARALLEL_SCAN); | 281 | ATA_HOST_PARALLEL_SCAN); |
282 | } | 282 | } |
283 | 283 | ||
284 | static const struct pci_device_id efar_pci_tbl[] = { | 284 | static const struct pci_device_id efar_pci_tbl[] = { |
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 8580eb3cd54d..7688868557b9 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c | |||
@@ -361,7 +361,7 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
361 | break; | 361 | break; |
362 | } | 362 | } |
363 | /* Now kick off ATA set up */ | 363 | /* Now kick off ATA set up */ |
364 | return ata_pci_sff_init_one(dev, ppi, &hpt36x_sht, hpriv, 0); | 364 | return ata_pci_bmdma_init_one(dev, ppi, &hpt36x_sht, hpriv, 0); |
365 | } | 365 | } |
366 | 366 | ||
367 | #ifdef CONFIG_PM | 367 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 98b498b6907c..9ae4c0830577 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c | |||
@@ -987,7 +987,7 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
987 | } | 987 | } |
988 | 988 | ||
989 | /* Now kick off ATA set up */ | 989 | /* Now kick off ATA set up */ |
990 | return ata_pci_sff_init_one(dev, ppi, &hpt37x_sht, private_data, 0); | 990 | return ata_pci_bmdma_init_one(dev, ppi, &hpt37x_sht, private_data, 0); |
991 | } | 991 | } |
992 | 992 | ||
993 | static const struct pci_device_id hpt37x[] = { | 993 | static const struct pci_device_id hpt37x[] = { |
diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index 8b95aeba0e74..32f3463216b8 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c | |||
@@ -548,7 +548,7 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
548 | outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c); | 548 | outb(inb(iobase + 0x9c) | 0x04, iobase + 0x9c); |
549 | 549 | ||
550 | /* Now kick off ATA set up */ | 550 | /* Now kick off ATA set up */ |
551 | return ata_pci_sff_init_one(dev, ppi, &hpt3x2n_sht, hpriv, 0); | 551 | return ata_pci_bmdma_init_one(dev, ppi, &hpt3x2n_sht, hpriv, 0); |
552 | } | 552 | } |
553 | 553 | ||
554 | static const struct pci_device_id hpt3x2n[] = { | 554 | static const struct pci_device_id hpt3x2n[] = { |
diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index 727a81ce4c9f..b63d5e2d4628 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c | |||
@@ -248,7 +248,7 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
248 | ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd"); | 248 | ata_port_pbar_desc(ap, 4, offset_cmd[i], "cmd"); |
249 | } | 249 | } |
250 | pci_set_master(pdev); | 250 | pci_set_master(pdev); |
251 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 251 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
252 | IRQF_SHARED, &hpt3x3_sht); | 252 | IRQF_SHARED, &hpt3x3_sht); |
253 | } | 253 | } |
254 | 254 | ||
diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index b56e8f722d20..9f2889fe43b2 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c | |||
@@ -470,7 +470,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info) | |||
470 | pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]); | 470 | pata_icside_setup_ioaddr(ap, info->base, info, info->port[i]); |
471 | } | 471 | } |
472 | 472 | ||
473 | return ata_host_activate(host, ec->irq, ata_sff_interrupt, 0, | 473 | return ata_host_activate(host, ec->irq, ata_bmdma_interrupt, 0, |
474 | &pata_icside_sht); | 474 | &pata_icside_sht); |
475 | } | 475 | } |
476 | 476 | ||
diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c index f971f0de88e6..4d142a2ab8fd 100644 --- a/drivers/ata/pata_it8213.c +++ b/drivers/ata/pata_it8213.c | |||
@@ -273,7 +273,7 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en | |||
273 | dev_printk(KERN_DEBUG, &pdev->dev, | 273 | dev_printk(KERN_DEBUG, &pdev->dev, |
274 | "version " DRV_VERSION "\n"); | 274 | "version " DRV_VERSION "\n"); |
275 | 275 | ||
276 | return ata_pci_sff_init_one(pdev, ppi, &it8213_sht, NULL, 0); | 276 | return ata_pci_bmdma_init_one(pdev, ppi, &it8213_sht, NULL, 0); |
277 | } | 277 | } |
278 | 278 | ||
279 | static const struct pci_device_id it8213_pci_tbl[] = { | 279 | static const struct pci_device_id it8213_pci_tbl[] = { |
diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 2bd2b002d14a..bf88f71a21f4 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c | |||
@@ -933,7 +933,7 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
933 | else | 933 | else |
934 | ppi[0] = &info_smart; | 934 | ppi[0] = &info_smart; |
935 | } | 935 | } |
936 | return ata_pci_sff_init_one(pdev, ppi, &it821x_sht, NULL, 0); | 936 | return ata_pci_bmdma_init_one(pdev, ppi, &it821x_sht, NULL, 0); |
937 | } | 937 | } |
938 | 938 | ||
939 | #ifdef CONFIG_PM | 939 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 565e01e6ac7c..cb3babbb7035 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c | |||
@@ -144,7 +144,7 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i | |||
144 | }; | 144 | }; |
145 | const struct ata_port_info *ppi[] = { &info, NULL }; | 145 | const struct ata_port_info *ppi[] = { &info, NULL }; |
146 | 146 | ||
147 | return ata_pci_sff_init_one(pdev, ppi, &jmicron_sht, NULL, 0); | 147 | return ata_pci_bmdma_init_one(pdev, ppi, &jmicron_sht, NULL, 0); |
148 | } | 148 | } |
149 | 149 | ||
150 | static const struct pci_device_id jmicron_pci_tbl[] = { | 150 | static const struct pci_device_id jmicron_pci_tbl[] = { |
diff --git a/drivers/ata/pata_macio.c b/drivers/ata/pata_macio.c index b5b48e703cb7..76640ac76888 100644 --- a/drivers/ata/pata_macio.c +++ b/drivers/ata/pata_macio.c | |||
@@ -1110,7 +1110,7 @@ static int __devinit pata_macio_common_init(struct pata_macio_priv *priv, | |||
1110 | 1110 | ||
1111 | /* Start it up */ | 1111 | /* Start it up */ |
1112 | priv->irq = irq; | 1112 | priv->irq = irq; |
1113 | return ata_host_activate(priv->host, irq, ata_sff_interrupt, 0, | 1113 | return ata_host_activate(priv->host, irq, ata_bmdma_interrupt, 0, |
1114 | &pata_macio_sht); | 1114 | &pata_macio_sht); |
1115 | } | 1115 | } |
1116 | 1116 | ||
diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index e8ca02e5a71d..dd38083dcbeb 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c | |||
@@ -153,7 +153,7 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i | |||
153 | return -ENODEV; | 153 | return -ENODEV; |
154 | } | 154 | } |
155 | #endif | 155 | #endif |
156 | return ata_pci_sff_init_one(pdev, ppi, &marvell_sht, NULL, 0); | 156 | return ata_pci_bmdma_init_one(pdev, ppi, &marvell_sht, NULL, 0); |
157 | } | 157 | } |
158 | 158 | ||
159 | static const struct pci_device_id marvell_pci_tbl[] = { | 159 | static const struct pci_device_id marvell_pci_tbl[] = { |
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 36afe2c1c747..f087ab55b1df 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c | |||
@@ -659,7 +659,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, | |||
659 | ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs); | 659 | ata_port_desc(ap, "ata_regs 0x%lx", raw_ata_regs); |
660 | 660 | ||
661 | /* activate host */ | 661 | /* activate host */ |
662 | return ata_host_activate(host, priv->ata_irq, ata_sff_interrupt, 0, | 662 | return ata_host_activate(host, priv->ata_irq, ata_bmdma_interrupt, 0, |
663 | &mpc52xx_ata_sht); | 663 | &mpc52xx_ata_sht); |
664 | } | 664 | } |
665 | 665 | ||
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index 94f979a7f4f7..3eb921c746a1 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c | |||
@@ -82,7 +82,7 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
82 | ata_pci_bmdma_clear_simplex(pdev); | 82 | ata_pci_bmdma_clear_simplex(pdev); |
83 | 83 | ||
84 | /* And let the library code do the work */ | 84 | /* And let the library code do the work */ |
85 | return ata_pci_sff_init_one(pdev, port_info, &netcell_sht, NULL, 0); | 85 | return ata_pci_bmdma_init_one(pdev, port_info, &netcell_sht, NULL, 0); |
86 | } | 86 | } |
87 | 87 | ||
88 | static const struct pci_device_id netcell_pci_tbl[] = { | 88 | static const struct pci_device_id netcell_pci_tbl[] = { |
diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index dd53a66b19e3..cc50bd09aa26 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c | |||
@@ -149,7 +149,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
149 | 149 | ||
150 | ninja32_program(base); | 150 | ninja32_program(base); |
151 | /* FIXME: Should we disable them at remove ? */ | 151 | /* FIXME: Should we disable them at remove ? */ |
152 | return ata_host_activate(host, dev->irq, ata_sff_interrupt, | 152 | return ata_host_activate(host, dev->irq, ata_bmdma_interrupt, |
153 | IRQF_SHARED, &ninja32_sht); | 153 | IRQF_SHARED, &ninja32_sht); |
154 | } | 154 | } |
155 | 155 | ||
diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index fdbba2d76d3e..605f198f958c 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c | |||
@@ -380,7 +380,7 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
380 | 380 | ||
381 | ns87415_fixup(pdev); | 381 | ns87415_fixup(pdev); |
382 | 382 | ||
383 | return ata_pci_sff_init_one(pdev, ppi, &ns87415_sht, NULL, 0); | 383 | return ata_pci_bmdma_init_one(pdev, ppi, &ns87415_sht, NULL, 0); |
384 | } | 384 | } |
385 | 385 | ||
386 | static const struct pci_device_id ns87415_pci_tbl[] = { | 386 | static const struct pci_device_id ns87415_pci_tbl[] = { |
diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 3001109352ea..06ddd91ffeda 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c | |||
@@ -750,20 +750,6 @@ static void octeon_cf_dev_config(struct ata_device *dev) | |||
750 | } | 750 | } |
751 | 751 | ||
752 | /* | 752 | /* |
753 | * Trap if driver tries to do standard bmdma commands. They are not | ||
754 | * supported. | ||
755 | */ | ||
756 | static void unreachable_qc(struct ata_queued_cmd *qc) | ||
757 | { | ||
758 | BUG(); | ||
759 | } | ||
760 | |||
761 | static u8 unreachable_port(struct ata_port *ap) | ||
762 | { | ||
763 | BUG(); | ||
764 | } | ||
765 | |||
766 | /* | ||
767 | * We don't do ATAPI DMA so return 0. | 753 | * We don't do ATAPI DMA so return 0. |
768 | */ | 754 | */ |
769 | static int octeon_cf_check_atapi_dma(struct ata_queued_cmd *qc) | 755 | static int octeon_cf_check_atapi_dma(struct ata_queued_cmd *qc) |
@@ -804,10 +790,6 @@ static struct ata_port_operations octeon_cf_ops = { | |||
804 | .sff_dev_select = octeon_cf_dev_select, | 790 | .sff_dev_select = octeon_cf_dev_select, |
805 | .sff_irq_on = octeon_cf_irq_on, | 791 | .sff_irq_on = octeon_cf_irq_on, |
806 | .sff_irq_clear = octeon_cf_irq_clear, | 792 | .sff_irq_clear = octeon_cf_irq_clear, |
807 | .bmdma_setup = unreachable_qc, | ||
808 | .bmdma_start = unreachable_qc, | ||
809 | .bmdma_stop = unreachable_qc, | ||
810 | .bmdma_status = unreachable_port, | ||
811 | .cable_detect = ata_cable_40wire, | 793 | .cable_detect = ata_cable_40wire, |
812 | .set_piomode = octeon_cf_set_piomode, | 794 | .set_piomode = octeon_cf_set_piomode, |
813 | .set_dmamode = octeon_cf_set_dmamode, | 795 | .set_dmamode = octeon_cf_set_dmamode, |
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index 988ef2627be3..b811c1636204 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c | |||
@@ -248,7 +248,7 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
248 | dev_printk(KERN_DEBUG, &pdev->dev, | 248 | dev_printk(KERN_DEBUG, &pdev->dev, |
249 | "version " DRV_VERSION "\n"); | 249 | "version " DRV_VERSION "\n"); |
250 | 250 | ||
251 | return ata_pci_sff_init_one(pdev, ppi, &oldpiix_sht, NULL, 0); | 251 | return ata_pci_bmdma_init_one(pdev, ppi, &oldpiix_sht, NULL, 0); |
252 | } | 252 | } |
253 | 253 | ||
254 | static const struct pci_device_id oldpiix_pci_tbl[] = { | 254 | static const struct pci_device_id oldpiix_pci_tbl[] = { |
diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 76b7d12b1e8d..0852cd07de08 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c | |||
@@ -429,7 +429,7 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
429 | if (optiplus_with_udma(dev)) | 429 | if (optiplus_with_udma(dev)) |
430 | ppi[0] = &info_82c700_udma; | 430 | ppi[0] = &info_82c700_udma; |
431 | 431 | ||
432 | return ata_pci_sff_init_one(dev, ppi, &optidma_sht, NULL, 0); | 432 | return ata_pci_bmdma_init_one(dev, ppi, &optidma_sht, NULL, 0); |
433 | } | 433 | } |
434 | 434 | ||
435 | static const struct pci_device_id optidma[] = { | 435 | static const struct pci_device_id optidma[] = { |
diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index 09f1f22c0307..b18351122525 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c | |||
@@ -754,7 +754,7 @@ static int __devinit pdc2027x_init_one(struct pci_dev *pdev, const struct pci_de | |||
754 | return -EIO; | 754 | return -EIO; |
755 | 755 | ||
756 | pci_set_master(pdev); | 756 | pci_set_master(pdev); |
757 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 757 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
758 | IRQF_SHARED, &pdc2027x_sht); | 758 | IRQF_SHARED, &pdc2027x_sht); |
759 | } | 759 | } |
760 | 760 | ||
diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index fa1e2f3bc0fd..c39f213e1bbc 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c | |||
@@ -337,7 +337,7 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id | |||
337 | return -ENODEV; | 337 | return -ENODEV; |
338 | } | 338 | } |
339 | } | 339 | } |
340 | return ata_pci_sff_init_one(dev, ppi, &pdc202xx_sht, NULL, 0); | 340 | return ata_pci_bmdma_init_one(dev, ppi, &pdc202xx_sht, NULL, 0); |
341 | } | 341 | } |
342 | 342 | ||
343 | static const struct pci_device_id pdc202xx[] = { | 343 | static const struct pci_device_id pdc202xx[] = { |
diff --git a/drivers/ata/pata_piccolo.c b/drivers/ata/pata_piccolo.c index 981615414849..cb01bf9496fe 100644 --- a/drivers/ata/pata_piccolo.c +++ b/drivers/ata/pata_piccolo.c | |||
@@ -95,7 +95,7 @@ static int ata_tosh_init_one(struct pci_dev *dev, const struct pci_device_id *id | |||
95 | }; | 95 | }; |
96 | const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; | 96 | const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; |
97 | /* Just one port for the moment */ | 97 | /* Just one port for the moment */ |
98 | return ata_pci_sff_init_one(dev, ppi, &tosh_sht, NULL, 0); | 98 | return ata_pci_bmdma_init_one(dev, ppi, &tosh_sht, NULL, 0); |
99 | } | 99 | } |
100 | 100 | ||
101 | static struct pci_device_id ata_tosh[] = { | 101 | static struct pci_device_id ata_tosh[] = { |
diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index a5fa388e5398..8574b31f1773 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c | |||
@@ -227,7 +227,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e | |||
227 | dev_printk(KERN_DEBUG, &pdev->dev, | 227 | dev_printk(KERN_DEBUG, &pdev->dev, |
228 | "version " DRV_VERSION "\n"); | 228 | "version " DRV_VERSION "\n"); |
229 | 229 | ||
230 | return ata_pci_sff_init_one(pdev, ppi, &radisys_sht, NULL, 0); | 230 | return ata_pci_bmdma_init_one(pdev, ppi, &radisys_sht, NULL, 0); |
231 | } | 231 | } |
232 | 232 | ||
233 | static const struct pci_device_id radisys_pci_tbl[] = { | 233 | static const struct pci_device_id radisys_pci_tbl[] = { |
diff --git a/drivers/ata/pata_rdc.c b/drivers/ata/pata_rdc.c index 37092cfd7bc6..5fbe9b166c69 100644 --- a/drivers/ata/pata_rdc.c +++ b/drivers/ata/pata_rdc.c | |||
@@ -344,7 +344,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev, | |||
344 | */ | 344 | */ |
345 | pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg); | 345 | pci_read_config_dword(pdev, 0x54, &hpriv->saved_iocfg); |
346 | 346 | ||
347 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | 347 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); |
348 | if (rc) | 348 | if (rc) |
349 | return rc; | 349 | return rc; |
350 | host->private_data = hpriv; | 350 | host->private_data = hpriv; |
@@ -354,7 +354,7 @@ static int __devinit rdc_init_one(struct pci_dev *pdev, | |||
354 | host->flags |= ATA_HOST_PARALLEL_SCAN; | 354 | host->flags |= ATA_HOST_PARALLEL_SCAN; |
355 | 355 | ||
356 | pci_set_master(pdev); | 356 | pci_set_master(pdev); |
357 | return ata_pci_sff_activate_host(host, ata_sff_interrupt, &rdc_sht); | 357 | return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, &rdc_sht); |
358 | } | 358 | } |
359 | 359 | ||
360 | static void rdc_remove_one(struct pci_dev *pdev) | 360 | static void rdc_remove_one(struct pci_dev *pdev) |
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 6b5b63a2fd8e..e2c18257adff 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c | |||
@@ -237,7 +237,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
237 | }; | 237 | }; |
238 | const struct ata_port_info *ppi[] = { &info, NULL }; | 238 | const struct ata_port_info *ppi[] = { &info, NULL }; |
239 | 239 | ||
240 | return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL, 0); | 240 | return ata_pci_bmdma_init_one(dev, ppi, &sc1200_sht, NULL, 0); |
241 | } | 241 | } |
242 | 242 | ||
243 | static const struct pci_device_id sc1200[] = { | 243 | static const struct pci_device_id sc1200[] = { |
diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index 6f6193b707cb..d9db3f8d60ef 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c | |||
@@ -875,7 +875,7 @@ static void scc_postreset(struct ata_link *link, unsigned int *classes) | |||
875 | * scc_irq_clear - Clear PCI IDE BMDMA interrupt. | 875 | * scc_irq_clear - Clear PCI IDE BMDMA interrupt. |
876 | * @ap: Port associated with this ATA transaction. | 876 | * @ap: Port associated with this ATA transaction. |
877 | * | 877 | * |
878 | * Note: Original code is ata_sff_irq_clear(). | 878 | * Note: Original code is ata_bmdma_irq_clear(). |
879 | */ | 879 | */ |
880 | 880 | ||
881 | static void scc_irq_clear (struct ata_port *ap) | 881 | static void scc_irq_clear (struct ata_port *ap) |
@@ -1105,7 +1105,7 @@ static int scc_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1105 | if (rc) | 1105 | if (rc) |
1106 | return rc; | 1106 | return rc; |
1107 | 1107 | ||
1108 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 1108 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
1109 | IRQF_SHARED, &scc_sht); | 1109 | IRQF_SHARED, &scc_sht); |
1110 | } | 1110 | } |
1111 | 1111 | ||
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index 86b3d0133c7c..e97b32f03a6e 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c | |||
@@ -179,7 +179,7 @@ static int __devinit sch_init_one(struct pci_dev *pdev, | |||
179 | dev_printk(KERN_DEBUG, &pdev->dev, | 179 | dev_printk(KERN_DEBUG, &pdev->dev, |
180 | "version " DRV_VERSION "\n"); | 180 | "version " DRV_VERSION "\n"); |
181 | 181 | ||
182 | return ata_pci_sff_init_one(pdev, ppi, &sch_sht, NULL, 0); | 182 | return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0); |
183 | } | 183 | } |
184 | 184 | ||
185 | static int __init sch_init(void) | 185 | static int __init sch_init(void) |
diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 43ea389df2b3..86dd714e3e1d 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c | |||
@@ -460,7 +460,7 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id | |||
460 | if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) | 460 | if (pdev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5IDE) |
461 | ata_pci_bmdma_clear_simplex(pdev); | 461 | ata_pci_bmdma_clear_simplex(pdev); |
462 | 462 | ||
463 | return ata_pci_sff_init_one(pdev, ppi, &serverworks_sht, NULL, 0); | 463 | return ata_pci_bmdma_init_one(pdev, ppi, &serverworks_sht, NULL, 0); |
464 | } | 464 | } |
465 | 465 | ||
466 | #ifdef CONFIG_PM | 466 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 43faf106f647..d3190d7ec304 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c | |||
@@ -374,11 +374,11 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, | |||
374 | ata_sff_std_ports(&host->ports[1]->ioaddr); | 374 | ata_sff_std_ports(&host->ports[1]->ioaddr); |
375 | 375 | ||
376 | /* Register & activate */ | 376 | /* Register & activate */ |
377 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 377 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
378 | IRQF_SHARED, &sil680_sht); | 378 | IRQF_SHARED, &sil680_sht); |
379 | 379 | ||
380 | use_ioports: | 380 | use_ioports: |
381 | return ata_pci_sff_init_one(pdev, ppi, &sil680_sht, NULL, 0); | 381 | return ata_pci_bmdma_init_one(pdev, ppi, &sil680_sht, NULL, 0); |
382 | } | 382 | } |
383 | 383 | ||
384 | #ifdef CONFIG_PM | 384 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index b6708032f321..60cea13cccce 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c | |||
@@ -826,7 +826,7 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) | |||
826 | 826 | ||
827 | sis_fixup(pdev, chipset); | 827 | sis_fixup(pdev, chipset); |
828 | 828 | ||
829 | return ata_pci_sff_init_one(pdev, ppi, &sis_sht, chipset, 0); | 829 | return ata_pci_bmdma_init_one(pdev, ppi, &sis_sht, chipset, 0); |
830 | } | 830 | } |
831 | 831 | ||
832 | #ifdef CONFIG_PM | 832 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 733b042a7469..98548f640c8e 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c | |||
@@ -316,7 +316,7 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id | |||
316 | val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; | 316 | val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; |
317 | pci_write_config_dword(dev, 0x40, val); | 317 | pci_write_config_dword(dev, 0x40, val); |
318 | 318 | ||
319 | return ata_pci_sff_init_one(dev, ppi, &sl82c105_sht, NULL, 0); | 319 | return ata_pci_bmdma_init_one(dev, ppi, &sl82c105_sht, NULL, 0); |
320 | } | 320 | } |
321 | 321 | ||
322 | static const struct pci_device_id sl82c105[] = { | 322 | static const struct pci_device_id sl82c105[] = { |
diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index 48f50600ed2a..0d1f89e571dd 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c | |||
@@ -201,7 +201,7 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) | |||
201 | if (!printed_version++) | 201 | if (!printed_version++) |
202 | dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); | 202 | dev_printk(KERN_DEBUG, &dev->dev, "version " DRV_VERSION "\n"); |
203 | 203 | ||
204 | return ata_pci_sff_init_one(dev, ppi, &triflex_sht, NULL, 0); | 204 | return ata_pci_bmdma_init_one(dev, ppi, &triflex_sht, NULL, 0); |
205 | } | 205 | } |
206 | 206 | ||
207 | static const struct pci_device_id triflex[] = { | 207 | static const struct pci_device_id triflex[] = { |
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 7e3e0a5598b7..5e659885de16 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c | |||
@@ -627,7 +627,7 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
627 | } | 627 | } |
628 | 628 | ||
629 | /* We have established the device type, now fire it up */ | 629 | /* We have established the device type, now fire it up */ |
630 | return ata_pci_sff_init_one(pdev, ppi, &via_sht, (void *)config, 0); | 630 | return ata_pci_bmdma_init_one(pdev, ppi, &via_sht, (void *)config, 0); |
631 | } | 631 | } |
632 | 632 | ||
633 | #ifdef CONFIG_PM | 633 | #ifdef CONFIG_PM |
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index f3471bc949d3..a476cd99b95d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c | |||
@@ -675,8 +675,6 @@ static struct ata_port_operations mv5_ops = { | |||
675 | .freeze = mv_eh_freeze, | 675 | .freeze = mv_eh_freeze, |
676 | .thaw = mv_eh_thaw, | 676 | .thaw = mv_eh_thaw, |
677 | .hardreset = mv_hardreset, | 677 | .hardreset = mv_hardreset, |
678 | .error_handler = ata_std_error_handler, /* avoid SFF EH */ | ||
679 | .post_internal_cmd = ATA_OP_NULL, | ||
680 | 678 | ||
681 | .scr_read = mv5_scr_read, | 679 | .scr_read = mv5_scr_read, |
682 | .scr_write = mv5_scr_write, | 680 | .scr_write = mv5_scr_write, |
@@ -2813,7 +2811,7 @@ static void mv_port_intr(struct ata_port *ap, u32 port_cause) | |||
2813 | } else if (!edma_was_enabled) { | 2811 | } else if (!edma_was_enabled) { |
2814 | struct ata_queued_cmd *qc = mv_get_active_qc(ap); | 2812 | struct ata_queued_cmd *qc = mv_get_active_qc(ap); |
2815 | if (qc) | 2813 | if (qc) |
2816 | ata_sff_host_intr(ap, qc); | 2814 | ata_bmdma_port_intr(ap, qc); |
2817 | else | 2815 | else |
2818 | mv_unexpected_intr(ap, edma_was_enabled); | 2816 | mv_unexpected_intr(ap, edma_was_enabled); |
2819 | } | 2817 | } |
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index baa8f0d2c86f..6fd114784116 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
@@ -920,7 +920,7 @@ static int nv_host_intr(struct ata_port *ap, u8 irq_stat) | |||
920 | } | 920 | } |
921 | 921 | ||
922 | /* handle interrupt */ | 922 | /* handle interrupt */ |
923 | return ata_sff_host_intr(ap, qc); | 923 | return ata_bmdma_port_intr(ap, qc); |
924 | } | 924 | } |
925 | 925 | ||
926 | static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) | 926 | static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance) |
@@ -1100,7 +1100,7 @@ static void nv_adma_irq_clear(struct ata_port *ap) | |||
1100 | u32 notifier_clears[2]; | 1100 | u32 notifier_clears[2]; |
1101 | 1101 | ||
1102 | if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { | 1102 | if (pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) { |
1103 | ata_sff_irq_clear(ap); | 1103 | ata_bmdma_irq_clear(ap); |
1104 | return; | 1104 | return; |
1105 | } | 1105 | } |
1106 | 1106 | ||
@@ -1505,7 +1505,7 @@ static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance) | |||
1505 | 1505 | ||
1506 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | 1506 | qc = ata_qc_from_tag(ap, ap->link.active_tag); |
1507 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { | 1507 | if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING))) { |
1508 | handled += ata_sff_host_intr(ap, qc); | 1508 | handled += ata_bmdma_port_intr(ap, qc); |
1509 | } else { | 1509 | } else { |
1510 | /* | 1510 | /* |
1511 | * No request pending? Clear interrupt status | 1511 | * No request pending? Clear interrupt status |
@@ -2430,7 +2430,7 @@ static int nv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
2430 | 2430 | ||
2431 | ppi[0] = &nv_port_info[type]; | 2431 | ppi[0] = &nv_port_info[type]; |
2432 | ipriv = ppi[0]->private_data; | 2432 | ipriv = ppi[0]->private_data; |
2433 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | 2433 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); |
2434 | if (rc) | 2434 | if (rc) |
2435 | return rc; | 2435 | return rc; |
2436 | 2436 | ||
diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index d533b3d20ca1..daeebf19a6a9 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c | |||
@@ -120,8 +120,6 @@ static void qs_host_stop(struct ata_host *host); | |||
120 | static void qs_qc_prep(struct ata_queued_cmd *qc); | 120 | static void qs_qc_prep(struct ata_queued_cmd *qc); |
121 | static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); | 121 | static unsigned int qs_qc_issue(struct ata_queued_cmd *qc); |
122 | static int qs_check_atapi_dma(struct ata_queued_cmd *qc); | 122 | static int qs_check_atapi_dma(struct ata_queued_cmd *qc); |
123 | static void qs_bmdma_stop(struct ata_queued_cmd *qc); | ||
124 | static u8 qs_bmdma_status(struct ata_port *ap); | ||
125 | static void qs_freeze(struct ata_port *ap); | 123 | static void qs_freeze(struct ata_port *ap); |
126 | static void qs_thaw(struct ata_port *ap); | 124 | static void qs_thaw(struct ata_port *ap); |
127 | static int qs_prereset(struct ata_link *link, unsigned long deadline); | 125 | static int qs_prereset(struct ata_link *link, unsigned long deadline); |
@@ -137,8 +135,6 @@ static struct ata_port_operations qs_ata_ops = { | |||
137 | .inherits = &ata_sff_port_ops, | 135 | .inherits = &ata_sff_port_ops, |
138 | 136 | ||
139 | .check_atapi_dma = qs_check_atapi_dma, | 137 | .check_atapi_dma = qs_check_atapi_dma, |
140 | .bmdma_stop = qs_bmdma_stop, | ||
141 | .bmdma_status = qs_bmdma_status, | ||
142 | .qc_prep = qs_qc_prep, | 138 | .qc_prep = qs_qc_prep, |
143 | .qc_issue = qs_qc_issue, | 139 | .qc_issue = qs_qc_issue, |
144 | 140 | ||
@@ -190,16 +186,6 @@ static int qs_check_atapi_dma(struct ata_queued_cmd *qc) | |||
190 | return 1; /* ATAPI DMA not supported */ | 186 | return 1; /* ATAPI DMA not supported */ |
191 | } | 187 | } |
192 | 188 | ||
193 | static void qs_bmdma_stop(struct ata_queued_cmd *qc) | ||
194 | { | ||
195 | /* nothing */ | ||
196 | } | ||
197 | |||
198 | static u8 qs_bmdma_status(struct ata_port *ap) | ||
199 | { | ||
200 | return 0; | ||
201 | } | ||
202 | |||
203 | static inline void qs_enter_reg_mode(struct ata_port *ap) | 189 | static inline void qs_enter_reg_mode(struct ata_port *ap) |
204 | { | 190 | { |
205 | u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); | 191 | u8 __iomem *chan = qs_mmio_base(ap->host) + (ap->port_no * 0x4000); |
@@ -454,7 +440,7 @@ static inline unsigned int qs_intr_mmio(struct ata_host *host) | |||
454 | if (!pp || pp->state != qs_state_mmio) | 440 | if (!pp || pp->state != qs_state_mmio) |
455 | continue; | 441 | continue; |
456 | if (!(qc->tf.flags & ATA_TFLAG_POLLING)) | 442 | if (!(qc->tf.flags & ATA_TFLAG_POLLING)) |
457 | handled |= ata_sff_host_intr(ap, qc); | 443 | handled |= ata_sff_port_intr(ap, qc); |
458 | } | 444 | } |
459 | return handled; | 445 | return handled; |
460 | } | 446 | } |
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index 2dda312b6b9a..3a4f84219719 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c | |||
@@ -503,7 +503,7 @@ static void sil_host_intr(struct ata_port *ap, u32 bmdma2) | |||
503 | goto err_hsm; | 503 | goto err_hsm; |
504 | 504 | ||
505 | /* ack bmdma irq events */ | 505 | /* ack bmdma irq events */ |
506 | ata_sff_irq_clear(ap); | 506 | ata_bmdma_irq_clear(ap); |
507 | 507 | ||
508 | /* kick HSM in the ass */ | 508 | /* kick HSM in the ass */ |
509 | ata_sff_hsm_move(ap, qc, status, 0); | 509 | ata_sff_hsm_move(ap, qc, status, 0); |
@@ -584,7 +584,7 @@ static void sil_thaw(struct ata_port *ap) | |||
584 | 584 | ||
585 | /* clear IRQ */ | 585 | /* clear IRQ */ |
586 | ap->ops->sff_check_status(ap); | 586 | ap->ops->sff_check_status(ap); |
587 | ata_sff_irq_clear(ap); | 587 | ata_bmdma_irq_clear(ap); |
588 | 588 | ||
589 | /* turn on SATA IRQ if supported */ | 589 | /* turn on SATA IRQ if supported */ |
590 | if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ)) | 590 | if (!(ap->flags & SIL_FLAG_NO_SATA_IRQ)) |
diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index f8a91bfd66a8..2bfe3ae03976 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c | |||
@@ -279,7 +279,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
279 | break; | 279 | break; |
280 | } | 280 | } |
281 | 281 | ||
282 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | 282 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); |
283 | if (rc) | 283 | if (rc) |
284 | return rc; | 284 | return rc; |
285 | 285 | ||
@@ -308,7 +308,7 @@ static int sis_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
308 | 308 | ||
309 | pci_set_master(pdev); | 309 | pci_set_master(pdev); |
310 | pci_intx(pdev, 1); | 310 | pci_intx(pdev, 1); |
311 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 311 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
312 | IRQF_SHARED, &sis_sht); | 312 | IRQF_SHARED, &sis_sht); |
313 | } | 313 | } |
314 | 314 | ||
diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 101fd6a19829..7d9db4aaf07e 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c | |||
@@ -502,7 +502,7 @@ static int k2_sata_init_one(struct pci_dev *pdev, const struct pci_device_id *en | |||
502 | writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); | 502 | writel(0x0, mmio_base + K2_SATA_SIM_OFFSET); |
503 | 503 | ||
504 | pci_set_master(pdev); | 504 | pci_set_master(pdev); |
505 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 505 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
506 | IRQF_SHARED, &k2_sata_sht); | 506 | IRQF_SHARED, &k2_sata_sht); |
507 | } | 507 | } |
508 | 508 | ||
diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index d8dac17dc2c8..b8578c32d344 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c | |||
@@ -242,7 +242,7 @@ static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
242 | 242 | ||
243 | pci_set_master(pdev); | 243 | pci_set_master(pdev); |
244 | pci_intx(pdev, 1); | 244 | pci_intx(pdev, 1); |
245 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 245 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
246 | IRQF_SHARED, &uli_sht); | 246 | IRQF_SHARED, &uli_sht); |
247 | } | 247 | } |
248 | 248 | ||
diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 08f65492cc81..101d8c219caf 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c | |||
@@ -308,7 +308,7 @@ static void svia_noop_freeze(struct ata_port *ap) | |||
308 | * certain way. Leave it alone and just clear pending IRQ. | 308 | * certain way. Leave it alone and just clear pending IRQ. |
309 | */ | 309 | */ |
310 | ap->ops->sff_check_status(ap); | 310 | ap->ops->sff_check_status(ap); |
311 | ata_sff_irq_clear(ap); | 311 | ata_bmdma_irq_clear(ap); |
312 | } | 312 | } |
313 | 313 | ||
314 | /** | 314 | /** |
@@ -463,7 +463,7 @@ static int vt6420_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) | |||
463 | struct ata_host *host; | 463 | struct ata_host *host; |
464 | int rc; | 464 | int rc; |
465 | 465 | ||
466 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | 466 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); |
467 | if (rc) | 467 | if (rc) |
468 | return rc; | 468 | return rc; |
469 | *r_host = host; | 469 | *r_host = host; |
@@ -520,7 +520,7 @@ static int vt8251_prepare_host(struct pci_dev *pdev, struct ata_host **r_host) | |||
520 | struct ata_host *host; | 520 | struct ata_host *host; |
521 | int i, rc; | 521 | int i, rc; |
522 | 522 | ||
523 | rc = ata_pci_sff_prepare_host(pdev, ppi, &host); | 523 | rc = ata_pci_bmdma_prepare_host(pdev, ppi, &host); |
524 | if (rc) | 524 | if (rc) |
525 | return rc; | 525 | return rc; |
526 | *r_host = host; | 526 | *r_host = host; |
@@ -628,7 +628,7 @@ static int svia_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
628 | svia_configure(pdev); | 628 | svia_configure(pdev); |
629 | 629 | ||
630 | pci_set_master(pdev); | 630 | pci_set_master(pdev); |
631 | return ata_host_activate(host, pdev->irq, ata_sff_interrupt, | 631 | return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt, |
632 | IRQF_SHARED, &svia_sht); | 632 | IRQF_SHARED, &svia_sht); |
633 | } | 633 | } |
634 | 634 | ||
diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index 2107952ebff1..b777176ff494 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c | |||
@@ -245,7 +245,7 @@ static void vsc_port_intr(u8 port_status, struct ata_port *ap) | |||
245 | 245 | ||
246 | qc = ata_qc_from_tag(ap, ap->link.active_tag); | 246 | qc = ata_qc_from_tag(ap, ap->link.active_tag); |
247 | if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING))) | 247 | if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING))) |
248 | handled = ata_sff_host_intr(ap, qc); | 248 | handled = ata_bmdma_port_intr(ap, qc); |
249 | 249 | ||
250 | /* We received an interrupt during a polled command, | 250 | /* We received an interrupt during a polled command, |
251 | * or some other spurious condition. Interrupt reporting | 251 | * or some other spurious condition. Interrupt reporting |
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/ps3flash.c b/drivers/char/ps3flash.c index 606048b72bcf..85c004a518ee 100644 --- a/drivers/char/ps3flash.c +++ b/drivers/char/ps3flash.c | |||
@@ -305,8 +305,7 @@ static int ps3flash_flush(struct file *file, fl_owner_t id) | |||
305 | return ps3flash_writeback(ps3flash_dev); | 305 | return ps3flash_writeback(ps3flash_dev); |
306 | } | 306 | } |
307 | 307 | ||
308 | static int ps3flash_fsync(struct file *file, struct dentry *dentry, | 308 | static int ps3flash_fsync(struct file *file, int datasync) |
309 | int datasync) | ||
310 | { | 309 | { |
311 | return ps3flash_writeback(ps3flash_dev); | 310 | return ps3flash_writeback(ps3flash_dev); |
312 | } | 311 | } |
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/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 12fdd3987a36..199488576a05 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -156,7 +156,7 @@ int cpuidle_enable_device(struct cpuidle_device *dev) | |||
156 | 156 | ||
157 | if (dev->enabled) | 157 | if (dev->enabled) |
158 | return 0; | 158 | return 0; |
159 | if (!cpuidle_curr_driver || !cpuidle_curr_governor) | 159 | if (!cpuidle_get_driver() || !cpuidle_curr_governor) |
160 | return -EIO; | 160 | return -EIO; |
161 | if (!dev->state_count) | 161 | if (!dev->state_count) |
162 | return -EINVAL; | 162 | return -EINVAL; |
@@ -207,7 +207,7 @@ void cpuidle_disable_device(struct cpuidle_device *dev) | |||
207 | { | 207 | { |
208 | if (!dev->enabled) | 208 | if (!dev->enabled) |
209 | return; | 209 | return; |
210 | if (!cpuidle_curr_driver || !cpuidle_curr_governor) | 210 | if (!cpuidle_get_driver() || !cpuidle_curr_governor) |
211 | return; | 211 | return; |
212 | 212 | ||
213 | dev->enabled = 0; | 213 | dev->enabled = 0; |
@@ -271,10 +271,11 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) | |||
271 | { | 271 | { |
272 | int ret; | 272 | int ret; |
273 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); | 273 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); |
274 | struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); | ||
274 | 275 | ||
275 | if (!sys_dev) | 276 | if (!sys_dev) |
276 | return -EINVAL; | 277 | return -EINVAL; |
277 | if (!try_module_get(cpuidle_curr_driver->owner)) | 278 | if (!try_module_get(cpuidle_driver->owner)) |
278 | return -EINVAL; | 279 | return -EINVAL; |
279 | 280 | ||
280 | init_completion(&dev->kobj_unregister); | 281 | init_completion(&dev->kobj_unregister); |
@@ -284,7 +285,7 @@ static int __cpuidle_register_device(struct cpuidle_device *dev) | |||
284 | per_cpu(cpuidle_devices, dev->cpu) = dev; | 285 | per_cpu(cpuidle_devices, dev->cpu) = dev; |
285 | list_add(&dev->device_list, &cpuidle_detected_devices); | 286 | list_add(&dev->device_list, &cpuidle_detected_devices); |
286 | if ((ret = cpuidle_add_sysfs(sys_dev))) { | 287 | if ((ret = cpuidle_add_sysfs(sys_dev))) { |
287 | module_put(cpuidle_curr_driver->owner); | 288 | module_put(cpuidle_driver->owner); |
288 | return ret; | 289 | return ret; |
289 | } | 290 | } |
290 | 291 | ||
@@ -325,6 +326,7 @@ EXPORT_SYMBOL_GPL(cpuidle_register_device); | |||
325 | void cpuidle_unregister_device(struct cpuidle_device *dev) | 326 | void cpuidle_unregister_device(struct cpuidle_device *dev) |
326 | { | 327 | { |
327 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); | 328 | struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu); |
329 | struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); | ||
328 | 330 | ||
329 | if (dev->registered == 0) | 331 | if (dev->registered == 0) |
330 | return; | 332 | return; |
@@ -340,7 +342,7 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) | |||
340 | 342 | ||
341 | cpuidle_resume_and_unlock(); | 343 | cpuidle_resume_and_unlock(); |
342 | 344 | ||
343 | module_put(cpuidle_curr_driver->owner); | 345 | module_put(cpuidle_driver->owner); |
344 | } | 346 | } |
345 | 347 | ||
346 | EXPORT_SYMBOL_GPL(cpuidle_unregister_device); | 348 | EXPORT_SYMBOL_GPL(cpuidle_unregister_device); |
diff --git a/drivers/cpuidle/cpuidle.h b/drivers/cpuidle/cpuidle.h index 9476ba33ee2c..33e50d556f17 100644 --- a/drivers/cpuidle/cpuidle.h +++ b/drivers/cpuidle/cpuidle.h | |||
@@ -9,7 +9,6 @@ | |||
9 | 9 | ||
10 | /* For internal use only */ | 10 | /* For internal use only */ |
11 | extern struct cpuidle_governor *cpuidle_curr_governor; | 11 | extern struct cpuidle_governor *cpuidle_curr_governor; |
12 | extern struct cpuidle_driver *cpuidle_curr_driver; | ||
13 | extern struct list_head cpuidle_governors; | 12 | extern struct list_head cpuidle_governors; |
14 | extern struct list_head cpuidle_detected_devices; | 13 | extern struct list_head cpuidle_detected_devices; |
15 | extern struct mutex cpuidle_lock; | 14 | extern struct mutex cpuidle_lock; |
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 2257004fe33d..fd1601e3d125 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include "cpuidle.h" | 15 | #include "cpuidle.h" |
16 | 16 | ||
17 | struct cpuidle_driver *cpuidle_curr_driver; | 17 | static struct cpuidle_driver *cpuidle_curr_driver; |
18 | DEFINE_SPINLOCK(cpuidle_driver_lock); | 18 | DEFINE_SPINLOCK(cpuidle_driver_lock); |
19 | 19 | ||
20 | /** | 20 | /** |
@@ -40,13 +40,25 @@ int cpuidle_register_driver(struct cpuidle_driver *drv) | |||
40 | EXPORT_SYMBOL_GPL(cpuidle_register_driver); | 40 | EXPORT_SYMBOL_GPL(cpuidle_register_driver); |
41 | 41 | ||
42 | /** | 42 | /** |
43 | * cpuidle_get_driver - return the current driver | ||
44 | */ | ||
45 | struct cpuidle_driver *cpuidle_get_driver(void) | ||
46 | { | ||
47 | return cpuidle_curr_driver; | ||
48 | } | ||
49 | EXPORT_SYMBOL_GPL(cpuidle_get_driver); | ||
50 | |||
51 | /** | ||
43 | * cpuidle_unregister_driver - unregisters a driver | 52 | * cpuidle_unregister_driver - unregisters a driver |
44 | * @drv: the driver | 53 | * @drv: the driver |
45 | */ | 54 | */ |
46 | void cpuidle_unregister_driver(struct cpuidle_driver *drv) | 55 | void cpuidle_unregister_driver(struct cpuidle_driver *drv) |
47 | { | 56 | { |
48 | if (!drv) | 57 | if (drv != cpuidle_curr_driver) { |
58 | WARN(1, "invalid cpuidle_unregister_driver(%s)\n", | ||
59 | drv->name); | ||
49 | return; | 60 | return; |
61 | } | ||
50 | 62 | ||
51 | spin_lock(&cpuidle_driver_lock); | 63 | spin_lock(&cpuidle_driver_lock); |
52 | cpuidle_curr_driver = NULL; | 64 | cpuidle_curr_driver = NULL; |
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 0ba9c8b8ee74..0310ffaec9df 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
@@ -47,10 +47,11 @@ static ssize_t show_current_driver(struct sysdev_class *class, | |||
47 | char *buf) | 47 | char *buf) |
48 | { | 48 | { |
49 | ssize_t ret; | 49 | ssize_t ret; |
50 | struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver(); | ||
50 | 51 | ||
51 | spin_lock(&cpuidle_driver_lock); | 52 | spin_lock(&cpuidle_driver_lock); |
52 | if (cpuidle_curr_driver) | 53 | if (cpuidle_driver) |
53 | ret = sprintf(buf, "%s\n", cpuidle_curr_driver->name); | 54 | ret = sprintf(buf, "%s\n", cpuidle_driver->name); |
54 | else | 55 | else |
55 | ret = sprintf(buf, "none\n"); | 56 | ret = sprintf(buf, "none\n"); |
56 | spin_unlock(&cpuidle_driver_lock); | 57 | spin_unlock(&cpuidle_driver_lock); |
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 1b8877922fb0..9e01e96fee94 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -166,6 +166,15 @@ config TIMB_DMA | |||
166 | config ARCH_HAS_ASYNC_TX_FIND_CHANNEL | 166 | config ARCH_HAS_ASYNC_TX_FIND_CHANNEL |
167 | bool | 167 | bool |
168 | 168 | ||
169 | config PL330_DMA | ||
170 | tristate "DMA API Driver for PL330" | ||
171 | select DMA_ENGINE | ||
172 | depends on PL330 | ||
173 | help | ||
174 | Select if your platform has one or more PL330 DMACs. | ||
175 | You need to provide platform specific settings via | ||
176 | platform_data for a dma-pl330 device. | ||
177 | |||
169 | config DMA_ENGINE | 178 | config DMA_ENGINE |
170 | bool | 179 | bool |
171 | 180 | ||
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 20881426c1ac..0fe5ebbfda5d 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile | |||
@@ -22,3 +22,4 @@ obj-$(CONFIG_COH901318) += coh901318.o coh901318_lli.o | |||
22 | obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ | 22 | obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/ |
23 | obj-$(CONFIG_TIMB_DMA) += timb_dma.o | 23 | obj-$(CONFIG_TIMB_DMA) += timb_dma.o |
24 | obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o | 24 | obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o |
25 | obj-$(CONFIG_PL330_DMA) += pl330.o | ||
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c new file mode 100644 index 000000000000..7c50f6dfd3f4 --- /dev/null +++ b/drivers/dma/pl330.c | |||
@@ -0,0 +1,866 @@ | |||
1 | /* linux/drivers/dma/pl330.c | ||
2 | * | ||
3 | * Copyright (C) 2010 Samsung Electronics Co. Ltd. | ||
4 | * Jaswinder Singh <jassi.brar@samsung.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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/io.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/dmaengine.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/amba/bus.h> | ||
19 | #include <linux/amba/pl330.h> | ||
20 | |||
21 | #define NR_DEFAULT_DESC 16 | ||
22 | |||
23 | enum desc_status { | ||
24 | /* In the DMAC pool */ | ||
25 | FREE, | ||
26 | /* | ||
27 | * Allocted to some channel during prep_xxx | ||
28 | * Also may be sitting on the work_list. | ||
29 | */ | ||
30 | PREP, | ||
31 | /* | ||
32 | * Sitting on the work_list and already submitted | ||
33 | * to the PL330 core. Not more than two descriptors | ||
34 | * of a channel can be BUSY at any time. | ||
35 | */ | ||
36 | BUSY, | ||
37 | /* | ||
38 | * Sitting on the channel work_list but xfer done | ||
39 | * by PL330 core | ||
40 | */ | ||
41 | DONE, | ||
42 | }; | ||
43 | |||
44 | struct dma_pl330_chan { | ||
45 | /* Schedule desc completion */ | ||
46 | struct tasklet_struct task; | ||
47 | |||
48 | /* DMA-Engine Channel */ | ||
49 | struct dma_chan chan; | ||
50 | |||
51 | /* Last completed cookie */ | ||
52 | dma_cookie_t completed; | ||
53 | |||
54 | /* List of to be xfered descriptors */ | ||
55 | struct list_head work_list; | ||
56 | |||
57 | /* Pointer to the DMAC that manages this channel, | ||
58 | * NULL if the channel is available to be acquired. | ||
59 | * As the parent, this DMAC also provides descriptors | ||
60 | * to the channel. | ||
61 | */ | ||
62 | struct dma_pl330_dmac *dmac; | ||
63 | |||
64 | /* To protect channel manipulation */ | ||
65 | spinlock_t lock; | ||
66 | |||
67 | /* Token of a hardware channel thread of PL330 DMAC | ||
68 | * NULL if the channel is available to be acquired. | ||
69 | */ | ||
70 | void *pl330_chid; | ||
71 | }; | ||
72 | |||
73 | struct dma_pl330_dmac { | ||
74 | struct pl330_info pif; | ||
75 | |||
76 | /* DMA-Engine Device */ | ||
77 | struct dma_device ddma; | ||
78 | |||
79 | /* Pool of descriptors available for the DMAC's channels */ | ||
80 | struct list_head desc_pool; | ||
81 | /* To protect desc_pool manipulation */ | ||
82 | spinlock_t pool_lock; | ||
83 | |||
84 | /* Peripheral channels connected to this DMAC */ | ||
85 | struct dma_pl330_chan peripherals[0]; /* keep at end */ | ||
86 | }; | ||
87 | |||
88 | struct dma_pl330_desc { | ||
89 | /* To attach to a queue as child */ | ||
90 | struct list_head node; | ||
91 | |||
92 | /* Descriptor for the DMA Engine API */ | ||
93 | struct dma_async_tx_descriptor txd; | ||
94 | |||
95 | /* Xfer for PL330 core */ | ||
96 | struct pl330_xfer px; | ||
97 | |||
98 | struct pl330_reqcfg rqcfg; | ||
99 | struct pl330_req req; | ||
100 | |||
101 | enum desc_status status; | ||
102 | |||
103 | /* The channel which currently holds this desc */ | ||
104 | struct dma_pl330_chan *pchan; | ||
105 | }; | ||
106 | |||
107 | static inline struct dma_pl330_chan * | ||
108 | to_pchan(struct dma_chan *ch) | ||
109 | { | ||
110 | if (!ch) | ||
111 | return NULL; | ||
112 | |||
113 | return container_of(ch, struct dma_pl330_chan, chan); | ||
114 | } | ||
115 | |||
116 | static inline struct dma_pl330_desc * | ||
117 | to_desc(struct dma_async_tx_descriptor *tx) | ||
118 | { | ||
119 | return container_of(tx, struct dma_pl330_desc, txd); | ||
120 | } | ||
121 | |||
122 | static inline void free_desc_list(struct list_head *list) | ||
123 | { | ||
124 | struct dma_pl330_dmac *pdmac; | ||
125 | struct dma_pl330_desc *desc; | ||
126 | struct dma_pl330_chan *pch; | ||
127 | unsigned long flags; | ||
128 | |||
129 | if (list_empty(list)) | ||
130 | return; | ||
131 | |||
132 | /* Finish off the work list */ | ||
133 | list_for_each_entry(desc, list, node) { | ||
134 | dma_async_tx_callback callback; | ||
135 | void *param; | ||
136 | |||
137 | /* All desc in a list belong to same channel */ | ||
138 | pch = desc->pchan; | ||
139 | callback = desc->txd.callback; | ||
140 | param = desc->txd.callback_param; | ||
141 | |||
142 | if (callback) | ||
143 | callback(param); | ||
144 | |||
145 | desc->pchan = NULL; | ||
146 | } | ||
147 | |||
148 | pdmac = pch->dmac; | ||
149 | |||
150 | spin_lock_irqsave(&pdmac->pool_lock, flags); | ||
151 | list_splice_tail_init(list, &pdmac->desc_pool); | ||
152 | spin_unlock_irqrestore(&pdmac->pool_lock, flags); | ||
153 | } | ||
154 | |||
155 | static inline void fill_queue(struct dma_pl330_chan *pch) | ||
156 | { | ||
157 | struct dma_pl330_desc *desc; | ||
158 | int ret; | ||
159 | |||
160 | list_for_each_entry(desc, &pch->work_list, node) { | ||
161 | |||
162 | /* If already submitted */ | ||
163 | if (desc->status == BUSY) | ||
164 | break; | ||
165 | |||
166 | ret = pl330_submit_req(pch->pl330_chid, | ||
167 | &desc->req); | ||
168 | if (!ret) { | ||
169 | desc->status = BUSY; | ||
170 | break; | ||
171 | } else if (ret == -EAGAIN) { | ||
172 | /* QFull or DMAC Dying */ | ||
173 | break; | ||
174 | } else { | ||
175 | /* Unacceptable request */ | ||
176 | desc->status = DONE; | ||
177 | dev_err(pch->dmac->pif.dev, "%s:%d Bad Desc(%d)\n", | ||
178 | __func__, __LINE__, desc->txd.cookie); | ||
179 | tasklet_schedule(&pch->task); | ||
180 | } | ||
181 | } | ||
182 | } | ||
183 | |||
184 | static void pl330_tasklet(unsigned long data) | ||
185 | { | ||
186 | struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; | ||
187 | struct dma_pl330_desc *desc, *_dt; | ||
188 | unsigned long flags; | ||
189 | LIST_HEAD(list); | ||
190 | |||
191 | spin_lock_irqsave(&pch->lock, flags); | ||
192 | |||
193 | /* Pick up ripe tomatoes */ | ||
194 | list_for_each_entry_safe(desc, _dt, &pch->work_list, node) | ||
195 | if (desc->status == DONE) { | ||
196 | pch->completed = desc->txd.cookie; | ||
197 | list_move_tail(&desc->node, &list); | ||
198 | } | ||
199 | |||
200 | /* Try to submit a req imm. next to the last completed cookie */ | ||
201 | fill_queue(pch); | ||
202 | |||
203 | /* Make sure the PL330 Channel thread is active */ | ||
204 | pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START); | ||
205 | |||
206 | spin_unlock_irqrestore(&pch->lock, flags); | ||
207 | |||
208 | free_desc_list(&list); | ||
209 | } | ||
210 | |||
211 | static void dma_pl330_rqcb(void *token, enum pl330_op_err err) | ||
212 | { | ||
213 | struct dma_pl330_desc *desc = token; | ||
214 | struct dma_pl330_chan *pch = desc->pchan; | ||
215 | unsigned long flags; | ||
216 | |||
217 | /* If desc aborted */ | ||
218 | if (!pch) | ||
219 | return; | ||
220 | |||
221 | spin_lock_irqsave(&pch->lock, flags); | ||
222 | |||
223 | desc->status = DONE; | ||
224 | |||
225 | spin_unlock_irqrestore(&pch->lock, flags); | ||
226 | |||
227 | tasklet_schedule(&pch->task); | ||
228 | } | ||
229 | |||
230 | static int pl330_alloc_chan_resources(struct dma_chan *chan) | ||
231 | { | ||
232 | struct dma_pl330_chan *pch = to_pchan(chan); | ||
233 | struct dma_pl330_dmac *pdmac = pch->dmac; | ||
234 | unsigned long flags; | ||
235 | |||
236 | spin_lock_irqsave(&pch->lock, flags); | ||
237 | |||
238 | pch->completed = chan->cookie = 1; | ||
239 | |||
240 | pch->pl330_chid = pl330_request_channel(&pdmac->pif); | ||
241 | if (!pch->pl330_chid) { | ||
242 | spin_unlock_irqrestore(&pch->lock, flags); | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | tasklet_init(&pch->task, pl330_tasklet, (unsigned long) pch); | ||
247 | |||
248 | spin_unlock_irqrestore(&pch->lock, flags); | ||
249 | |||
250 | return 1; | ||
251 | } | ||
252 | |||
253 | static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, unsigned long arg) | ||
254 | { | ||
255 | struct dma_pl330_chan *pch = to_pchan(chan); | ||
256 | struct dma_pl330_desc *desc; | ||
257 | unsigned long flags; | ||
258 | |||
259 | /* Only supports DMA_TERMINATE_ALL */ | ||
260 | if (cmd != DMA_TERMINATE_ALL) | ||
261 | return -ENXIO; | ||
262 | |||
263 | spin_lock_irqsave(&pch->lock, flags); | ||
264 | |||
265 | /* FLUSH the PL330 Channel thread */ | ||
266 | pl330_chan_ctrl(pch->pl330_chid, PL330_OP_FLUSH); | ||
267 | |||
268 | /* Mark all desc done */ | ||
269 | list_for_each_entry(desc, &pch->work_list, node) | ||
270 | desc->status = DONE; | ||
271 | |||
272 | spin_unlock_irqrestore(&pch->lock, flags); | ||
273 | |||
274 | pl330_tasklet((unsigned long) pch); | ||
275 | |||
276 | return 0; | ||
277 | } | ||
278 | |||
279 | static void pl330_free_chan_resources(struct dma_chan *chan) | ||
280 | { | ||
281 | struct dma_pl330_chan *pch = to_pchan(chan); | ||
282 | unsigned long flags; | ||
283 | |||
284 | spin_lock_irqsave(&pch->lock, flags); | ||
285 | |||
286 | tasklet_kill(&pch->task); | ||
287 | |||
288 | pl330_release_channel(pch->pl330_chid); | ||
289 | pch->pl330_chid = NULL; | ||
290 | |||
291 | spin_unlock_irqrestore(&pch->lock, flags); | ||
292 | } | ||
293 | |||
294 | static enum dma_status | ||
295 | pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie, | ||
296 | struct dma_tx_state *txstate) | ||
297 | { | ||
298 | struct dma_pl330_chan *pch = to_pchan(chan); | ||
299 | dma_cookie_t last_done, last_used; | ||
300 | int ret; | ||
301 | |||
302 | last_done = pch->completed; | ||
303 | last_used = chan->cookie; | ||
304 | |||
305 | ret = dma_async_is_complete(cookie, last_done, last_used); | ||
306 | |||
307 | dma_set_tx_state(txstate, last_done, last_used, 0); | ||
308 | |||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | static void pl330_issue_pending(struct dma_chan *chan) | ||
313 | { | ||
314 | pl330_tasklet((unsigned long) to_pchan(chan)); | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * We returned the last one of the circular list of descriptor(s) | ||
319 | * from prep_xxx, so the argument to submit corresponds to the last | ||
320 | * descriptor of the list. | ||
321 | */ | ||
322 | static dma_cookie_t pl330_tx_submit(struct dma_async_tx_descriptor *tx) | ||
323 | { | ||
324 | struct dma_pl330_desc *desc, *last = to_desc(tx); | ||
325 | struct dma_pl330_chan *pch = to_pchan(tx->chan); | ||
326 | dma_cookie_t cookie; | ||
327 | unsigned long flags; | ||
328 | |||
329 | spin_lock_irqsave(&pch->lock, flags); | ||
330 | |||
331 | /* Assign cookies to all nodes */ | ||
332 | cookie = tx->chan->cookie; | ||
333 | |||
334 | while (!list_empty(&last->node)) { | ||
335 | desc = list_entry(last->node.next, struct dma_pl330_desc, node); | ||
336 | |||
337 | if (++cookie < 0) | ||
338 | cookie = 1; | ||
339 | desc->txd.cookie = cookie; | ||
340 | |||
341 | list_move_tail(&desc->node, &pch->work_list); | ||
342 | } | ||
343 | |||
344 | if (++cookie < 0) | ||
345 | cookie = 1; | ||
346 | last->txd.cookie = cookie; | ||
347 | |||
348 | list_add_tail(&last->node, &pch->work_list); | ||
349 | |||
350 | tx->chan->cookie = cookie; | ||
351 | |||
352 | spin_unlock_irqrestore(&pch->lock, flags); | ||
353 | |||
354 | return cookie; | ||
355 | } | ||
356 | |||
357 | static inline void _init_desc(struct dma_pl330_desc *desc) | ||
358 | { | ||
359 | desc->pchan = NULL; | ||
360 | desc->req.x = &desc->px; | ||
361 | desc->req.token = desc; | ||
362 | desc->rqcfg.swap = SWAP_NO; | ||
363 | desc->rqcfg.privileged = 0; | ||
364 | desc->rqcfg.insnaccess = 0; | ||
365 | desc->rqcfg.scctl = SCCTRL0; | ||
366 | desc->rqcfg.dcctl = DCCTRL0; | ||
367 | desc->req.cfg = &desc->rqcfg; | ||
368 | desc->req.xfer_cb = dma_pl330_rqcb; | ||
369 | desc->txd.tx_submit = pl330_tx_submit; | ||
370 | |||
371 | INIT_LIST_HEAD(&desc->node); | ||
372 | } | ||
373 | |||
374 | /* Returns the number of descriptors added to the DMAC pool */ | ||
375 | int add_desc(struct dma_pl330_dmac *pdmac, gfp_t flg, int count) | ||
376 | { | ||
377 | struct dma_pl330_desc *desc; | ||
378 | unsigned long flags; | ||
379 | int i; | ||
380 | |||
381 | if (!pdmac) | ||
382 | return 0; | ||
383 | |||
384 | desc = kmalloc(count * sizeof(*desc), flg); | ||
385 | if (!desc) | ||
386 | return 0; | ||
387 | |||
388 | spin_lock_irqsave(&pdmac->pool_lock, flags); | ||
389 | |||
390 | for (i = 0; i < count; i++) { | ||
391 | _init_desc(&desc[i]); | ||
392 | list_add_tail(&desc[i].node, &pdmac->desc_pool); | ||
393 | } | ||
394 | |||
395 | spin_unlock_irqrestore(&pdmac->pool_lock, flags); | ||
396 | |||
397 | return count; | ||
398 | } | ||
399 | |||
400 | static struct dma_pl330_desc * | ||
401 | pluck_desc(struct dma_pl330_dmac *pdmac) | ||
402 | { | ||
403 | struct dma_pl330_desc *desc = NULL; | ||
404 | unsigned long flags; | ||
405 | |||
406 | if (!pdmac) | ||
407 | return NULL; | ||
408 | |||
409 | spin_lock_irqsave(&pdmac->pool_lock, flags); | ||
410 | |||
411 | if (!list_empty(&pdmac->desc_pool)) { | ||
412 | desc = list_entry(pdmac->desc_pool.next, | ||
413 | struct dma_pl330_desc, node); | ||
414 | |||
415 | list_del_init(&desc->node); | ||
416 | |||
417 | desc->status = PREP; | ||
418 | desc->txd.callback = NULL; | ||
419 | } | ||
420 | |||
421 | spin_unlock_irqrestore(&pdmac->pool_lock, flags); | ||
422 | |||
423 | return desc; | ||
424 | } | ||
425 | |||
426 | static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) | ||
427 | { | ||
428 | struct dma_pl330_dmac *pdmac = pch->dmac; | ||
429 | struct dma_pl330_peri *peri = pch->chan.private; | ||
430 | struct dma_pl330_desc *desc; | ||
431 | |||
432 | /* Pluck one desc from the pool of DMAC */ | ||
433 | desc = pluck_desc(pdmac); | ||
434 | |||
435 | /* If the DMAC pool is empty, alloc new */ | ||
436 | if (!desc) { | ||
437 | if (!add_desc(pdmac, GFP_ATOMIC, 1)) | ||
438 | return NULL; | ||
439 | |||
440 | /* Try again */ | ||
441 | desc = pluck_desc(pdmac); | ||
442 | if (!desc) { | ||
443 | dev_err(pch->dmac->pif.dev, | ||
444 | "%s:%d ALERT!\n", __func__, __LINE__); | ||
445 | return NULL; | ||
446 | } | ||
447 | } | ||
448 | |||
449 | /* Initialize the descriptor */ | ||
450 | desc->pchan = pch; | ||
451 | desc->txd.cookie = 0; | ||
452 | async_tx_ack(&desc->txd); | ||
453 | |||
454 | desc->req.rqtype = peri->rqtype; | ||
455 | desc->req.peri = peri->peri_id; | ||
456 | |||
457 | dma_async_tx_descriptor_init(&desc->txd, &pch->chan); | ||
458 | |||
459 | return desc; | ||
460 | } | ||
461 | |||
462 | static inline void fill_px(struct pl330_xfer *px, | ||
463 | dma_addr_t dst, dma_addr_t src, size_t len) | ||
464 | { | ||
465 | px->next = NULL; | ||
466 | px->bytes = len; | ||
467 | px->dst_addr = dst; | ||
468 | px->src_addr = src; | ||
469 | } | ||
470 | |||
471 | static struct dma_pl330_desc * | ||
472 | __pl330_prep_dma_memcpy(struct dma_pl330_chan *pch, dma_addr_t dst, | ||
473 | dma_addr_t src, size_t len) | ||
474 | { | ||
475 | struct dma_pl330_desc *desc = pl330_get_desc(pch); | ||
476 | |||
477 | if (!desc) { | ||
478 | dev_err(pch->dmac->pif.dev, "%s:%d Unable to fetch desc\n", | ||
479 | __func__, __LINE__); | ||
480 | return NULL; | ||
481 | } | ||
482 | |||
483 | /* | ||
484 | * Ideally we should lookout for reqs bigger than | ||
485 | * those that can be programmed with 256 bytes of | ||
486 | * MC buffer, but considering a req size is seldom | ||
487 | * going to be word-unaligned and more than 200MB, | ||
488 | * we take it easy. | ||
489 | * Also, should the limit is reached we'd rather | ||
490 | * have the platform increase MC buffer size than | ||
491 | * complicating this API driver. | ||
492 | */ | ||
493 | fill_px(&desc->px, dst, src, len); | ||
494 | |||
495 | return desc; | ||
496 | } | ||
497 | |||
498 | /* Call after fixing burst size */ | ||
499 | static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) | ||
500 | { | ||
501 | struct dma_pl330_chan *pch = desc->pchan; | ||
502 | struct pl330_info *pi = &pch->dmac->pif; | ||
503 | int burst_len; | ||
504 | |||
505 | burst_len = pi->pcfg.data_bus_width / 8; | ||
506 | burst_len *= pi->pcfg.data_buf_dep; | ||
507 | burst_len >>= desc->rqcfg.brst_size; | ||
508 | |||
509 | /* src/dst_burst_len can't be more than 16 */ | ||
510 | if (burst_len > 16) | ||
511 | burst_len = 16; | ||
512 | |||
513 | while (burst_len > 1) { | ||
514 | if (!(len % (burst_len << desc->rqcfg.brst_size))) | ||
515 | break; | ||
516 | burst_len--; | ||
517 | } | ||
518 | |||
519 | return burst_len; | ||
520 | } | ||
521 | |||
522 | static struct dma_async_tx_descriptor * | ||
523 | pl330_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dst, | ||
524 | dma_addr_t src, size_t len, unsigned long flags) | ||
525 | { | ||
526 | struct dma_pl330_desc *desc; | ||
527 | struct dma_pl330_chan *pch = to_pchan(chan); | ||
528 | struct dma_pl330_peri *peri = chan->private; | ||
529 | struct pl330_info *pi; | ||
530 | int burst; | ||
531 | |||
532 | if (unlikely(!pch || !len || !peri)) | ||
533 | return NULL; | ||
534 | |||
535 | if (peri->rqtype != MEMTOMEM) | ||
536 | return NULL; | ||
537 | |||
538 | pi = &pch->dmac->pif; | ||
539 | |||
540 | desc = __pl330_prep_dma_memcpy(pch, dst, src, len); | ||
541 | if (!desc) | ||
542 | return NULL; | ||
543 | |||
544 | desc->rqcfg.src_inc = 1; | ||
545 | desc->rqcfg.dst_inc = 1; | ||
546 | |||
547 | /* Select max possible burst size */ | ||
548 | burst = pi->pcfg.data_bus_width / 8; | ||
549 | |||
550 | while (burst > 1) { | ||
551 | if (!(len % burst)) | ||
552 | break; | ||
553 | burst /= 2; | ||
554 | } | ||
555 | |||
556 | desc->rqcfg.brst_size = 0; | ||
557 | while (burst != (1 << desc->rqcfg.brst_size)) | ||
558 | desc->rqcfg.brst_size++; | ||
559 | |||
560 | desc->rqcfg.brst_len = get_burst_len(desc, len); | ||
561 | |||
562 | desc->txd.flags = flags; | ||
563 | |||
564 | return &desc->txd; | ||
565 | } | ||
566 | |||
567 | static struct dma_async_tx_descriptor * | ||
568 | pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | ||
569 | unsigned int sg_len, enum dma_data_direction direction, | ||
570 | unsigned long flg) | ||
571 | { | ||
572 | struct dma_pl330_desc *first, *desc = NULL; | ||
573 | struct dma_pl330_chan *pch = to_pchan(chan); | ||
574 | struct dma_pl330_peri *peri = chan->private; | ||
575 | struct scatterlist *sg; | ||
576 | unsigned long flags; | ||
577 | int i, burst_size; | ||
578 | dma_addr_t addr; | ||
579 | |||
580 | if (unlikely(!pch || !sgl || !sg_len)) | ||
581 | return NULL; | ||
582 | |||
583 | /* Make sure the direction is consistent */ | ||
584 | if ((direction == DMA_TO_DEVICE && | ||
585 | peri->rqtype != MEMTODEV) || | ||
586 | (direction == DMA_FROM_DEVICE && | ||
587 | peri->rqtype != DEVTOMEM)) { | ||
588 | dev_err(pch->dmac->pif.dev, "%s:%d Invalid Direction\n", | ||
589 | __func__, __LINE__); | ||
590 | return NULL; | ||
591 | } | ||
592 | |||
593 | addr = peri->fifo_addr; | ||
594 | burst_size = peri->burst_sz; | ||
595 | |||
596 | first = NULL; | ||
597 | |||
598 | for_each_sg(sgl, sg, sg_len, i) { | ||
599 | |||
600 | desc = pl330_get_desc(pch); | ||
601 | if (!desc) { | ||
602 | struct dma_pl330_dmac *pdmac = pch->dmac; | ||
603 | |||
604 | dev_err(pch->dmac->pif.dev, | ||
605 | "%s:%d Unable to fetch desc\n", | ||
606 | __func__, __LINE__); | ||
607 | if (!first) | ||
608 | return NULL; | ||
609 | |||
610 | spin_lock_irqsave(&pdmac->pool_lock, flags); | ||
611 | |||
612 | while (!list_empty(&first->node)) { | ||
613 | desc = list_entry(first->node.next, | ||
614 | struct dma_pl330_desc, node); | ||
615 | list_move_tail(&desc->node, &pdmac->desc_pool); | ||
616 | } | ||
617 | |||
618 | list_move_tail(&first->node, &pdmac->desc_pool); | ||
619 | |||
620 | spin_unlock_irqrestore(&pdmac->pool_lock, flags); | ||
621 | |||
622 | return NULL; | ||
623 | } | ||
624 | |||
625 | if (!first) | ||
626 | first = desc; | ||
627 | else | ||
628 | list_add_tail(&desc->node, &first->node); | ||
629 | |||
630 | if (direction == DMA_TO_DEVICE) { | ||
631 | desc->rqcfg.src_inc = 1; | ||
632 | desc->rqcfg.dst_inc = 0; | ||
633 | fill_px(&desc->px, | ||
634 | addr, sg_dma_address(sg), sg_dma_len(sg)); | ||
635 | } else { | ||
636 | desc->rqcfg.src_inc = 0; | ||
637 | desc->rqcfg.dst_inc = 1; | ||
638 | fill_px(&desc->px, | ||
639 | sg_dma_address(sg), addr, sg_dma_len(sg)); | ||
640 | } | ||
641 | |||
642 | desc->rqcfg.brst_size = burst_size; | ||
643 | desc->rqcfg.brst_len = 1; | ||
644 | } | ||
645 | |||
646 | /* Return the last desc in the chain */ | ||
647 | desc->txd.flags = flg; | ||
648 | return &desc->txd; | ||
649 | } | ||
650 | |||
651 | static irqreturn_t pl330_irq_handler(int irq, void *data) | ||
652 | { | ||
653 | if (pl330_update(data)) | ||
654 | return IRQ_HANDLED; | ||
655 | else | ||
656 | return IRQ_NONE; | ||
657 | } | ||
658 | |||
659 | static int __devinit | ||
660 | pl330_probe(struct amba_device *adev, struct amba_id *id) | ||
661 | { | ||
662 | struct dma_pl330_platdata *pdat; | ||
663 | struct dma_pl330_dmac *pdmac; | ||
664 | struct dma_pl330_chan *pch; | ||
665 | struct pl330_info *pi; | ||
666 | struct dma_device *pd; | ||
667 | struct resource *res; | ||
668 | int i, ret, irq; | ||
669 | |||
670 | pdat = adev->dev.platform_data; | ||
671 | |||
672 | if (!pdat || !pdat->nr_valid_peri) { | ||
673 | dev_err(&adev->dev, "platform data missing\n"); | ||
674 | return -ENODEV; | ||
675 | } | ||
676 | |||
677 | /* Allocate a new DMAC and its Channels */ | ||
678 | pdmac = kzalloc(pdat->nr_valid_peri * sizeof(*pch) | ||
679 | + sizeof(*pdmac), GFP_KERNEL); | ||
680 | if (!pdmac) { | ||
681 | dev_err(&adev->dev, "unable to allocate mem\n"); | ||
682 | return -ENOMEM; | ||
683 | } | ||
684 | |||
685 | pi = &pdmac->pif; | ||
686 | pi->dev = &adev->dev; | ||
687 | pi->pl330_data = NULL; | ||
688 | pi->mcbufsz = pdat->mcbuf_sz; | ||
689 | |||
690 | res = &adev->res; | ||
691 | request_mem_region(res->start, resource_size(res), "dma-pl330"); | ||
692 | |||
693 | pi->base = ioremap(res->start, resource_size(res)); | ||
694 | if (!pi->base) { | ||
695 | ret = -ENXIO; | ||
696 | goto probe_err1; | ||
697 | } | ||
698 | |||
699 | irq = adev->irq[0]; | ||
700 | ret = request_irq(irq, pl330_irq_handler, 0, | ||
701 | dev_name(&adev->dev), pi); | ||
702 | if (ret) | ||
703 | goto probe_err2; | ||
704 | |||
705 | ret = pl330_add(pi); | ||
706 | if (ret) | ||
707 | goto probe_err3; | ||
708 | |||
709 | INIT_LIST_HEAD(&pdmac->desc_pool); | ||
710 | spin_lock_init(&pdmac->pool_lock); | ||
711 | |||
712 | /* Create a descriptor pool of default size */ | ||
713 | if (!add_desc(pdmac, GFP_KERNEL, NR_DEFAULT_DESC)) | ||
714 | dev_warn(&adev->dev, "unable to allocate desc\n"); | ||
715 | |||
716 | pd = &pdmac->ddma; | ||
717 | INIT_LIST_HEAD(&pd->channels); | ||
718 | |||
719 | /* Initialize channel parameters */ | ||
720 | for (i = 0; i < pdat->nr_valid_peri; i++) { | ||
721 | struct dma_pl330_peri *peri = &pdat->peri[i]; | ||
722 | pch = &pdmac->peripherals[i]; | ||
723 | |||
724 | switch (peri->rqtype) { | ||
725 | case MEMTOMEM: | ||
726 | dma_cap_set(DMA_MEMCPY, pd->cap_mask); | ||
727 | break; | ||
728 | case MEMTODEV: | ||
729 | case DEVTOMEM: | ||
730 | dma_cap_set(DMA_SLAVE, pd->cap_mask); | ||
731 | break; | ||
732 | default: | ||
733 | dev_err(&adev->dev, "DEVTODEV Not Supported\n"); | ||
734 | continue; | ||
735 | } | ||
736 | |||
737 | INIT_LIST_HEAD(&pch->work_list); | ||
738 | spin_lock_init(&pch->lock); | ||
739 | pch->pl330_chid = NULL; | ||
740 | pch->chan.private = peri; | ||
741 | pch->chan.device = pd; | ||
742 | pch->chan.chan_id = i; | ||
743 | pch->dmac = pdmac; | ||
744 | |||
745 | /* Add the channel to the DMAC list */ | ||
746 | pd->chancnt++; | ||
747 | list_add_tail(&pch->chan.device_node, &pd->channels); | ||
748 | } | ||
749 | |||
750 | pd->dev = &adev->dev; | ||
751 | |||
752 | pd->device_alloc_chan_resources = pl330_alloc_chan_resources; | ||
753 | pd->device_free_chan_resources = pl330_free_chan_resources; | ||
754 | pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy; | ||
755 | pd->device_tx_status = pl330_tx_status; | ||
756 | pd->device_prep_slave_sg = pl330_prep_slave_sg; | ||
757 | pd->device_control = pl330_control; | ||
758 | pd->device_issue_pending = pl330_issue_pending; | ||
759 | |||
760 | ret = dma_async_device_register(pd); | ||
761 | if (ret) { | ||
762 | dev_err(&adev->dev, "unable to register DMAC\n"); | ||
763 | goto probe_err4; | ||
764 | } | ||
765 | |||
766 | amba_set_drvdata(adev, pdmac); | ||
767 | |||
768 | dev_info(&adev->dev, | ||
769 | "Loaded driver for PL330 DMAC-%d\n", adev->periphid); | ||
770 | dev_info(&adev->dev, | ||
771 | "\tDBUFF-%ux%ubytes Num_Chans-%u Num_Peri-%u Num_Events-%u\n", | ||
772 | pi->pcfg.data_buf_dep, | ||
773 | pi->pcfg.data_bus_width / 8, pi->pcfg.num_chan, | ||
774 | pi->pcfg.num_peri, pi->pcfg.num_events); | ||
775 | |||
776 | return 0; | ||
777 | |||
778 | probe_err4: | ||
779 | pl330_del(pi); | ||
780 | probe_err3: | ||
781 | free_irq(irq, pi); | ||
782 | probe_err2: | ||
783 | iounmap(pi->base); | ||
784 | probe_err1: | ||
785 | release_mem_region(res->start, resource_size(res)); | ||
786 | kfree(pdmac); | ||
787 | |||
788 | return ret; | ||
789 | } | ||
790 | |||
791 | static int __devexit pl330_remove(struct amba_device *adev) | ||
792 | { | ||
793 | struct dma_pl330_dmac *pdmac = amba_get_drvdata(adev); | ||
794 | struct dma_pl330_chan *pch, *_p; | ||
795 | struct pl330_info *pi; | ||
796 | struct resource *res; | ||
797 | int irq; | ||
798 | |||
799 | if (!pdmac) | ||
800 | return 0; | ||
801 | |||
802 | amba_set_drvdata(adev, NULL); | ||
803 | |||
804 | /* Idle the DMAC */ | ||
805 | list_for_each_entry_safe(pch, _p, &pdmac->ddma.channels, | ||
806 | chan.device_node) { | ||
807 | |||
808 | /* Remove the channel */ | ||
809 | list_del(&pch->chan.device_node); | ||
810 | |||
811 | /* Flush the channel */ | ||
812 | pl330_control(&pch->chan, DMA_TERMINATE_ALL, 0); | ||
813 | pl330_free_chan_resources(&pch->chan); | ||
814 | } | ||
815 | |||
816 | pi = &pdmac->pif; | ||
817 | |||
818 | pl330_del(pi); | ||
819 | |||
820 | irq = adev->irq[0]; | ||
821 | free_irq(irq, pi); | ||
822 | |||
823 | iounmap(pi->base); | ||
824 | |||
825 | res = &adev->res; | ||
826 | release_mem_region(res->start, resource_size(res)); | ||
827 | |||
828 | kfree(pdmac); | ||
829 | |||
830 | return 0; | ||
831 | } | ||
832 | |||
833 | static struct amba_id pl330_ids[] = { | ||
834 | { | ||
835 | .id = 0x00041330, | ||
836 | .mask = 0x000fffff, | ||
837 | }, | ||
838 | { 0, 0 }, | ||
839 | }; | ||
840 | |||
841 | static struct amba_driver pl330_driver = { | ||
842 | .drv = { | ||
843 | .owner = THIS_MODULE, | ||
844 | .name = "dma-pl330", | ||
845 | }, | ||
846 | .id_table = pl330_ids, | ||
847 | .probe = pl330_probe, | ||
848 | .remove = pl330_remove, | ||
849 | }; | ||
850 | |||
851 | static int __init pl330_init(void) | ||
852 | { | ||
853 | return amba_driver_register(&pl330_driver); | ||
854 | } | ||
855 | module_init(pl330_init); | ||
856 | |||
857 | static void __exit pl330_exit(void) | ||
858 | { | ||
859 | amba_driver_unregister(&pl330_driver); | ||
860 | return; | ||
861 | } | ||
862 | module_exit(pl330_exit); | ||
863 | |||
864 | MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); | ||
865 | MODULE_DESCRIPTION("API Driver for PL330 DMAC"); | ||
866 | MODULE_LICENSE("GPL"); | ||
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..724038dab4ca 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 |
@@ -188,6 +195,13 @@ config GPIO_PCF857X | |||
188 | This driver provides an in-kernel interface to those GPIOs using | 195 | This driver provides an in-kernel interface to those GPIOs using |
189 | platform-neutral GPIO calls. | 196 | platform-neutral GPIO calls. |
190 | 197 | ||
198 | config GPIO_TC35892 | ||
199 | bool "TC35892 GPIOs" | ||
200 | depends on MFD_TC35892 | ||
201 | help | ||
202 | This enables support for the GPIOs found on the TC35892 | ||
203 | I/O Expander. | ||
204 | |||
191 | config GPIO_TWL4030 | 205 | config GPIO_TWL4030 |
192 | tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" | 206 | tristate "TWL4030, TWL5030, and TPS659x0 GPIOs" |
193 | depends on TWL4030_CORE | 207 | depends on TWL4030_CORE |
@@ -264,10 +278,10 @@ config GPIO_BT8XX | |||
264 | If unsure, say N. | 278 | If unsure, say N. |
265 | 279 | ||
266 | config GPIO_LANGWELL | 280 | config GPIO_LANGWELL |
267 | bool "Intel Moorestown Platform Langwell GPIO support" | 281 | bool "Intel Langwell/Penwell GPIO support" |
268 | depends on PCI | 282 | depends on PCI |
269 | help | 283 | help |
270 | Say Y here to support Intel Moorestown platform GPIO. | 284 | Say Y here to support Intel Langwell/Penwell GPIO. |
271 | 285 | ||
272 | config GPIO_TIMBERDALE | 286 | config GPIO_TIMBERDALE |
273 | bool "Support for timberdale GPIO IP" | 287 | bool "Support for timberdale GPIO IP" |
@@ -275,6 +289,15 @@ config GPIO_TIMBERDALE | |||
275 | ---help--- | 289 | ---help--- |
276 | Add support for the GPIO IP in the timberdale FPGA. | 290 | Add support for the GPIO IP in the timberdale FPGA. |
277 | 291 | ||
292 | config GPIO_RDC321X | ||
293 | tristate "RDC R-321x GPIO support" | ||
294 | depends on PCI && GPIOLIB | ||
295 | select MFD_CORE | ||
296 | select MFD_RDC321X | ||
297 | help | ||
298 | Support for the RDC R321x SoC GPIOs over southbridge | ||
299 | PCI configuration space. | ||
300 | |||
278 | comment "SPI GPIO expanders:" | 301 | comment "SPI GPIO expanders:" |
279 | 302 | ||
280 | config GPIO_MAX7301 | 303 | config GPIO_MAX7301 |
@@ -310,4 +333,14 @@ config GPIO_UCB1400 | |||
310 | To compile this driver as a module, choose M here: the | 333 | To compile this driver as a module, choose M here: the |
311 | module will be called ucb1400_gpio. | 334 | module will be called ucb1400_gpio. |
312 | 335 | ||
336 | comment "MODULbus GPIO expanders:" | ||
337 | |||
338 | config GPIO_JANZ_TTL | ||
339 | tristate "Janz VMOD-TTL Digital IO Module" | ||
340 | depends on MFD_JANZ_CMODIO | ||
341 | help | ||
342 | This enables support for the Janz VMOD-TTL Digital IO module. | ||
343 | This driver provides support for driving the pins in output | ||
344 | mode only. Input mode is not supported. | ||
345 | |||
313 | endif | 346 | endif |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 10f3f8d958b1..51c3cdd41b5a 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o | |||
16 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o | 16 | obj-$(CONFIG_GPIO_PCA953X) += pca953x.o |
17 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o | 17 | obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o |
18 | obj-$(CONFIG_GPIO_PL061) += pl061.o | 18 | obj-$(CONFIG_GPIO_PL061) += pl061.o |
19 | obj-$(CONFIG_GPIO_TC35892) += tc35892-gpio.o | ||
19 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o | 20 | obj-$(CONFIG_GPIO_TIMBERDALE) += timbgpio.o |
20 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o | 21 | obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o |
21 | obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o | 22 | obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o |
@@ -27,4 +28,6 @@ obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | |||
27 | obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o | 28 | obj-$(CONFIG_GPIO_WM831X) += wm831x-gpio.o |
28 | obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o | 29 | obj-$(CONFIG_GPIO_WM8350) += wm8350-gpiolib.o |
29 | obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o | 30 | obj-$(CONFIG_GPIO_WM8994) += wm8994-gpio.o |
30 | obj-$(CONFIG_GPIO_SCH) += sch_gpio.o \ No newline at end of file | 31 | obj-$(CONFIG_GPIO_SCH) += sch_gpio.o |
32 | obj-$(CONFIG_GPIO_RDC321X) += rdc321x-gpio.o | ||
33 | obj-$(CONFIG_GPIO_JANZ_TTL) += janz-ttl.o | ||
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/janz-ttl.c b/drivers/gpio/janz-ttl.c new file mode 100644 index 000000000000..813ac077e5d7 --- /dev/null +++ b/drivers/gpio/janz-ttl.c | |||
@@ -0,0 +1,258 @@ | |||
1 | /* | ||
2 | * Janz MODULbus VMOD-TTL GPIO Driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include <linux/mfd/janz.h> | ||
23 | |||
24 | #define DRV_NAME "janz-ttl" | ||
25 | |||
26 | #define PORTA_DIRECTION 0x23 | ||
27 | #define PORTB_DIRECTION 0x2B | ||
28 | #define PORTC_DIRECTION 0x06 | ||
29 | #define PORTA_IOCTL 0x24 | ||
30 | #define PORTB_IOCTL 0x2C | ||
31 | #define PORTC_IOCTL 0x07 | ||
32 | |||
33 | #define MASTER_INT_CTL 0x00 | ||
34 | #define MASTER_CONF_CTL 0x01 | ||
35 | |||
36 | #define CONF_PAE (1 << 2) | ||
37 | #define CONF_PBE (1 << 7) | ||
38 | #define CONF_PCE (1 << 4) | ||
39 | |||
40 | struct ttl_control_regs { | ||
41 | __be16 portc; | ||
42 | __be16 portb; | ||
43 | __be16 porta; | ||
44 | __be16 control; | ||
45 | }; | ||
46 | |||
47 | struct ttl_module { | ||
48 | struct gpio_chip gpio; | ||
49 | |||
50 | /* base address of registers */ | ||
51 | struct ttl_control_regs __iomem *regs; | ||
52 | |||
53 | u8 portc_shadow; | ||
54 | u8 portb_shadow; | ||
55 | u8 porta_shadow; | ||
56 | |||
57 | spinlock_t lock; | ||
58 | }; | ||
59 | |||
60 | static int ttl_get_value(struct gpio_chip *gpio, unsigned offset) | ||
61 | { | ||
62 | struct ttl_module *mod = dev_get_drvdata(gpio->dev); | ||
63 | u8 *shadow; | ||
64 | int ret; | ||
65 | |||
66 | if (offset < 8) { | ||
67 | shadow = &mod->porta_shadow; | ||
68 | } else if (offset < 16) { | ||
69 | shadow = &mod->portb_shadow; | ||
70 | offset -= 8; | ||
71 | } else { | ||
72 | shadow = &mod->portc_shadow; | ||
73 | offset -= 16; | ||
74 | } | ||
75 | |||
76 | spin_lock(&mod->lock); | ||
77 | ret = *shadow & (1 << offset); | ||
78 | spin_unlock(&mod->lock); | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | static void ttl_set_value(struct gpio_chip *gpio, unsigned offset, int value) | ||
83 | { | ||
84 | struct ttl_module *mod = dev_get_drvdata(gpio->dev); | ||
85 | void __iomem *port; | ||
86 | u8 *shadow; | ||
87 | |||
88 | if (offset < 8) { | ||
89 | port = &mod->regs->porta; | ||
90 | shadow = &mod->porta_shadow; | ||
91 | } else if (offset < 16) { | ||
92 | port = &mod->regs->portb; | ||
93 | shadow = &mod->portb_shadow; | ||
94 | offset -= 8; | ||
95 | } else { | ||
96 | port = &mod->regs->portc; | ||
97 | shadow = &mod->portc_shadow; | ||
98 | offset -= 16; | ||
99 | } | ||
100 | |||
101 | spin_lock(&mod->lock); | ||
102 | if (value) | ||
103 | *shadow |= (1 << offset); | ||
104 | else | ||
105 | *shadow &= ~(1 << offset); | ||
106 | |||
107 | iowrite16be(*shadow, port); | ||
108 | spin_unlock(&mod->lock); | ||
109 | } | ||
110 | |||
111 | static void __devinit ttl_write_reg(struct ttl_module *mod, u8 reg, u16 val) | ||
112 | { | ||
113 | iowrite16be(reg, &mod->regs->control); | ||
114 | iowrite16be(val, &mod->regs->control); | ||
115 | } | ||
116 | |||
117 | static void __devinit ttl_setup_device(struct ttl_module *mod) | ||
118 | { | ||
119 | /* reset the device to a known state */ | ||
120 | iowrite16be(0x0000, &mod->regs->control); | ||
121 | iowrite16be(0x0001, &mod->regs->control); | ||
122 | iowrite16be(0x0000, &mod->regs->control); | ||
123 | |||
124 | /* put all ports in open-drain mode */ | ||
125 | ttl_write_reg(mod, PORTA_IOCTL, 0x00ff); | ||
126 | ttl_write_reg(mod, PORTB_IOCTL, 0x00ff); | ||
127 | ttl_write_reg(mod, PORTC_IOCTL, 0x000f); | ||
128 | |||
129 | /* set all ports as outputs */ | ||
130 | ttl_write_reg(mod, PORTA_DIRECTION, 0x0000); | ||
131 | ttl_write_reg(mod, PORTB_DIRECTION, 0x0000); | ||
132 | ttl_write_reg(mod, PORTC_DIRECTION, 0x0000); | ||
133 | |||
134 | /* set all ports to drive zeroes */ | ||
135 | iowrite16be(0x0000, &mod->regs->porta); | ||
136 | iowrite16be(0x0000, &mod->regs->portb); | ||
137 | iowrite16be(0x0000, &mod->regs->portc); | ||
138 | |||
139 | /* enable all ports */ | ||
140 | ttl_write_reg(mod, MASTER_CONF_CTL, CONF_PAE | CONF_PBE | CONF_PCE); | ||
141 | } | ||
142 | |||
143 | static int __devinit ttl_probe(struct platform_device *pdev) | ||
144 | { | ||
145 | struct janz_platform_data *pdata; | ||
146 | struct device *dev = &pdev->dev; | ||
147 | struct ttl_module *mod; | ||
148 | struct gpio_chip *gpio; | ||
149 | struct resource *res; | ||
150 | int ret; | ||
151 | |||
152 | pdata = pdev->dev.platform_data; | ||
153 | if (!pdata) { | ||
154 | dev_err(dev, "no platform data\n"); | ||
155 | ret = -ENXIO; | ||
156 | goto out_return; | ||
157 | } | ||
158 | |||
159 | mod = kzalloc(sizeof(*mod), GFP_KERNEL); | ||
160 | if (!mod) { | ||
161 | dev_err(dev, "unable to allocate private data\n"); | ||
162 | ret = -ENOMEM; | ||
163 | goto out_return; | ||
164 | } | ||
165 | |||
166 | platform_set_drvdata(pdev, mod); | ||
167 | spin_lock_init(&mod->lock); | ||
168 | |||
169 | /* get access to the MODULbus registers for this module */ | ||
170 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
171 | if (!res) { | ||
172 | dev_err(dev, "MODULbus registers not found\n"); | ||
173 | ret = -ENODEV; | ||
174 | goto out_free_mod; | ||
175 | } | ||
176 | |||
177 | mod->regs = ioremap(res->start, resource_size(res)); | ||
178 | if (!mod->regs) { | ||
179 | dev_err(dev, "MODULbus registers not ioremap\n"); | ||
180 | ret = -ENOMEM; | ||
181 | goto out_free_mod; | ||
182 | } | ||
183 | |||
184 | ttl_setup_device(mod); | ||
185 | |||
186 | /* Initialize the GPIO data structures */ | ||
187 | gpio = &mod->gpio; | ||
188 | gpio->dev = &pdev->dev; | ||
189 | gpio->label = pdev->name; | ||
190 | gpio->get = ttl_get_value; | ||
191 | gpio->set = ttl_set_value; | ||
192 | gpio->owner = THIS_MODULE; | ||
193 | |||
194 | /* request dynamic allocation */ | ||
195 | gpio->base = -1; | ||
196 | gpio->ngpio = 20; | ||
197 | |||
198 | ret = gpiochip_add(gpio); | ||
199 | if (ret) { | ||
200 | dev_err(dev, "unable to add GPIO chip\n"); | ||
201 | goto out_iounmap_regs; | ||
202 | } | ||
203 | |||
204 | dev_info(&pdev->dev, "module %d: registered GPIO device\n", | ||
205 | pdata->modno); | ||
206 | return 0; | ||
207 | |||
208 | out_iounmap_regs: | ||
209 | iounmap(mod->regs); | ||
210 | out_free_mod: | ||
211 | kfree(mod); | ||
212 | out_return: | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static int __devexit ttl_remove(struct platform_device *pdev) | ||
217 | { | ||
218 | struct ttl_module *mod = platform_get_drvdata(pdev); | ||
219 | struct device *dev = &pdev->dev; | ||
220 | int ret; | ||
221 | |||
222 | ret = gpiochip_remove(&mod->gpio); | ||
223 | if (ret) { | ||
224 | dev_err(dev, "unable to remove GPIO chip\n"); | ||
225 | return ret; | ||
226 | } | ||
227 | |||
228 | iounmap(mod->regs); | ||
229 | kfree(mod); | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static struct platform_driver ttl_driver = { | ||
234 | .driver = { | ||
235 | .name = DRV_NAME, | ||
236 | .owner = THIS_MODULE, | ||
237 | }, | ||
238 | .probe = ttl_probe, | ||
239 | .remove = __devexit_p(ttl_remove), | ||
240 | }; | ||
241 | |||
242 | static int __init ttl_init(void) | ||
243 | { | ||
244 | return platform_driver_register(&ttl_driver); | ||
245 | } | ||
246 | |||
247 | static void __exit ttl_exit(void) | ||
248 | { | ||
249 | platform_driver_unregister(&ttl_driver); | ||
250 | } | ||
251 | |||
252 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | ||
253 | MODULE_DESCRIPTION("Janz MODULbus VMOD-TTL Driver"); | ||
254 | MODULE_LICENSE("GPL"); | ||
255 | MODULE_ALIAS("platform:janz-ttl"); | ||
256 | |||
257 | module_init(ttl_init); | ||
258 | module_exit(ttl_exit); | ||
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/gpio/rdc321x-gpio.c b/drivers/gpio/rdc321x-gpio.c new file mode 100644 index 000000000000..2762698e0204 --- /dev/null +++ b/drivers/gpio/rdc321x-gpio.c | |||
@@ -0,0 +1,246 @@ | |||
1 | /* | ||
2 | * RDC321x GPIO driver | ||
3 | * | ||
4 | * Copyright (C) 2008, Volker Weiss <dev@tintuc.de> | ||
5 | * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org> | ||
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, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/spinlock.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <linux/pci.h> | ||
28 | #include <linux/gpio.h> | ||
29 | #include <linux/mfd/rdc321x.h> | ||
30 | #include <linux/slab.h> | ||
31 | |||
32 | struct rdc321x_gpio { | ||
33 | spinlock_t lock; | ||
34 | struct pci_dev *sb_pdev; | ||
35 | u32 data_reg[2]; | ||
36 | int reg1_ctrl_base; | ||
37 | int reg1_data_base; | ||
38 | int reg2_ctrl_base; | ||
39 | int reg2_data_base; | ||
40 | struct gpio_chip chip; | ||
41 | }; | ||
42 | |||
43 | /* read GPIO pin */ | ||
44 | static int rdc_gpio_get_value(struct gpio_chip *chip, unsigned gpio) | ||
45 | { | ||
46 | struct rdc321x_gpio *gpch; | ||
47 | u32 value = 0; | ||
48 | int reg; | ||
49 | |||
50 | gpch = container_of(chip, struct rdc321x_gpio, chip); | ||
51 | reg = gpio < 32 ? gpch->reg1_data_base : gpch->reg2_data_base; | ||
52 | |||
53 | spin_lock(&gpch->lock); | ||
54 | pci_write_config_dword(gpch->sb_pdev, reg, | ||
55 | gpch->data_reg[gpio < 32 ? 0 : 1]); | ||
56 | pci_read_config_dword(gpch->sb_pdev, reg, &value); | ||
57 | spin_unlock(&gpch->lock); | ||
58 | |||
59 | return (1 << (gpio & 0x1f)) & value ? 1 : 0; | ||
60 | } | ||
61 | |||
62 | static void rdc_gpio_set_value_impl(struct gpio_chip *chip, | ||
63 | unsigned gpio, int value) | ||
64 | { | ||
65 | struct rdc321x_gpio *gpch; | ||
66 | int reg = (gpio < 32) ? 0 : 1; | ||
67 | |||
68 | gpch = container_of(chip, struct rdc321x_gpio, chip); | ||
69 | |||
70 | if (value) | ||
71 | gpch->data_reg[reg] |= 1 << (gpio & 0x1f); | ||
72 | else | ||
73 | gpch->data_reg[reg] &= ~(1 << (gpio & 0x1f)); | ||
74 | |||
75 | pci_write_config_dword(gpch->sb_pdev, | ||
76 | reg ? gpch->reg2_data_base : gpch->reg1_data_base, | ||
77 | gpch->data_reg[reg]); | ||
78 | } | ||
79 | |||
80 | /* set GPIO pin to value */ | ||
81 | static void rdc_gpio_set_value(struct gpio_chip *chip, | ||
82 | unsigned gpio, int value) | ||
83 | { | ||
84 | struct rdc321x_gpio *gpch; | ||
85 | |||
86 | gpch = container_of(chip, struct rdc321x_gpio, chip); | ||
87 | spin_lock(&gpch->lock); | ||
88 | rdc_gpio_set_value_impl(chip, gpio, value); | ||
89 | spin_unlock(&gpch->lock); | ||
90 | } | ||
91 | |||
92 | static int rdc_gpio_config(struct gpio_chip *chip, | ||
93 | unsigned gpio, int value) | ||
94 | { | ||
95 | struct rdc321x_gpio *gpch; | ||
96 | int err; | ||
97 | u32 reg; | ||
98 | |||
99 | gpch = container_of(chip, struct rdc321x_gpio, chip); | ||
100 | |||
101 | spin_lock(&gpch->lock); | ||
102 | err = pci_read_config_dword(gpch->sb_pdev, gpio < 32 ? | ||
103 | gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, ®); | ||
104 | if (err) | ||
105 | goto unlock; | ||
106 | |||
107 | reg |= 1 << (gpio & 0x1f); | ||
108 | |||
109 | err = pci_write_config_dword(gpch->sb_pdev, gpio < 32 ? | ||
110 | gpch->reg1_ctrl_base : gpch->reg2_ctrl_base, reg); | ||
111 | if (err) | ||
112 | goto unlock; | ||
113 | |||
114 | rdc_gpio_set_value_impl(chip, gpio, value); | ||
115 | |||
116 | unlock: | ||
117 | spin_unlock(&gpch->lock); | ||
118 | |||
119 | return err; | ||
120 | } | ||
121 | |||
122 | /* configure GPIO pin as input */ | ||
123 | static int rdc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) | ||
124 | { | ||
125 | return rdc_gpio_config(chip, gpio, 1); | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Cache the initial value of both GPIO data registers | ||
130 | */ | ||
131 | static int __devinit rdc321x_gpio_probe(struct platform_device *pdev) | ||
132 | { | ||
133 | int err; | ||
134 | struct resource *r; | ||
135 | struct rdc321x_gpio *rdc321x_gpio_dev; | ||
136 | struct rdc321x_gpio_pdata *pdata; | ||
137 | |||
138 | pdata = pdev->dev.platform_data; | ||
139 | if (!pdata) { | ||
140 | dev_err(&pdev->dev, "no platform data supplied\n"); | ||
141 | return -ENODEV; | ||
142 | } | ||
143 | |||
144 | rdc321x_gpio_dev = kzalloc(sizeof(struct rdc321x_gpio), GFP_KERNEL); | ||
145 | if (!rdc321x_gpio_dev) { | ||
146 | dev_err(&pdev->dev, "failed to allocate private data\n"); | ||
147 | return -ENOMEM; | ||
148 | } | ||
149 | |||
150 | r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg1"); | ||
151 | if (!r) { | ||
152 | dev_err(&pdev->dev, "failed to get gpio-reg1 resource\n"); | ||
153 | err = -ENODEV; | ||
154 | goto out_free; | ||
155 | } | ||
156 | |||
157 | spin_lock_init(&rdc321x_gpio_dev->lock); | ||
158 | rdc321x_gpio_dev->sb_pdev = pdata->sb_pdev; | ||
159 | rdc321x_gpio_dev->reg1_ctrl_base = r->start; | ||
160 | rdc321x_gpio_dev->reg1_data_base = r->start + 0x4; | ||
161 | |||
162 | r = platform_get_resource_byname(pdev, IORESOURCE_IO, "gpio-reg2"); | ||
163 | if (!r) { | ||
164 | dev_err(&pdev->dev, "failed to get gpio-reg2 resource\n"); | ||
165 | err = -ENODEV; | ||
166 | goto out_free; | ||
167 | } | ||
168 | |||
169 | rdc321x_gpio_dev->reg2_ctrl_base = r->start; | ||
170 | rdc321x_gpio_dev->reg2_data_base = r->start + 0x4; | ||
171 | |||
172 | rdc321x_gpio_dev->chip.label = "rdc321x-gpio"; | ||
173 | rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input; | ||
174 | rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config; | ||
175 | rdc321x_gpio_dev->chip.get = rdc_gpio_get_value; | ||
176 | rdc321x_gpio_dev->chip.set = rdc_gpio_set_value; | ||
177 | rdc321x_gpio_dev->chip.base = 0; | ||
178 | rdc321x_gpio_dev->chip.ngpio = pdata->max_gpios; | ||
179 | |||
180 | platform_set_drvdata(pdev, rdc321x_gpio_dev); | ||
181 | |||
182 | /* This might not be, what others (BIOS, bootloader, etc.) | ||
183 | wrote to these registers before, but it's a good guess. Still | ||
184 | better than just using 0xffffffff. */ | ||
185 | err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev, | ||
186 | rdc321x_gpio_dev->reg1_data_base, | ||
187 | &rdc321x_gpio_dev->data_reg[0]); | ||
188 | if (err) | ||
189 | goto out_drvdata; | ||
190 | |||
191 | err = pci_read_config_dword(rdc321x_gpio_dev->sb_pdev, | ||
192 | rdc321x_gpio_dev->reg2_data_base, | ||
193 | &rdc321x_gpio_dev->data_reg[1]); | ||
194 | if (err) | ||
195 | goto out_drvdata; | ||
196 | |||
197 | dev_info(&pdev->dev, "registering %d GPIOs\n", | ||
198 | rdc321x_gpio_dev->chip.ngpio); | ||
199 | return gpiochip_add(&rdc321x_gpio_dev->chip); | ||
200 | |||
201 | out_drvdata: | ||
202 | platform_set_drvdata(pdev, NULL); | ||
203 | out_free: | ||
204 | kfree(rdc321x_gpio_dev); | ||
205 | return err; | ||
206 | } | ||
207 | |||
208 | static int __devexit rdc321x_gpio_remove(struct platform_device *pdev) | ||
209 | { | ||
210 | int ret; | ||
211 | struct rdc321x_gpio *rdc321x_gpio_dev = platform_get_drvdata(pdev); | ||
212 | |||
213 | ret = gpiochip_remove(&rdc321x_gpio_dev->chip); | ||
214 | if (ret) | ||
215 | dev_err(&pdev->dev, "failed to unregister chip\n"); | ||
216 | |||
217 | kfree(rdc321x_gpio_dev); | ||
218 | platform_set_drvdata(pdev, NULL); | ||
219 | |||
220 | return ret; | ||
221 | } | ||
222 | |||
223 | static struct platform_driver rdc321x_gpio_driver = { | ||
224 | .driver.name = "rdc321x-gpio", | ||
225 | .driver.owner = THIS_MODULE, | ||
226 | .probe = rdc321x_gpio_probe, | ||
227 | .remove = __devexit_p(rdc321x_gpio_remove), | ||
228 | }; | ||
229 | |||
230 | static int __init rdc321x_gpio_init(void) | ||
231 | { | ||
232 | return platform_driver_register(&rdc321x_gpio_driver); | ||
233 | } | ||
234 | |||
235 | static void __exit rdc321x_gpio_exit(void) | ||
236 | { | ||
237 | platform_driver_unregister(&rdc321x_gpio_driver); | ||
238 | } | ||
239 | |||
240 | module_init(rdc321x_gpio_init); | ||
241 | module_exit(rdc321x_gpio_exit); | ||
242 | |||
243 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | ||
244 | MODULE_DESCRIPTION("RDC321x GPIO driver"); | ||
245 | MODULE_LICENSE("GPL"); | ||
246 | MODULE_ALIAS("platform:rdc321x-gpio"); | ||
diff --git a/drivers/gpio/tc35892-gpio.c b/drivers/gpio/tc35892-gpio.c new file mode 100644 index 000000000000..1be6288780de --- /dev/null +++ b/drivers/gpio/tc35892-gpio.c | |||
@@ -0,0 +1,381 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson | ||
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/gpio.h> | ||
14 | #include <linux/irq.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/mfd/tc35892.h> | ||
17 | |||
18 | /* | ||
19 | * These registers are modified under the irq bus lock and cached to avoid | ||
20 | * unnecessary writes in bus_sync_unlock. | ||
21 | */ | ||
22 | enum { REG_IBE, REG_IEV, REG_IS, REG_IE }; | ||
23 | |||
24 | #define CACHE_NR_REGS 4 | ||
25 | #define CACHE_NR_BANKS 3 | ||
26 | |||
27 | struct tc35892_gpio { | ||
28 | struct gpio_chip chip; | ||
29 | struct tc35892 *tc35892; | ||
30 | struct device *dev; | ||
31 | struct mutex irq_lock; | ||
32 | |||
33 | int irq_base; | ||
34 | |||
35 | /* Caches of interrupt control registers for bus_lock */ | ||
36 | u8 regs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
37 | u8 oldregs[CACHE_NR_REGS][CACHE_NR_BANKS]; | ||
38 | }; | ||
39 | |||
40 | static inline struct tc35892_gpio *to_tc35892_gpio(struct gpio_chip *chip) | ||
41 | { | ||
42 | return container_of(chip, struct tc35892_gpio, chip); | ||
43 | } | ||
44 | |||
45 | static int tc35892_gpio_get(struct gpio_chip *chip, unsigned offset) | ||
46 | { | ||
47 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
48 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
49 | u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2; | ||
50 | u8 mask = 1 << (offset % 8); | ||
51 | int ret; | ||
52 | |||
53 | ret = tc35892_reg_read(tc35892, reg); | ||
54 | if (ret < 0) | ||
55 | return ret; | ||
56 | |||
57 | return ret & mask; | ||
58 | } | ||
59 | |||
60 | static void tc35892_gpio_set(struct gpio_chip *chip, unsigned offset, int val) | ||
61 | { | ||
62 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
63 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
64 | u8 reg = TC35892_GPIODATA0 + (offset / 8) * 2; | ||
65 | unsigned pos = offset % 8; | ||
66 | u8 data[] = {!!val << pos, 1 << pos}; | ||
67 | |||
68 | tc35892_block_write(tc35892, reg, ARRAY_SIZE(data), data); | ||
69 | } | ||
70 | |||
71 | static int tc35892_gpio_direction_output(struct gpio_chip *chip, | ||
72 | unsigned offset, int val) | ||
73 | { | ||
74 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
75 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
76 | u8 reg = TC35892_GPIODIR0 + offset / 8; | ||
77 | unsigned pos = offset % 8; | ||
78 | |||
79 | tc35892_gpio_set(chip, offset, val); | ||
80 | |||
81 | return tc35892_set_bits(tc35892, reg, 1 << pos, 1 << pos); | ||
82 | } | ||
83 | |||
84 | static int tc35892_gpio_direction_input(struct gpio_chip *chip, | ||
85 | unsigned offset) | ||
86 | { | ||
87 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
88 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
89 | u8 reg = TC35892_GPIODIR0 + offset / 8; | ||
90 | unsigned pos = offset % 8; | ||
91 | |||
92 | return tc35892_set_bits(tc35892, reg, 1 << pos, 0); | ||
93 | } | ||
94 | |||
95 | static int tc35892_gpio_to_irq(struct gpio_chip *chip, unsigned offset) | ||
96 | { | ||
97 | struct tc35892_gpio *tc35892_gpio = to_tc35892_gpio(chip); | ||
98 | |||
99 | return tc35892_gpio->irq_base + offset; | ||
100 | } | ||
101 | |||
102 | static struct gpio_chip template_chip = { | ||
103 | .label = "tc35892", | ||
104 | .owner = THIS_MODULE, | ||
105 | .direction_input = tc35892_gpio_direction_input, | ||
106 | .get = tc35892_gpio_get, | ||
107 | .direction_output = tc35892_gpio_direction_output, | ||
108 | .set = tc35892_gpio_set, | ||
109 | .to_irq = tc35892_gpio_to_irq, | ||
110 | .can_sleep = 1, | ||
111 | }; | ||
112 | |||
113 | static int tc35892_gpio_irq_set_type(unsigned int irq, unsigned int type) | ||
114 | { | ||
115 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
116 | int offset = irq - tc35892_gpio->irq_base; | ||
117 | int regoffset = offset / 8; | ||
118 | int mask = 1 << (offset % 8); | ||
119 | |||
120 | if (type == IRQ_TYPE_EDGE_BOTH) { | ||
121 | tc35892_gpio->regs[REG_IBE][regoffset] |= mask; | ||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | tc35892_gpio->regs[REG_IBE][regoffset] &= ~mask; | ||
126 | |||
127 | if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_LEVEL_HIGH) | ||
128 | tc35892_gpio->regs[REG_IS][regoffset] |= mask; | ||
129 | else | ||
130 | tc35892_gpio->regs[REG_IS][regoffset] &= ~mask; | ||
131 | |||
132 | if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) | ||
133 | tc35892_gpio->regs[REG_IEV][regoffset] |= mask; | ||
134 | else | ||
135 | tc35892_gpio->regs[REG_IEV][regoffset] &= ~mask; | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void tc35892_gpio_irq_lock(unsigned int irq) | ||
141 | { | ||
142 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
143 | |||
144 | mutex_lock(&tc35892_gpio->irq_lock); | ||
145 | } | ||
146 | |||
147 | static void tc35892_gpio_irq_sync_unlock(unsigned int irq) | ||
148 | { | ||
149 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
150 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
151 | static const u8 regmap[] = { | ||
152 | [REG_IBE] = TC35892_GPIOIBE0, | ||
153 | [REG_IEV] = TC35892_GPIOIEV0, | ||
154 | [REG_IS] = TC35892_GPIOIS0, | ||
155 | [REG_IE] = TC35892_GPIOIE0, | ||
156 | }; | ||
157 | int i, j; | ||
158 | |||
159 | for (i = 0; i < CACHE_NR_REGS; i++) { | ||
160 | for (j = 0; j < CACHE_NR_BANKS; j++) { | ||
161 | u8 old = tc35892_gpio->oldregs[i][j]; | ||
162 | u8 new = tc35892_gpio->regs[i][j]; | ||
163 | |||
164 | if (new == old) | ||
165 | continue; | ||
166 | |||
167 | tc35892_gpio->oldregs[i][j] = new; | ||
168 | tc35892_reg_write(tc35892, regmap[i] + j * 8, new); | ||
169 | } | ||
170 | } | ||
171 | |||
172 | mutex_unlock(&tc35892_gpio->irq_lock); | ||
173 | } | ||
174 | |||
175 | static void tc35892_gpio_irq_mask(unsigned int irq) | ||
176 | { | ||
177 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
178 | int offset = irq - tc35892_gpio->irq_base; | ||
179 | int regoffset = offset / 8; | ||
180 | int mask = 1 << (offset % 8); | ||
181 | |||
182 | tc35892_gpio->regs[REG_IE][regoffset] &= ~mask; | ||
183 | } | ||
184 | |||
185 | static void tc35892_gpio_irq_unmask(unsigned int irq) | ||
186 | { | ||
187 | struct tc35892_gpio *tc35892_gpio = get_irq_chip_data(irq); | ||
188 | int offset = irq - tc35892_gpio->irq_base; | ||
189 | int regoffset = offset / 8; | ||
190 | int mask = 1 << (offset % 8); | ||
191 | |||
192 | tc35892_gpio->regs[REG_IE][regoffset] |= mask; | ||
193 | } | ||
194 | |||
195 | static struct irq_chip tc35892_gpio_irq_chip = { | ||
196 | .name = "tc35892-gpio", | ||
197 | .bus_lock = tc35892_gpio_irq_lock, | ||
198 | .bus_sync_unlock = tc35892_gpio_irq_sync_unlock, | ||
199 | .mask = tc35892_gpio_irq_mask, | ||
200 | .unmask = tc35892_gpio_irq_unmask, | ||
201 | .set_type = tc35892_gpio_irq_set_type, | ||
202 | }; | ||
203 | |||
204 | static irqreturn_t tc35892_gpio_irq(int irq, void *dev) | ||
205 | { | ||
206 | struct tc35892_gpio *tc35892_gpio = dev; | ||
207 | struct tc35892 *tc35892 = tc35892_gpio->tc35892; | ||
208 | u8 status[CACHE_NR_BANKS]; | ||
209 | int ret; | ||
210 | int i; | ||
211 | |||
212 | ret = tc35892_block_read(tc35892, TC35892_GPIOMIS0, | ||
213 | ARRAY_SIZE(status), status); | ||
214 | if (ret < 0) | ||
215 | return IRQ_NONE; | ||
216 | |||
217 | for (i = 0; i < ARRAY_SIZE(status); i++) { | ||
218 | unsigned int stat = status[i]; | ||
219 | if (!stat) | ||
220 | continue; | ||
221 | |||
222 | while (stat) { | ||
223 | int bit = __ffs(stat); | ||
224 | int line = i * 8 + bit; | ||
225 | |||
226 | handle_nested_irq(tc35892_gpio->irq_base + line); | ||
227 | stat &= ~(1 << bit); | ||
228 | } | ||
229 | |||
230 | tc35892_reg_write(tc35892, TC35892_GPIOIC0 + i, status[i]); | ||
231 | } | ||
232 | |||
233 | return IRQ_HANDLED; | ||
234 | } | ||
235 | |||
236 | static int tc35892_gpio_irq_init(struct tc35892_gpio *tc35892_gpio) | ||
237 | { | ||
238 | int base = tc35892_gpio->irq_base; | ||
239 | int irq; | ||
240 | |||
241 | for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) { | ||
242 | set_irq_chip_data(irq, tc35892_gpio); | ||
243 | set_irq_chip_and_handler(irq, &tc35892_gpio_irq_chip, | ||
244 | handle_simple_irq); | ||
245 | set_irq_nested_thread(irq, 1); | ||
246 | #ifdef CONFIG_ARM | ||
247 | set_irq_flags(irq, IRQF_VALID); | ||
248 | #else | ||
249 | set_irq_noprobe(irq); | ||
250 | #endif | ||
251 | } | ||
252 | |||
253 | return 0; | ||
254 | } | ||
255 | |||
256 | static void tc35892_gpio_irq_remove(struct tc35892_gpio *tc35892_gpio) | ||
257 | { | ||
258 | int base = tc35892_gpio->irq_base; | ||
259 | int irq; | ||
260 | |||
261 | for (irq = base; irq < base + tc35892_gpio->chip.ngpio; irq++) { | ||
262 | #ifdef CONFIG_ARM | ||
263 | set_irq_flags(irq, 0); | ||
264 | #endif | ||
265 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
266 | set_irq_chip_data(irq, NULL); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | static int __devinit tc35892_gpio_probe(struct platform_device *pdev) | ||
271 | { | ||
272 | struct tc35892 *tc35892 = dev_get_drvdata(pdev->dev.parent); | ||
273 | struct tc35892_gpio_platform_data *pdata; | ||
274 | struct tc35892_gpio *tc35892_gpio; | ||
275 | int ret; | ||
276 | int irq; | ||
277 | |||
278 | pdata = tc35892->pdata->gpio; | ||
279 | if (!pdata) | ||
280 | return -ENODEV; | ||
281 | |||
282 | irq = platform_get_irq(pdev, 0); | ||
283 | if (irq < 0) | ||
284 | return irq; | ||
285 | |||
286 | tc35892_gpio = kzalloc(sizeof(struct tc35892_gpio), GFP_KERNEL); | ||
287 | if (!tc35892_gpio) | ||
288 | return -ENOMEM; | ||
289 | |||
290 | mutex_init(&tc35892_gpio->irq_lock); | ||
291 | |||
292 | tc35892_gpio->dev = &pdev->dev; | ||
293 | tc35892_gpio->tc35892 = tc35892; | ||
294 | |||
295 | tc35892_gpio->chip = template_chip; | ||
296 | tc35892_gpio->chip.ngpio = tc35892->num_gpio; | ||
297 | tc35892_gpio->chip.dev = &pdev->dev; | ||
298 | tc35892_gpio->chip.base = pdata->gpio_base; | ||
299 | |||
300 | tc35892_gpio->irq_base = tc35892->irq_base + TC35892_INT_GPIO(0); | ||
301 | |||
302 | /* Bring the GPIO module out of reset */ | ||
303 | ret = tc35892_set_bits(tc35892, TC35892_RSTCTRL, | ||
304 | TC35892_RSTCTRL_GPIRST, 0); | ||
305 | if (ret < 0) | ||
306 | goto out_free; | ||
307 | |||
308 | ret = tc35892_gpio_irq_init(tc35892_gpio); | ||
309 | if (ret) | ||
310 | goto out_free; | ||
311 | |||
312 | ret = request_threaded_irq(irq, NULL, tc35892_gpio_irq, IRQF_ONESHOT, | ||
313 | "tc35892-gpio", tc35892_gpio); | ||
314 | if (ret) { | ||
315 | dev_err(&pdev->dev, "unable to get irq: %d\n", ret); | ||
316 | goto out_removeirq; | ||
317 | } | ||
318 | |||
319 | ret = gpiochip_add(&tc35892_gpio->chip); | ||
320 | if (ret) { | ||
321 | dev_err(&pdev->dev, "unable to add gpiochip: %d\n", ret); | ||
322 | goto out_freeirq; | ||
323 | } | ||
324 | |||
325 | platform_set_drvdata(pdev, tc35892_gpio); | ||
326 | |||
327 | return 0; | ||
328 | |||
329 | out_freeirq: | ||
330 | free_irq(irq, tc35892_gpio); | ||
331 | out_removeirq: | ||
332 | tc35892_gpio_irq_remove(tc35892_gpio); | ||
333 | out_free: | ||
334 | kfree(tc35892_gpio); | ||
335 | return ret; | ||
336 | } | ||
337 | |||
338 | static int __devexit tc35892_gpio_remove(struct platform_device *pdev) | ||
339 | { | ||
340 | struct tc35892_gpio *tc35892_gpio = platform_get_drvdata(pdev); | ||
341 | int irq = platform_get_irq(pdev, 0); | ||
342 | int ret; | ||
343 | |||
344 | ret = gpiochip_remove(&tc35892_gpio->chip); | ||
345 | if (ret < 0) { | ||
346 | dev_err(tc35892_gpio->dev, | ||
347 | "unable to remove gpiochip: %d\n", ret); | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | free_irq(irq, tc35892_gpio); | ||
352 | tc35892_gpio_irq_remove(tc35892_gpio); | ||
353 | |||
354 | platform_set_drvdata(pdev, NULL); | ||
355 | kfree(tc35892_gpio); | ||
356 | |||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | static struct platform_driver tc35892_gpio_driver = { | ||
361 | .driver.name = "tc35892-gpio", | ||
362 | .driver.owner = THIS_MODULE, | ||
363 | .probe = tc35892_gpio_probe, | ||
364 | .remove = __devexit_p(tc35892_gpio_remove), | ||
365 | }; | ||
366 | |||
367 | static int __init tc35892_gpio_init(void) | ||
368 | { | ||
369 | return platform_driver_register(&tc35892_gpio_driver); | ||
370 | } | ||
371 | subsys_initcall(tc35892_gpio_init); | ||
372 | |||
373 | static void __exit tc35892_gpio_exit(void) | ||
374 | { | ||
375 | platform_driver_unregister(&tc35892_gpio_driver); | ||
376 | } | ||
377 | module_exit(tc35892_gpio_exit); | ||
378 | |||
379 | MODULE_LICENSE("GPL v2"); | ||
380 | MODULE_DESCRIPTION("TC35892 GPIO driver"); | ||
381 | MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); | ||
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/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index cc5316dcf580..b3ba44c0a818 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c | |||
@@ -900,9 +900,10 @@ static void radeon_cp_dispatch_clear(struct drm_device * dev, | |||
900 | flags |= RADEON_FRONT; | 900 | flags |= RADEON_FRONT; |
901 | } | 901 | } |
902 | if (flags & (RADEON_DEPTH|RADEON_STENCIL)) { | 902 | if (flags & (RADEON_DEPTH|RADEON_STENCIL)) { |
903 | if (!dev_priv->have_z_offset) | 903 | if (!dev_priv->have_z_offset) { |
904 | printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n"); | 904 | printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n"); |
905 | flags &= ~(RADEON_DEPTH | RADEON_STENCIL); | 905 | flags &= ~(RADEON_DEPTH | RADEON_STENCIL); |
906 | } | ||
906 | } | 907 | } |
907 | 908 | ||
908 | if (flags & (RADEON_FRONT | RADEON_BACK)) { | 909 | if (flags & (RADEON_FRONT | RADEON_BACK)) { |
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/idle/Kconfig b/drivers/idle/Kconfig index f15e90a453d1..fb5c5186d4aa 100644 --- a/drivers/idle/Kconfig +++ b/drivers/idle/Kconfig | |||
@@ -1,3 +1,14 @@ | |||
1 | config INTEL_IDLE | ||
2 | tristate "Cpuidle Driver for Intel Processors" | ||
3 | depends on CPU_IDLE | ||
4 | depends on X86 | ||
5 | depends on CPU_SUP_INTEL | ||
6 | depends on EXPERIMENTAL | ||
7 | help | ||
8 | Enable intel_idle, a cpuidle driver that includes knowledge of | ||
9 | native Intel hardware idle features. The acpi_idle driver | ||
10 | can be configured at the same time, in order to handle | ||
11 | processors intel_idle does not support. | ||
1 | 12 | ||
2 | menu "Memory power savings" | 13 | menu "Memory power savings" |
3 | depends on X86_64 | 14 | depends on X86_64 |
diff --git a/drivers/idle/Makefile b/drivers/idle/Makefile index 5f68fc377e21..23d295cf10f2 100644 --- a/drivers/idle/Makefile +++ b/drivers/idle/Makefile | |||
@@ -1,2 +1,3 @@ | |||
1 | obj-$(CONFIG_I7300_IDLE) += i7300_idle.o | 1 | obj-$(CONFIG_I7300_IDLE) += i7300_idle.o |
2 | obj-$(CONFIG_INTEL_IDLE) += intel_idle.o | ||
2 | 3 | ||
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c new file mode 100755 index 000000000000..54f0fb4cd5d2 --- /dev/null +++ b/drivers/idle/intel_idle.c | |||
@@ -0,0 +1,461 @@ | |||
1 | /* | ||
2 | * intel_idle.c - native hardware idle loop for modern Intel processors | ||
3 | * | ||
4 | * Copyright (c) 2010, Intel Corporation. | ||
5 | * Len Brown <len.brown@intel.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * intel_idle is a cpuidle driver that loads on specific Intel processors | ||
23 | * in lieu of the legacy ACPI processor_idle driver. The intent is to | ||
24 | * make Linux more efficient on these processors, as intel_idle knows | ||
25 | * more than ACPI, as well as make Linux more immune to ACPI BIOS bugs. | ||
26 | */ | ||
27 | |||
28 | /* | ||
29 | * Design Assumptions | ||
30 | * | ||
31 | * All CPUs have same idle states as boot CPU | ||
32 | * | ||
33 | * Chipset BM_STS (bus master status) bit is a NOP | ||
34 | * for preventing entry into deep C-stats | ||
35 | */ | ||
36 | |||
37 | /* | ||
38 | * Known limitations | ||
39 | * | ||
40 | * The driver currently initializes for_each_online_cpu() upon modprobe. | ||
41 | * It it unaware of subsequent processors hot-added to the system. | ||
42 | * This means that if you boot with maxcpus=n and later online | ||
43 | * processors above n, those processors will use C1 only. | ||
44 | * | ||
45 | * ACPI has a .suspend hack to turn off deep c-statees during suspend | ||
46 | * to avoid complications with the lapic timer workaround. | ||
47 | * Have not seen issues with suspend, but may need same workaround here. | ||
48 | * | ||
49 | * There is currently no kernel-based automatic probing/loading mechanism | ||
50 | * if the driver is built as a module. | ||
51 | */ | ||
52 | |||
53 | /* un-comment DEBUG to enable pr_debug() statements */ | ||
54 | #define DEBUG | ||
55 | |||
56 | #include <linux/kernel.h> | ||
57 | #include <linux/cpuidle.h> | ||
58 | #include <linux/clockchips.h> | ||
59 | #include <linux/hrtimer.h> /* ktime_get_real() */ | ||
60 | #include <trace/events/power.h> | ||
61 | #include <linux/sched.h> | ||
62 | |||
63 | #define INTEL_IDLE_VERSION "0.4" | ||
64 | #define PREFIX "intel_idle: " | ||
65 | |||
66 | #define MWAIT_SUBSTATE_MASK (0xf) | ||
67 | #define MWAIT_CSTATE_MASK (0xf) | ||
68 | #define MWAIT_SUBSTATE_SIZE (4) | ||
69 | #define MWAIT_MAX_NUM_CSTATES 8 | ||
70 | #define CPUID_MWAIT_LEAF (5) | ||
71 | #define CPUID5_ECX_EXTENSIONS_SUPPORTED (0x1) | ||
72 | #define CPUID5_ECX_INTERRUPT_BREAK (0x2) | ||
73 | |||
74 | static struct cpuidle_driver intel_idle_driver = { | ||
75 | .name = "intel_idle", | ||
76 | .owner = THIS_MODULE, | ||
77 | }; | ||
78 | /* intel_idle.max_cstate=0 disables driver */ | ||
79 | static int max_cstate = MWAIT_MAX_NUM_CSTATES - 1; | ||
80 | static int power_policy = 7; /* 0 = max perf; 15 = max powersave */ | ||
81 | |||
82 | static unsigned int substates; | ||
83 | static int (*choose_substate)(int); | ||
84 | |||
85 | /* Reliable LAPIC Timer States, bit 1 for C1 etc. */ | ||
86 | static unsigned int lapic_timer_reliable_states; | ||
87 | |||
88 | static struct cpuidle_device *intel_idle_cpuidle_devices; | ||
89 | static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state); | ||
90 | |||
91 | static struct cpuidle_state *cpuidle_state_table; | ||
92 | |||
93 | /* | ||
94 | * States are indexed by the cstate number, | ||
95 | * which is also the index into the MWAIT hint array. | ||
96 | * Thus C0 is a dummy. | ||
97 | */ | ||
98 | static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = { | ||
99 | { /* MWAIT C0 */ }, | ||
100 | { /* MWAIT C1 */ | ||
101 | .name = "NHM-C1", | ||
102 | .desc = "MWAIT 0x00", | ||
103 | .driver_data = (void *) 0x00, | ||
104 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
105 | .exit_latency = 3, | ||
106 | .power_usage = 1000, | ||
107 | .target_residency = 6, | ||
108 | .enter = &intel_idle }, | ||
109 | { /* MWAIT C2 */ | ||
110 | .name = "NHM-C3", | ||
111 | .desc = "MWAIT 0x10", | ||
112 | .driver_data = (void *) 0x10, | ||
113 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
114 | .exit_latency = 20, | ||
115 | .power_usage = 500, | ||
116 | .target_residency = 80, | ||
117 | .enter = &intel_idle }, | ||
118 | { /* MWAIT C3 */ | ||
119 | .name = "NHM-C6", | ||
120 | .desc = "MWAIT 0x20", | ||
121 | .driver_data = (void *) 0x20, | ||
122 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
123 | .exit_latency = 200, | ||
124 | .power_usage = 350, | ||
125 | .target_residency = 800, | ||
126 | .enter = &intel_idle }, | ||
127 | }; | ||
128 | |||
129 | static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { | ||
130 | { /* MWAIT C0 */ }, | ||
131 | { /* MWAIT C1 */ | ||
132 | .name = "ATM-C1", | ||
133 | .desc = "MWAIT 0x00", | ||
134 | .driver_data = (void *) 0x00, | ||
135 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
136 | .exit_latency = 1, | ||
137 | .power_usage = 1000, | ||
138 | .target_residency = 4, | ||
139 | .enter = &intel_idle }, | ||
140 | { /* MWAIT C2 */ | ||
141 | .name = "ATM-C2", | ||
142 | .desc = "MWAIT 0x10", | ||
143 | .driver_data = (void *) 0x10, | ||
144 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
145 | .exit_latency = 20, | ||
146 | .power_usage = 500, | ||
147 | .target_residency = 80, | ||
148 | .enter = &intel_idle }, | ||
149 | { /* MWAIT C3 */ }, | ||
150 | { /* MWAIT C4 */ | ||
151 | .name = "ATM-C4", | ||
152 | .desc = "MWAIT 0x30", | ||
153 | .driver_data = (void *) 0x30, | ||
154 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
155 | .exit_latency = 100, | ||
156 | .power_usage = 250, | ||
157 | .target_residency = 400, | ||
158 | .enter = &intel_idle }, | ||
159 | { /* MWAIT C5 */ }, | ||
160 | { /* MWAIT C6 */ | ||
161 | .name = "ATM-C6", | ||
162 | .desc = "MWAIT 0x40", | ||
163 | .driver_data = (void *) 0x40, | ||
164 | .flags = CPUIDLE_FLAG_TIME_VALID, | ||
165 | .exit_latency = 200, | ||
166 | .power_usage = 150, | ||
167 | .target_residency = 800, | ||
168 | .enter = NULL }, /* disabled */ | ||
169 | }; | ||
170 | |||
171 | /* | ||
172 | * choose_tunable_substate() | ||
173 | * | ||
174 | * Run-time decision on which C-state substate to invoke | ||
175 | * If power_policy = 0, choose shallowest substate (0) | ||
176 | * If power_policy = 15, choose deepest substate | ||
177 | * If power_policy = middle, choose middle substate etc. | ||
178 | */ | ||
179 | static int choose_tunable_substate(int cstate) | ||
180 | { | ||
181 | unsigned int num_substates; | ||
182 | unsigned int substate_choice; | ||
183 | |||
184 | power_policy &= 0xF; /* valid range: 0-15 */ | ||
185 | cstate &= 7; /* valid range: 0-7 */ | ||
186 | |||
187 | num_substates = (substates >> ((cstate) * 4)) & MWAIT_SUBSTATE_MASK; | ||
188 | |||
189 | if (num_substates <= 1) | ||
190 | return 0; | ||
191 | |||
192 | substate_choice = ((power_policy + (power_policy + 1) * | ||
193 | (num_substates - 1)) / 16); | ||
194 | |||
195 | return substate_choice; | ||
196 | } | ||
197 | |||
198 | /* | ||
199 | * choose_zero_substate() | ||
200 | */ | ||
201 | static int choose_zero_substate(int cstate) | ||
202 | { | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * intel_idle | ||
208 | * @dev: cpuidle_device | ||
209 | * @state: cpuidle state | ||
210 | * | ||
211 | */ | ||
212 | static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state) | ||
213 | { | ||
214 | unsigned long ecx = 1; /* break on interrupt flag */ | ||
215 | unsigned long eax = (unsigned long)cpuidle_get_statedata(state); | ||
216 | unsigned int cstate; | ||
217 | ktime_t kt_before, kt_after; | ||
218 | s64 usec_delta; | ||
219 | int cpu = smp_processor_id(); | ||
220 | |||
221 | cstate = (((eax) >> MWAIT_SUBSTATE_SIZE) & MWAIT_CSTATE_MASK) + 1; | ||
222 | |||
223 | eax = eax + (choose_substate)(cstate); | ||
224 | |||
225 | local_irq_disable(); | ||
226 | |||
227 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) | ||
228 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); | ||
229 | |||
230 | kt_before = ktime_get_real(); | ||
231 | |||
232 | stop_critical_timings(); | ||
233 | #ifndef MODULE | ||
234 | trace_power_start(POWER_CSTATE, (eax >> 4) + 1); | ||
235 | #endif | ||
236 | if (!need_resched()) { | ||
237 | |||
238 | __monitor((void *)¤t_thread_info()->flags, 0, 0); | ||
239 | smp_mb(); | ||
240 | if (!need_resched()) | ||
241 | __mwait(eax, ecx); | ||
242 | } | ||
243 | |||
244 | start_critical_timings(); | ||
245 | |||
246 | kt_after = ktime_get_real(); | ||
247 | usec_delta = ktime_to_us(ktime_sub(kt_after, kt_before)); | ||
248 | |||
249 | local_irq_enable(); | ||
250 | |||
251 | if (!(lapic_timer_reliable_states & (1 << (cstate)))) | ||
252 | clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); | ||
253 | |||
254 | return usec_delta; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * intel_idle_probe() | ||
259 | */ | ||
260 | static int intel_idle_probe(void) | ||
261 | { | ||
262 | unsigned int eax, ebx, ecx, edx; | ||
263 | |||
264 | if (max_cstate == 0) { | ||
265 | pr_debug(PREFIX "disabled\n"); | ||
266 | return -EPERM; | ||
267 | } | ||
268 | |||
269 | if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL) | ||
270 | return -ENODEV; | ||
271 | |||
272 | if (!boot_cpu_has(X86_FEATURE_MWAIT)) | ||
273 | return -ENODEV; | ||
274 | |||
275 | if (boot_cpu_data.cpuid_level < CPUID_MWAIT_LEAF) | ||
276 | return -ENODEV; | ||
277 | |||
278 | cpuid(CPUID_MWAIT_LEAF, &eax, &ebx, &ecx, &edx); | ||
279 | |||
280 | if (!(ecx & CPUID5_ECX_EXTENSIONS_SUPPORTED) || | ||
281 | !(ecx & CPUID5_ECX_INTERRUPT_BREAK)) | ||
282 | return -ENODEV; | ||
283 | #ifdef DEBUG | ||
284 | if (substates == 0) /* can over-ride via modparam */ | ||
285 | #endif | ||
286 | substates = edx; | ||
287 | |||
288 | pr_debug(PREFIX "MWAIT substates: 0x%x\n", substates); | ||
289 | |||
290 | if (boot_cpu_has(X86_FEATURE_ARAT)) /* Always Reliable APIC Timer */ | ||
291 | lapic_timer_reliable_states = 0xFFFFFFFF; | ||
292 | |||
293 | if (boot_cpu_data.x86 != 6) /* family 6 */ | ||
294 | return -ENODEV; | ||
295 | |||
296 | switch (boot_cpu_data.x86_model) { | ||
297 | |||
298 | case 0x1A: /* Core i7, Xeon 5500 series */ | ||
299 | case 0x1E: /* Core i7 and i5 Processor - Lynnfield Jasper Forest */ | ||
300 | case 0x1F: /* Core i7 and i5 Processor - Nehalem */ | ||
301 | case 0x2E: /* Nehalem-EX Xeon */ | ||
302 | lapic_timer_reliable_states = (1 << 1); /* C1 */ | ||
303 | |||
304 | case 0x25: /* Westmere */ | ||
305 | case 0x2C: /* Westmere */ | ||
306 | cpuidle_state_table = nehalem_cstates; | ||
307 | choose_substate = choose_tunable_substate; | ||
308 | break; | ||
309 | |||
310 | case 0x1C: /* 28 - Atom Processor */ | ||
311 | lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ | ||
312 | cpuidle_state_table = atom_cstates; | ||
313 | choose_substate = choose_zero_substate; | ||
314 | break; | ||
315 | #ifdef FUTURE_USE | ||
316 | case 0x17: /* 23 - Core 2 Duo */ | ||
317 | lapic_timer_reliable_states = (1 << 2) | (1 << 1); /* C2, C1 */ | ||
318 | #endif | ||
319 | |||
320 | default: | ||
321 | pr_debug(PREFIX "does not run on family %d model %d\n", | ||
322 | boot_cpu_data.x86, boot_cpu_data.x86_model); | ||
323 | return -ENODEV; | ||
324 | } | ||
325 | |||
326 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION | ||
327 | " model 0x%X\n", boot_cpu_data.x86_model); | ||
328 | |||
329 | pr_debug(PREFIX "lapic_timer_reliable_states 0x%x\n", | ||
330 | lapic_timer_reliable_states); | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * intel_idle_cpuidle_devices_uninit() | ||
336 | * unregister, free cpuidle_devices | ||
337 | */ | ||
338 | static void intel_idle_cpuidle_devices_uninit(void) | ||
339 | { | ||
340 | int i; | ||
341 | struct cpuidle_device *dev; | ||
342 | |||
343 | for_each_online_cpu(i) { | ||
344 | dev = per_cpu_ptr(intel_idle_cpuidle_devices, i); | ||
345 | cpuidle_unregister_device(dev); | ||
346 | } | ||
347 | |||
348 | free_percpu(intel_idle_cpuidle_devices); | ||
349 | return; | ||
350 | } | ||
351 | /* | ||
352 | * intel_idle_cpuidle_devices_init() | ||
353 | * allocate, initialize, register cpuidle_devices | ||
354 | */ | ||
355 | static int intel_idle_cpuidle_devices_init(void) | ||
356 | { | ||
357 | int i, cstate; | ||
358 | struct cpuidle_device *dev; | ||
359 | |||
360 | intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device); | ||
361 | if (intel_idle_cpuidle_devices == NULL) | ||
362 | return -ENOMEM; | ||
363 | |||
364 | for_each_online_cpu(i) { | ||
365 | dev = per_cpu_ptr(intel_idle_cpuidle_devices, i); | ||
366 | |||
367 | dev->state_count = 1; | ||
368 | |||
369 | for (cstate = 1; cstate < MWAIT_MAX_NUM_CSTATES; ++cstate) { | ||
370 | int num_substates; | ||
371 | |||
372 | if (cstate > max_cstate) { | ||
373 | printk(PREFIX "max_cstate %d reached\n", | ||
374 | max_cstate); | ||
375 | break; | ||
376 | } | ||
377 | |||
378 | /* does the state exist in CPUID.MWAIT? */ | ||
379 | num_substates = (substates >> ((cstate) * 4)) | ||
380 | & MWAIT_SUBSTATE_MASK; | ||
381 | if (num_substates == 0) | ||
382 | continue; | ||
383 | /* is the state not enabled? */ | ||
384 | if (cpuidle_state_table[cstate].enter == NULL) { | ||
385 | /* does the driver not know about the state? */ | ||
386 | if (*cpuidle_state_table[cstate].name == '\0') | ||
387 | pr_debug(PREFIX "unaware of model 0x%x" | ||
388 | " MWAIT %d please" | ||
389 | " contact lenb@kernel.org", | ||
390 | boot_cpu_data.x86_model, cstate); | ||
391 | continue; | ||
392 | } | ||
393 | |||
394 | if ((cstate > 2) && | ||
395 | !boot_cpu_has(X86_FEATURE_NONSTOP_TSC)) | ||
396 | mark_tsc_unstable("TSC halts in idle" | ||
397 | " states deeper than C2"); | ||
398 | |||
399 | dev->states[dev->state_count] = /* structure copy */ | ||
400 | cpuidle_state_table[cstate]; | ||
401 | |||
402 | dev->state_count += 1; | ||
403 | } | ||
404 | |||
405 | dev->cpu = i; | ||
406 | if (cpuidle_register_device(dev)) { | ||
407 | pr_debug(PREFIX "cpuidle_register_device %d failed!\n", | ||
408 | i); | ||
409 | intel_idle_cpuidle_devices_uninit(); | ||
410 | return -EIO; | ||
411 | } | ||
412 | } | ||
413 | |||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | |||
418 | static int __init intel_idle_init(void) | ||
419 | { | ||
420 | int retval; | ||
421 | |||
422 | retval = intel_idle_probe(); | ||
423 | if (retval) | ||
424 | return retval; | ||
425 | |||
426 | retval = cpuidle_register_driver(&intel_idle_driver); | ||
427 | if (retval) { | ||
428 | printk(KERN_DEBUG PREFIX "intel_idle yielding to %s", | ||
429 | cpuidle_get_driver()->name); | ||
430 | return retval; | ||
431 | } | ||
432 | |||
433 | retval = intel_idle_cpuidle_devices_init(); | ||
434 | if (retval) { | ||
435 | cpuidle_unregister_driver(&intel_idle_driver); | ||
436 | return retval; | ||
437 | } | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | static void __exit intel_idle_exit(void) | ||
443 | { | ||
444 | intel_idle_cpuidle_devices_uninit(); | ||
445 | cpuidle_unregister_driver(&intel_idle_driver); | ||
446 | |||
447 | return; | ||
448 | } | ||
449 | |||
450 | module_init(intel_idle_init); | ||
451 | module_exit(intel_idle_exit); | ||
452 | |||
453 | module_param(power_policy, int, 0644); | ||
454 | module_param(max_cstate, int, 0444); | ||
455 | #ifdef DEBUG | ||
456 | module_param(substates, int, 0444); | ||
457 | #endif | ||
458 | |||
459 | MODULE_AUTHOR("Len Brown <len.brown@intel.com>"); | ||
460 | MODULE_DESCRIPTION("Cpuidle driver for Intel Hardware v" INTEL_IDLE_VERSION); | ||
461 | MODULE_LICENSE("GPL"); | ||
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/core/ucm.c b/drivers/infiniband/core/ucm.c index 46474842cfe9..08f948df8fa9 100644 --- a/drivers/infiniband/core/ucm.c +++ b/drivers/infiniband/core/ucm.c | |||
@@ -706,14 +706,9 @@ static int ib_ucm_alloc_data(const void **dest, u64 src, u32 len) | |||
706 | if (!len) | 706 | if (!len) |
707 | return 0; | 707 | return 0; |
708 | 708 | ||
709 | data = kmalloc(len, GFP_KERNEL); | 709 | data = memdup_user((void __user *)(unsigned long)src, len); |
710 | if (!data) | 710 | if (IS_ERR(data)) |
711 | return -ENOMEM; | 711 | return PTR_ERR(data); |
712 | |||
713 | if (copy_from_user(data, (void __user *)(unsigned long)src, len)) { | ||
714 | kfree(data); | ||
715 | return -EFAULT; | ||
716 | } | ||
717 | 712 | ||
718 | *dest = data; | 713 | *dest = data; |
719 | return 0; | 714 | return 0; |
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/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index 755470440ef1..edef8527eb34 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c | |||
@@ -144,10 +144,11 @@ static ssize_t dev_counters_read(struct file *file, char __user *buf, | |||
144 | size_t count, loff_t *ppos) | 144 | size_t count, loff_t *ppos) |
145 | { | 145 | { |
146 | u64 *counters; | 146 | u64 *counters; |
147 | size_t avail; | ||
147 | struct qib_devdata *dd = private2dd(file); | 148 | struct qib_devdata *dd = private2dd(file); |
148 | 149 | ||
149 | return simple_read_from_buffer(buf, count, ppos, counters, | 150 | avail = dd->f_read_cntrs(dd, *ppos, NULL, &counters); |
150 | dd->f_read_cntrs(dd, *ppos, NULL, &counters)); | 151 | return simple_read_from_buffer(buf, count, ppos, counters, avail); |
151 | } | 152 | } |
152 | 153 | ||
153 | /* read the per-device counters */ | 154 | /* read the per-device counters */ |
@@ -155,10 +156,11 @@ static ssize_t dev_names_read(struct file *file, char __user *buf, | |||
155 | size_t count, loff_t *ppos) | 156 | size_t count, loff_t *ppos) |
156 | { | 157 | { |
157 | char *names; | 158 | char *names; |
159 | size_t avail; | ||
158 | struct qib_devdata *dd = private2dd(file); | 160 | struct qib_devdata *dd = private2dd(file); |
159 | 161 | ||
160 | return simple_read_from_buffer(buf, count, ppos, names, | 162 | avail = dd->f_read_cntrs(dd, *ppos, &names, NULL); |
161 | dd->f_read_cntrs(dd, *ppos, &names, NULL)); | 163 | return simple_read_from_buffer(buf, count, ppos, names, avail); |
162 | } | 164 | } |
163 | 165 | ||
164 | static const struct file_operations cntr_ops[] = { | 166 | static const struct file_operations cntr_ops[] = { |
@@ -176,10 +178,11 @@ static ssize_t portnames_read(struct file *file, char __user *buf, | |||
176 | size_t count, loff_t *ppos) | 178 | size_t count, loff_t *ppos) |
177 | { | 179 | { |
178 | char *names; | 180 | char *names; |
181 | size_t avail; | ||
179 | struct qib_devdata *dd = private2dd(file); | 182 | struct qib_devdata *dd = private2dd(file); |
180 | 183 | ||
181 | return simple_read_from_buffer(buf, count, ppos, names, | 184 | avail = dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL); |
182 | dd->f_read_portcntrs(dd, *ppos, 0, &names, NULL)); | 185 | return simple_read_from_buffer(buf, count, ppos, names, avail); |
183 | } | 186 | } |
184 | 187 | ||
185 | /* read the per-port counters for port 1 (pidx 0) */ | 188 | /* read the per-port counters for port 1 (pidx 0) */ |
@@ -187,10 +190,11 @@ static ssize_t portcntrs_1_read(struct file *file, char __user *buf, | |||
187 | size_t count, loff_t *ppos) | 190 | size_t count, loff_t *ppos) |
188 | { | 191 | { |
189 | u64 *counters; | 192 | u64 *counters; |
193 | size_t avail; | ||
190 | struct qib_devdata *dd = private2dd(file); | 194 | struct qib_devdata *dd = private2dd(file); |
191 | 195 | ||
192 | return simple_read_from_buffer(buf, count, ppos, counters, | 196 | avail = dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters); |
193 | dd->f_read_portcntrs(dd, *ppos, 0, NULL, &counters)); | 197 | return simple_read_from_buffer(buf, count, ppos, counters, avail); |
194 | } | 198 | } |
195 | 199 | ||
196 | /* read the per-port counters for port 2 (pidx 1) */ | 200 | /* read the per-port counters for port 2 (pidx 1) */ |
@@ -198,10 +202,11 @@ static ssize_t portcntrs_2_read(struct file *file, char __user *buf, | |||
198 | size_t count, loff_t *ppos) | 202 | size_t count, loff_t *ppos) |
199 | { | 203 | { |
200 | u64 *counters; | 204 | u64 *counters; |
205 | size_t avail; | ||
201 | struct qib_devdata *dd = private2dd(file); | 206 | struct qib_devdata *dd = private2dd(file); |
202 | 207 | ||
203 | return simple_read_from_buffer(buf, count, ppos, counters, | 208 | avail = dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters); |
204 | dd->f_read_portcntrs(dd, *ppos, 1, NULL, &counters)); | 209 | return simple_read_from_buffer(buf, count, ppos, counters, avail); |
205 | } | 210 | } |
206 | 211 | ||
207 | static const struct file_operations portcntr_ops[] = { | 212 | static const struct file_operations portcntr_ops[] = { |
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index 7b6549fd429b..1eadadc13da8 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c | |||
@@ -3475,14 +3475,6 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev, | |||
3475 | struct qib_devdata *dd; | 3475 | struct qib_devdata *dd; |
3476 | int ret; | 3476 | int ret; |
3477 | 3477 | ||
3478 | #ifndef CONFIG_PCI_MSI | ||
3479 | qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot " | ||
3480 | "work if CONFIG_PCI_MSI is not enabled\n", | ||
3481 | ent->device); | ||
3482 | dd = ERR_PTR(-ENODEV); | ||
3483 | goto bail; | ||
3484 | #endif | ||
3485 | |||
3486 | dd = qib_alloc_devdata(pdev, sizeof(struct qib_pportdata) + | 3478 | dd = qib_alloc_devdata(pdev, sizeof(struct qib_pportdata) + |
3487 | sizeof(struct qib_chip_specific)); | 3479 | sizeof(struct qib_chip_specific)); |
3488 | if (IS_ERR(dd)) | 3480 | if (IS_ERR(dd)) |
@@ -3554,10 +3546,6 @@ struct qib_devdata *qib_init_iba6120_funcs(struct pci_dev *pdev, | |||
3554 | if (qib_mini_init) | 3546 | if (qib_mini_init) |
3555 | goto bail; | 3547 | goto bail; |
3556 | 3548 | ||
3557 | #ifndef CONFIG_PCI_MSI | ||
3558 | qib_dev_err(dd, "PCI_MSI not configured, NO interrupts\n"); | ||
3559 | #endif | ||
3560 | |||
3561 | if (qib_pcie_params(dd, 8, NULL, NULL)) | 3549 | if (qib_pcie_params(dd, 8, NULL, NULL)) |
3562 | qib_dev_err(dd, "Failed to setup PCIe or interrupts; " | 3550 | qib_dev_err(dd, "Failed to setup PCIe or interrupts; " |
3563 | "continuing anyway\n"); | 3551 | "continuing anyway\n"); |
diff --git a/drivers/infiniband/hw/qib/qib_iba7322.c b/drivers/infiniband/hw/qib/qib_iba7322.c index 2c24eab35b54..503992d9c5ce 100644 --- a/drivers/infiniband/hw/qib/qib_iba7322.c +++ b/drivers/infiniband/hw/qib/qib_iba7322.c | |||
@@ -42,9 +42,6 @@ | |||
42 | #include <linux/jiffies.h> | 42 | #include <linux/jiffies.h> |
43 | #include <rdma/ib_verbs.h> | 43 | #include <rdma/ib_verbs.h> |
44 | #include <rdma/ib_smi.h> | 44 | #include <rdma/ib_smi.h> |
45 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
46 | #include <linux/dca.h> | ||
47 | #endif | ||
48 | 45 | ||
49 | #include "qib.h" | 46 | #include "qib.h" |
50 | #include "qib_7322_regs.h" | 47 | #include "qib_7322_regs.h" |
@@ -114,40 +111,18 @@ static ushort qib_singleport; | |||
114 | module_param_named(singleport, qib_singleport, ushort, S_IRUGO); | 111 | module_param_named(singleport, qib_singleport, ushort, S_IRUGO); |
115 | MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space"); | 112 | MODULE_PARM_DESC(singleport, "Use only IB port 1; more per-port buffer space"); |
116 | 113 | ||
117 | |||
118 | /* | ||
119 | * Setup QMH7342 receive and transmit parameters, necessary because | ||
120 | * each bay, Mez connector, and IB port need different tuning, beyond | ||
121 | * what the switch and HCA can do automatically. | ||
122 | * It's expected to be done by cat'ing files to the modules file, | ||
123 | * rather than setting up as a module parameter. | ||
124 | * It's a "write-only" file, returns 0 when read back. | ||
125 | * The unit, port, bay (if given), and values MUST be done as a single write. | ||
126 | * The unit, port, and bay must precede the values to be effective. | ||
127 | */ | ||
128 | static int setup_qmh_params(const char *, struct kernel_param *); | ||
129 | static unsigned dummy_qmh_params; | ||
130 | module_param_call(qmh_serdes_setup, setup_qmh_params, param_get_uint, | ||
131 | &dummy_qmh_params, S_IWUSR | S_IRUGO); | ||
132 | |||
133 | /* similarly for QME7342, but it's simpler */ | ||
134 | static int setup_qme_params(const char *, struct kernel_param *); | ||
135 | static unsigned dummy_qme_params; | ||
136 | module_param_call(qme_serdes_setup, setup_qme_params, param_get_uint, | ||
137 | &dummy_qme_params, S_IWUSR | S_IRUGO); | ||
138 | |||
139 | #define MAX_ATTEN_LEN 64 /* plenty for any real system */ | 114 | #define MAX_ATTEN_LEN 64 /* plenty for any real system */ |
140 | /* for read back, default index is ~5m copper cable */ | 115 | /* for read back, default index is ~5m copper cable */ |
141 | static char cable_atten_list[MAX_ATTEN_LEN] = "10"; | 116 | static char txselect_list[MAX_ATTEN_LEN] = "10"; |
142 | static struct kparam_string kp_cable_atten = { | 117 | static struct kparam_string kp_txselect = { |
143 | .string = cable_atten_list, | 118 | .string = txselect_list, |
144 | .maxlen = MAX_ATTEN_LEN | 119 | .maxlen = MAX_ATTEN_LEN |
145 | }; | 120 | }; |
146 | static int setup_cable_atten(const char *, struct kernel_param *); | 121 | static int setup_txselect(const char *, struct kernel_param *); |
147 | module_param_call(cable_atten, setup_cable_atten, param_get_string, | 122 | module_param_call(txselect, setup_txselect, param_get_string, |
148 | &kp_cable_atten, S_IWUSR | S_IRUGO); | 123 | &kp_txselect, S_IWUSR | S_IRUGO); |
149 | MODULE_PARM_DESC(cable_atten, \ | 124 | MODULE_PARM_DESC(txselect, \ |
150 | "cable attenuation indices for cables with invalid EEPROM"); | 125 | "Tx serdes indices (for no QSFP or invalid QSFP data)"); |
151 | 126 | ||
152 | #define BOARD_QME7342 5 | 127 | #define BOARD_QME7342 5 |
153 | #define BOARD_QMH7342 6 | 128 | #define BOARD_QMH7342 6 |
@@ -540,12 +515,6 @@ struct qib_chip_specific { | |||
540 | u32 lastbuf_for_pio; | 515 | u32 lastbuf_for_pio; |
541 | u32 stay_in_freeze; | 516 | u32 stay_in_freeze; |
542 | u32 recovery_ports_initted; | 517 | u32 recovery_ports_initted; |
543 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
544 | u32 dca_ctrl; | ||
545 | int rhdr_cpu[18]; | ||
546 | int sdma_cpu[2]; | ||
547 | u64 dca_rcvhdr_ctrl[5]; /* B, C, D, E, F */ | ||
548 | #endif | ||
549 | struct msix_entry *msix_entries; | 518 | struct msix_entry *msix_entries; |
550 | void **msix_arg; | 519 | void **msix_arg; |
551 | unsigned long *sendchkenable; | 520 | unsigned long *sendchkenable; |
@@ -574,11 +543,12 @@ struct vendor_txdds_ent { | |||
574 | static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); | 543 | static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); |
575 | 544 | ||
576 | #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ | 545 | #define TXDDS_TABLE_SZ 16 /* number of entries per speed in onchip table */ |
546 | #define TXDDS_EXTRA_SZ 11 /* number of extra tx settings entries */ | ||
577 | #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */ | 547 | #define SERDES_CHANS 4 /* yes, it's obvious, but one less magic number */ |
578 | 548 | ||
579 | #define H1_FORCE_VAL 8 | 549 | #define H1_FORCE_VAL 8 |
580 | #define H1_FORCE_QME 1 /* may be overridden via setup_qme_params() */ | 550 | #define H1_FORCE_QME 1 /* may be overridden via setup_txselect() */ |
581 | #define H1_FORCE_QMH 7 /* may be overridden via setup_qmh_params() */ | 551 | #define H1_FORCE_QMH 7 /* may be overridden via setup_txselect() */ |
582 | 552 | ||
583 | /* The static and dynamic registers are paired, and the pairs indexed by spd */ | 553 | /* The static and dynamic registers are paired, and the pairs indexed by spd */ |
584 | #define krp_static_adapt_dis(spd) (KREG_IBPORT_IDX(ADAPT_DISABLE_STATIC_SDR) \ | 554 | #define krp_static_adapt_dis(spd) (KREG_IBPORT_IDX(ADAPT_DISABLE_STATIC_SDR) \ |
@@ -590,15 +560,6 @@ static void write_tx_serdes_param(struct qib_pportdata *, struct txdds_ent *); | |||
590 | #define QDR_STATIC_ADAPT_INIT 0xffffffffffULL /* up, disable H0,H1-8, LE */ | 560 | #define QDR_STATIC_ADAPT_INIT 0xffffffffffULL /* up, disable H0,H1-8, LE */ |
591 | #define QDR_STATIC_ADAPT_INIT_R1 0xf0ffffffffULL /* r1 up, disable H0,H1-8 */ | 561 | #define QDR_STATIC_ADAPT_INIT_R1 0xf0ffffffffULL /* r1 up, disable H0,H1-8 */ |
592 | 562 | ||
593 | static const struct txdds_ent qmh_sdr_txdds = { 11, 0, 5, 6 }; | ||
594 | static const struct txdds_ent qmh_ddr_txdds = { 7, 0, 2, 8 }; | ||
595 | static const struct txdds_ent qmh_qdr_txdds = { 0, 1, 3, 10 }; | ||
596 | |||
597 | /* this is used for unknown mez cards also */ | ||
598 | static const struct txdds_ent qme_sdr_txdds = { 11, 0, 4, 4 }; | ||
599 | static const struct txdds_ent qme_ddr_txdds = { 7, 0, 2, 7 }; | ||
600 | static const struct txdds_ent qme_qdr_txdds = { 0, 1, 12, 11 }; | ||
601 | |||
602 | struct qib_chippport_specific { | 563 | struct qib_chippport_specific { |
603 | u64 __iomem *kpregbase; | 564 | u64 __iomem *kpregbase; |
604 | u64 __iomem *cpregbase; | 565 | u64 __iomem *cpregbase; |
@@ -637,12 +598,8 @@ struct qib_chippport_specific { | |||
637 | * Per-bay per-channel rcv QMH H1 values and Tx values for QDR. | 598 | * Per-bay per-channel rcv QMH H1 values and Tx values for QDR. |
638 | * entry zero is unused, to simplify indexing | 599 | * entry zero is unused, to simplify indexing |
639 | */ | 600 | */ |
640 | u16 h1_val; | 601 | u8 h1_val; |
641 | u8 amp[SERDES_CHANS]; | 602 | u8 no_eep; /* txselect table index to use if no qsfp info */ |
642 | u8 pre[SERDES_CHANS]; | ||
643 | u8 mainv[SERDES_CHANS]; | ||
644 | u8 post[SERDES_CHANS]; | ||
645 | u8 no_eep; /* attenuation index to use if no qsfp info */ | ||
646 | u8 ipg_tries; | 603 | u8 ipg_tries; |
647 | u8 ibmalfusesnap; | 604 | u8 ibmalfusesnap; |
648 | struct qib_qsfp_data qsfp_data; | 605 | struct qib_qsfp_data qsfp_data; |
@@ -676,52 +633,6 @@ static struct { | |||
676 | SYM_LSB(IntStatus, SDmaCleanupDone_1), 2 }, | 633 | SYM_LSB(IntStatus, SDmaCleanupDone_1), 2 }, |
677 | }; | 634 | }; |
678 | 635 | ||
679 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
680 | static const struct dca_reg_map { | ||
681 | int shadow_inx; | ||
682 | int lsb; | ||
683 | u64 mask; | ||
684 | u16 regno; | ||
685 | } dca_rcvhdr_reg_map[] = { | ||
686 | { 0, SYM_LSB(DCACtrlB, RcvHdrq0DCAOPH), | ||
687 | ~SYM_MASK(DCACtrlB, RcvHdrq0DCAOPH) , KREG_IDX(DCACtrlB) }, | ||
688 | { 0, SYM_LSB(DCACtrlB, RcvHdrq1DCAOPH), | ||
689 | ~SYM_MASK(DCACtrlB, RcvHdrq1DCAOPH) , KREG_IDX(DCACtrlB) }, | ||
690 | { 0, SYM_LSB(DCACtrlB, RcvHdrq2DCAOPH), | ||
691 | ~SYM_MASK(DCACtrlB, RcvHdrq2DCAOPH) , KREG_IDX(DCACtrlB) }, | ||
692 | { 0, SYM_LSB(DCACtrlB, RcvHdrq3DCAOPH), | ||
693 | ~SYM_MASK(DCACtrlB, RcvHdrq3DCAOPH) , KREG_IDX(DCACtrlB) }, | ||
694 | { 1, SYM_LSB(DCACtrlC, RcvHdrq4DCAOPH), | ||
695 | ~SYM_MASK(DCACtrlC, RcvHdrq4DCAOPH) , KREG_IDX(DCACtrlC) }, | ||
696 | { 1, SYM_LSB(DCACtrlC, RcvHdrq5DCAOPH), | ||
697 | ~SYM_MASK(DCACtrlC, RcvHdrq5DCAOPH) , KREG_IDX(DCACtrlC) }, | ||
698 | { 1, SYM_LSB(DCACtrlC, RcvHdrq6DCAOPH), | ||
699 | ~SYM_MASK(DCACtrlC, RcvHdrq6DCAOPH) , KREG_IDX(DCACtrlC) }, | ||
700 | { 1, SYM_LSB(DCACtrlC, RcvHdrq7DCAOPH), | ||
701 | ~SYM_MASK(DCACtrlC, RcvHdrq7DCAOPH) , KREG_IDX(DCACtrlC) }, | ||
702 | { 2, SYM_LSB(DCACtrlD, RcvHdrq8DCAOPH), | ||
703 | ~SYM_MASK(DCACtrlD, RcvHdrq8DCAOPH) , KREG_IDX(DCACtrlD) }, | ||
704 | { 2, SYM_LSB(DCACtrlD, RcvHdrq9DCAOPH), | ||
705 | ~SYM_MASK(DCACtrlD, RcvHdrq9DCAOPH) , KREG_IDX(DCACtrlD) }, | ||
706 | { 2, SYM_LSB(DCACtrlD, RcvHdrq10DCAOPH), | ||
707 | ~SYM_MASK(DCACtrlD, RcvHdrq10DCAOPH) , KREG_IDX(DCACtrlD) }, | ||
708 | { 2, SYM_LSB(DCACtrlD, RcvHdrq11DCAOPH), | ||
709 | ~SYM_MASK(DCACtrlD, RcvHdrq11DCAOPH) , KREG_IDX(DCACtrlD) }, | ||
710 | { 3, SYM_LSB(DCACtrlE, RcvHdrq12DCAOPH), | ||
711 | ~SYM_MASK(DCACtrlE, RcvHdrq12DCAOPH) , KREG_IDX(DCACtrlE) }, | ||
712 | { 3, SYM_LSB(DCACtrlE, RcvHdrq13DCAOPH), | ||
713 | ~SYM_MASK(DCACtrlE, RcvHdrq13DCAOPH) , KREG_IDX(DCACtrlE) }, | ||
714 | { 3, SYM_LSB(DCACtrlE, RcvHdrq14DCAOPH), | ||
715 | ~SYM_MASK(DCACtrlE, RcvHdrq14DCAOPH) , KREG_IDX(DCACtrlE) }, | ||
716 | { 3, SYM_LSB(DCACtrlE, RcvHdrq15DCAOPH), | ||
717 | ~SYM_MASK(DCACtrlE, RcvHdrq15DCAOPH) , KREG_IDX(DCACtrlE) }, | ||
718 | { 4, SYM_LSB(DCACtrlF, RcvHdrq16DCAOPH), | ||
719 | ~SYM_MASK(DCACtrlF, RcvHdrq16DCAOPH) , KREG_IDX(DCACtrlF) }, | ||
720 | { 4, SYM_LSB(DCACtrlF, RcvHdrq17DCAOPH), | ||
721 | ~SYM_MASK(DCACtrlF, RcvHdrq17DCAOPH) , KREG_IDX(DCACtrlF) }, | ||
722 | }; | ||
723 | #endif | ||
724 | |||
725 | /* ibcctrl bits */ | 636 | /* ibcctrl bits */ |
726 | #define QLOGIC_IB_IBCC_LINKINITCMD_DISABLE 1 | 637 | #define QLOGIC_IB_IBCC_LINKINITCMD_DISABLE 1 |
727 | /* cycle through TS1/TS2 till OK */ | 638 | /* cycle through TS1/TS2 till OK */ |
@@ -2572,95 +2483,6 @@ static void qib_setup_7322_setextled(struct qib_pportdata *ppd, u32 on) | |||
2572 | qib_write_kreg_port(ppd, krp_rcvpktledcnt, ledblink); | 2483 | qib_write_kreg_port(ppd, krp_rcvpktledcnt, ledblink); |
2573 | } | 2484 | } |
2574 | 2485 | ||
2575 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
2576 | static void qib_update_rhdrq_dca(struct qib_ctxtdata *rcd) | ||
2577 | { | ||
2578 | struct qib_devdata *dd = rcd->dd; | ||
2579 | struct qib_chip_specific *cspec = dd->cspec; | ||
2580 | int cpu = get_cpu(); | ||
2581 | |||
2582 | if (cspec->rhdr_cpu[rcd->ctxt] != cpu) { | ||
2583 | const struct dca_reg_map *rmp; | ||
2584 | |||
2585 | cspec->rhdr_cpu[rcd->ctxt] = cpu; | ||
2586 | rmp = &dca_rcvhdr_reg_map[rcd->ctxt]; | ||
2587 | cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] &= rmp->mask; | ||
2588 | cspec->dca_rcvhdr_ctrl[rmp->shadow_inx] |= | ||
2589 | (u64) dca3_get_tag(&dd->pcidev->dev, cpu) << rmp->lsb; | ||
2590 | qib_write_kreg(dd, rmp->regno, | ||
2591 | cspec->dca_rcvhdr_ctrl[rmp->shadow_inx]); | ||
2592 | cspec->dca_ctrl |= SYM_MASK(DCACtrlA, RcvHdrqDCAEnable); | ||
2593 | qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl); | ||
2594 | } | ||
2595 | put_cpu(); | ||
2596 | } | ||
2597 | |||
2598 | static void qib_update_sdma_dca(struct qib_pportdata *ppd) | ||
2599 | { | ||
2600 | struct qib_devdata *dd = ppd->dd; | ||
2601 | struct qib_chip_specific *cspec = dd->cspec; | ||
2602 | int cpu = get_cpu(); | ||
2603 | unsigned pidx = ppd->port - 1; | ||
2604 | |||
2605 | if (cspec->sdma_cpu[pidx] != cpu) { | ||
2606 | cspec->sdma_cpu[pidx] = cpu; | ||
2607 | cspec->dca_rcvhdr_ctrl[4] &= ~(ppd->hw_pidx ? | ||
2608 | SYM_MASK(DCACtrlF, SendDma1DCAOPH) : | ||
2609 | SYM_MASK(DCACtrlF, SendDma0DCAOPH)); | ||
2610 | cspec->dca_rcvhdr_ctrl[4] |= | ||
2611 | (u64) dca3_get_tag(&dd->pcidev->dev, cpu) << | ||
2612 | (ppd->hw_pidx ? | ||
2613 | SYM_LSB(DCACtrlF, SendDma1DCAOPH) : | ||
2614 | SYM_LSB(DCACtrlF, SendDma0DCAOPH)); | ||
2615 | qib_write_kreg(dd, KREG_IDX(DCACtrlF), | ||
2616 | cspec->dca_rcvhdr_ctrl[4]); | ||
2617 | cspec->dca_ctrl |= ppd->hw_pidx ? | ||
2618 | SYM_MASK(DCACtrlA, SendDMAHead1DCAEnable) : | ||
2619 | SYM_MASK(DCACtrlA, SendDMAHead0DCAEnable); | ||
2620 | qib_write_kreg(dd, KREG_IDX(DCACtrlA), cspec->dca_ctrl); | ||
2621 | } | ||
2622 | put_cpu(); | ||
2623 | } | ||
2624 | |||
2625 | static void qib_setup_dca(struct qib_devdata *dd) | ||
2626 | { | ||
2627 | struct qib_chip_specific *cspec = dd->cspec; | ||
2628 | int i; | ||
2629 | |||
2630 | for (i = 0; i < ARRAY_SIZE(cspec->rhdr_cpu); i++) | ||
2631 | cspec->rhdr_cpu[i] = -1; | ||
2632 | for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++) | ||
2633 | cspec->sdma_cpu[i] = -1; | ||
2634 | cspec->dca_rcvhdr_ctrl[0] = | ||
2635 | (1ULL << SYM_LSB(DCACtrlB, RcvHdrq0DCAXfrCnt)) | | ||
2636 | (1ULL << SYM_LSB(DCACtrlB, RcvHdrq1DCAXfrCnt)) | | ||
2637 | (1ULL << SYM_LSB(DCACtrlB, RcvHdrq2DCAXfrCnt)) | | ||
2638 | (1ULL << SYM_LSB(DCACtrlB, RcvHdrq3DCAXfrCnt)); | ||
2639 | cspec->dca_rcvhdr_ctrl[1] = | ||
2640 | (1ULL << SYM_LSB(DCACtrlC, RcvHdrq4DCAXfrCnt)) | | ||
2641 | (1ULL << SYM_LSB(DCACtrlC, RcvHdrq5DCAXfrCnt)) | | ||
2642 | (1ULL << SYM_LSB(DCACtrlC, RcvHdrq6DCAXfrCnt)) | | ||
2643 | (1ULL << SYM_LSB(DCACtrlC, RcvHdrq7DCAXfrCnt)); | ||
2644 | cspec->dca_rcvhdr_ctrl[2] = | ||
2645 | (1ULL << SYM_LSB(DCACtrlD, RcvHdrq8DCAXfrCnt)) | | ||
2646 | (1ULL << SYM_LSB(DCACtrlD, RcvHdrq9DCAXfrCnt)) | | ||
2647 | (1ULL << SYM_LSB(DCACtrlD, RcvHdrq10DCAXfrCnt)) | | ||
2648 | (1ULL << SYM_LSB(DCACtrlD, RcvHdrq11DCAXfrCnt)); | ||
2649 | cspec->dca_rcvhdr_ctrl[3] = | ||
2650 | (1ULL << SYM_LSB(DCACtrlE, RcvHdrq12DCAXfrCnt)) | | ||
2651 | (1ULL << SYM_LSB(DCACtrlE, RcvHdrq13DCAXfrCnt)) | | ||
2652 | (1ULL << SYM_LSB(DCACtrlE, RcvHdrq14DCAXfrCnt)) | | ||
2653 | (1ULL << SYM_LSB(DCACtrlE, RcvHdrq15DCAXfrCnt)); | ||
2654 | cspec->dca_rcvhdr_ctrl[4] = | ||
2655 | (1ULL << SYM_LSB(DCACtrlF, RcvHdrq16DCAXfrCnt)) | | ||
2656 | (1ULL << SYM_LSB(DCACtrlF, RcvHdrq17DCAXfrCnt)); | ||
2657 | for (i = 0; i < ARRAY_SIZE(cspec->sdma_cpu); i++) | ||
2658 | qib_write_kreg(dd, KREG_IDX(DCACtrlB) + i, | ||
2659 | cspec->dca_rcvhdr_ctrl[i]); | ||
2660 | } | ||
2661 | |||
2662 | #endif | ||
2663 | |||
2664 | /* | 2486 | /* |
2665 | * Disable MSIx interrupt if enabled, call generic MSIx code | 2487 | * Disable MSIx interrupt if enabled, call generic MSIx code |
2666 | * to cleanup, and clear pending MSIx interrupts. | 2488 | * to cleanup, and clear pending MSIx interrupts. |
@@ -2701,15 +2523,6 @@ static void qib_setup_7322_cleanup(struct qib_devdata *dd) | |||
2701 | { | 2523 | { |
2702 | int i; | 2524 | int i; |
2703 | 2525 | ||
2704 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
2705 | if (dd->flags & QIB_DCA_ENABLED) { | ||
2706 | dca_remove_requester(&dd->pcidev->dev); | ||
2707 | dd->flags &= ~QIB_DCA_ENABLED; | ||
2708 | dd->cspec->dca_ctrl = 0; | ||
2709 | qib_write_kreg(dd, KREG_IDX(DCACtrlA), dd->cspec->dca_ctrl); | ||
2710 | } | ||
2711 | #endif | ||
2712 | |||
2713 | qib_7322_free_irq(dd); | 2526 | qib_7322_free_irq(dd); |
2714 | kfree(dd->cspec->cntrs); | 2527 | kfree(dd->cspec->cntrs); |
2715 | kfree(dd->cspec->sendchkenable); | 2528 | kfree(dd->cspec->sendchkenable); |
@@ -3017,11 +2830,6 @@ static irqreturn_t qib_7322pintr(int irq, void *data) | |||
3017 | if (dd->int_counter != (u32) -1) | 2830 | if (dd->int_counter != (u32) -1) |
3018 | dd->int_counter++; | 2831 | dd->int_counter++; |
3019 | 2832 | ||
3020 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
3021 | if (dd->flags & QIB_DCA_ENABLED) | ||
3022 | qib_update_rhdrq_dca(rcd); | ||
3023 | #endif | ||
3024 | |||
3025 | /* Clear the interrupt bit we expect to be set. */ | 2833 | /* Clear the interrupt bit we expect to be set. */ |
3026 | qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) | | 2834 | qib_write_kreg(dd, kr_intclear, ((1ULL << QIB_I_RCVAVAIL_LSB) | |
3027 | (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt); | 2835 | (1ULL << QIB_I_RCVURG_LSB)) << rcd->ctxt); |
@@ -3085,11 +2893,6 @@ static irqreturn_t sdma_intr(int irq, void *data) | |||
3085 | if (dd->int_counter != (u32) -1) | 2893 | if (dd->int_counter != (u32) -1) |
3086 | dd->int_counter++; | 2894 | dd->int_counter++; |
3087 | 2895 | ||
3088 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
3089 | if (dd->flags & QIB_DCA_ENABLED) | ||
3090 | qib_update_sdma_dca(ppd); | ||
3091 | #endif | ||
3092 | |||
3093 | /* Clear the interrupt bit we expect to be set. */ | 2896 | /* Clear the interrupt bit we expect to be set. */ |
3094 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? | 2897 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? |
3095 | INT_MASK_P(SDma, 1) : INT_MASK_P(SDma, 0)); | 2898 | INT_MASK_P(SDma, 1) : INT_MASK_P(SDma, 0)); |
@@ -3119,11 +2922,6 @@ static irqreturn_t sdma_idle_intr(int irq, void *data) | |||
3119 | if (dd->int_counter != (u32) -1) | 2922 | if (dd->int_counter != (u32) -1) |
3120 | dd->int_counter++; | 2923 | dd->int_counter++; |
3121 | 2924 | ||
3122 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
3123 | if (dd->flags & QIB_DCA_ENABLED) | ||
3124 | qib_update_sdma_dca(ppd); | ||
3125 | #endif | ||
3126 | |||
3127 | /* Clear the interrupt bit we expect to be set. */ | 2925 | /* Clear the interrupt bit we expect to be set. */ |
3128 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? | 2926 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? |
3129 | INT_MASK_P(SDmaIdle, 1) : INT_MASK_P(SDmaIdle, 0)); | 2927 | INT_MASK_P(SDmaIdle, 1) : INT_MASK_P(SDmaIdle, 0)); |
@@ -3153,11 +2951,6 @@ static irqreturn_t sdma_progress_intr(int irq, void *data) | |||
3153 | if (dd->int_counter != (u32) -1) | 2951 | if (dd->int_counter != (u32) -1) |
3154 | dd->int_counter++; | 2952 | dd->int_counter++; |
3155 | 2953 | ||
3156 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
3157 | if (dd->flags & QIB_DCA_ENABLED) | ||
3158 | qib_update_sdma_dca(ppd); | ||
3159 | #endif | ||
3160 | |||
3161 | /* Clear the interrupt bit we expect to be set. */ | 2954 | /* Clear the interrupt bit we expect to be set. */ |
3162 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? | 2955 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? |
3163 | INT_MASK_P(SDmaProgress, 1) : | 2956 | INT_MASK_P(SDmaProgress, 1) : |
@@ -3188,11 +2981,6 @@ static irqreturn_t sdma_cleanup_intr(int irq, void *data) | |||
3188 | if (dd->int_counter != (u32) -1) | 2981 | if (dd->int_counter != (u32) -1) |
3189 | dd->int_counter++; | 2982 | dd->int_counter++; |
3190 | 2983 | ||
3191 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
3192 | if (dd->flags & QIB_DCA_ENABLED) | ||
3193 | qib_update_sdma_dca(ppd); | ||
3194 | #endif | ||
3195 | |||
3196 | /* Clear the interrupt bit we expect to be set. */ | 2984 | /* Clear the interrupt bit we expect to be set. */ |
3197 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? | 2985 | qib_write_kreg(dd, kr_intclear, ppd->hw_pidx ? |
3198 | INT_MASK_PM(SDmaCleanupDone, 1) : | 2986 | INT_MASK_PM(SDmaCleanupDone, 1) : |
@@ -4299,10 +4087,6 @@ static void rcvctrl_7322_mod(struct qib_pportdata *ppd, unsigned int op, | |||
4299 | qib_write_kreg_ctxt(dd, krc_rcvhdraddr, ctxt, | 4087 | qib_write_kreg_ctxt(dd, krc_rcvhdraddr, ctxt, |
4300 | rcd->rcvhdrq_phys); | 4088 | rcd->rcvhdrq_phys); |
4301 | rcd->seq_cnt = 1; | 4089 | rcd->seq_cnt = 1; |
4302 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
4303 | if (dd->flags & QIB_DCA_ENABLED) | ||
4304 | qib_update_rhdrq_dca(rcd); | ||
4305 | #endif | ||
4306 | } | 4090 | } |
4307 | if (op & QIB_RCVCTRL_CTXT_DIS) | 4091 | if (op & QIB_RCVCTRL_CTXT_DIS) |
4308 | ppd->p_rcvctrl &= | 4092 | ppd->p_rcvctrl &= |
@@ -5360,7 +5144,13 @@ static int qib_7322_ib_updown(struct qib_pportdata *ppd, int ibup, u64 ibcs) | |||
5360 | QIBL_IB_AUTONEG_INPROG))) | 5144 | QIBL_IB_AUTONEG_INPROG))) |
5361 | set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled); | 5145 | set_7322_ibspeed_fast(ppd, ppd->link_speed_enabled); |
5362 | if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) { | 5146 | if (!(ppd->lflags & QIBL_IB_AUTONEG_INPROG)) { |
5147 | /* unlock the Tx settings, speed may change */ | ||
5148 | qib_write_kreg_port(ppd, krp_tx_deemph_override, | ||
5149 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
5150 | reset_tx_deemphasis_override)); | ||
5363 | qib_cancel_sends(ppd); | 5151 | qib_cancel_sends(ppd); |
5152 | /* on link down, ensure sane pcs state */ | ||
5153 | qib_7322_mini_pcs_reset(ppd); | ||
5364 | spin_lock_irqsave(&ppd->sdma_lock, flags); | 5154 | spin_lock_irqsave(&ppd->sdma_lock, flags); |
5365 | if (__qib_sdma_running(ppd)) | 5155 | if (__qib_sdma_running(ppd)) |
5366 | __qib_sdma_process_event(ppd, | 5156 | __qib_sdma_process_event(ppd, |
@@ -5766,26 +5556,28 @@ static void qib_init_7322_qsfp(struct qib_pportdata *ppd) | |||
5766 | } | 5556 | } |
5767 | 5557 | ||
5768 | /* | 5558 | /* |
5769 | * called at device initialization time, and also if the cable_atten | 5559 | * called at device initialization time, and also if the txselect |
5770 | * module parameter is changed. This is used for cables that don't | 5560 | * module parameter is changed. This is used for cables that don't |
5771 | * have valid QSFP EEPROMs (not present, or attenuation is zero). | 5561 | * have valid QSFP EEPROMs (not present, or attenuation is zero). |
5772 | * We initialize to the default, then if there is a specific | 5562 | * We initialize to the default, then if there is a specific |
5773 | * unit,port match, we use that. | 5563 | * unit,port match, we use that (and set it immediately, for the |
5564 | * current speed, if the link is at INIT or better). | ||
5774 | * String format is "default# unit#,port#=# ... u,p=#", separators must | 5565 | * String format is "default# unit#,port#=# ... u,p=#", separators must |
5775 | * be a SPACE character. A newline terminates. | 5566 | * be a SPACE character. A newline terminates. The u,p=# tuples may |
5567 | * optionally have "u,p=#,#", where the final # is the H1 value | ||
5776 | * The last specific match is used (actually, all are used, but last | 5568 | * The last specific match is used (actually, all are used, but last |
5777 | * one is the one that winds up set); if none at all, fall back on default. | 5569 | * one is the one that winds up set); if none at all, fall back on default. |
5778 | */ | 5570 | */ |
5779 | static void set_no_qsfp_atten(struct qib_devdata *dd, int change) | 5571 | static void set_no_qsfp_atten(struct qib_devdata *dd, int change) |
5780 | { | 5572 | { |
5781 | char *nxt, *str; | 5573 | char *nxt, *str; |
5782 | int pidx, unit, port, deflt; | 5574 | u32 pidx, unit, port, deflt, h1; |
5783 | unsigned long val; | 5575 | unsigned long val; |
5784 | int any = 0; | 5576 | int any = 0, seth1; |
5785 | 5577 | ||
5786 | str = cable_atten_list; | 5578 | str = txselect_list; |
5787 | 5579 | ||
5788 | /* default number is validated in setup_cable_atten() */ | 5580 | /* default number is validated in setup_txselect() */ |
5789 | deflt = simple_strtoul(str, &nxt, 0); | 5581 | deflt = simple_strtoul(str, &nxt, 0); |
5790 | for (pidx = 0; pidx < dd->num_pports; ++pidx) | 5582 | for (pidx = 0; pidx < dd->num_pports; ++pidx) |
5791 | dd->pport[pidx].cpspec->no_eep = deflt; | 5583 | dd->pport[pidx].cpspec->no_eep = deflt; |
@@ -5812,16 +5604,28 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) | |||
5812 | ; | 5604 | ; |
5813 | continue; | 5605 | continue; |
5814 | } | 5606 | } |
5815 | if (val >= TXDDS_TABLE_SZ) | 5607 | if (val >= TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ) |
5816 | continue; | 5608 | continue; |
5609 | seth1 = 0; | ||
5610 | h1 = 0; /* gcc thinks it might be used uninitted */ | ||
5611 | if (*nxt == ',' && nxt[1]) { | ||
5612 | str = ++nxt; | ||
5613 | h1 = (u32)simple_strtoul(str, &nxt, 0); | ||
5614 | if (nxt == str) | ||
5615 | while (*nxt && *nxt++ != ' ') /* skip */ | ||
5616 | ; | ||
5617 | else | ||
5618 | seth1 = 1; | ||
5619 | } | ||
5817 | for (pidx = 0; dd->unit == unit && pidx < dd->num_pports; | 5620 | for (pidx = 0; dd->unit == unit && pidx < dd->num_pports; |
5818 | ++pidx) { | 5621 | ++pidx) { |
5819 | if (dd->pport[pidx].port != port || | 5622 | struct qib_pportdata *ppd = &dd->pport[pidx]; |
5820 | !dd->pport[pidx].link_speed_supported) | 5623 | |
5624 | if (ppd->port != port || !ppd->link_speed_supported) | ||
5821 | continue; | 5625 | continue; |
5822 | dd->pport[pidx].cpspec->no_eep = val; | 5626 | ppd->cpspec->no_eep = val; |
5823 | /* now change the IBC and serdes, overriding generic */ | 5627 | /* now change the IBC and serdes, overriding generic */ |
5824 | init_txdds_table(&dd->pport[pidx], 1); | 5628 | init_txdds_table(ppd, 1); |
5825 | any++; | 5629 | any++; |
5826 | } | 5630 | } |
5827 | if (*nxt == '\n') | 5631 | if (*nxt == '\n') |
@@ -5832,35 +5636,35 @@ static void set_no_qsfp_atten(struct qib_devdata *dd, int change) | |||
5832 | * Change the IBC and serdes, but since it's | 5636 | * Change the IBC and serdes, but since it's |
5833 | * general, don't override specific settings. | 5637 | * general, don't override specific settings. |
5834 | */ | 5638 | */ |
5835 | for (pidx = 0; pidx < dd->num_pports; ++pidx) { | 5639 | for (pidx = 0; pidx < dd->num_pports; ++pidx) |
5836 | if (!dd->pport[pidx].link_speed_supported) | 5640 | if (dd->pport[pidx].link_speed_supported) |
5837 | continue; | 5641 | init_txdds_table(&dd->pport[pidx], 0); |
5838 | init_txdds_table(&dd->pport[pidx], 0); | ||
5839 | } | ||
5840 | } | 5642 | } |
5841 | } | 5643 | } |
5842 | 5644 | ||
5843 | /* handle the cable_atten parameter changing */ | 5645 | /* handle the txselect parameter changing */ |
5844 | static int setup_cable_atten(const char *str, struct kernel_param *kp) | 5646 | static int setup_txselect(const char *str, struct kernel_param *kp) |
5845 | { | 5647 | { |
5846 | struct qib_devdata *dd; | 5648 | struct qib_devdata *dd; |
5847 | unsigned long val; | 5649 | unsigned long val; |
5848 | char *n; | 5650 | char *n; |
5849 | if (strlen(str) >= MAX_ATTEN_LEN) { | 5651 | if (strlen(str) >= MAX_ATTEN_LEN) { |
5850 | printk(KERN_INFO QIB_DRV_NAME " cable_atten_values string " | 5652 | printk(KERN_INFO QIB_DRV_NAME " txselect_values string " |
5851 | "too long\n"); | 5653 | "too long\n"); |
5852 | return -ENOSPC; | 5654 | return -ENOSPC; |
5853 | } | 5655 | } |
5854 | val = simple_strtoul(str, &n, 0); | 5656 | val = simple_strtoul(str, &n, 0); |
5855 | if (n == str || val >= TXDDS_TABLE_SZ) { | 5657 | if (n == str || val >= (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) { |
5856 | printk(KERN_INFO QIB_DRV_NAME | 5658 | printk(KERN_INFO QIB_DRV_NAME |
5857 | "cable_atten_values must start with a number\n"); | 5659 | "txselect_values must start with a number < %d\n", |
5660 | TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ); | ||
5858 | return -EINVAL; | 5661 | return -EINVAL; |
5859 | } | 5662 | } |
5860 | strcpy(cable_atten_list, str); | 5663 | strcpy(txselect_list, str); |
5861 | 5664 | ||
5862 | list_for_each_entry(dd, &qib_dev_list, list) | 5665 | list_for_each_entry(dd, &qib_dev_list, list) |
5863 | set_no_qsfp_atten(dd, 1); | 5666 | if (dd->deviceid == PCI_DEVICE_ID_QLOGIC_IB_7322) |
5667 | set_no_qsfp_atten(dd, 1); | ||
5864 | return 0; | 5668 | return 0; |
5865 | } | 5669 | } |
5866 | 5670 | ||
@@ -6261,28 +6065,17 @@ static int qib_init_7322_variables(struct qib_devdata *dd) | |||
6261 | * in adapter-specific routines. | 6065 | * in adapter-specific routines. |
6262 | */ | 6066 | */ |
6263 | if (!(ppd->dd->flags & QIB_HAS_QSFP)) { | 6067 | if (!(ppd->dd->flags & QIB_HAS_QSFP)) { |
6264 | int i; | ||
6265 | const struct txdds_ent *txdds; | ||
6266 | |||
6267 | if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd)) | 6068 | if (!IS_QMH(ppd->dd) && !IS_QME(ppd->dd)) |
6268 | qib_devinfo(ppd->dd->pcidev, "IB%u:%u: " | 6069 | qib_devinfo(ppd->dd->pcidev, "IB%u:%u: " |
6269 | "Unknown mezzanine card type\n", | 6070 | "Unknown mezzanine card type\n", |
6270 | ppd->dd->unit, ppd->port); | 6071 | dd->unit, ppd->port); |
6271 | txdds = IS_QMH(ppd->dd) ? &qmh_qdr_txdds : | 6072 | cp->h1_val = IS_QMH(dd) ? H1_FORCE_QMH : H1_FORCE_QME; |
6272 | &qme_qdr_txdds; | ||
6273 | |||
6274 | /* | 6073 | /* |
6275 | * set values in case link comes up | 6074 | * Choose center value as default tx serdes setting |
6276 | * before table is written to driver. | 6075 | * until changed through module parameter. |
6277 | */ | 6076 | */ |
6278 | cp->h1_val = IS_QMH(ppd->dd) ? H1_FORCE_QMH : | 6077 | ppd->cpspec->no_eep = IS_QMH(dd) ? |
6279 | H1_FORCE_QME; | 6078 | TXDDS_TABLE_SZ + 2 : TXDDS_TABLE_SZ + 4; |
6280 | for (i = 0; i < SERDES_CHANS; i++) { | ||
6281 | cp->amp[i] = txdds->amp; | ||
6282 | cp->pre[i] = txdds->pre; | ||
6283 | cp->mainv[i] = txdds->main; | ||
6284 | cp->post[i] = txdds->post; | ||
6285 | } | ||
6286 | } else | 6079 | } else |
6287 | cp->h1_val = H1_FORCE_VAL; | 6080 | cp->h1_val = H1_FORCE_VAL; |
6288 | 6081 | ||
@@ -6299,8 +6092,7 @@ static int qib_init_7322_variables(struct qib_devdata *dd) | |||
6299 | 6092 | ||
6300 | dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE; | 6093 | dd->rcvhdrentsize = QIB_RCVHDR_ENTSIZE; |
6301 | dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE; | 6094 | dd->rcvhdrsize = QIB_DFLT_RCVHDRSIZE; |
6302 | dd->rhf_offset = | 6095 | dd->rhf_offset = dd->rcvhdrentsize - sizeof(u64) / sizeof(u32); |
6303 | dd->rcvhdrentsize - sizeof(u64) / sizeof(u32); | ||
6304 | 6096 | ||
6305 | /* we always allocate at least 2048 bytes for eager buffers */ | 6097 | /* we always allocate at least 2048 bytes for eager buffers */ |
6306 | dd->rcvegrbufsize = max(mtu, 2048); | 6098 | dd->rcvegrbufsize = max(mtu, 2048); |
@@ -6919,13 +6711,6 @@ struct qib_devdata *qib_init_iba7322_funcs(struct pci_dev *pdev, | |||
6919 | /* clear diagctrl register, in case diags were running and crashed */ | 6711 | /* clear diagctrl register, in case diags were running and crashed */ |
6920 | qib_write_kreg(dd, kr_hwdiagctrl, 0); | 6712 | qib_write_kreg(dd, kr_hwdiagctrl, 0); |
6921 | 6713 | ||
6922 | #if defined(CONFIG_DCA) || defined(CONFIG_DCA_MODULE) | ||
6923 | ret = dca_add_requester(&pdev->dev); | ||
6924 | if (!ret) { | ||
6925 | dd->flags |= QIB_DCA_ENABLED; | ||
6926 | qib_setup_dca(dd); | ||
6927 | } | ||
6928 | #endif | ||
6929 | goto bail; | 6714 | goto bail; |
6930 | 6715 | ||
6931 | bail_cleanup: | 6716 | bail_cleanup: |
@@ -7111,8 +6896,8 @@ static const struct txdds_ent txdds_ddr[TXDDS_TABLE_SZ] = { | |||
7111 | static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = { | 6896 | static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = { |
7112 | /* amp, pre, main, post */ | 6897 | /* amp, pre, main, post */ |
7113 | { 2, 2, 15, 6 }, /* Loopback */ | 6898 | { 2, 2, 15, 6 }, /* Loopback */ |
7114 | { 0, 1, 0, 7 }, /* 2 dB */ | 6899 | { 0, 1, 0, 7 }, /* 2 dB (also QMH7342) */ |
7115 | { 0, 1, 0, 9 }, /* 3 dB */ | 6900 | { 0, 1, 0, 9 }, /* 3 dB (also QMH7342) */ |
7116 | { 0, 1, 0, 11 }, /* 4 dB */ | 6901 | { 0, 1, 0, 11 }, /* 4 dB */ |
7117 | { 0, 1, 0, 13 }, /* 5 dB */ | 6902 | { 0, 1, 0, 13 }, /* 5 dB */ |
7118 | { 0, 1, 0, 15 }, /* 6 dB */ | 6903 | { 0, 1, 0, 15 }, /* 6 dB */ |
@@ -7128,6 +6913,57 @@ static const struct txdds_ent txdds_qdr[TXDDS_TABLE_SZ] = { | |||
7128 | { 0, 2, 9, 15 }, /* 16 dB */ | 6913 | { 0, 2, 9, 15 }, /* 16 dB */ |
7129 | }; | 6914 | }; |
7130 | 6915 | ||
6916 | /* | ||
6917 | * extra entries for use with txselect, for indices >= TXDDS_TABLE_SZ. | ||
6918 | * These are mostly used for mez cards going through connectors | ||
6919 | * and backplane traces, but can be used to add other "unusual" | ||
6920 | * table values as well. | ||
6921 | */ | ||
6922 | static const struct txdds_ent txdds_extra_sdr[TXDDS_EXTRA_SZ] = { | ||
6923 | /* amp, pre, main, post */ | ||
6924 | { 0, 0, 0, 1 }, /* QMH7342 backplane settings */ | ||
6925 | { 0, 0, 0, 1 }, /* QMH7342 backplane settings */ | ||
6926 | { 0, 0, 0, 2 }, /* QMH7342 backplane settings */ | ||
6927 | { 0, 0, 0, 2 }, /* QMH7342 backplane settings */ | ||
6928 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
6929 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
6930 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
6931 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
6932 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
6933 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
6934 | { 0, 0, 0, 11 }, /* QME7342 backplane settings */ | ||
6935 | }; | ||
6936 | |||
6937 | static const struct txdds_ent txdds_extra_ddr[TXDDS_EXTRA_SZ] = { | ||
6938 | /* amp, pre, main, post */ | ||
6939 | { 0, 0, 0, 7 }, /* QMH7342 backplane settings */ | ||
6940 | { 0, 0, 0, 7 }, /* QMH7342 backplane settings */ | ||
6941 | { 0, 0, 0, 8 }, /* QMH7342 backplane settings */ | ||
6942 | { 0, 0, 0, 8 }, /* QMH7342 backplane settings */ | ||
6943 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
6944 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
6945 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
6946 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
6947 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
6948 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
6949 | { 0, 0, 0, 13 }, /* QME7342 backplane settings */ | ||
6950 | }; | ||
6951 | |||
6952 | static const struct txdds_ent txdds_extra_qdr[TXDDS_EXTRA_SZ] = { | ||
6953 | /* amp, pre, main, post */ | ||
6954 | { 0, 1, 0, 4 }, /* QMH7342 backplane settings */ | ||
6955 | { 0, 1, 0, 5 }, /* QMH7342 backplane settings */ | ||
6956 | { 0, 1, 0, 6 }, /* QMH7342 backplane settings */ | ||
6957 | { 0, 1, 0, 8 }, /* QMH7342 backplane settings */ | ||
6958 | { 0, 1, 12, 10 }, /* QME7342 backplane setting */ | ||
6959 | { 0, 1, 12, 11 }, /* QME7342 backplane setting */ | ||
6960 | { 0, 1, 12, 12 }, /* QME7342 backplane setting */ | ||
6961 | { 0, 1, 12, 14 }, /* QME7342 backplane setting */ | ||
6962 | { 0, 1, 12, 6 }, /* QME7342 backplane setting */ | ||
6963 | { 0, 1, 12, 7 }, /* QME7342 backplane setting */ | ||
6964 | { 0, 1, 12, 8 }, /* QME7342 backplane setting */ | ||
6965 | }; | ||
6966 | |||
7131 | static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, | 6967 | static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, |
7132 | unsigned atten) | 6968 | unsigned atten) |
7133 | { | 6969 | { |
@@ -7145,7 +6981,7 @@ static const struct txdds_ent *get_atten_table(const struct txdds_ent *txdds, | |||
7145 | } | 6981 | } |
7146 | 6982 | ||
7147 | /* | 6983 | /* |
7148 | * if override is set, the module parameter cable_atten has a value | 6984 | * if override is set, the module parameter txselect has a value |
7149 | * for this specific port, so use it, rather than our normal mechanism. | 6985 | * for this specific port, so use it, rather than our normal mechanism. |
7150 | */ | 6986 | */ |
7151 | static void find_best_ent(struct qib_pportdata *ppd, | 6987 | static void find_best_ent(struct qib_pportdata *ppd, |
@@ -7184,15 +7020,28 @@ static void find_best_ent(struct qib_pportdata *ppd, | |||
7184 | *ddr_dds = get_atten_table(txdds_ddr, qd->atten[0]); | 7020 | *ddr_dds = get_atten_table(txdds_ddr, qd->atten[0]); |
7185 | *qdr_dds = get_atten_table(txdds_qdr, qd->atten[1]); | 7021 | *qdr_dds = get_atten_table(txdds_qdr, qd->atten[1]); |
7186 | return; | 7022 | return; |
7187 | } else { | 7023 | } else if (ppd->cpspec->no_eep < TXDDS_TABLE_SZ) { |
7188 | /* | 7024 | /* |
7189 | * If we have no (or incomplete) data from the cable | 7025 | * If we have no (or incomplete) data from the cable |
7190 | * EEPROM, or no QSFP, use the module parameter value | 7026 | * EEPROM, or no QSFP, or override is set, use the |
7191 | * to index into the attentuation table. | 7027 | * module parameter value to index into the attentuation |
7028 | * table. | ||
7192 | */ | 7029 | */ |
7193 | *sdr_dds = &txdds_sdr[ppd->cpspec->no_eep]; | 7030 | idx = ppd->cpspec->no_eep; |
7194 | *ddr_dds = &txdds_ddr[ppd->cpspec->no_eep]; | 7031 | *sdr_dds = &txdds_sdr[idx]; |
7195 | *qdr_dds = &txdds_qdr[ppd->cpspec->no_eep]; | 7032 | *ddr_dds = &txdds_ddr[idx]; |
7033 | *qdr_dds = &txdds_qdr[idx]; | ||
7034 | } else if (ppd->cpspec->no_eep < (TXDDS_TABLE_SZ + TXDDS_EXTRA_SZ)) { | ||
7035 | /* similar to above, but index into the "extra" table. */ | ||
7036 | idx = ppd->cpspec->no_eep - TXDDS_TABLE_SZ; | ||
7037 | *sdr_dds = &txdds_extra_sdr[idx]; | ||
7038 | *ddr_dds = &txdds_extra_ddr[idx]; | ||
7039 | *qdr_dds = &txdds_extra_qdr[idx]; | ||
7040 | } else { | ||
7041 | /* this shouldn't happen, it's range checked */ | ||
7042 | *sdr_dds = txdds_sdr + qib_long_atten; | ||
7043 | *ddr_dds = txdds_ddr + qib_long_atten; | ||
7044 | *qdr_dds = txdds_qdr + qib_long_atten; | ||
7196 | } | 7045 | } |
7197 | } | 7046 | } |
7198 | 7047 | ||
@@ -7203,33 +7052,24 @@ static void init_txdds_table(struct qib_pportdata *ppd, int override) | |||
7203 | int idx; | 7052 | int idx; |
7204 | int single_ent = 0; | 7053 | int single_ent = 0; |
7205 | 7054 | ||
7206 | if (IS_QMH(ppd->dd)) { | 7055 | find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override); |
7207 | /* normally will be overridden, via setup_qmh() */ | 7056 | |
7208 | sdr_dds = &qmh_sdr_txdds; | 7057 | /* for mez cards or override, use the selected value for all entries */ |
7209 | ddr_dds = &qmh_ddr_txdds; | 7058 | if (!(ppd->dd->flags & QIB_HAS_QSFP) || override) |
7210 | qdr_dds = &qmh_qdr_txdds; | ||
7211 | single_ent = 1; | ||
7212 | } else if (IS_QME(ppd->dd)) { | ||
7213 | sdr_dds = &qme_sdr_txdds; | ||
7214 | ddr_dds = &qme_ddr_txdds; | ||
7215 | qdr_dds = &qme_qdr_txdds; | ||
7216 | single_ent = 1; | 7059 | single_ent = 1; |
7217 | } else | ||
7218 | find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, override); | ||
7219 | 7060 | ||
7220 | /* Fill in the first entry with the best entry found. */ | 7061 | /* Fill in the first entry with the best entry found. */ |
7221 | set_txdds(ppd, 0, sdr_dds); | 7062 | set_txdds(ppd, 0, sdr_dds); |
7222 | set_txdds(ppd, TXDDS_TABLE_SZ, ddr_dds); | 7063 | set_txdds(ppd, TXDDS_TABLE_SZ, ddr_dds); |
7223 | set_txdds(ppd, 2 * TXDDS_TABLE_SZ, qdr_dds); | 7064 | set_txdds(ppd, 2 * TXDDS_TABLE_SZ, qdr_dds); |
7224 | 7065 | if (ppd->lflags & (QIBL_LINKINIT | QIBL_LINKARMED | | |
7225 | /* | 7066 | QIBL_LINKACTIVE)) { |
7226 | * for our current speed, also write that value into the | 7067 | dds = (struct txdds_ent *)(ppd->link_speed_active == |
7227 | * tx serdes registers. | 7068 | QIB_IB_QDR ? qdr_dds : |
7228 | */ | 7069 | (ppd->link_speed_active == |
7229 | dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ? | 7070 | QIB_IB_DDR ? ddr_dds : sdr_dds)); |
7230 | qdr_dds : (ppd->link_speed_active == | 7071 | write_tx_serdes_param(ppd, dds); |
7231 | QIB_IB_DDR ? ddr_dds : sdr_dds)); | 7072 | } |
7232 | write_tx_serdes_param(ppd, dds); | ||
7233 | 7073 | ||
7234 | /* Fill in the remaining entries with the default table values. */ | 7074 | /* Fill in the remaining entries with the default table values. */ |
7235 | for (idx = 1; idx < ARRAY_SIZE(txdds_sdr); ++idx) { | 7075 | for (idx = 1; idx < ARRAY_SIZE(txdds_sdr); ++idx) { |
@@ -7352,6 +7192,11 @@ static int serdes_7322_init(struct qib_pportdata *ppd) | |||
7352 | */ | 7192 | */ |
7353 | init_txdds_table(ppd, 0); | 7193 | init_txdds_table(ppd, 0); |
7354 | 7194 | ||
7195 | /* ensure no tx overrides from earlier driver loads */ | ||
7196 | qib_write_kreg_port(ppd, krp_tx_deemph_override, | ||
7197 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7198 | reset_tx_deemphasis_override)); | ||
7199 | |||
7355 | /* Patch some SerDes defaults to "Better for IB" */ | 7200 | /* Patch some SerDes defaults to "Better for IB" */ |
7356 | /* Timing Loop Bandwidth: cdr_timing[11:9] = 0 */ | 7201 | /* Timing Loop Bandwidth: cdr_timing[11:9] = 0 */ |
7357 | ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9)); | 7202 | ibsd_wr_allchans(ppd, 2, 0, BMASK(11, 9)); |
@@ -7421,7 +7266,7 @@ static int serdes_7322_init(struct qib_pportdata *ppd) | |||
7421 | QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN); | 7266 | QDR_STATIC_ADAPT_DOWN_R1 : QDR_STATIC_ADAPT_DOWN); |
7422 | ppd->cpspec->qdr_dfe_on = 1; | 7267 | ppd->cpspec->qdr_dfe_on = 1; |
7423 | 7268 | ||
7424 | /* (FLoop LOS gate: PPM filter enabled */ | 7269 | /* FLoop LOS gate: PPM filter enabled */ |
7425 | ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10); | 7270 | ibsd_wr_allchans(ppd, 38, 0 << 10, 1 << 10); |
7426 | 7271 | ||
7427 | /* rx offset center enabled */ | 7272 | /* rx offset center enabled */ |
@@ -7486,68 +7331,39 @@ static void write_tx_serdes_param(struct qib_pportdata *ppd, | |||
7486 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txc0_ena) | | 7331 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txc0_ena) | |
7487 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcp1_ena) | | 7332 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcp1_ena) | |
7488 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcn1_ena)); | 7333 | SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, txcn1_ena)); |
7489 | deemph |= 1ULL << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7334 | |
7490 | tx_override_deemphasis_select); | 7335 | deemph |= SYM_MASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
7491 | deemph |= txdds->amp << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7336 | tx_override_deemphasis_select); |
7492 | txampcntl_d2a); | 7337 | deemph |= (txdds->amp & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
7493 | deemph |= txdds->main << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7338 | txampcntl_d2a)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
7494 | txc0_ena); | 7339 | txampcntl_d2a); |
7495 | deemph |= txdds->post << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7340 | deemph |= (txdds->main & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
7496 | txcp1_ena); | 7341 | txc0_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, |
7497 | deemph |= txdds->pre << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | 7342 | txc0_ena); |
7343 | deemph |= (txdds->post & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7344 | txcp1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7345 | txcp1_ena); | ||
7346 | deemph |= (txdds->pre & SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7347 | txcn1_ena)) << SYM_LSB(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7498 | txcn1_ena); | 7348 | txcn1_ena); |
7499 | qib_write_kreg_port(ppd, krp_tx_deemph_override, deemph); | 7349 | qib_write_kreg_port(ppd, krp_tx_deemph_override, deemph); |
7500 | } | 7350 | } |
7501 | 7351 | ||
7502 | /* | 7352 | /* |
7503 | * set per-bay, per channel parameters. For now, we ignore | 7353 | * Set the parameters for mez cards on link bounce, so they are |
7504 | * do_tx, and always set tx parameters, and set them with the same value | 7354 | * always exactly what was requested. Similar logic to init_txdds |
7505 | * for all channels, using the channel 0 value. We may switch to | 7355 | * but does just the serdes. |
7506 | * per-channel settings in the future, and that method only needs | ||
7507 | * to be done once. | ||
7508 | * Because this also writes the IBC txdds table with a single set | ||
7509 | * of values, it should be called only for cases where we want to completely | ||
7510 | * force a specific setting, typically only for mez cards. | ||
7511 | */ | 7356 | */ |
7512 | static void adj_tx_serdes(struct qib_pportdata *ppd) | 7357 | static void adj_tx_serdes(struct qib_pportdata *ppd) |
7513 | { | 7358 | { |
7514 | struct txdds_ent txdds; | 7359 | const struct txdds_ent *sdr_dds, *ddr_dds, *qdr_dds; |
7515 | int i; | 7360 | struct txdds_ent *dds; |
7516 | u8 *amp, *pre, *mainv, *post; | ||
7517 | |||
7518 | /* | ||
7519 | * Because we use TX_DEEMPHASIS_OVERRIDE, we need to | ||
7520 | * always do tx side, just like H1, since it is cleared | ||
7521 | * by link down | ||
7522 | */ | ||
7523 | amp = ppd->cpspec->amp; | ||
7524 | pre = ppd->cpspec->pre; | ||
7525 | mainv = ppd->cpspec->mainv; | ||
7526 | post = ppd->cpspec->post; | ||
7527 | |||
7528 | amp[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7529 | txampcntl_d2a); | ||
7530 | mainv[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7531 | txc0_ena); | ||
7532 | post[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7533 | txcp1_ena); | ||
7534 | pre[0] &= SYM_RMASK(IBSD_TX_DEEMPHASIS_OVERRIDE_0, | ||
7535 | txcn1_ena); | ||
7536 | |||
7537 | /* | ||
7538 | * Use the channel zero values, only, for now, for | ||
7539 | * all channels | ||
7540 | */ | ||
7541 | txdds.amp = amp[0]; | ||
7542 | txdds.pre = pre[0]; | ||
7543 | txdds.main = mainv[0]; | ||
7544 | txdds.post = post[0]; | ||
7545 | |||
7546 | /* write the QDR table for IBC use, as backup for link down */ | ||
7547 | for (i = 0; i < ARRAY_SIZE(txdds_qdr); ++i) | ||
7548 | set_txdds(ppd, i + 32, &txdds); | ||
7549 | 7361 | ||
7550 | write_tx_serdes_param(ppd, &txdds); | 7362 | find_best_ent(ppd, &sdr_dds, &ddr_dds, &qdr_dds, 1); |
7363 | dds = (struct txdds_ent *)(ppd->link_speed_active == QIB_IB_QDR ? | ||
7364 | qdr_dds : (ppd->link_speed_active == QIB_IB_DDR ? | ||
7365 | ddr_dds : sdr_dds)); | ||
7366 | write_tx_serdes_param(ppd, dds); | ||
7551 | } | 7367 | } |
7552 | 7368 | ||
7553 | /* set QDR forced value for H1, if needed */ | 7369 | /* set QDR forced value for H1, if needed */ |
@@ -7567,235 +7383,6 @@ static void force_h1(struct qib_pportdata *ppd) | |||
7567 | } | 7383 | } |
7568 | } | 7384 | } |
7569 | 7385 | ||
7570 | /* | ||
7571 | * Parse the parameters for the QMH7342, to get rx and tx serdes | ||
7572 | * settings for that Bay, for both possible mez connectors (PCIe bus) | ||
7573 | * and IB link (one link on mez1, two possible on mez2). | ||
7574 | * | ||
7575 | * Data is comma or white space separated. | ||
7576 | * | ||
7577 | * A set of data has 7 groups, rx and tx groups have SERDES_CHANS values, | ||
7578 | * one per IB lane (serdes channel). | ||
7579 | * The groups are Bay, bus# H1 rcv, and amp, pre, post, main Tx values (QDR). | ||
7580 | * The Bay # is used only for debugging currently. | ||
7581 | * H1 values are set whenever the link goes down, or is at cfg_test or | ||
7582 | * cfg_wait_enh. Tx values are programmed once, when this routine is called | ||
7583 | * (and with default values at chip initialization). Values are any base, in | ||
7584 | * strtoul style, and values are seperated by comma, or any white space | ||
7585 | * (space, tab, newline). | ||
7586 | * | ||
7587 | * An example set might look like this (white space vs | ||
7588 | * comma used for human ease of reading) | ||
7589 | * The ordering is a set of Bay# Bus# H1, amp, pre, post, and main for mez1 IB1, | ||
7590 | * repeat for mez2 IB1, then mez2 IB2. | ||
7591 | * | ||
7592 | * B B H1:0 amp:0 pre:0 post: 0 main:0 | ||
7593 | * a u H1: 1 amp: 1 pre: 1 post: 1 main: 1 | ||
7594 | * y s H1: 2 amp: 2 pre: 2 post: 2 main: 2 | ||
7595 | * H1: 4 amp: 3 pre: 3 post: 3 main: 3 | ||
7596 | * 1 3 8,6,5,6 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3 | ||
7597 | * 1 6 7,6,6,7 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3 | ||
7598 | * 1 6 9,7,7,8 0,0,0,0 1,1,1,1 10,10,10,10 3,3,3,3 | ||
7599 | */ | ||
7600 | #define N_QMH_FIELDS 22 | ||
7601 | static int setup_qmh_params(const char *str, struct kernel_param *kp) | ||
7602 | { | ||
7603 | char *abuf, *v, *nv, *nvp; | ||
7604 | struct qib_devdata *dd; | ||
7605 | struct qib_pportdata *ppd; | ||
7606 | u32 mez, vlen, nf, port, bay; | ||
7607 | int ret = 0, found = 0; | ||
7608 | |||
7609 | vlen = strlen(str) + 1; | ||
7610 | abuf = kmalloc(vlen, GFP_KERNEL); | ||
7611 | if (!abuf) { | ||
7612 | printk(KERN_INFO QIB_DRV_NAME | ||
7613 | " Unable to allocate QMH param buffer; ignoring\n"); | ||
7614 | return 0; | ||
7615 | } | ||
7616 | memcpy(abuf, str, vlen); | ||
7617 | v = abuf; | ||
7618 | |||
7619 | /* these 3 are because gcc can't know they are set before used */ | ||
7620 | port = 1; | ||
7621 | mez = 1; /* used only for debugging */ | ||
7622 | bay = 0; /* used only for debugging */ | ||
7623 | ppd = NULL; | ||
7624 | for (nf = 0; (nv = strsep(&v, ", \t\n\r")) && | ||
7625 | nf < (N_QMH_FIELDS * 3);) { | ||
7626 | u32 val; | ||
7627 | |||
7628 | if (!*nv) | ||
7629 | /* allow for multiple separators */ | ||
7630 | continue; | ||
7631 | |||
7632 | val = simple_strtoul(nv, &nvp, 0); | ||
7633 | if (nv == nvp) { | ||
7634 | printk(KERN_INFO QIB_DRV_NAME | ||
7635 | " Bay%u, mez%u IB%u non-numeric value (%s) " | ||
7636 | "field #%u, ignoring rest\n", bay, mez, | ||
7637 | port, nv, nf % (N_QMH_FIELDS * 3)); | ||
7638 | ret = -EINVAL; | ||
7639 | goto bail; | ||
7640 | } | ||
7641 | if (!(nf % N_QMH_FIELDS)) { | ||
7642 | ppd = NULL; | ||
7643 | bay = val; | ||
7644 | if (!bay || bay > 16) { | ||
7645 | printk(KERN_INFO QIB_DRV_NAME | ||
7646 | " Invalid bay # %u, field %u, " | ||
7647 | "ignoring rest\n", bay, nf); | ||
7648 | ret = -EINVAL; | ||
7649 | goto bail; | ||
7650 | } | ||
7651 | } else if ((nf % N_QMH_FIELDS) == 1) { | ||
7652 | u32 bus = val; | ||
7653 | if (nf == 1) { | ||
7654 | mez = 1; | ||
7655 | port = 1; | ||
7656 | } else if (nf == (N_QMH_FIELDS + 1)) { | ||
7657 | mez = 2; | ||
7658 | port = 1; | ||
7659 | } else { | ||
7660 | mez = 2; | ||
7661 | port = 2; | ||
7662 | } | ||
7663 | list_for_each_entry(dd, &qib_dev_list, list) { | ||
7664 | if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322 | ||
7665 | || !IS_QMH(dd)) | ||
7666 | continue; /* only for QMH cards */ | ||
7667 | if (dd->pcidev->bus->number == bus) { | ||
7668 | found++; | ||
7669 | ppd = &dd->pport[port - 1]; | ||
7670 | } | ||
7671 | } | ||
7672 | } else if (ppd) { | ||
7673 | u32 parm = (nf % N_QMH_FIELDS) - 2; | ||
7674 | if (parm < SERDES_CHANS && !(parm % SERDES_CHANS)) | ||
7675 | ppd->cpspec->h1_val = val; | ||
7676 | else if (parm < (2 * SERDES_CHANS)) | ||
7677 | ppd->cpspec->amp[parm % SERDES_CHANS] = val; | ||
7678 | else if (parm < (3 * SERDES_CHANS)) | ||
7679 | ppd->cpspec->pre[parm % SERDES_CHANS] = val; | ||
7680 | else if (parm < (4 * SERDES_CHANS)) | ||
7681 | ppd->cpspec->post[parm % SERDES_CHANS] = val; | ||
7682 | else { | ||
7683 | ppd->cpspec->mainv[parm % SERDES_CHANS] = val; | ||
7684 | /* At the end of a port, set params */ | ||
7685 | if (parm == ((5 * SERDES_CHANS) - 1)) | ||
7686 | adj_tx_serdes(ppd); | ||
7687 | } | ||
7688 | } | ||
7689 | nf++; | ||
7690 | } | ||
7691 | if (!found) { | ||
7692 | printk(KERN_ERR QIB_DRV_NAME | ||
7693 | ": No match found for qmh_serdes_setup parameter\n"); | ||
7694 | ret = -EINVAL; | ||
7695 | } | ||
7696 | bail: | ||
7697 | kfree(abuf); | ||
7698 | return ret; | ||
7699 | } | ||
7700 | |||
7701 | /* | ||
7702 | * Similarly for QME7342, but the format is simpler, values are the | ||
7703 | * same for all mez card positions in a blade (2 or 4 per blade), but | ||
7704 | * are different for some blades vs others, and we don't need to | ||
7705 | * specify different parameters for different serdes channels or different | ||
7706 | * IB ports. | ||
7707 | * Format is: h1 amp,pre,post,main | ||
7708 | * Alternate format (so ports can be different): Pport# h1 amp,pre,post,main | ||
7709 | */ | ||
7710 | #define N_QME_FIELDS 5 | ||
7711 | static int setup_qme_params(const char *str, struct kernel_param *kp) | ||
7712 | { | ||
7713 | char *abuf, *v, *nv, *nvp; | ||
7714 | struct qib_devdata *dd; | ||
7715 | u32 vlen, nf, port = 0; | ||
7716 | u8 h1, tx[4]; /* amp, pre, post, main */ | ||
7717 | int ret = -EINVAL; | ||
7718 | char *seplist; | ||
7719 | |||
7720 | vlen = strlen(str) + 1; | ||
7721 | abuf = kmalloc(vlen, GFP_KERNEL); | ||
7722 | if (!abuf) { | ||
7723 | printk(KERN_INFO QIB_DRV_NAME | ||
7724 | " Unable to allocate QME param buffer; ignoring\n"); | ||
7725 | return 0; | ||
7726 | } | ||
7727 | strncpy(abuf, str, vlen); | ||
7728 | |||
7729 | v = abuf; | ||
7730 | seplist = " \t"; | ||
7731 | h1 = H1_FORCE_QME; /* gcc can't figure out always set before used */ | ||
7732 | |||
7733 | for (nf = 0; (nv = strsep(&v, seplist)); ) { | ||
7734 | u32 val; | ||
7735 | |||
7736 | if (!*nv) | ||
7737 | /* allow for multiple separators */ | ||
7738 | continue; | ||
7739 | |||
7740 | if (!nf && *nv == 'P') { | ||
7741 | /* alternate format with port */ | ||
7742 | val = simple_strtoul(++nv, &nvp, 0); | ||
7743 | if (nv == nvp || port >= NUM_IB_PORTS) { | ||
7744 | printk(KERN_INFO QIB_DRV_NAME | ||
7745 | " %s: non-numeric port value (%s) " | ||
7746 | "ignoring rest\n", __func__, nv); | ||
7747 | goto done; | ||
7748 | } | ||
7749 | port = val; | ||
7750 | continue; /* without incrementing nf */ | ||
7751 | } | ||
7752 | val = simple_strtoul(nv, &nvp, 0); | ||
7753 | if (nv == nvp) { | ||
7754 | printk(KERN_INFO QIB_DRV_NAME | ||
7755 | " %s: non-numeric value (%s) " | ||
7756 | "field #%u, ignoring rest\n", __func__, | ||
7757 | nv, nf); | ||
7758 | goto done; | ||
7759 | } | ||
7760 | if (!nf) { | ||
7761 | h1 = val; | ||
7762 | seplist = ","; | ||
7763 | } else | ||
7764 | tx[nf - 1] = val; | ||
7765 | if (++nf == N_QME_FIELDS) { | ||
7766 | list_for_each_entry(dd, &qib_dev_list, list) { | ||
7767 | int pidx, i; | ||
7768 | if (dd->deviceid != PCI_DEVICE_ID_QLOGIC_IB_7322 | ||
7769 | || !IS_QME(dd)) | ||
7770 | continue; /* only for QME cards */ | ||
7771 | for (pidx = 0; pidx < dd->num_pports; ++pidx) { | ||
7772 | struct qib_pportdata *ppd; | ||
7773 | ppd = &dd->pport[pidx]; | ||
7774 | if ((port && ppd->port != port) || | ||
7775 | !ppd->link_speed_supported) | ||
7776 | continue; | ||
7777 | ppd->cpspec->h1_val = h1; | ||
7778 | for (i = 0; i < SERDES_CHANS; i++) { | ||
7779 | ppd->cpspec->amp[i] = tx[0]; | ||
7780 | ppd->cpspec->pre[i] = tx[1]; | ||
7781 | ppd->cpspec->post[i] = tx[2]; | ||
7782 | ppd->cpspec->mainv[i] = tx[3]; | ||
7783 | } | ||
7784 | adj_tx_serdes(ppd); | ||
7785 | } | ||
7786 | } | ||
7787 | ret = 0; | ||
7788 | goto done; | ||
7789 | } | ||
7790 | } | ||
7791 | printk(KERN_INFO QIB_DRV_NAME | ||
7792 | " %s: Only %u of %u fields provided, skipping\n", | ||
7793 | __func__, nf, N_QME_FIELDS); | ||
7794 | done: | ||
7795 | kfree(abuf); | ||
7796 | return ret; | ||
7797 | } | ||
7798 | |||
7799 | #define SJA_EN SYM_MASK(SPC_JTAG_ACCESS_REG, SPC_JTAG_ACCESS_EN) | 7386 | #define SJA_EN SYM_MASK(SPC_JTAG_ACCESS_REG, SPC_JTAG_ACCESS_EN) |
7800 | #define BISTEN_LSB SYM_LSB(SPC_JTAG_ACCESS_REG, bist_en) | 7387 | #define BISTEN_LSB SYM_LSB(SPC_JTAG_ACCESS_REG, bist_en) |
7801 | 7388 | ||
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index c0139c07e97e..9b40f345ac3f 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c | |||
@@ -1237,7 +1237,13 @@ static int __devinit qib_init_one(struct pci_dev *pdev, | |||
1237 | */ | 1237 | */ |
1238 | switch (ent->device) { | 1238 | switch (ent->device) { |
1239 | case PCI_DEVICE_ID_QLOGIC_IB_6120: | 1239 | case PCI_DEVICE_ID_QLOGIC_IB_6120: |
1240 | #ifdef CONFIG_PCI_MSI | ||
1240 | dd = qib_init_iba6120_funcs(pdev, ent); | 1241 | dd = qib_init_iba6120_funcs(pdev, ent); |
1242 | #else | ||
1243 | qib_early_err(&pdev->dev, "QLogic PCIE device 0x%x cannot " | ||
1244 | "work if CONFIG_PCI_MSI is not enabled\n", | ||
1245 | ent->device); | ||
1246 | #endif | ||
1241 | break; | 1247 | break; |
1242 | 1248 | ||
1243 | case PCI_DEVICE_ID_QLOGIC_IB_7220: | 1249 | case PCI_DEVICE_ID_QLOGIC_IB_7220: |
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/Kconfig b/drivers/input/touchscreen/Kconfig index b9f58ca82fd1..6703c6b9800a 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
@@ -590,4 +590,17 @@ config TOUCHSCREEN_PCAP | |||
590 | 590 | ||
591 | To compile this driver as a module, choose M here: the | 591 | To compile this driver as a module, choose M here: the |
592 | module will be called pcap_ts. | 592 | module will be called pcap_ts. |
593 | |||
594 | config TOUCHSCREEN_TPS6507X | ||
595 | tristate "TPS6507x based touchscreens" | ||
596 | depends on I2C | ||
597 | help | ||
598 | Say Y here if you have a TPS6507x based touchscreen | ||
599 | controller. | ||
600 | |||
601 | If unsure, say N. | ||
602 | |||
603 | To compile this driver as a module, choose M here: the | ||
604 | module will be called tps6507x_ts. | ||
605 | |||
593 | endif | 606 | endif |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 8ad36eef90a2..497964a7a214 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
@@ -46,3 +46,4 @@ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ATMEL) += atmel-wm97xx.o | |||
46 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o | 46 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o |
47 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o | 47 | obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o |
48 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o | 48 | obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o |
49 | obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o | ||
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/tps6507x-ts.c b/drivers/input/touchscreen/tps6507x-ts.c new file mode 100644 index 000000000000..5de80a1a730b --- /dev/null +++ b/drivers/input/touchscreen/tps6507x-ts.c | |||
@@ -0,0 +1,400 @@ | |||
1 | /* | ||
2 | * drivers/input/touchscreen/tps6507x_ts.c | ||
3 | * | ||
4 | * Touchscreen driver for the tps6507x chip. | ||
5 | * | ||
6 | * Copyright (c) 2009 RidgeRun (todd.fischer@ridgerun.com) | ||
7 | * | ||
8 | * Credits: | ||
9 | * | ||
10 | * Using code from tsc2007, MtekVision Co., Ltd. | ||
11 | * | ||
12 | * For licencing details see kernel-base/COPYING | ||
13 | * | ||
14 | * TPS65070, TPS65073, TPS650731, and TPS650732 support | ||
15 | * 10 bit touch screen interface. | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/workqueue.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/input.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/mfd/tps6507x.h> | ||
24 | #include <linux/input/tps6507x-ts.h> | ||
25 | #include <linux/delay.h> | ||
26 | |||
27 | #define TSC_DEFAULT_POLL_PERIOD 30 /* ms */ | ||
28 | #define TPS_DEFAULT_MIN_PRESSURE 0x30 | ||
29 | #define MAX_10BIT ((1 << 10) - 1) | ||
30 | |||
31 | #define TPS6507X_ADCONFIG_CONVERT_TS (TPS6507X_ADCONFIG_AD_ENABLE | \ | ||
32 | TPS6507X_ADCONFIG_START_CONVERSION | \ | ||
33 | TPS6507X_ADCONFIG_INPUT_REAL_TSC) | ||
34 | #define TPS6507X_ADCONFIG_POWER_DOWN_TS (TPS6507X_ADCONFIG_INPUT_REAL_TSC) | ||
35 | |||
36 | struct ts_event { | ||
37 | u16 x; | ||
38 | u16 y; | ||
39 | u16 pressure; | ||
40 | }; | ||
41 | |||
42 | struct tps6507x_ts { | ||
43 | struct input_dev *input_dev; | ||
44 | struct device *dev; | ||
45 | char phys[32]; | ||
46 | struct workqueue_struct *wq; | ||
47 | struct delayed_work work; | ||
48 | unsigned polling; /* polling is active */ | ||
49 | struct ts_event tc; | ||
50 | struct tps6507x_dev *mfd; | ||
51 | u16 model; | ||
52 | unsigned pendown; | ||
53 | int irq; | ||
54 | void (*clear_penirq)(void); | ||
55 | unsigned long poll_period; /* ms */ | ||
56 | u16 min_pressure; | ||
57 | int vref; /* non-zero to leave vref on */ | ||
58 | }; | ||
59 | |||
60 | static int tps6507x_read_u8(struct tps6507x_ts *tsc, u8 reg, u8 *data) | ||
61 | { | ||
62 | int err; | ||
63 | |||
64 | err = tsc->mfd->read_dev(tsc->mfd, reg, 1, data); | ||
65 | |||
66 | if (err) | ||
67 | return err; | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int tps6507x_write_u8(struct tps6507x_ts *tsc, u8 reg, u8 data) | ||
73 | { | ||
74 | return tsc->mfd->write_dev(tsc->mfd, reg, 1, &data); | ||
75 | } | ||
76 | |||
77 | static s32 tps6507x_adc_conversion(struct tps6507x_ts *tsc, | ||
78 | u8 tsc_mode, u16 *value) | ||
79 | { | ||
80 | s32 ret; | ||
81 | u8 adc_status; | ||
82 | u8 result; | ||
83 | |||
84 | /* Route input signal to A/D converter */ | ||
85 | |||
86 | ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, tsc_mode); | ||
87 | if (ret) { | ||
88 | dev_err(tsc->dev, "TSC mode read failed\n"); | ||
89 | goto err; | ||
90 | } | ||
91 | |||
92 | /* Start A/D conversion */ | ||
93 | |||
94 | ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG, | ||
95 | TPS6507X_ADCONFIG_CONVERT_TS); | ||
96 | if (ret) { | ||
97 | dev_err(tsc->dev, "ADC config write failed\n"); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | do { | ||
102 | ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADCONFIG, | ||
103 | &adc_status); | ||
104 | if (ret) { | ||
105 | dev_err(tsc->dev, "ADC config read failed\n"); | ||
106 | goto err; | ||
107 | } | ||
108 | } while (adc_status & TPS6507X_ADCONFIG_START_CONVERSION); | ||
109 | |||
110 | ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_2, &result); | ||
111 | if (ret) { | ||
112 | dev_err(tsc->dev, "ADC result 2 read failed\n"); | ||
113 | goto err; | ||
114 | } | ||
115 | |||
116 | *value = (result & TPS6507X_REG_ADRESULT_2_MASK) << 8; | ||
117 | |||
118 | ret = tps6507x_read_u8(tsc, TPS6507X_REG_ADRESULT_1, &result); | ||
119 | if (ret) { | ||
120 | dev_err(tsc->dev, "ADC result 1 read failed\n"); | ||
121 | goto err; | ||
122 | } | ||
123 | |||
124 | *value |= result; | ||
125 | |||
126 | dev_dbg(tsc->dev, "TSC channel %d = 0x%X\n", tsc_mode, *value); | ||
127 | |||
128 | err: | ||
129 | return ret; | ||
130 | } | ||
131 | |||
132 | /* Need to call tps6507x_adc_standby() after using A/D converter for the | ||
133 | * touch screen interrupt to work properly. | ||
134 | */ | ||
135 | |||
136 | static s32 tps6507x_adc_standby(struct tps6507x_ts *tsc) | ||
137 | { | ||
138 | s32 ret; | ||
139 | s32 loops = 0; | ||
140 | u8 val; | ||
141 | |||
142 | ret = tps6507x_write_u8(tsc, TPS6507X_REG_ADCONFIG, | ||
143 | TPS6507X_ADCONFIG_INPUT_TSC); | ||
144 | if (ret) | ||
145 | return ret; | ||
146 | |||
147 | ret = tps6507x_write_u8(tsc, TPS6507X_REG_TSCMODE, | ||
148 | TPS6507X_TSCMODE_STANDBY); | ||
149 | if (ret) | ||
150 | return ret; | ||
151 | |||
152 | ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val); | ||
153 | if (ret) | ||
154 | return ret; | ||
155 | |||
156 | while (val & TPS6507X_REG_TSC_INT) { | ||
157 | mdelay(10); | ||
158 | ret = tps6507x_read_u8(tsc, TPS6507X_REG_INT, &val); | ||
159 | if (ret) | ||
160 | return ret; | ||
161 | loops++; | ||
162 | } | ||
163 | |||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | static void tps6507x_ts_handler(struct work_struct *work) | ||
168 | { | ||
169 | struct tps6507x_ts *tsc = container_of(work, | ||
170 | struct tps6507x_ts, work.work); | ||
171 | struct input_dev *input_dev = tsc->input_dev; | ||
172 | int pendown; | ||
173 | int schd; | ||
174 | int poll = 0; | ||
175 | s32 ret; | ||
176 | |||
177 | ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_PRESSURE, | ||
178 | &tsc->tc.pressure); | ||
179 | if (ret) | ||
180 | goto done; | ||
181 | |||
182 | pendown = tsc->tc.pressure > tsc->min_pressure; | ||
183 | |||
184 | if (unlikely(!pendown && tsc->pendown)) { | ||
185 | dev_dbg(tsc->dev, "UP\n"); | ||
186 | input_report_key(input_dev, BTN_TOUCH, 0); | ||
187 | input_report_abs(input_dev, ABS_PRESSURE, 0); | ||
188 | input_sync(input_dev); | ||
189 | tsc->pendown = 0; | ||
190 | } | ||
191 | |||
192 | if (pendown) { | ||
193 | |||
194 | if (!tsc->pendown) { | ||
195 | dev_dbg(tsc->dev, "DOWN\n"); | ||
196 | input_report_key(input_dev, BTN_TOUCH, 1); | ||
197 | } else | ||
198 | dev_dbg(tsc->dev, "still down\n"); | ||
199 | |||
200 | ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_X_POSITION, | ||
201 | &tsc->tc.x); | ||
202 | if (ret) | ||
203 | goto done; | ||
204 | |||
205 | ret = tps6507x_adc_conversion(tsc, TPS6507X_TSCMODE_Y_POSITION, | ||
206 | &tsc->tc.y); | ||
207 | if (ret) | ||
208 | goto done; | ||
209 | |||
210 | input_report_abs(input_dev, ABS_X, tsc->tc.x); | ||
211 | input_report_abs(input_dev, ABS_Y, tsc->tc.y); | ||
212 | input_report_abs(input_dev, ABS_PRESSURE, tsc->tc.pressure); | ||
213 | input_sync(input_dev); | ||
214 | tsc->pendown = 1; | ||
215 | poll = 1; | ||
216 | } | ||
217 | |||
218 | done: | ||
219 | /* always poll if not using interrupts */ | ||
220 | poll = 1; | ||
221 | |||
222 | if (poll) { | ||
223 | schd = queue_delayed_work(tsc->wq, &tsc->work, | ||
224 | tsc->poll_period * HZ / 1000); | ||
225 | if (schd) | ||
226 | tsc->polling = 1; | ||
227 | else { | ||
228 | tsc->polling = 0; | ||
229 | dev_err(tsc->dev, "re-schedule failed"); | ||
230 | } | ||
231 | } else | ||
232 | tsc->polling = 0; | ||
233 | |||
234 | ret = tps6507x_adc_standby(tsc); | ||
235 | } | ||
236 | |||
237 | static int tps6507x_ts_probe(struct platform_device *pdev) | ||
238 | { | ||
239 | int error; | ||
240 | struct tps6507x_ts *tsc; | ||
241 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); | ||
242 | struct touchscreen_init_data *init_data; | ||
243 | struct input_dev *input_dev; | ||
244 | struct tps6507x_board *tps_board; | ||
245 | int schd; | ||
246 | |||
247 | /** | ||
248 | * tps_board points to pmic related constants | ||
249 | * coming from the board-evm file. | ||
250 | */ | ||
251 | |||
252 | tps_board = (struct tps6507x_board *)tps6507x_dev->dev->platform_data; | ||
253 | |||
254 | if (!tps_board) { | ||
255 | dev_err(tps6507x_dev->dev, | ||
256 | "Could not find tps6507x platform data\n"); | ||
257 | return -EIO; | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * init_data points to array of regulator_init structures | ||
262 | * coming from the board-evm file. | ||
263 | */ | ||
264 | |||
265 | init_data = tps_board->tps6507x_ts_init_data; | ||
266 | |||
267 | tsc = kzalloc(sizeof(struct tps6507x_ts), GFP_KERNEL); | ||
268 | if (!tsc) { | ||
269 | dev_err(tps6507x_dev->dev, "failed to allocate driver data\n"); | ||
270 | error = -ENOMEM; | ||
271 | goto err0; | ||
272 | } | ||
273 | |||
274 | tps6507x_dev->ts = tsc; | ||
275 | tsc->mfd = tps6507x_dev; | ||
276 | tsc->dev = tps6507x_dev->dev; | ||
277 | input_dev = input_allocate_device(); | ||
278 | if (!input_dev) { | ||
279 | dev_err(tsc->dev, "Failed to allocate input device.\n"); | ||
280 | error = -ENOMEM; | ||
281 | goto err1; | ||
282 | } | ||
283 | |||
284 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
285 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
286 | |||
287 | input_set_abs_params(input_dev, ABS_X, 0, MAX_10BIT, 0, 0); | ||
288 | input_set_abs_params(input_dev, ABS_Y, 0, MAX_10BIT, 0, 0); | ||
289 | input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_10BIT, 0, 0); | ||
290 | |||
291 | input_dev->name = "TPS6507x Touchscreen"; | ||
292 | input_dev->id.bustype = BUS_I2C; | ||
293 | input_dev->dev.parent = tsc->dev; | ||
294 | |||
295 | snprintf(tsc->phys, sizeof(tsc->phys), | ||
296 | "%s/input0", dev_name(tsc->dev)); | ||
297 | input_dev->phys = tsc->phys; | ||
298 | |||
299 | dev_dbg(tsc->dev, "device: %s\n", input_dev->phys); | ||
300 | |||
301 | input_set_drvdata(input_dev, tsc); | ||
302 | |||
303 | tsc->input_dev = input_dev; | ||
304 | |||
305 | INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler); | ||
306 | tsc->wq = create_workqueue("TPS6507x Touchscreen"); | ||
307 | |||
308 | if (init_data) { | ||
309 | tsc->poll_period = init_data->poll_period; | ||
310 | tsc->vref = init_data->vref; | ||
311 | tsc->min_pressure = init_data->min_pressure; | ||
312 | input_dev->id.vendor = init_data->vendor; | ||
313 | input_dev->id.product = init_data->product; | ||
314 | input_dev->id.version = init_data->version; | ||
315 | } else { | ||
316 | tsc->poll_period = TSC_DEFAULT_POLL_PERIOD; | ||
317 | tsc->min_pressure = TPS_DEFAULT_MIN_PRESSURE; | ||
318 | } | ||
319 | |||
320 | error = tps6507x_adc_standby(tsc); | ||
321 | if (error) | ||
322 | goto err2; | ||
323 | |||
324 | error = input_register_device(input_dev); | ||
325 | if (error) | ||
326 | goto err2; | ||
327 | |||
328 | schd = queue_delayed_work(tsc->wq, &tsc->work, | ||
329 | tsc->poll_period * HZ / 1000); | ||
330 | |||
331 | if (schd) | ||
332 | tsc->polling = 1; | ||
333 | else { | ||
334 | tsc->polling = 0; | ||
335 | dev_err(tsc->dev, "schedule failed"); | ||
336 | goto err2; | ||
337 | } | ||
338 | |||
339 | return 0; | ||
340 | |||
341 | err2: | ||
342 | cancel_delayed_work(&tsc->work); | ||
343 | flush_workqueue(tsc->wq); | ||
344 | destroy_workqueue(tsc->wq); | ||
345 | tsc->wq = 0; | ||
346 | input_free_device(input_dev); | ||
347 | err1: | ||
348 | kfree(tsc); | ||
349 | tps6507x_dev->ts = NULL; | ||
350 | err0: | ||
351 | return error; | ||
352 | } | ||
353 | |||
354 | static int __devexit tps6507x_ts_remove(struct platform_device *pdev) | ||
355 | { | ||
356 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); | ||
357 | struct tps6507x_ts *tsc = tps6507x_dev->ts; | ||
358 | struct input_dev *input_dev = tsc->input_dev; | ||
359 | |||
360 | if (!tsc) | ||
361 | return 0; | ||
362 | |||
363 | cancel_delayed_work(&tsc->work); | ||
364 | flush_workqueue(tsc->wq); | ||
365 | destroy_workqueue(tsc->wq); | ||
366 | tsc->wq = 0; | ||
367 | |||
368 | input_free_device(input_dev); | ||
369 | |||
370 | tps6507x_dev->ts = NULL; | ||
371 | kfree(tsc); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | static struct platform_driver tps6507x_ts_driver = { | ||
377 | .driver = { | ||
378 | .name = "tps6507x-ts", | ||
379 | .owner = THIS_MODULE, | ||
380 | }, | ||
381 | .probe = tps6507x_ts_probe, | ||
382 | .remove = __devexit_p(tps6507x_ts_remove), | ||
383 | }; | ||
384 | |||
385 | static int __init tps6507x_ts_init(void) | ||
386 | { | ||
387 | return platform_driver_register(&tps6507x_ts_driver); | ||
388 | } | ||
389 | module_init(tps6507x_ts_init); | ||
390 | |||
391 | static void __exit tps6507x_ts_exit(void) | ||
392 | { | ||
393 | platform_driver_unregister(&tps6507x_ts_driver); | ||
394 | } | ||
395 | module_exit(tps6507x_ts_exit); | ||
396 | |||
397 | MODULE_AUTHOR("Todd Fischer <todd.fischer@ridgerun.com>"); | ||
398 | MODULE_DESCRIPTION("TPS6507x - TouchScreen driver"); | ||
399 | MODULE_LICENSE("GPL v2"); | ||
400 | MODULE_ALIAS("platform:tps6507x-tsc"); | ||
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/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..81bf25e67ce1 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -21,7 +21,7 @@ comment "LED drivers" | |||
21 | 21 | ||
22 | config LEDS_88PM860X | 22 | config LEDS_88PM860X |
23 | tristate "LED Support for Marvell 88PM860x PMIC" | 23 | tristate "LED Support for Marvell 88PM860x PMIC" |
24 | depends on LEDS_CLASS && MFD_88PM860X | 24 | depends on MFD_88PM860X |
25 | help | 25 | help |
26 | This option enables support for on-chip LED drivers found on Marvell | 26 | This option enables support for on-chip LED drivers found on Marvell |
27 | Semiconductor 88PM8606 PMIC. | 27 | Semiconductor 88PM8606 PMIC. |
@@ -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_TRIGGERS | ||
73 | depends on X86 && 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..cc22eeefa10b 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); |
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/88pm860x-core.c b/drivers/mfd/88pm860x-core.c index 405d2d5183cf..2c65a2c57294 100644 --- a/drivers/mfd/88pm860x-core.c +++ b/drivers/mfd/88pm860x-core.c | |||
@@ -566,7 +566,7 @@ out: | |||
566 | return ret; | 566 | return ret; |
567 | } | 567 | } |
568 | 568 | ||
569 | static void __devexit device_irq_exit(struct pm860x_chip *chip) | 569 | static void device_irq_exit(struct pm860x_chip *chip) |
570 | { | 570 | { |
571 | if (chip->core_irq) | 571 | if (chip->core_irq) |
572 | free_irq(chip->core_irq, chip); | 572 | free_irq(chip->core_irq, chip); |
@@ -703,7 +703,7 @@ out: | |||
703 | return; | 703 | return; |
704 | } | 704 | } |
705 | 705 | ||
706 | int pm860x_device_init(struct pm860x_chip *chip, | 706 | int __devinit pm860x_device_init(struct pm860x_chip *chip, |
707 | struct pm860x_platform_data *pdata) | 707 | struct pm860x_platform_data *pdata) |
708 | { | 708 | { |
709 | chip->core_irq = 0; | 709 | chip->core_irq = 0; |
@@ -731,7 +731,7 @@ int pm860x_device_init(struct pm860x_chip *chip, | |||
731 | return 0; | 731 | return 0; |
732 | } | 732 | } |
733 | 733 | ||
734 | void pm860x_device_exit(struct pm860x_chip *chip) | 734 | void __devexit pm860x_device_exit(struct pm860x_chip *chip) |
735 | { | 735 | { |
736 | device_irq_exit(chip); | 736 | device_irq_exit(chip); |
737 | mfd_remove_devices(chip->dev); | 737 | mfd_remove_devices(chip->dev); |
diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c index 4a6e7186334e..c933b64d1283 100644 --- a/drivers/mfd/88pm860x-i2c.c +++ b/drivers/mfd/88pm860x-i2c.c | |||
@@ -200,8 +200,8 @@ static int __devexit pm860x_remove(struct i2c_client *client) | |||
200 | 200 | ||
201 | pm860x_device_exit(chip); | 201 | pm860x_device_exit(chip); |
202 | i2c_unregister_device(chip->companion); | 202 | i2c_unregister_device(chip->companion); |
203 | i2c_set_clientdata(chip->companion, NULL); | ||
204 | i2c_set_clientdata(chip->client, NULL); | 203 | i2c_set_clientdata(chip->client, NULL); |
204 | i2c_set_clientdata(client, NULL); | ||
205 | kfree(chip); | 205 | kfree(chip); |
206 | return 0; | 206 | return 0; |
207 | } | 207 | } |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 3c6a9860dd9c..9da0e504bbe9 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -2,8 +2,14 @@ | |||
2 | # Multifunction miscellaneous devices | 2 | # Multifunction miscellaneous devices |
3 | # | 3 | # |
4 | 4 | ||
5 | menu "Multifunction device drivers" | 5 | menuconfig MFD_SUPPORT |
6 | bool "Multifunction device drivers" | ||
6 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | default y | ||
9 | help | ||
10 | Configure MFD device drivers. | ||
11 | |||
12 | if MFD_SUPPORT | ||
7 | 13 | ||
8 | config MFD_CORE | 14 | config MFD_CORE |
9 | tristate | 15 | tristate |
@@ -116,6 +122,18 @@ config TPS65010 | |||
116 | This driver can also be built as a module. If so, the module | 122 | This driver can also be built as a module. If so, the module |
117 | will be called tps65010. | 123 | will be called tps65010. |
118 | 124 | ||
125 | config TPS6507X | ||
126 | tristate "TPS6507x Power Management / Touch Screen chips" | ||
127 | select MFD_CORE | ||
128 | depends on I2C | ||
129 | help | ||
130 | If you say yes here you get support for the TPS6507x series of | ||
131 | Power Management / Touch Screen chips. These include voltage | ||
132 | regulators, lithium ion/polymer battery charging, touch screen | ||
133 | and other features that are often used in portable devices. | ||
134 | This driver can also be built as a module. If so, the module | ||
135 | will be called tps6507x. | ||
136 | |||
119 | config MENELAUS | 137 | config MENELAUS |
120 | bool "Texas Instruments TWL92330/Menelaus PM chip" | 138 | bool "Texas Instruments TWL92330/Menelaus PM chip" |
121 | depends on I2C=y && ARCH_OMAP2 | 139 | depends on I2C=y && ARCH_OMAP2 |
@@ -159,6 +177,17 @@ config TWL4030_CODEC | |||
159 | select MFD_CORE | 177 | select MFD_CORE |
160 | default n | 178 | default n |
161 | 179 | ||
180 | config MFD_TC35892 | ||
181 | bool "Support Toshiba TC35892" | ||
182 | depends on I2C=y && GENERIC_HARDIRQS | ||
183 | select MFD_CORE | ||
184 | help | ||
185 | Support for the Toshiba TC35892 I/O Expander. | ||
186 | |||
187 | This driver provides common support for accessing the device, | ||
188 | additional drivers must be enabled in order to use the | ||
189 | functionality of the device. | ||
190 | |||
162 | config MFD_TMIO | 191 | config MFD_TMIO |
163 | bool | 192 | bool |
164 | default n | 193 | default n |
@@ -351,9 +380,19 @@ config PCF50633_GPIO | |||
351 | Say yes here if you want to include support GPIO for pins on | 380 | Say yes here if you want to include support GPIO for pins on |
352 | the PCF50633 chip. | 381 | the PCF50633 chip. |
353 | 382 | ||
383 | config ABX500_CORE | ||
384 | bool "ST-Ericsson ABX500 Mixed Signal Circuit register functions" | ||
385 | default y if ARCH_U300 | ||
386 | help | ||
387 | Say yes here if you have the ABX500 Mixed Signal IC family | ||
388 | chips. This core driver expose register access functions. | ||
389 | Functionality specific drivers using these functions can | ||
390 | remain unchanged when IC changes. Binding of the functions to | ||
391 | actual register access is done by the IC core driver. | ||
392 | |||
354 | config AB3100_CORE | 393 | config AB3100_CORE |
355 | bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" | 394 | bool "ST-Ericsson AB3100 Mixed Signal Circuit core functions" |
356 | depends on I2C=y | 395 | depends on I2C=y && ABX500_CORE |
357 | default y if ARCH_U300 | 396 | default y if ARCH_U300 |
358 | help | 397 | help |
359 | Select this to enable the AB3100 Mixed Signal IC core | 398 | Select this to enable the AB3100 Mixed Signal IC core |
@@ -381,15 +420,30 @@ config EZX_PCAP | |||
381 | This enables the PCAP ASIC present on EZX Phones. This is | 420 | This enables the PCAP ASIC present on EZX Phones. This is |
382 | needed for MMC, TouchScreen, Sound, USB, etc.. | 421 | needed for MMC, TouchScreen, Sound, USB, etc.. |
383 | 422 | ||
384 | config AB4500_CORE | 423 | config AB8500_CORE |
385 | tristate "ST-Ericsson's AB4500 Mixed Signal Power management chip" | 424 | bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" |
386 | depends on SPI | 425 | depends on SPI=y && GENERIC_HARDIRQS |
426 | select MFD_CORE | ||
387 | help | 427 | help |
388 | Select this option to enable access to AB4500 power management | 428 | Select this option to enable access to AB8500 power management |
389 | chip. This connects to U8500 on the SSP/SPI bus and exports | 429 | chip. This connects to U8500 on the SSP/SPI bus and exports |
390 | read/write functions for the devices to get access to this chip. | 430 | read/write functions for the devices to get access to this chip. |
391 | This chip embeds various other multimedia funtionalities as well. | 431 | This chip embeds various other multimedia funtionalities as well. |
392 | 432 | ||
433 | config AB3550_CORE | ||
434 | bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions" | ||
435 | select MFD_CORE | ||
436 | depends on I2C=y && GENERIC_HARDIRQS && ABX500_CORE | ||
437 | help | ||
438 | Select this to enable the AB3550 Mixed Signal IC core | ||
439 | functionality. This connects to a AB3550 on the I2C bus | ||
440 | and expose a number of symbols needed for dependent devices | ||
441 | to read and write registers and subscribe to events from | ||
442 | this multi-functional IC. This is needed to use other features | ||
443 | of the AB3550 such as battery-backed RTC, charging control, | ||
444 | LEDs, vibrator, system power and temperature, power management | ||
445 | and ALSA sound. | ||
446 | |||
393 | config MFD_TIMBERDALE | 447 | config MFD_TIMBERDALE |
394 | tristate "Support for the Timberdale FPGA" | 448 | tristate "Support for the Timberdale FPGA" |
395 | select MFD_CORE | 449 | select MFD_CORE |
@@ -409,7 +463,26 @@ config LPC_SCH | |||
409 | LPC bridge function of the Intel SCH provides support for | 463 | LPC bridge function of the Intel SCH provides support for |
410 | System Management Bus and General Purpose I/O. | 464 | System Management Bus and General Purpose I/O. |
411 | 465 | ||
412 | endmenu | 466 | config MFD_RDC321X |
467 | tristate "Support for RDC-R321x southbridge" | ||
468 | select MFD_CORE | ||
469 | depends on PCI | ||
470 | help | ||
471 | Say yes here if you want to have support for the RDC R-321x SoC | ||
472 | southbridge which provides access to GPIOs and Watchdog using the | ||
473 | southbridge PCI device configuration space. | ||
474 | |||
475 | config MFD_JANZ_CMODIO | ||
476 | tristate "Support for Janz CMOD-IO PCI MODULbus Carrier Board" | ||
477 | select MFD_CORE | ||
478 | depends on PCI | ||
479 | help | ||
480 | This is the core driver for the Janz CMOD-IO PCI MODULbus | ||
481 | carrier board. This device is a PCI to MODULbus bridge which may | ||
482 | host many different types of MODULbus daughterboards, including | ||
483 | CAN and GPIO controllers. | ||
484 | |||
485 | endif # MFD_SUPPORT | ||
413 | 486 | ||
414 | menu "Multimedia Capabilities Port drivers" | 487 | menu "Multimedia Capabilities Port drivers" |
415 | depends on ARCH_SA1100 | 488 | depends on ARCH_SA1100 |
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 87935f967aa0..fb503e77dc60 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_HTC_I2CPLD) += htc-i2cpld.o | |||
15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o | 15 | obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o |
16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o | 16 | obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o |
17 | 17 | ||
18 | obj-$(CONFIG_MFD_TC35892) += tc35892.o | ||
18 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o | 19 | obj-$(CONFIG_MFD_T7L66XB) += t7l66xb.o tmio_core.o |
19 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o | 20 | obj-$(CONFIG_MFD_TC6387XB) += tc6387xb.o tmio_core.o |
20 | obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o | 21 | obj-$(CONFIG_MFD_TC6393XB) += tc6393xb.o tmio_core.o |
@@ -29,6 +30,7 @@ obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o | |||
29 | obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o | 30 | obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o |
30 | 31 | ||
31 | obj-$(CONFIG_TPS65010) += tps65010.o | 32 | obj-$(CONFIG_TPS65010) += tps65010.o |
33 | obj-$(CONFIG_TPS6507X) += tps6507x.o | ||
32 | obj-$(CONFIG_MENELAUS) += menelaus.o | 34 | obj-$(CONFIG_MENELAUS) += menelaus.o |
33 | 35 | ||
34 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o | 36 | obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o |
@@ -55,12 +57,17 @@ obj-$(CONFIG_PMIC_DA903X) += da903x.o | |||
55 | max8925-objs := max8925-core.o max8925-i2c.o | 57 | max8925-objs := max8925-core.o max8925-i2c.o |
56 | obj-$(CONFIG_MFD_MAX8925) += max8925.o | 58 | obj-$(CONFIG_MFD_MAX8925) += max8925.o |
57 | 59 | ||
58 | obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o | 60 | pcf50633-objs := pcf50633-core.o pcf50633-irq.o |
61 | obj-$(CONFIG_MFD_PCF50633) += pcf50633.o | ||
59 | obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o | 62 | obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o |
60 | obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o | 63 | obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o |
64 | obj-$(CONFIG_ABX500_CORE) += abx500-core.o | ||
61 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o | 65 | obj-$(CONFIG_AB3100_CORE) += ab3100-core.o |
62 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o | 66 | obj-$(CONFIG_AB3100_OTP) += ab3100-otp.o |
63 | obj-$(CONFIG_AB4500_CORE) += ab4500-core.o | 67 | obj-$(CONFIG_AB3550_CORE) += ab3550-core.o |
68 | obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-spi.o | ||
64 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o | 69 | obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o |
65 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o | 70 | obj-$(CONFIG_PMIC_ADP5520) += adp5520.o |
66 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o \ No newline at end of file | 71 | obj-$(CONFIG_LPC_SCH) += lpc_sch.o |
72 | obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o | ||
73 | obj-$(CONFIG_MFD_JANZ_CMODIO) += janz-cmodio.o | ||
diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index e4ca5909e424..53ebfee548fa 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/debugfs.h> | 19 | #include <linux/debugfs.h> |
20 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/mfd/ab3100.h> | 22 | #include <linux/mfd/abx500.h> |
23 | 23 | ||
24 | /* These are the only registers inside AB3100 used in this main file */ | 24 | /* These are the only registers inside AB3100 used in this main file */ |
25 | 25 | ||
@@ -59,24 +59,15 @@ | |||
59 | * The AB3100 is usually assigned address 0x48 (7-bit) | 59 | * The AB3100 is usually assigned address 0x48 (7-bit) |
60 | * The chip is defined in the platform i2c_board_data section. | 60 | * The chip is defined in the platform i2c_board_data section. |
61 | */ | 61 | */ |
62 | 62 | static int ab3100_get_chip_id(struct device *dev) | |
63 | u8 ab3100_get_chip_type(struct ab3100 *ab3100) | ||
64 | { | 63 | { |
65 | u8 chip = ABUNKNOWN; | 64 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); |
66 | 65 | ||
67 | switch (ab3100->chip_id & 0xf0) { | 66 | return (int)ab3100->chip_id; |
68 | case 0xa0: | ||
69 | chip = AB3000; | ||
70 | break; | ||
71 | case 0xc0: | ||
72 | chip = AB3100; | ||
73 | break; | ||
74 | } | ||
75 | return chip; | ||
76 | } | 67 | } |
77 | EXPORT_SYMBOL(ab3100_get_chip_type); | ||
78 | 68 | ||
79 | int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval) | 69 | static int ab3100_set_register_interruptible(struct ab3100 *ab3100, |
70 | u8 reg, u8 regval) | ||
80 | { | 71 | { |
81 | u8 regandval[2] = {reg, regval}; | 72 | u8 regandval[2] = {reg, regval}; |
82 | int err; | 73 | int err; |
@@ -108,8 +99,14 @@ int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval) | |||
108 | mutex_unlock(&ab3100->access_mutex); | 99 | mutex_unlock(&ab3100->access_mutex); |
109 | return err; | 100 | return err; |
110 | } | 101 | } |
111 | EXPORT_SYMBOL(ab3100_set_register_interruptible); | ||
112 | 102 | ||
103 | static int set_register_interruptible(struct device *dev, | ||
104 | u8 bank, u8 reg, u8 value) | ||
105 | { | ||
106 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
107 | |||
108 | return ab3100_set_register_interruptible(ab3100, reg, value); | ||
109 | } | ||
113 | 110 | ||
114 | /* | 111 | /* |
115 | * The test registers exist at an I2C bus address up one | 112 | * The test registers exist at an I2C bus address up one |
@@ -148,8 +145,8 @@ static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100, | |||
148 | return err; | 145 | return err; |
149 | } | 146 | } |
150 | 147 | ||
151 | 148 | static int ab3100_get_register_interruptible(struct ab3100 *ab3100, | |
152 | int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval) | 149 | u8 reg, u8 *regval) |
153 | { | 150 | { |
154 | int err; | 151 | int err; |
155 | 152 | ||
@@ -203,10 +200,16 @@ int ab3100_get_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 *regval) | |||
203 | mutex_unlock(&ab3100->access_mutex); | 200 | mutex_unlock(&ab3100->access_mutex); |
204 | return err; | 201 | return err; |
205 | } | 202 | } |
206 | EXPORT_SYMBOL(ab3100_get_register_interruptible); | ||
207 | 203 | ||
204 | static int get_register_interruptible(struct device *dev, u8 bank, u8 reg, | ||
205 | u8 *value) | ||
206 | { | ||
207 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
208 | |||
209 | return ab3100_get_register_interruptible(ab3100, reg, value); | ||
210 | } | ||
208 | 211 | ||
209 | int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, | 212 | static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, |
210 | u8 first_reg, u8 *regvals, u8 numregs) | 213 | u8 first_reg, u8 *regvals, u8 numregs) |
211 | { | 214 | { |
212 | int err; | 215 | int err; |
@@ -260,10 +263,17 @@ int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, | |||
260 | mutex_unlock(&ab3100->access_mutex); | 263 | mutex_unlock(&ab3100->access_mutex); |
261 | return err; | 264 | return err; |
262 | } | 265 | } |
263 | EXPORT_SYMBOL(ab3100_get_register_page_interruptible); | ||
264 | 266 | ||
267 | static int get_register_page_interruptible(struct device *dev, u8 bank, | ||
268 | u8 first_reg, u8 *regvals, u8 numregs) | ||
269 | { | ||
270 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
271 | |||
272 | return ab3100_get_register_page_interruptible(ab3100, | ||
273 | first_reg, regvals, numregs); | ||
274 | } | ||
265 | 275 | ||
266 | int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, | 276 | static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, |
267 | u8 reg, u8 andmask, u8 ormask) | 277 | u8 reg, u8 andmask, u8 ormask) |
268 | { | 278 | { |
269 | u8 regandval[2] = {reg, 0}; | 279 | u8 regandval[2] = {reg, 0}; |
@@ -331,8 +341,15 @@ int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, | |||
331 | mutex_unlock(&ab3100->access_mutex); | 341 | mutex_unlock(&ab3100->access_mutex); |
332 | return err; | 342 | return err; |
333 | } | 343 | } |
334 | EXPORT_SYMBOL(ab3100_mask_and_set_register_interruptible); | ||
335 | 344 | ||
345 | static int mask_and_set_register_interruptible(struct device *dev, u8 bank, | ||
346 | u8 reg, u8 bitmask, u8 bitvalues) | ||
347 | { | ||
348 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
349 | |||
350 | return ab3100_mask_and_set_register_interruptible(ab3100, | ||
351 | reg, bitmask, (bitmask & bitvalues)); | ||
352 | } | ||
336 | 353 | ||
337 | /* | 354 | /* |
338 | * Register a simple callback for handling any AB3100 events. | 355 | * Register a simple callback for handling any AB3100 events. |
@@ -357,15 +374,27 @@ int ab3100_event_unregister(struct ab3100 *ab3100, | |||
357 | EXPORT_SYMBOL(ab3100_event_unregister); | 374 | EXPORT_SYMBOL(ab3100_event_unregister); |
358 | 375 | ||
359 | 376 | ||
360 | int ab3100_event_registers_startup_state_get(struct ab3100 *ab3100, | 377 | static int ab3100_event_registers_startup_state_get(struct device *dev, |
361 | u32 *fatevent) | 378 | u8 *event) |
362 | { | 379 | { |
380 | struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); | ||
363 | if (!ab3100->startup_events_read) | 381 | if (!ab3100->startup_events_read) |
364 | return -EAGAIN; /* Try again later */ | 382 | return -EAGAIN; /* Try again later */ |
365 | *fatevent = ab3100->startup_events; | 383 | memcpy(event, ab3100->startup_events, 3); |
366 | return 0; | 384 | return 0; |
367 | } | 385 | } |
368 | EXPORT_SYMBOL(ab3100_event_registers_startup_state_get); | 386 | |
387 | static struct abx500_ops ab3100_ops = { | ||
388 | .get_chip_id = ab3100_get_chip_id, | ||
389 | .set_register = set_register_interruptible, | ||
390 | .get_register = get_register_interruptible, | ||
391 | .get_register_page = get_register_page_interruptible, | ||
392 | .set_register_page = NULL, | ||
393 | .mask_and_set_register = mask_and_set_register_interruptible, | ||
394 | .event_registers_startup_state_get = | ||
395 | ab3100_event_registers_startup_state_get, | ||
396 | .startup_irq_enabled = NULL, | ||
397 | }; | ||
369 | 398 | ||
370 | /* | 399 | /* |
371 | * This is a threaded interrupt handler so we can make some | 400 | * This is a threaded interrupt handler so we can make some |
@@ -390,7 +419,9 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data) | |||
390 | event_regs[2]; | 419 | event_regs[2]; |
391 | 420 | ||
392 | if (!ab3100->startup_events_read) { | 421 | if (!ab3100->startup_events_read) { |
393 | ab3100->startup_events = fatevent; | 422 | ab3100->startup_events[0] = event_regs[0]; |
423 | ab3100->startup_events[1] = event_regs[1]; | ||
424 | ab3100->startup_events[2] = event_regs[2]; | ||
394 | ab3100->startup_events_read = true; | 425 | ab3100->startup_events_read = true; |
395 | } | 426 | } |
396 | /* | 427 | /* |
@@ -703,7 +734,8 @@ static int __init ab3100_setup(struct ab3100 *ab3100) | |||
703 | dev_warn(ab3100->dev, | 734 | dev_warn(ab3100->dev, |
704 | "AB3100 P1E variant detected, " | 735 | "AB3100 P1E variant detected, " |
705 | "forcing chip to 32KHz\n"); | 736 | "forcing chip to 32KHz\n"); |
706 | err = ab3100_set_test_register_interruptible(ab3100, 0x02, 0x08); | 737 | err = ab3100_set_test_register_interruptible(ab3100, |
738 | 0x02, 0x08); | ||
707 | } | 739 | } |
708 | 740 | ||
709 | exit_no_setup: | 741 | exit_no_setup: |
@@ -898,6 +930,10 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
898 | if (err) | 930 | if (err) |
899 | goto exit_no_irq; | 931 | goto exit_no_irq; |
900 | 932 | ||
933 | err = abx500_register_ops(&client->dev, &ab3100_ops); | ||
934 | if (err) | ||
935 | goto exit_no_ops; | ||
936 | |||
901 | /* Set parent and a pointer back to the container in device data */ | 937 | /* Set parent and a pointer back to the container in device data */ |
902 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) { | 938 | for (i = 0; i < ARRAY_SIZE(ab3100_platform_devs); i++) { |
903 | ab3100_platform_devs[i]->dev.parent = | 939 | ab3100_platform_devs[i]->dev.parent = |
@@ -915,11 +951,13 @@ static int __init ab3100_probe(struct i2c_client *client, | |||
915 | 951 | ||
916 | return 0; | 952 | return 0; |
917 | 953 | ||
954 | exit_no_ops: | ||
918 | exit_no_irq: | 955 | exit_no_irq: |
919 | exit_no_setup: | 956 | exit_no_setup: |
920 | i2c_unregister_device(ab3100->testreg_client); | 957 | i2c_unregister_device(ab3100->testreg_client); |
921 | exit_no_testreg_client: | 958 | exit_no_testreg_client: |
922 | exit_no_detect: | 959 | exit_no_detect: |
960 | i2c_set_clientdata(client, NULL); | ||
923 | kfree(ab3100); | 961 | kfree(ab3100); |
924 | return err; | 962 | return err; |
925 | } | 963 | } |
@@ -941,6 +979,7 @@ static int __exit ab3100_remove(struct i2c_client *client) | |||
941 | * their notifiers so deactivate IRQ | 979 | * their notifiers so deactivate IRQ |
942 | */ | 980 | */ |
943 | free_irq(client->irq, ab3100); | 981 | free_irq(client->irq, ab3100); |
982 | i2c_set_clientdata(client, NULL); | ||
944 | kfree(ab3100); | 983 | kfree(ab3100); |
945 | return 0; | 984 | return 0; |
946 | } | 985 | } |
diff --git a/drivers/mfd/ab3100-otp.c b/drivers/mfd/ab3100-otp.c index 2d14655fdebd..63d2b727ddbb 100644 --- a/drivers/mfd/ab3100-otp.c +++ b/drivers/mfd/ab3100-otp.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/mfd/ab3100.h> | 15 | #include <linux/mfd/abx500.h> |
16 | #include <linux/debugfs.h> | 16 | #include <linux/debugfs.h> |
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | 18 | ||
@@ -30,7 +30,6 @@ | |||
30 | /** | 30 | /** |
31 | * struct ab3100_otp | 31 | * struct ab3100_otp |
32 | * @dev containing device | 32 | * @dev containing device |
33 | * @ab3100 a pointer to the parent ab3100 device struct | ||
34 | * @locked whether the OTP is locked, after locking, no more bits | 33 | * @locked whether the OTP is locked, after locking, no more bits |
35 | * can be changed but before locking it is still possible | 34 | * can be changed but before locking it is still possible |
36 | * to change bits from 1->0. | 35 | * to change bits from 1->0. |
@@ -49,7 +48,6 @@ | |||
49 | */ | 48 | */ |
50 | struct ab3100_otp { | 49 | struct ab3100_otp { |
51 | struct device *dev; | 50 | struct device *dev; |
52 | struct ab3100 *ab3100; | ||
53 | bool locked; | 51 | bool locked; |
54 | u32 freq; | 52 | u32 freq; |
55 | bool paf; | 53 | bool paf; |
@@ -63,19 +61,19 @@ struct ab3100_otp { | |||
63 | 61 | ||
64 | static int __init ab3100_otp_read(struct ab3100_otp *otp) | 62 | static int __init ab3100_otp_read(struct ab3100_otp *otp) |
65 | { | 63 | { |
66 | struct ab3100 *ab = otp->ab3100; | ||
67 | u8 otpval[8]; | 64 | u8 otpval[8]; |
68 | u8 otpp; | 65 | u8 otpp; |
69 | int err; | 66 | int err; |
70 | 67 | ||
71 | err = ab3100_get_register_interruptible(ab, AB3100_OTPP, &otpp); | 68 | err = abx500_get_register_interruptible(otp->dev, 0, |
69 | AB3100_OTPP, &otpp); | ||
72 | if (err) { | 70 | if (err) { |
73 | dev_err(otp->dev, "unable to read OTPP register\n"); | 71 | dev_err(otp->dev, "unable to read OTPP register\n"); |
74 | return err; | 72 | return err; |
75 | } | 73 | } |
76 | 74 | ||
77 | err = ab3100_get_register_page_interruptible(ab, AB3100_OTP0, | 75 | err = abx500_get_register_page_interruptible(otp->dev, 0, |
78 | otpval, 8); | 76 | AB3100_OTP0, otpval, 8); |
79 | if (err) { | 77 | if (err) { |
80 | dev_err(otp->dev, "unable to read OTP register page\n"); | 78 | dev_err(otp->dev, "unable to read OTP register page\n"); |
81 | return err; | 79 | return err; |
@@ -197,7 +195,6 @@ static int __init ab3100_otp_probe(struct platform_device *pdev) | |||
197 | otp->dev = &pdev->dev; | 195 | otp->dev = &pdev->dev; |
198 | 196 | ||
199 | /* Replace platform data coming in with a local struct */ | 197 | /* Replace platform data coming in with a local struct */ |
200 | otp->ab3100 = platform_get_drvdata(pdev); | ||
201 | platform_set_drvdata(pdev, otp); | 198 | platform_set_drvdata(pdev, otp); |
202 | 199 | ||
203 | err = ab3100_otp_read(otp); | 200 | err = ab3100_otp_read(otp); |
diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c new file mode 100644 index 000000000000..1060f8e1c40a --- /dev/null +++ b/drivers/mfd/ab3550-core.c | |||
@@ -0,0 +1,1401 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2010 ST-Ericsson | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Low-level core for exclusive access to the AB3550 IC on the I2C bus | ||
5 | * and some basic chip-configuration. | ||
6 | * Author: Bengt Jonsson <bengt.g.jonsson@stericsson.com> | ||
7 | * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> | ||
8 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> | ||
9 | * Author: Rickard Andersson <rickard.andersson@stericsson.com> | ||
10 | */ | ||
11 | |||
12 | #include <linux/i2c.h> | ||
13 | #include <linux/mutex.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/platform_device.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/random.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <linux/debugfs.h> | ||
23 | #include <linux/seq_file.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/mfd/abx500.h> | ||
26 | #include <linux/list.h> | ||
27 | #include <linux/bitops.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | #include <linux/mfd/core.h> | ||
30 | |||
31 | #define AB3550_NAME_STRING "ab3550" | ||
32 | #define AB3550_ID_FORMAT_STRING "AB3550 %s" | ||
33 | #define AB3550_NUM_BANKS 2 | ||
34 | #define AB3550_NUM_EVENT_REG 5 | ||
35 | |||
36 | /* These are the only registers inside AB3550 used in this main file */ | ||
37 | |||
38 | /* Chip ID register */ | ||
39 | #define AB3550_CID_REG 0x20 | ||
40 | |||
41 | /* Interrupt event registers */ | ||
42 | #define AB3550_EVENT_BANK 0 | ||
43 | #define AB3550_EVENT_REG 0x22 | ||
44 | |||
45 | /* Read/write operation values. */ | ||
46 | #define AB3550_PERM_RD (0x01) | ||
47 | #define AB3550_PERM_WR (0x02) | ||
48 | |||
49 | /* Read/write permissions. */ | ||
50 | #define AB3550_PERM_RO (AB3550_PERM_RD) | ||
51 | #define AB3550_PERM_RW (AB3550_PERM_RD | AB3550_PERM_WR) | ||
52 | |||
53 | /** | ||
54 | * struct ab3550 | ||
55 | * @access_mutex: lock out concurrent accesses to the AB registers | ||
56 | * @i2c_client: I2C client for this chip | ||
57 | * @chip_name: name of this chip variant | ||
58 | * @chip_id: 8 bit chip ID for this chip variant | ||
59 | * @mask_work: a worker for writing to mask registers | ||
60 | * @event_lock: a lock to protect the event_mask | ||
61 | * @event_mask: a local copy of the mask event registers | ||
62 | * @startup_events: a copy of the first reading of the event registers | ||
63 | * @startup_events_read: whether the first events have been read | ||
64 | */ | ||
65 | struct ab3550 { | ||
66 | struct mutex access_mutex; | ||
67 | struct i2c_client *i2c_client[AB3550_NUM_BANKS]; | ||
68 | char chip_name[32]; | ||
69 | u8 chip_id; | ||
70 | struct work_struct mask_work; | ||
71 | spinlock_t event_lock; | ||
72 | u8 event_mask[AB3550_NUM_EVENT_REG]; | ||
73 | u8 startup_events[AB3550_NUM_EVENT_REG]; | ||
74 | bool startup_events_read; | ||
75 | #ifdef CONFIG_DEBUG_FS | ||
76 | unsigned int debug_bank; | ||
77 | unsigned int debug_address; | ||
78 | #endif | ||
79 | }; | ||
80 | |||
81 | /** | ||
82 | * struct ab3550_reg_range | ||
83 | * @first: the first address of the range | ||
84 | * @last: the last address of the range | ||
85 | * @perm: access permissions for the range | ||
86 | */ | ||
87 | struct ab3550_reg_range { | ||
88 | u8 first; | ||
89 | u8 last; | ||
90 | u8 perm; | ||
91 | }; | ||
92 | |||
93 | /** | ||
94 | * struct ab3550_reg_ranges | ||
95 | * @count: the number of ranges in the list | ||
96 | * @range: the list of register ranges | ||
97 | */ | ||
98 | struct ab3550_reg_ranges { | ||
99 | u8 count; | ||
100 | const struct ab3550_reg_range *range; | ||
101 | }; | ||
102 | |||
103 | /* | ||
104 | * Permissible register ranges for reading and writing per device and bank. | ||
105 | * | ||
106 | * The ranges must be listed in increasing address order, and no overlaps are | ||
107 | * allowed. It is assumed that write permission implies read permission | ||
108 | * (i.e. only RO and RW permissions should be used). Ranges with write | ||
109 | * permission must not be split up. | ||
110 | */ | ||
111 | |||
112 | #define NO_RANGE {.count = 0, .range = NULL,} | ||
113 | |||
114 | static struct | ||
115 | ab3550_reg_ranges ab3550_reg_ranges[AB3550_NUM_DEVICES][AB3550_NUM_BANKS] = { | ||
116 | [AB3550_DEVID_DAC] = { | ||
117 | NO_RANGE, | ||
118 | { | ||
119 | .count = 2, | ||
120 | .range = (struct ab3550_reg_range[]) { | ||
121 | { | ||
122 | .first = 0xb0, | ||
123 | .last = 0xba, | ||
124 | .perm = AB3550_PERM_RW, | ||
125 | }, | ||
126 | { | ||
127 | .first = 0xbc, | ||
128 | .last = 0xc3, | ||
129 | .perm = AB3550_PERM_RW, | ||
130 | }, | ||
131 | }, | ||
132 | }, | ||
133 | }, | ||
134 | [AB3550_DEVID_LEDS] = { | ||
135 | NO_RANGE, | ||
136 | { | ||
137 | .count = 2, | ||
138 | .range = (struct ab3550_reg_range[]) { | ||
139 | { | ||
140 | .first = 0x5a, | ||
141 | .last = 0x88, | ||
142 | .perm = AB3550_PERM_RW, | ||
143 | }, | ||
144 | { | ||
145 | .first = 0x8a, | ||
146 | .last = 0xad, | ||
147 | .perm = AB3550_PERM_RW, | ||
148 | }, | ||
149 | } | ||
150 | }, | ||
151 | }, | ||
152 | [AB3550_DEVID_POWER] = { | ||
153 | { | ||
154 | .count = 1, | ||
155 | .range = (struct ab3550_reg_range[]) { | ||
156 | { | ||
157 | .first = 0x21, | ||
158 | .last = 0x21, | ||
159 | .perm = AB3550_PERM_RO, | ||
160 | }, | ||
161 | } | ||
162 | }, | ||
163 | NO_RANGE, | ||
164 | }, | ||
165 | [AB3550_DEVID_REGULATORS] = { | ||
166 | { | ||
167 | .count = 1, | ||
168 | .range = (struct ab3550_reg_range[]) { | ||
169 | { | ||
170 | .first = 0x69, | ||
171 | .last = 0xa3, | ||
172 | .perm = AB3550_PERM_RW, | ||
173 | }, | ||
174 | } | ||
175 | }, | ||
176 | { | ||
177 | .count = 1, | ||
178 | .range = (struct ab3550_reg_range[]) { | ||
179 | { | ||
180 | .first = 0x14, | ||
181 | .last = 0x16, | ||
182 | .perm = AB3550_PERM_RW, | ||
183 | }, | ||
184 | } | ||
185 | }, | ||
186 | }, | ||
187 | [AB3550_DEVID_SIM] = { | ||
188 | { | ||
189 | .count = 1, | ||
190 | .range = (struct ab3550_reg_range[]) { | ||
191 | { | ||
192 | .first = 0x21, | ||
193 | .last = 0x21, | ||
194 | .perm = AB3550_PERM_RO, | ||
195 | }, | ||
196 | } | ||
197 | }, | ||
198 | { | ||
199 | .count = 1, | ||
200 | .range = (struct ab3550_reg_range[]) { | ||
201 | { | ||
202 | .first = 0x14, | ||
203 | .last = 0x17, | ||
204 | .perm = AB3550_PERM_RW, | ||
205 | }, | ||
206 | } | ||
207 | |||
208 | }, | ||
209 | }, | ||
210 | [AB3550_DEVID_UART] = { | ||
211 | NO_RANGE, | ||
212 | NO_RANGE, | ||
213 | }, | ||
214 | [AB3550_DEVID_RTC] = { | ||
215 | { | ||
216 | .count = 1, | ||
217 | .range = (struct ab3550_reg_range[]) { | ||
218 | { | ||
219 | .first = 0x00, | ||
220 | .last = 0x0c, | ||
221 | .perm = AB3550_PERM_RW, | ||
222 | }, | ||
223 | } | ||
224 | }, | ||
225 | NO_RANGE, | ||
226 | }, | ||
227 | [AB3550_DEVID_CHARGER] = { | ||
228 | { | ||
229 | .count = 2, | ||
230 | .range = (struct ab3550_reg_range[]) { | ||
231 | { | ||
232 | .first = 0x10, | ||
233 | .last = 0x1a, | ||
234 | .perm = AB3550_PERM_RW, | ||
235 | }, | ||
236 | { | ||
237 | .first = 0x21, | ||
238 | .last = 0x21, | ||
239 | .perm = AB3550_PERM_RO, | ||
240 | }, | ||
241 | } | ||
242 | }, | ||
243 | NO_RANGE, | ||
244 | }, | ||
245 | [AB3550_DEVID_ADC] = { | ||
246 | NO_RANGE, | ||
247 | { | ||
248 | .count = 1, | ||
249 | .range = (struct ab3550_reg_range[]) { | ||
250 | { | ||
251 | .first = 0x20, | ||
252 | .last = 0x56, | ||
253 | .perm = AB3550_PERM_RW, | ||
254 | }, | ||
255 | |||
256 | } | ||
257 | }, | ||
258 | }, | ||
259 | [AB3550_DEVID_FUELGAUGE] = { | ||
260 | { | ||
261 | .count = 1, | ||
262 | .range = (struct ab3550_reg_range[]) { | ||
263 | { | ||
264 | .first = 0x21, | ||
265 | .last = 0x21, | ||
266 | .perm = AB3550_PERM_RO, | ||
267 | }, | ||
268 | } | ||
269 | }, | ||
270 | { | ||
271 | .count = 1, | ||
272 | .range = (struct ab3550_reg_range[]) { | ||
273 | { | ||
274 | .first = 0x00, | ||
275 | .last = 0x0e, | ||
276 | .perm = AB3550_PERM_RW, | ||
277 | }, | ||
278 | } | ||
279 | }, | ||
280 | }, | ||
281 | [AB3550_DEVID_VIBRATOR] = { | ||
282 | NO_RANGE, | ||
283 | { | ||
284 | .count = 1, | ||
285 | .range = (struct ab3550_reg_range[]) { | ||
286 | { | ||
287 | .first = 0x10, | ||
288 | .last = 0x13, | ||
289 | .perm = AB3550_PERM_RW, | ||
290 | }, | ||
291 | |||
292 | } | ||
293 | }, | ||
294 | }, | ||
295 | [AB3550_DEVID_CODEC] = { | ||
296 | { | ||
297 | .count = 2, | ||
298 | .range = (struct ab3550_reg_range[]) { | ||
299 | { | ||
300 | .first = 0x31, | ||
301 | .last = 0x63, | ||
302 | .perm = AB3550_PERM_RW, | ||
303 | }, | ||
304 | { | ||
305 | .first = 0x65, | ||
306 | .last = 0x68, | ||
307 | .perm = AB3550_PERM_RW, | ||
308 | }, | ||
309 | } | ||
310 | }, | ||
311 | NO_RANGE, | ||
312 | }, | ||
313 | }; | ||
314 | |||
315 | static struct mfd_cell ab3550_devs[AB3550_NUM_DEVICES] = { | ||
316 | [AB3550_DEVID_DAC] = { | ||
317 | .name = "ab3550-dac", | ||
318 | .id = AB3550_DEVID_DAC, | ||
319 | .num_resources = 0, | ||
320 | }, | ||
321 | [AB3550_DEVID_LEDS] = { | ||
322 | .name = "ab3550-leds", | ||
323 | .id = AB3550_DEVID_LEDS, | ||
324 | }, | ||
325 | [AB3550_DEVID_POWER] = { | ||
326 | .name = "ab3550-power", | ||
327 | .id = AB3550_DEVID_POWER, | ||
328 | }, | ||
329 | [AB3550_DEVID_REGULATORS] = { | ||
330 | .name = "ab3550-regulators", | ||
331 | .id = AB3550_DEVID_REGULATORS, | ||
332 | }, | ||
333 | [AB3550_DEVID_SIM] = { | ||
334 | .name = "ab3550-sim", | ||
335 | .id = AB3550_DEVID_SIM, | ||
336 | }, | ||
337 | [AB3550_DEVID_UART] = { | ||
338 | .name = "ab3550-uart", | ||
339 | .id = AB3550_DEVID_UART, | ||
340 | }, | ||
341 | [AB3550_DEVID_RTC] = { | ||
342 | .name = "ab3550-rtc", | ||
343 | .id = AB3550_DEVID_RTC, | ||
344 | }, | ||
345 | [AB3550_DEVID_CHARGER] = { | ||
346 | .name = "ab3550-charger", | ||
347 | .id = AB3550_DEVID_CHARGER, | ||
348 | }, | ||
349 | [AB3550_DEVID_ADC] = { | ||
350 | .name = "ab3550-adc", | ||
351 | .id = AB3550_DEVID_ADC, | ||
352 | .num_resources = 10, | ||
353 | .resources = (struct resource[]) { | ||
354 | { | ||
355 | .name = "TRIGGER-0", | ||
356 | .flags = IORESOURCE_IRQ, | ||
357 | .start = 16, | ||
358 | .end = 16, | ||
359 | }, | ||
360 | { | ||
361 | .name = "TRIGGER-1", | ||
362 | .flags = IORESOURCE_IRQ, | ||
363 | .start = 17, | ||
364 | .end = 17, | ||
365 | }, | ||
366 | { | ||
367 | .name = "TRIGGER-2", | ||
368 | .flags = IORESOURCE_IRQ, | ||
369 | .start = 18, | ||
370 | .end = 18, | ||
371 | }, | ||
372 | { | ||
373 | .name = "TRIGGER-3", | ||
374 | .flags = IORESOURCE_IRQ, | ||
375 | .start = 19, | ||
376 | .end = 19, | ||
377 | }, | ||
378 | { | ||
379 | .name = "TRIGGER-4", | ||
380 | .flags = IORESOURCE_IRQ, | ||
381 | .start = 20, | ||
382 | .end = 20, | ||
383 | }, | ||
384 | { | ||
385 | .name = "TRIGGER-5", | ||
386 | .flags = IORESOURCE_IRQ, | ||
387 | .start = 21, | ||
388 | .end = 21, | ||
389 | }, | ||
390 | { | ||
391 | .name = "TRIGGER-6", | ||
392 | .flags = IORESOURCE_IRQ, | ||
393 | .start = 22, | ||
394 | .end = 22, | ||
395 | }, | ||
396 | { | ||
397 | .name = "TRIGGER-7", | ||
398 | .flags = IORESOURCE_IRQ, | ||
399 | .start = 23, | ||
400 | .end = 23, | ||
401 | }, | ||
402 | { | ||
403 | .name = "TRIGGER-VBAT-TXON", | ||
404 | .flags = IORESOURCE_IRQ, | ||
405 | .start = 13, | ||
406 | .end = 13, | ||
407 | }, | ||
408 | { | ||
409 | .name = "TRIGGER-VBAT", | ||
410 | .flags = IORESOURCE_IRQ, | ||
411 | .start = 12, | ||
412 | .end = 12, | ||
413 | }, | ||
414 | }, | ||
415 | }, | ||
416 | [AB3550_DEVID_FUELGAUGE] = { | ||
417 | .name = "ab3550-fuelgauge", | ||
418 | .id = AB3550_DEVID_FUELGAUGE, | ||
419 | }, | ||
420 | [AB3550_DEVID_VIBRATOR] = { | ||
421 | .name = "ab3550-vibrator", | ||
422 | .id = AB3550_DEVID_VIBRATOR, | ||
423 | }, | ||
424 | [AB3550_DEVID_CODEC] = { | ||
425 | .name = "ab3550-codec", | ||
426 | .id = AB3550_DEVID_CODEC, | ||
427 | }, | ||
428 | }; | ||
429 | |||
430 | /* | ||
431 | * I2C transactions with error messages. | ||
432 | */ | ||
433 | static int ab3550_i2c_master_send(struct ab3550 *ab, u8 bank, u8 *data, | ||
434 | u8 count) | ||
435 | { | ||
436 | int err; | ||
437 | |||
438 | err = i2c_master_send(ab->i2c_client[bank], data, count); | ||
439 | if (err < 0) { | ||
440 | dev_err(&ab->i2c_client[0]->dev, "send error: %d\n", err); | ||
441 | return err; | ||
442 | } | ||
443 | return 0; | ||
444 | } | ||
445 | |||
446 | static int ab3550_i2c_master_recv(struct ab3550 *ab, u8 bank, u8 *data, | ||
447 | u8 count) | ||
448 | { | ||
449 | int err; | ||
450 | |||
451 | err = i2c_master_recv(ab->i2c_client[bank], data, count); | ||
452 | if (err < 0) { | ||
453 | dev_err(&ab->i2c_client[0]->dev, "receive error: %d\n", err); | ||
454 | return err; | ||
455 | } | ||
456 | return 0; | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * Functionality for getting/setting register values. | ||
461 | */ | ||
462 | static int get_register_interruptible(struct ab3550 *ab, u8 bank, u8 reg, | ||
463 | u8 *value) | ||
464 | { | ||
465 | int err; | ||
466 | |||
467 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
468 | if (err) | ||
469 | return err; | ||
470 | |||
471 | err = ab3550_i2c_master_send(ab, bank, ®, 1); | ||
472 | if (!err) | ||
473 | err = ab3550_i2c_master_recv(ab, bank, value, 1); | ||
474 | |||
475 | mutex_unlock(&ab->access_mutex); | ||
476 | return err; | ||
477 | } | ||
478 | |||
479 | static int get_register_page_interruptible(struct ab3550 *ab, u8 bank, | ||
480 | u8 first_reg, u8 *regvals, u8 numregs) | ||
481 | { | ||
482 | int err; | ||
483 | |||
484 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
485 | if (err) | ||
486 | return err; | ||
487 | |||
488 | err = ab3550_i2c_master_send(ab, bank, &first_reg, 1); | ||
489 | if (!err) | ||
490 | err = ab3550_i2c_master_recv(ab, bank, regvals, numregs); | ||
491 | |||
492 | mutex_unlock(&ab->access_mutex); | ||
493 | return err; | ||
494 | } | ||
495 | |||
496 | static int mask_and_set_register_interruptible(struct ab3550 *ab, u8 bank, | ||
497 | u8 reg, u8 bitmask, u8 bitvalues) | ||
498 | { | ||
499 | int err = 0; | ||
500 | |||
501 | if (likely(bitmask)) { | ||
502 | u8 reg_bits[2] = {reg, 0}; | ||
503 | |||
504 | err = mutex_lock_interruptible(&ab->access_mutex); | ||
505 | if (err) | ||
506 | return err; | ||
507 | |||
508 | if (bitmask == 0xFF) /* No need to read in this case. */ | ||
509 | reg_bits[1] = bitvalues; | ||
510 | else { /* Read and modify the register value. */ | ||
511 | u8 bits; | ||
512 | |||
513 | err = ab3550_i2c_master_send(ab, bank, ®, 1); | ||
514 | if (err) | ||
515 | goto unlock_and_return; | ||
516 | err = ab3550_i2c_master_recv(ab, bank, &bits, 1); | ||
517 | if (err) | ||
518 | goto unlock_and_return; | ||
519 | reg_bits[1] = ((~bitmask & bits) | | ||
520 | (bitmask & bitvalues)); | ||
521 | } | ||
522 | /* Write the new value. */ | ||
523 | err = ab3550_i2c_master_send(ab, bank, reg_bits, 2); | ||
524 | unlock_and_return: | ||
525 | mutex_unlock(&ab->access_mutex); | ||
526 | } | ||
527 | return err; | ||
528 | } | ||
529 | |||
530 | /* | ||
531 | * Read/write permission checking functions. | ||
532 | */ | ||
533 | static bool page_write_allowed(const struct ab3550_reg_ranges *ranges, | ||
534 | u8 first_reg, u8 last_reg) | ||
535 | { | ||
536 | u8 i; | ||
537 | |||
538 | if (last_reg < first_reg) | ||
539 | return false; | ||
540 | |||
541 | for (i = 0; i < ranges->count; i++) { | ||
542 | if (first_reg < ranges->range[i].first) | ||
543 | break; | ||
544 | if ((last_reg <= ranges->range[i].last) && | ||
545 | (ranges->range[i].perm & AB3550_PERM_WR)) | ||
546 | return true; | ||
547 | } | ||
548 | return false; | ||
549 | } | ||
550 | |||
551 | static bool reg_write_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | ||
552 | { | ||
553 | return page_write_allowed(ranges, reg, reg); | ||
554 | } | ||
555 | |||
556 | static bool page_read_allowed(const struct ab3550_reg_ranges *ranges, | ||
557 | u8 first_reg, u8 last_reg) | ||
558 | { | ||
559 | u8 i; | ||
560 | |||
561 | if (last_reg < first_reg) | ||
562 | return false; | ||
563 | /* Find the range (if it exists in the list) that includes first_reg. */ | ||
564 | for (i = 0; i < ranges->count; i++) { | ||
565 | if (first_reg < ranges->range[i].first) | ||
566 | return false; | ||
567 | if (first_reg <= ranges->range[i].last) | ||
568 | break; | ||
569 | } | ||
570 | /* Make sure that the entire range up to and including last_reg is | ||
571 | * readable. This may span several of the ranges in the list. | ||
572 | */ | ||
573 | while ((i < ranges->count) && | ||
574 | (ranges->range[i].perm & AB3550_PERM_RD)) { | ||
575 | if (last_reg <= ranges->range[i].last) | ||
576 | return true; | ||
577 | if ((++i >= ranges->count) || | ||
578 | (ranges->range[i].first != | ||
579 | (ranges->range[i - 1].last + 1))) { | ||
580 | break; | ||
581 | } | ||
582 | } | ||
583 | return false; | ||
584 | } | ||
585 | |||
586 | static bool reg_read_allowed(const struct ab3550_reg_ranges *ranges, u8 reg) | ||
587 | { | ||
588 | return page_read_allowed(ranges, reg, reg); | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * The exported register access functionality. | ||
593 | */ | ||
594 | int ab3550_get_chip_id(struct device *dev) | ||
595 | { | ||
596 | struct ab3550 *ab = dev_get_drvdata(dev->parent); | ||
597 | return (int)ab->chip_id; | ||
598 | } | ||
599 | |||
600 | int ab3550_mask_and_set_register_interruptible(struct device *dev, u8 bank, | ||
601 | u8 reg, u8 bitmask, u8 bitvalues) | ||
602 | { | ||
603 | struct ab3550 *ab; | ||
604 | struct platform_device *pdev = to_platform_device(dev); | ||
605 | |||
606 | if ((AB3550_NUM_BANKS <= bank) || | ||
607 | !reg_write_allowed(&ab3550_reg_ranges[pdev->id][bank], reg)) | ||
608 | return -EINVAL; | ||
609 | |||
610 | ab = dev_get_drvdata(dev->parent); | ||
611 | return mask_and_set_register_interruptible(ab, bank, reg, | ||
612 | bitmask, bitvalues); | ||
613 | } | ||
614 | |||
615 | int ab3550_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | ||
616 | u8 value) | ||
617 | { | ||
618 | return ab3550_mask_and_set_register_interruptible(dev, bank, reg, 0xFF, | ||
619 | value); | ||
620 | } | ||
621 | |||
622 | int ab3550_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | ||
623 | u8 *value) | ||
624 | { | ||
625 | struct ab3550 *ab; | ||
626 | struct platform_device *pdev = to_platform_device(dev); | ||
627 | |||
628 | if ((AB3550_NUM_BANKS <= bank) || | ||
629 | !reg_read_allowed(&ab3550_reg_ranges[pdev->id][bank], reg)) | ||
630 | return -EINVAL; | ||
631 | |||
632 | ab = dev_get_drvdata(dev->parent); | ||
633 | return get_register_interruptible(ab, bank, reg, value); | ||
634 | } | ||
635 | |||
636 | int ab3550_get_register_page_interruptible(struct device *dev, u8 bank, | ||
637 | u8 first_reg, u8 *regvals, u8 numregs) | ||
638 | { | ||
639 | struct ab3550 *ab; | ||
640 | struct platform_device *pdev = to_platform_device(dev); | ||
641 | |||
642 | if ((AB3550_NUM_BANKS <= bank) || | ||
643 | !page_read_allowed(&ab3550_reg_ranges[pdev->id][bank], | ||
644 | first_reg, (first_reg + numregs - 1))) | ||
645 | return -EINVAL; | ||
646 | |||
647 | ab = dev_get_drvdata(dev->parent); | ||
648 | return get_register_page_interruptible(ab, bank, first_reg, regvals, | ||
649 | numregs); | ||
650 | } | ||
651 | |||
652 | int ab3550_event_registers_startup_state_get(struct device *dev, u8 *event) | ||
653 | { | ||
654 | struct ab3550 *ab; | ||
655 | |||
656 | ab = dev_get_drvdata(dev->parent); | ||
657 | if (!ab->startup_events_read) | ||
658 | return -EAGAIN; /* Try again later */ | ||
659 | |||
660 | memcpy(event, ab->startup_events, AB3550_NUM_EVENT_REG); | ||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | int ab3550_startup_irq_enabled(struct device *dev, unsigned int irq) | ||
665 | { | ||
666 | struct ab3550 *ab; | ||
667 | struct ab3550_platform_data *plf_data; | ||
668 | bool val; | ||
669 | |||
670 | ab = get_irq_chip_data(irq); | ||
671 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
672 | irq -= plf_data->irq.base; | ||
673 | val = ((ab->startup_events[irq / 8] & BIT(irq % 8)) != 0); | ||
674 | |||
675 | return val; | ||
676 | } | ||
677 | |||
678 | static struct abx500_ops ab3550_ops = { | ||
679 | .get_chip_id = ab3550_get_chip_id, | ||
680 | .get_register = ab3550_get_register_interruptible, | ||
681 | .set_register = ab3550_set_register_interruptible, | ||
682 | .get_register_page = ab3550_get_register_page_interruptible, | ||
683 | .set_register_page = NULL, | ||
684 | .mask_and_set_register = ab3550_mask_and_set_register_interruptible, | ||
685 | .event_registers_startup_state_get = | ||
686 | ab3550_event_registers_startup_state_get, | ||
687 | .startup_irq_enabled = ab3550_startup_irq_enabled, | ||
688 | }; | ||
689 | |||
690 | static irqreturn_t ab3550_irq_handler(int irq, void *data) | ||
691 | { | ||
692 | struct ab3550 *ab = data; | ||
693 | int err; | ||
694 | unsigned int i; | ||
695 | u8 e[AB3550_NUM_EVENT_REG]; | ||
696 | u8 *events; | ||
697 | unsigned long flags; | ||
698 | |||
699 | events = (ab->startup_events_read ? e : ab->startup_events); | ||
700 | |||
701 | err = get_register_page_interruptible(ab, AB3550_EVENT_BANK, | ||
702 | AB3550_EVENT_REG, events, AB3550_NUM_EVENT_REG); | ||
703 | if (err) | ||
704 | goto err_event_rd; | ||
705 | |||
706 | if (!ab->startup_events_read) { | ||
707 | dev_info(&ab->i2c_client[0]->dev, | ||
708 | "startup events 0x%x,0x%x,0x%x,0x%x,0x%x\n", | ||
709 | ab->startup_events[0], ab->startup_events[1], | ||
710 | ab->startup_events[2], ab->startup_events[3], | ||
711 | ab->startup_events[4]); | ||
712 | ab->startup_events_read = true; | ||
713 | goto out; | ||
714 | } | ||
715 | |||
716 | /* The two highest bits in event[4] are not used. */ | ||
717 | events[4] &= 0x3f; | ||
718 | |||
719 | spin_lock_irqsave(&ab->event_lock, flags); | ||
720 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) | ||
721 | events[i] &= ~ab->event_mask[i]; | ||
722 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
723 | |||
724 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) { | ||
725 | u8 bit; | ||
726 | u8 event_reg; | ||
727 | |||
728 | dev_dbg(&ab->i2c_client[0]->dev, "IRQ Event[%d]: 0x%2x\n", | ||
729 | i, events[i]); | ||
730 | |||
731 | event_reg = events[i]; | ||
732 | for (bit = 0; event_reg; bit++, event_reg /= 2) { | ||
733 | if (event_reg % 2) { | ||
734 | unsigned int irq; | ||
735 | struct ab3550_platform_data *plf_data; | ||
736 | |||
737 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
738 | irq = plf_data->irq.base + (i * 8) + bit; | ||
739 | handle_nested_irq(irq); | ||
740 | } | ||
741 | } | ||
742 | } | ||
743 | out: | ||
744 | return IRQ_HANDLED; | ||
745 | |||
746 | err_event_rd: | ||
747 | dev_dbg(&ab->i2c_client[0]->dev, "error reading event registers\n"); | ||
748 | return IRQ_HANDLED; | ||
749 | } | ||
750 | |||
751 | #ifdef CONFIG_DEBUG_FS | ||
752 | static struct ab3550_reg_ranges debug_ranges[AB3550_NUM_BANKS] = { | ||
753 | { | ||
754 | .count = 6, | ||
755 | .range = (struct ab3550_reg_range[]) { | ||
756 | { | ||
757 | .first = 0x00, | ||
758 | .last = 0x0e, | ||
759 | }, | ||
760 | { | ||
761 | .first = 0x10, | ||
762 | .last = 0x1a, | ||
763 | }, | ||
764 | { | ||
765 | .first = 0x1e, | ||
766 | .last = 0x4f, | ||
767 | }, | ||
768 | { | ||
769 | .first = 0x51, | ||
770 | .last = 0x63, | ||
771 | }, | ||
772 | { | ||
773 | .first = 0x65, | ||
774 | .last = 0xa3, | ||
775 | }, | ||
776 | { | ||
777 | .first = 0xa5, | ||
778 | .last = 0xa8, | ||
779 | }, | ||
780 | } | ||
781 | }, | ||
782 | { | ||
783 | .count = 8, | ||
784 | .range = (struct ab3550_reg_range[]) { | ||
785 | { | ||
786 | .first = 0x00, | ||
787 | .last = 0x0e, | ||
788 | }, | ||
789 | { | ||
790 | .first = 0x10, | ||
791 | .last = 0x17, | ||
792 | }, | ||
793 | { | ||
794 | .first = 0x1a, | ||
795 | .last = 0x1c, | ||
796 | }, | ||
797 | { | ||
798 | .first = 0x20, | ||
799 | .last = 0x56, | ||
800 | }, | ||
801 | { | ||
802 | .first = 0x5a, | ||
803 | .last = 0x88, | ||
804 | }, | ||
805 | { | ||
806 | .first = 0x8a, | ||
807 | .last = 0xad, | ||
808 | }, | ||
809 | { | ||
810 | .first = 0xb0, | ||
811 | .last = 0xba, | ||
812 | }, | ||
813 | { | ||
814 | .first = 0xbc, | ||
815 | .last = 0xc3, | ||
816 | }, | ||
817 | } | ||
818 | }, | ||
819 | }; | ||
820 | |||
821 | static int ab3550_registers_print(struct seq_file *s, void *p) | ||
822 | { | ||
823 | struct ab3550 *ab = s->private; | ||
824 | int bank; | ||
825 | |||
826 | seq_printf(s, AB3550_NAME_STRING " register values:\n"); | ||
827 | |||
828 | for (bank = 0; bank < AB3550_NUM_BANKS; bank++) { | ||
829 | unsigned int i; | ||
830 | |||
831 | seq_printf(s, " bank %d:\n", bank); | ||
832 | for (i = 0; i < debug_ranges[bank].count; i++) { | ||
833 | u8 reg; | ||
834 | |||
835 | for (reg = debug_ranges[bank].range[i].first; | ||
836 | reg <= debug_ranges[bank].range[i].last; | ||
837 | reg++) { | ||
838 | u8 value; | ||
839 | |||
840 | get_register_interruptible(ab, bank, reg, | ||
841 | &value); | ||
842 | seq_printf(s, " [%d/0x%02X]: 0x%02X\n", bank, | ||
843 | reg, value); | ||
844 | } | ||
845 | } | ||
846 | } | ||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | static int ab3550_registers_open(struct inode *inode, struct file *file) | ||
851 | { | ||
852 | return single_open(file, ab3550_registers_print, inode->i_private); | ||
853 | } | ||
854 | |||
855 | static const struct file_operations ab3550_registers_fops = { | ||
856 | .open = ab3550_registers_open, | ||
857 | .read = seq_read, | ||
858 | .llseek = seq_lseek, | ||
859 | .release = single_release, | ||
860 | .owner = THIS_MODULE, | ||
861 | }; | ||
862 | |||
863 | static int ab3550_bank_print(struct seq_file *s, void *p) | ||
864 | { | ||
865 | struct ab3550 *ab = s->private; | ||
866 | |||
867 | seq_printf(s, "%d\n", ab->debug_bank); | ||
868 | return 0; | ||
869 | } | ||
870 | |||
871 | static int ab3550_bank_open(struct inode *inode, struct file *file) | ||
872 | { | ||
873 | return single_open(file, ab3550_bank_print, inode->i_private); | ||
874 | } | ||
875 | |||
876 | static ssize_t ab3550_bank_write(struct file *file, | ||
877 | const char __user *user_buf, | ||
878 | size_t count, loff_t *ppos) | ||
879 | { | ||
880 | struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private; | ||
881 | char buf[32]; | ||
882 | int buf_size; | ||
883 | unsigned long user_bank; | ||
884 | int err; | ||
885 | |||
886 | /* Get userspace string and assure termination */ | ||
887 | buf_size = min(count, (sizeof(buf) - 1)); | ||
888 | if (copy_from_user(buf, user_buf, buf_size)) | ||
889 | return -EFAULT; | ||
890 | buf[buf_size] = 0; | ||
891 | |||
892 | err = strict_strtoul(buf, 0, &user_bank); | ||
893 | if (err) | ||
894 | return -EINVAL; | ||
895 | |||
896 | if (user_bank >= AB3550_NUM_BANKS) { | ||
897 | dev_err(&ab->i2c_client[0]->dev, | ||
898 | "debugfs error input > number of banks\n"); | ||
899 | return -EINVAL; | ||
900 | } | ||
901 | |||
902 | ab->debug_bank = user_bank; | ||
903 | |||
904 | return buf_size; | ||
905 | } | ||
906 | |||
907 | static int ab3550_address_print(struct seq_file *s, void *p) | ||
908 | { | ||
909 | struct ab3550 *ab = s->private; | ||
910 | |||
911 | seq_printf(s, "0x%02X\n", ab->debug_address); | ||
912 | return 0; | ||
913 | } | ||
914 | |||
915 | static int ab3550_address_open(struct inode *inode, struct file *file) | ||
916 | { | ||
917 | return single_open(file, ab3550_address_print, inode->i_private); | ||
918 | } | ||
919 | |||
920 | static ssize_t ab3550_address_write(struct file *file, | ||
921 | const char __user *user_buf, | ||
922 | size_t count, loff_t *ppos) | ||
923 | { | ||
924 | struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private; | ||
925 | char buf[32]; | ||
926 | int buf_size; | ||
927 | unsigned long user_address; | ||
928 | int err; | ||
929 | |||
930 | /* Get userspace string and assure termination */ | ||
931 | buf_size = min(count, (sizeof(buf) - 1)); | ||
932 | if (copy_from_user(buf, user_buf, buf_size)) | ||
933 | return -EFAULT; | ||
934 | buf[buf_size] = 0; | ||
935 | |||
936 | err = strict_strtoul(buf, 0, &user_address); | ||
937 | if (err) | ||
938 | return -EINVAL; | ||
939 | if (user_address > 0xff) { | ||
940 | dev_err(&ab->i2c_client[0]->dev, | ||
941 | "debugfs error input > 0xff\n"); | ||
942 | return -EINVAL; | ||
943 | } | ||
944 | ab->debug_address = user_address; | ||
945 | return buf_size; | ||
946 | } | ||
947 | |||
948 | static int ab3550_val_print(struct seq_file *s, void *p) | ||
949 | { | ||
950 | struct ab3550 *ab = s->private; | ||
951 | int err; | ||
952 | u8 regvalue; | ||
953 | |||
954 | err = get_register_interruptible(ab, (u8)ab->debug_bank, | ||
955 | (u8)ab->debug_address, ®value); | ||
956 | if (err) | ||
957 | return -EINVAL; | ||
958 | seq_printf(s, "0x%02X\n", regvalue); | ||
959 | |||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | static int ab3550_val_open(struct inode *inode, struct file *file) | ||
964 | { | ||
965 | return single_open(file, ab3550_val_print, inode->i_private); | ||
966 | } | ||
967 | |||
968 | static ssize_t ab3550_val_write(struct file *file, | ||
969 | const char __user *user_buf, | ||
970 | size_t count, loff_t *ppos) | ||
971 | { | ||
972 | struct ab3550 *ab = ((struct seq_file *)(file->private_data))->private; | ||
973 | char buf[32]; | ||
974 | int buf_size; | ||
975 | unsigned long user_val; | ||
976 | int err; | ||
977 | u8 regvalue; | ||
978 | |||
979 | /* Get userspace string and assure termination */ | ||
980 | buf_size = min(count, (sizeof(buf)-1)); | ||
981 | if (copy_from_user(buf, user_buf, buf_size)) | ||
982 | return -EFAULT; | ||
983 | buf[buf_size] = 0; | ||
984 | |||
985 | err = strict_strtoul(buf, 0, &user_val); | ||
986 | if (err) | ||
987 | return -EINVAL; | ||
988 | if (user_val > 0xff) { | ||
989 | dev_err(&ab->i2c_client[0]->dev, | ||
990 | "debugfs error input > 0xff\n"); | ||
991 | return -EINVAL; | ||
992 | } | ||
993 | err = mask_and_set_register_interruptible( | ||
994 | ab, (u8)ab->debug_bank, | ||
995 | (u8)ab->debug_address, 0xFF, (u8)user_val); | ||
996 | if (err) | ||
997 | return -EINVAL; | ||
998 | |||
999 | get_register_interruptible(ab, (u8)ab->debug_bank, | ||
1000 | (u8)ab->debug_address, ®value); | ||
1001 | if (err) | ||
1002 | return -EINVAL; | ||
1003 | |||
1004 | return buf_size; | ||
1005 | } | ||
1006 | |||
1007 | static const struct file_operations ab3550_bank_fops = { | ||
1008 | .open = ab3550_bank_open, | ||
1009 | .write = ab3550_bank_write, | ||
1010 | .read = seq_read, | ||
1011 | .llseek = seq_lseek, | ||
1012 | .release = single_release, | ||
1013 | .owner = THIS_MODULE, | ||
1014 | }; | ||
1015 | |||
1016 | static const struct file_operations ab3550_address_fops = { | ||
1017 | .open = ab3550_address_open, | ||
1018 | .write = ab3550_address_write, | ||
1019 | .read = seq_read, | ||
1020 | .llseek = seq_lseek, | ||
1021 | .release = single_release, | ||
1022 | .owner = THIS_MODULE, | ||
1023 | }; | ||
1024 | |||
1025 | static const struct file_operations ab3550_val_fops = { | ||
1026 | .open = ab3550_val_open, | ||
1027 | .write = ab3550_val_write, | ||
1028 | .read = seq_read, | ||
1029 | .llseek = seq_lseek, | ||
1030 | .release = single_release, | ||
1031 | .owner = THIS_MODULE, | ||
1032 | }; | ||
1033 | |||
1034 | static struct dentry *ab3550_dir; | ||
1035 | static struct dentry *ab3550_reg_file; | ||
1036 | static struct dentry *ab3550_bank_file; | ||
1037 | static struct dentry *ab3550_address_file; | ||
1038 | static struct dentry *ab3550_val_file; | ||
1039 | |||
1040 | static inline void ab3550_setup_debugfs(struct ab3550 *ab) | ||
1041 | { | ||
1042 | ab->debug_bank = 0; | ||
1043 | ab->debug_address = 0x00; | ||
1044 | |||
1045 | ab3550_dir = debugfs_create_dir(AB3550_NAME_STRING, NULL); | ||
1046 | if (!ab3550_dir) | ||
1047 | goto exit_no_debugfs; | ||
1048 | |||
1049 | ab3550_reg_file = debugfs_create_file("all-registers", | ||
1050 | S_IRUGO, ab3550_dir, ab, &ab3550_registers_fops); | ||
1051 | if (!ab3550_reg_file) | ||
1052 | goto exit_destroy_dir; | ||
1053 | |||
1054 | ab3550_bank_file = debugfs_create_file("register-bank", | ||
1055 | (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_bank_fops); | ||
1056 | if (!ab3550_bank_file) | ||
1057 | goto exit_destroy_reg; | ||
1058 | |||
1059 | ab3550_address_file = debugfs_create_file("register-address", | ||
1060 | (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_address_fops); | ||
1061 | if (!ab3550_address_file) | ||
1062 | goto exit_destroy_bank; | ||
1063 | |||
1064 | ab3550_val_file = debugfs_create_file("register-value", | ||
1065 | (S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_val_fops); | ||
1066 | if (!ab3550_val_file) | ||
1067 | goto exit_destroy_address; | ||
1068 | |||
1069 | return; | ||
1070 | |||
1071 | exit_destroy_address: | ||
1072 | debugfs_remove(ab3550_address_file); | ||
1073 | exit_destroy_bank: | ||
1074 | debugfs_remove(ab3550_bank_file); | ||
1075 | exit_destroy_reg: | ||
1076 | debugfs_remove(ab3550_reg_file); | ||
1077 | exit_destroy_dir: | ||
1078 | debugfs_remove(ab3550_dir); | ||
1079 | exit_no_debugfs: | ||
1080 | dev_err(&ab->i2c_client[0]->dev, "failed to create debugfs entries.\n"); | ||
1081 | return; | ||
1082 | } | ||
1083 | |||
1084 | static inline void ab3550_remove_debugfs(void) | ||
1085 | { | ||
1086 | debugfs_remove(ab3550_val_file); | ||
1087 | debugfs_remove(ab3550_address_file); | ||
1088 | debugfs_remove(ab3550_bank_file); | ||
1089 | debugfs_remove(ab3550_reg_file); | ||
1090 | debugfs_remove(ab3550_dir); | ||
1091 | } | ||
1092 | |||
1093 | #else /* !CONFIG_DEBUG_FS */ | ||
1094 | static inline void ab3550_setup_debugfs(struct ab3550 *ab) | ||
1095 | { | ||
1096 | } | ||
1097 | static inline void ab3550_remove_debugfs(void) | ||
1098 | { | ||
1099 | } | ||
1100 | #endif | ||
1101 | |||
1102 | /* | ||
1103 | * Basic set-up, datastructure creation/destruction and I2C interface. | ||
1104 | * This sets up a default config in the AB3550 chip so that it | ||
1105 | * will work as expected. | ||
1106 | */ | ||
1107 | static int __init ab3550_setup(struct ab3550 *ab) | ||
1108 | { | ||
1109 | int err = 0; | ||
1110 | int i; | ||
1111 | struct ab3550_platform_data *plf_data; | ||
1112 | struct abx500_init_settings *settings; | ||
1113 | |||
1114 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
1115 | settings = plf_data->init_settings; | ||
1116 | |||
1117 | for (i = 0; i < plf_data->init_settings_sz; i++) { | ||
1118 | err = mask_and_set_register_interruptible(ab, | ||
1119 | settings[i].bank, | ||
1120 | settings[i].reg, | ||
1121 | 0xFF, settings[i].setting); | ||
1122 | if (err) | ||
1123 | goto exit_no_setup; | ||
1124 | |||
1125 | /* If event mask register update the event mask in ab3550 */ | ||
1126 | if ((settings[i].bank == 0) && | ||
1127 | (AB3550_IMR1 <= settings[i].reg) && | ||
1128 | (settings[i].reg <= AB3550_IMR5)) { | ||
1129 | ab->event_mask[settings[i].reg - AB3550_IMR1] = | ||
1130 | settings[i].setting; | ||
1131 | } | ||
1132 | } | ||
1133 | exit_no_setup: | ||
1134 | return err; | ||
1135 | } | ||
1136 | |||
1137 | static void ab3550_mask_work(struct work_struct *work) | ||
1138 | { | ||
1139 | struct ab3550 *ab = container_of(work, struct ab3550, mask_work); | ||
1140 | int i; | ||
1141 | unsigned long flags; | ||
1142 | u8 mask[AB3550_NUM_EVENT_REG]; | ||
1143 | |||
1144 | spin_lock_irqsave(&ab->event_lock, flags); | ||
1145 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) | ||
1146 | mask[i] = ab->event_mask[i]; | ||
1147 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
1148 | |||
1149 | for (i = 0; i < AB3550_NUM_EVENT_REG; i++) { | ||
1150 | int err; | ||
1151 | |||
1152 | err = mask_and_set_register_interruptible(ab, 0, | ||
1153 | (AB3550_IMR1 + i), ~0, mask[i]); | ||
1154 | if (err) | ||
1155 | dev_err(&ab->i2c_client[0]->dev, | ||
1156 | "ab3550_mask_work failed 0x%x,0x%x\n", | ||
1157 | (AB3550_IMR1 + i), mask[i]); | ||
1158 | } | ||
1159 | } | ||
1160 | |||
1161 | static void ab3550_mask(unsigned int irq) | ||
1162 | { | ||
1163 | unsigned long flags; | ||
1164 | struct ab3550 *ab; | ||
1165 | struct ab3550_platform_data *plf_data; | ||
1166 | |||
1167 | ab = get_irq_chip_data(irq); | ||
1168 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
1169 | irq -= plf_data->irq.base; | ||
1170 | |||
1171 | spin_lock_irqsave(&ab->event_lock, flags); | ||
1172 | ab->event_mask[irq / 8] |= BIT(irq % 8); | ||
1173 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
1174 | |||
1175 | schedule_work(&ab->mask_work); | ||
1176 | } | ||
1177 | |||
1178 | static void ab3550_unmask(unsigned int irq) | ||
1179 | { | ||
1180 | unsigned long flags; | ||
1181 | struct ab3550 *ab; | ||
1182 | struct ab3550_platform_data *plf_data; | ||
1183 | |||
1184 | ab = get_irq_chip_data(irq); | ||
1185 | plf_data = ab->i2c_client[0]->dev.platform_data; | ||
1186 | irq -= plf_data->irq.base; | ||
1187 | |||
1188 | spin_lock_irqsave(&ab->event_lock, flags); | ||
1189 | ab->event_mask[irq / 8] &= ~BIT(irq % 8); | ||
1190 | spin_unlock_irqrestore(&ab->event_lock, flags); | ||
1191 | |||
1192 | schedule_work(&ab->mask_work); | ||
1193 | } | ||
1194 | |||
1195 | static void noop(unsigned int irq) | ||
1196 | { | ||
1197 | } | ||
1198 | |||
1199 | static struct irq_chip ab3550_irq_chip = { | ||
1200 | .name = "ab3550-core", /* Keep the same name as the request */ | ||
1201 | .startup = NULL, /* defaults to enable */ | ||
1202 | .shutdown = NULL, /* defaults to disable */ | ||
1203 | .enable = NULL, /* defaults to unmask */ | ||
1204 | .disable = ab3550_mask, /* No default to mask in chip.c */ | ||
1205 | .ack = noop, | ||
1206 | .mask = ab3550_mask, | ||
1207 | .unmask = ab3550_unmask, | ||
1208 | .end = NULL, | ||
1209 | }; | ||
1210 | |||
1211 | struct ab_family_id { | ||
1212 | u8 id; | ||
1213 | char *name; | ||
1214 | }; | ||
1215 | |||
1216 | static const struct ab_family_id ids[] __initdata = { | ||
1217 | /* AB3550 */ | ||
1218 | { | ||
1219 | .id = AB3550_P1A, | ||
1220 | .name = "P1A" | ||
1221 | }, | ||
1222 | /* Terminator */ | ||
1223 | { | ||
1224 | .id = 0x00, | ||
1225 | } | ||
1226 | }; | ||
1227 | |||
1228 | static int __init ab3550_probe(struct i2c_client *client, | ||
1229 | const struct i2c_device_id *id) | ||
1230 | { | ||
1231 | struct ab3550 *ab; | ||
1232 | struct ab3550_platform_data *ab3550_plf_data = | ||
1233 | client->dev.platform_data; | ||
1234 | int err; | ||
1235 | int i; | ||
1236 | int num_i2c_clients = 0; | ||
1237 | |||
1238 | ab = kzalloc(sizeof(struct ab3550), GFP_KERNEL); | ||
1239 | if (!ab) { | ||
1240 | dev_err(&client->dev, | ||
1241 | "could not allocate " AB3550_NAME_STRING " device\n"); | ||
1242 | return -ENOMEM; | ||
1243 | } | ||
1244 | |||
1245 | /* Initialize data structure */ | ||
1246 | mutex_init(&ab->access_mutex); | ||
1247 | spin_lock_init(&ab->event_lock); | ||
1248 | ab->i2c_client[0] = client; | ||
1249 | |||
1250 | i2c_set_clientdata(client, ab); | ||
1251 | |||
1252 | /* Read chip ID register */ | ||
1253 | err = get_register_interruptible(ab, 0, AB3550_CID_REG, &ab->chip_id); | ||
1254 | if (err) { | ||
1255 | dev_err(&client->dev, "could not communicate with the analog " | ||
1256 | "baseband chip\n"); | ||
1257 | goto exit_no_detect; | ||
1258 | } | ||
1259 | |||
1260 | for (i = 0; ids[i].id != 0x0; i++) { | ||
1261 | if (ids[i].id == ab->chip_id) { | ||
1262 | snprintf(&ab->chip_name[0], sizeof(ab->chip_name) - 1, | ||
1263 | AB3550_ID_FORMAT_STRING, ids[i].name); | ||
1264 | break; | ||
1265 | } | ||
1266 | } | ||
1267 | |||
1268 | if (ids[i].id == 0x0) { | ||
1269 | dev_err(&client->dev, "unknown analog baseband chip id: 0x%x\n", | ||
1270 | ab->chip_id); | ||
1271 | dev_err(&client->dev, "driver not started!\n"); | ||
1272 | goto exit_no_detect; | ||
1273 | } | ||
1274 | |||
1275 | dev_info(&client->dev, "detected AB chip: %s\n", &ab->chip_name[0]); | ||
1276 | |||
1277 | /* Attach other dummy I2C clients. */ | ||
1278 | while (++num_i2c_clients < AB3550_NUM_BANKS) { | ||
1279 | ab->i2c_client[num_i2c_clients] = | ||
1280 | i2c_new_dummy(client->adapter, | ||
1281 | (client->addr + num_i2c_clients)); | ||
1282 | if (!ab->i2c_client[num_i2c_clients]) { | ||
1283 | err = -ENOMEM; | ||
1284 | goto exit_no_dummy_client; | ||
1285 | } | ||
1286 | strlcpy(ab->i2c_client[num_i2c_clients]->name, id->name, | ||
1287 | sizeof(ab->i2c_client[num_i2c_clients]->name)); | ||
1288 | } | ||
1289 | |||
1290 | err = ab3550_setup(ab); | ||
1291 | if (err) | ||
1292 | goto exit_no_setup; | ||
1293 | |||
1294 | INIT_WORK(&ab->mask_work, ab3550_mask_work); | ||
1295 | |||
1296 | for (i = 0; i < ab3550_plf_data->irq.count; i++) { | ||
1297 | unsigned int irq; | ||
1298 | |||
1299 | irq = ab3550_plf_data->irq.base + i; | ||
1300 | set_irq_chip_data(irq, ab); | ||
1301 | set_irq_chip_and_handler(irq, &ab3550_irq_chip, | ||
1302 | handle_simple_irq); | ||
1303 | set_irq_nested_thread(irq, 1); | ||
1304 | #ifdef CONFIG_ARM | ||
1305 | set_irq_flags(irq, IRQF_VALID); | ||
1306 | #else | ||
1307 | set_irq_noprobe(irq); | ||
1308 | #endif | ||
1309 | } | ||
1310 | |||
1311 | err = request_threaded_irq(client->irq, NULL, ab3550_irq_handler, | ||
1312 | IRQF_ONESHOT, "ab3550-core", ab); | ||
1313 | /* This real unpredictable IRQ is of course sampled for entropy */ | ||
1314 | rand_initialize_irq(client->irq); | ||
1315 | |||
1316 | if (err) | ||
1317 | goto exit_no_irq; | ||
1318 | |||
1319 | err = abx500_register_ops(&client->dev, &ab3550_ops); | ||
1320 | if (err) | ||
1321 | goto exit_no_ops; | ||
1322 | |||
1323 | /* Set up and register the platform devices. */ | ||
1324 | for (i = 0; i < AB3550_NUM_DEVICES; i++) { | ||
1325 | ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i]; | ||
1326 | ab3550_devs[i].data_size = ab3550_plf_data->dev_data_sz[i]; | ||
1327 | } | ||
1328 | |||
1329 | err = mfd_add_devices(&client->dev, 0, ab3550_devs, | ||
1330 | ARRAY_SIZE(ab3550_devs), NULL, | ||
1331 | ab3550_plf_data->irq.base); | ||
1332 | |||
1333 | ab3550_setup_debugfs(ab); | ||
1334 | |||
1335 | return 0; | ||
1336 | |||
1337 | exit_no_ops: | ||
1338 | exit_no_irq: | ||
1339 | exit_no_setup: | ||
1340 | exit_no_dummy_client: | ||
1341 | /* Unregister the dummy i2c clients. */ | ||
1342 | while (--num_i2c_clients) | ||
1343 | i2c_unregister_device(ab->i2c_client[num_i2c_clients]); | ||
1344 | exit_no_detect: | ||
1345 | kfree(ab); | ||
1346 | return err; | ||
1347 | } | ||
1348 | |||
1349 | static int __exit ab3550_remove(struct i2c_client *client) | ||
1350 | { | ||
1351 | struct ab3550 *ab = i2c_get_clientdata(client); | ||
1352 | int num_i2c_clients = AB3550_NUM_BANKS; | ||
1353 | |||
1354 | mfd_remove_devices(&client->dev); | ||
1355 | ab3550_remove_debugfs(); | ||
1356 | |||
1357 | while (--num_i2c_clients) | ||
1358 | i2c_unregister_device(ab->i2c_client[num_i2c_clients]); | ||
1359 | |||
1360 | /* | ||
1361 | * At this point, all subscribers should have unregistered | ||
1362 | * their notifiers so deactivate IRQ | ||
1363 | */ | ||
1364 | free_irq(client->irq, ab); | ||
1365 | i2c_set_clientdata(client, NULL); | ||
1366 | kfree(ab); | ||
1367 | return 0; | ||
1368 | } | ||
1369 | |||
1370 | static const struct i2c_device_id ab3550_id[] = { | ||
1371 | {AB3550_NAME_STRING, 0}, | ||
1372 | {} | ||
1373 | }; | ||
1374 | MODULE_DEVICE_TABLE(i2c, ab3550_id); | ||
1375 | |||
1376 | static struct i2c_driver ab3550_driver = { | ||
1377 | .driver = { | ||
1378 | .name = AB3550_NAME_STRING, | ||
1379 | .owner = THIS_MODULE, | ||
1380 | }, | ||
1381 | .id_table = ab3550_id, | ||
1382 | .probe = ab3550_probe, | ||
1383 | .remove = __exit_p(ab3550_remove), | ||
1384 | }; | ||
1385 | |||
1386 | static int __init ab3550_i2c_init(void) | ||
1387 | { | ||
1388 | return i2c_add_driver(&ab3550_driver); | ||
1389 | } | ||
1390 | |||
1391 | static void __exit ab3550_i2c_exit(void) | ||
1392 | { | ||
1393 | i2c_del_driver(&ab3550_driver); | ||
1394 | } | ||
1395 | |||
1396 | subsys_initcall(ab3550_i2c_init); | ||
1397 | module_exit(ab3550_i2c_exit); | ||
1398 | |||
1399 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); | ||
1400 | MODULE_DESCRIPTION("AB3550 core driver"); | ||
1401 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/ab4500-core.c b/drivers/mfd/ab4500-core.c deleted file mode 100644 index c275daa3ab1a..000000000000 --- a/drivers/mfd/ab4500-core.c +++ /dev/null | |||
@@ -1,209 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2009 ST-Ericsson | ||
3 | * | ||
4 | * Author: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it | ||
7 | * and/or modify it under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * AB4500 is a companion power management chip used with U8500. | ||
11 | * On this platform, this is interfaced with SSP0 controller | ||
12 | * which is a ARM primecell pl022. | ||
13 | * | ||
14 | * At the moment the module just exports read/write features. | ||
15 | * Interrupt management to be added - TODO. | ||
16 | */ | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/spi/spi.h> | ||
23 | #include <linux/mfd/ab4500.h> | ||
24 | |||
25 | /* just required if probe fails, we need to | ||
26 | * unregister the device | ||
27 | */ | ||
28 | static struct spi_driver ab4500_driver; | ||
29 | |||
30 | /* | ||
31 | * This funtion writes to any AB4500 registers using | ||
32 | * SPI protocol & before it writes it packs the data | ||
33 | * in the below 24 bit frame format | ||
34 | * | ||
35 | * *|------------------------------------| | ||
36 | * *| 23|22...18|17.......10|9|8|7......0| | ||
37 | * *| r/w bank adr data | | ||
38 | * * ------------------------------------ | ||
39 | * | ||
40 | * This function shouldn't be called from interrupt | ||
41 | * context | ||
42 | */ | ||
43 | int ab4500_write(struct ab4500 *ab4500, unsigned char block, | ||
44 | unsigned long addr, unsigned char data) | ||
45 | { | ||
46 | struct spi_transfer xfer; | ||
47 | struct spi_message msg; | ||
48 | int err; | ||
49 | unsigned long spi_data = | ||
50 | block << 18 | addr << 10 | data; | ||
51 | |||
52 | mutex_lock(&ab4500->lock); | ||
53 | ab4500->tx_buf[0] = spi_data; | ||
54 | ab4500->rx_buf[0] = 0; | ||
55 | |||
56 | xfer.tx_buf = ab4500->tx_buf; | ||
57 | xfer.rx_buf = NULL; | ||
58 | xfer.len = sizeof(unsigned long); | ||
59 | |||
60 | spi_message_init(&msg); | ||
61 | spi_message_add_tail(&xfer, &msg); | ||
62 | |||
63 | err = spi_sync(ab4500->spi, &msg); | ||
64 | mutex_unlock(&ab4500->lock); | ||
65 | |||
66 | return err; | ||
67 | } | ||
68 | EXPORT_SYMBOL(ab4500_write); | ||
69 | |||
70 | int ab4500_read(struct ab4500 *ab4500, unsigned char block, | ||
71 | unsigned long addr) | ||
72 | { | ||
73 | struct spi_transfer xfer; | ||
74 | struct spi_message msg; | ||
75 | unsigned long spi_data = | ||
76 | 1 << 23 | block << 18 | addr << 10; | ||
77 | |||
78 | mutex_lock(&ab4500->lock); | ||
79 | ab4500->tx_buf[0] = spi_data; | ||
80 | ab4500->rx_buf[0] = 0; | ||
81 | |||
82 | xfer.tx_buf = ab4500->tx_buf; | ||
83 | xfer.rx_buf = ab4500->rx_buf; | ||
84 | xfer.len = sizeof(unsigned long); | ||
85 | |||
86 | spi_message_init(&msg); | ||
87 | spi_message_add_tail(&xfer, &msg); | ||
88 | |||
89 | spi_sync(ab4500->spi, &msg); | ||
90 | mutex_unlock(&ab4500->lock); | ||
91 | |||
92 | return ab4500->rx_buf[0]; | ||
93 | } | ||
94 | EXPORT_SYMBOL(ab4500_read); | ||
95 | |||
96 | /* ref: ab3100 core */ | ||
97 | #define AB4500_DEVICE(devname, devid) \ | ||
98 | static struct platform_device ab4500_##devname##_device = { \ | ||
99 | .name = devid, \ | ||
100 | .id = -1, \ | ||
101 | } | ||
102 | |||
103 | /* list of childern devices of ab4500 - all are | ||
104 | * not populated here - TODO | ||
105 | */ | ||
106 | AB4500_DEVICE(charger, "ab4500-charger"); | ||
107 | AB4500_DEVICE(audio, "ab4500-audio"); | ||
108 | AB4500_DEVICE(usb, "ab4500-usb"); | ||
109 | AB4500_DEVICE(tvout, "ab4500-tvout"); | ||
110 | AB4500_DEVICE(sim, "ab4500-sim"); | ||
111 | AB4500_DEVICE(gpadc, "ab4500-gpadc"); | ||
112 | AB4500_DEVICE(clkmgt, "ab4500-clkmgt"); | ||
113 | AB4500_DEVICE(misc, "ab4500-misc"); | ||
114 | |||
115 | static struct platform_device *ab4500_platform_devs[] = { | ||
116 | &ab4500_charger_device, | ||
117 | &ab4500_audio_device, | ||
118 | &ab4500_usb_device, | ||
119 | &ab4500_tvout_device, | ||
120 | &ab4500_sim_device, | ||
121 | &ab4500_gpadc_device, | ||
122 | &ab4500_clkmgt_device, | ||
123 | &ab4500_misc_device, | ||
124 | }; | ||
125 | |||
126 | static int __init ab4500_probe(struct spi_device *spi) | ||
127 | { | ||
128 | struct ab4500 *ab4500; | ||
129 | unsigned char revision; | ||
130 | int err = 0; | ||
131 | int i; | ||
132 | |||
133 | ab4500 = kzalloc(sizeof *ab4500, GFP_KERNEL); | ||
134 | if (!ab4500) { | ||
135 | dev_err(&spi->dev, "could not allocate AB4500\n"); | ||
136 | err = -ENOMEM; | ||
137 | goto not_detect; | ||
138 | } | ||
139 | |||
140 | ab4500->spi = spi; | ||
141 | spi_set_drvdata(spi, ab4500); | ||
142 | |||
143 | mutex_init(&ab4500->lock); | ||
144 | |||
145 | /* read the revision register */ | ||
146 | revision = ab4500_read(ab4500, AB4500_MISC, AB4500_REV_REG); | ||
147 | |||
148 | /* revision id 0x0 is for early drop, 0x10 is for cut1.0 */ | ||
149 | if (revision == 0x0 || revision == 0x10) | ||
150 | dev_info(&spi->dev, "Detected chip: %s, revision = %x\n", | ||
151 | ab4500_driver.driver.name, revision); | ||
152 | else { | ||
153 | dev_err(&spi->dev, "unknown chip: 0x%x\n", revision); | ||
154 | goto not_detect; | ||
155 | } | ||
156 | |||
157 | for (i = 0; i < ARRAY_SIZE(ab4500_platform_devs); i++) { | ||
158 | ab4500_platform_devs[i]->dev.parent = | ||
159 | &spi->dev; | ||
160 | platform_set_drvdata(ab4500_platform_devs[i], ab4500); | ||
161 | } | ||
162 | |||
163 | /* register the ab4500 platform devices */ | ||
164 | platform_add_devices(ab4500_platform_devs, | ||
165 | ARRAY_SIZE(ab4500_platform_devs)); | ||
166 | |||
167 | return err; | ||
168 | |||
169 | not_detect: | ||
170 | spi_unregister_driver(&ab4500_driver); | ||
171 | kfree(ab4500); | ||
172 | return err; | ||
173 | } | ||
174 | |||
175 | static int __devexit ab4500_remove(struct spi_device *spi) | ||
176 | { | ||
177 | struct ab4500 *ab4500 = | ||
178 | spi_get_drvdata(spi); | ||
179 | |||
180 | kfree(ab4500); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static struct spi_driver ab4500_driver = { | ||
186 | .driver = { | ||
187 | .name = "ab4500", | ||
188 | .owner = THIS_MODULE, | ||
189 | }, | ||
190 | .probe = ab4500_probe, | ||
191 | .remove = __devexit_p(ab4500_remove) | ||
192 | }; | ||
193 | |||
194 | static int __devinit ab4500_init(void) | ||
195 | { | ||
196 | return spi_register_driver(&ab4500_driver); | ||
197 | } | ||
198 | |||
199 | static void __exit ab4500_exit(void) | ||
200 | { | ||
201 | spi_unregister_driver(&ab4500_driver); | ||
202 | } | ||
203 | |||
204 | subsys_initcall(ab4500_init); | ||
205 | module_exit(ab4500_exit); | ||
206 | |||
207 | MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com"); | ||
208 | MODULE_DESCRIPTION("AB4500 core driver"); | ||
209 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c new file mode 100644 index 000000000000..f3d26fa9c34d --- /dev/null +++ b/drivers/mfd/ab8500-core.c | |||
@@ -0,0 +1,444 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | ||
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> | ||
7 | */ | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/irq.h> | ||
13 | #include <linux/delay.h> | ||
14 | #include <linux/interrupt.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/mfd/core.h> | ||
18 | #include <linux/mfd/ab8500.h> | ||
19 | |||
20 | /* | ||
21 | * Interrupt register offsets | ||
22 | * Bank : 0x0E | ||
23 | */ | ||
24 | #define AB8500_IT_SOURCE1_REG 0x0E00 | ||
25 | #define AB8500_IT_SOURCE2_REG 0x0E01 | ||
26 | #define AB8500_IT_SOURCE3_REG 0x0E02 | ||
27 | #define AB8500_IT_SOURCE4_REG 0x0E03 | ||
28 | #define AB8500_IT_SOURCE5_REG 0x0E04 | ||
29 | #define AB8500_IT_SOURCE6_REG 0x0E05 | ||
30 | #define AB8500_IT_SOURCE7_REG 0x0E06 | ||
31 | #define AB8500_IT_SOURCE8_REG 0x0E07 | ||
32 | #define AB8500_IT_SOURCE19_REG 0x0E12 | ||
33 | #define AB8500_IT_SOURCE20_REG 0x0E13 | ||
34 | #define AB8500_IT_SOURCE21_REG 0x0E14 | ||
35 | #define AB8500_IT_SOURCE22_REG 0x0E15 | ||
36 | #define AB8500_IT_SOURCE23_REG 0x0E16 | ||
37 | #define AB8500_IT_SOURCE24_REG 0x0E17 | ||
38 | |||
39 | /* | ||
40 | * latch registers | ||
41 | */ | ||
42 | #define AB8500_IT_LATCH1_REG 0x0E20 | ||
43 | #define AB8500_IT_LATCH2_REG 0x0E21 | ||
44 | #define AB8500_IT_LATCH3_REG 0x0E22 | ||
45 | #define AB8500_IT_LATCH4_REG 0x0E23 | ||
46 | #define AB8500_IT_LATCH5_REG 0x0E24 | ||
47 | #define AB8500_IT_LATCH6_REG 0x0E25 | ||
48 | #define AB8500_IT_LATCH7_REG 0x0E26 | ||
49 | #define AB8500_IT_LATCH8_REG 0x0E27 | ||
50 | #define AB8500_IT_LATCH9_REG 0x0E28 | ||
51 | #define AB8500_IT_LATCH10_REG 0x0E29 | ||
52 | #define AB8500_IT_LATCH19_REG 0x0E32 | ||
53 | #define AB8500_IT_LATCH20_REG 0x0E33 | ||
54 | #define AB8500_IT_LATCH21_REG 0x0E34 | ||
55 | #define AB8500_IT_LATCH22_REG 0x0E35 | ||
56 | #define AB8500_IT_LATCH23_REG 0x0E36 | ||
57 | #define AB8500_IT_LATCH24_REG 0x0E37 | ||
58 | |||
59 | /* | ||
60 | * mask registers | ||
61 | */ | ||
62 | |||
63 | #define AB8500_IT_MASK1_REG 0x0E40 | ||
64 | #define AB8500_IT_MASK2_REG 0x0E41 | ||
65 | #define AB8500_IT_MASK3_REG 0x0E42 | ||
66 | #define AB8500_IT_MASK4_REG 0x0E43 | ||
67 | #define AB8500_IT_MASK5_REG 0x0E44 | ||
68 | #define AB8500_IT_MASK6_REG 0x0E45 | ||
69 | #define AB8500_IT_MASK7_REG 0x0E46 | ||
70 | #define AB8500_IT_MASK8_REG 0x0E47 | ||
71 | #define AB8500_IT_MASK9_REG 0x0E48 | ||
72 | #define AB8500_IT_MASK10_REG 0x0E49 | ||
73 | #define AB8500_IT_MASK11_REG 0x0E4A | ||
74 | #define AB8500_IT_MASK12_REG 0x0E4B | ||
75 | #define AB8500_IT_MASK13_REG 0x0E4C | ||
76 | #define AB8500_IT_MASK14_REG 0x0E4D | ||
77 | #define AB8500_IT_MASK15_REG 0x0E4E | ||
78 | #define AB8500_IT_MASK16_REG 0x0E4F | ||
79 | #define AB8500_IT_MASK17_REG 0x0E50 | ||
80 | #define AB8500_IT_MASK18_REG 0x0E51 | ||
81 | #define AB8500_IT_MASK19_REG 0x0E52 | ||
82 | #define AB8500_IT_MASK20_REG 0x0E53 | ||
83 | #define AB8500_IT_MASK21_REG 0x0E54 | ||
84 | #define AB8500_IT_MASK22_REG 0x0E55 | ||
85 | #define AB8500_IT_MASK23_REG 0x0E56 | ||
86 | #define AB8500_IT_MASK24_REG 0x0E57 | ||
87 | |||
88 | #define AB8500_REV_REG 0x1080 | ||
89 | |||
90 | /* | ||
91 | * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt | ||
92 | * numbers are indexed into this array with (num / 8). | ||
93 | * | ||
94 | * This is one off from the register names, i.e. AB8500_IT_MASK1_REG is at | ||
95 | * offset 0. | ||
96 | */ | ||
97 | static const int ab8500_irq_regoffset[AB8500_NUM_IRQ_REGS] = { | ||
98 | 0, 1, 2, 3, 4, 6, 7, 8, 9, 18, 19, 20, 21, | ||
99 | }; | ||
100 | |||
101 | static int __ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data) | ||
102 | { | ||
103 | int ret; | ||
104 | |||
105 | dev_vdbg(ab8500->dev, "wr: addr %#x <= %#x\n", addr, data); | ||
106 | |||
107 | ret = ab8500->write(ab8500, addr, data); | ||
108 | if (ret < 0) | ||
109 | dev_err(ab8500->dev, "failed to write reg %#x: %d\n", | ||
110 | addr, ret); | ||
111 | |||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | /** | ||
116 | * ab8500_write() - write an AB8500 register | ||
117 | * @ab8500: device to write to | ||
118 | * @addr: address of the register | ||
119 | * @data: value to write | ||
120 | */ | ||
121 | int ab8500_write(struct ab8500 *ab8500, u16 addr, u8 data) | ||
122 | { | ||
123 | int ret; | ||
124 | |||
125 | mutex_lock(&ab8500->lock); | ||
126 | ret = __ab8500_write(ab8500, addr, data); | ||
127 | mutex_unlock(&ab8500->lock); | ||
128 | |||
129 | return ret; | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(ab8500_write); | ||
132 | |||
133 | static int __ab8500_read(struct ab8500 *ab8500, u16 addr) | ||
134 | { | ||
135 | int ret; | ||
136 | |||
137 | ret = ab8500->read(ab8500, addr); | ||
138 | if (ret < 0) | ||
139 | dev_err(ab8500->dev, "failed to read reg %#x: %d\n", | ||
140 | addr, ret); | ||
141 | |||
142 | dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * ab8500_read() - read an AB8500 register | ||
149 | * @ab8500: device to read from | ||
150 | * @addr: address of the register | ||
151 | */ | ||
152 | int ab8500_read(struct ab8500 *ab8500, u16 addr) | ||
153 | { | ||
154 | int ret; | ||
155 | |||
156 | mutex_lock(&ab8500->lock); | ||
157 | ret = __ab8500_read(ab8500, addr); | ||
158 | mutex_unlock(&ab8500->lock); | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | EXPORT_SYMBOL_GPL(ab8500_read); | ||
163 | |||
164 | /** | ||
165 | * ab8500_set_bits() - set a bitfield in an AB8500 register | ||
166 | * @ab8500: device to read from | ||
167 | * @addr: address of the register | ||
168 | * @mask: mask of the bitfield to modify | ||
169 | * @data: value to set to the bitfield | ||
170 | */ | ||
171 | int ab8500_set_bits(struct ab8500 *ab8500, u16 addr, u8 mask, u8 data) | ||
172 | { | ||
173 | int ret; | ||
174 | |||
175 | mutex_lock(&ab8500->lock); | ||
176 | |||
177 | ret = __ab8500_read(ab8500, addr); | ||
178 | if (ret < 0) | ||
179 | goto out; | ||
180 | |||
181 | ret &= ~mask; | ||
182 | ret |= data; | ||
183 | |||
184 | ret = __ab8500_write(ab8500, addr, ret); | ||
185 | |||
186 | out: | ||
187 | mutex_unlock(&ab8500->lock); | ||
188 | return ret; | ||
189 | } | ||
190 | EXPORT_SYMBOL_GPL(ab8500_set_bits); | ||
191 | |||
192 | static void ab8500_irq_lock(unsigned int irq) | ||
193 | { | ||
194 | struct ab8500 *ab8500 = get_irq_chip_data(irq); | ||
195 | |||
196 | mutex_lock(&ab8500->irq_lock); | ||
197 | } | ||
198 | |||
199 | static void ab8500_irq_sync_unlock(unsigned int irq) | ||
200 | { | ||
201 | struct ab8500 *ab8500 = get_irq_chip_data(irq); | ||
202 | int i; | ||
203 | |||
204 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { | ||
205 | u8 old = ab8500->oldmask[i]; | ||
206 | u8 new = ab8500->mask[i]; | ||
207 | int reg; | ||
208 | |||
209 | if (new == old) | ||
210 | continue; | ||
211 | |||
212 | ab8500->oldmask[i] = new; | ||
213 | |||
214 | reg = AB8500_IT_MASK1_REG + ab8500_irq_regoffset[i]; | ||
215 | ab8500_write(ab8500, reg, new); | ||
216 | } | ||
217 | |||
218 | mutex_unlock(&ab8500->irq_lock); | ||
219 | } | ||
220 | |||
221 | static void ab8500_irq_mask(unsigned int irq) | ||
222 | { | ||
223 | struct ab8500 *ab8500 = get_irq_chip_data(irq); | ||
224 | int offset = irq - ab8500->irq_base; | ||
225 | int index = offset / 8; | ||
226 | int mask = 1 << (offset % 8); | ||
227 | |||
228 | ab8500->mask[index] |= mask; | ||
229 | } | ||
230 | |||
231 | static void ab8500_irq_unmask(unsigned int irq) | ||
232 | { | ||
233 | struct ab8500 *ab8500 = get_irq_chip_data(irq); | ||
234 | int offset = irq - ab8500->irq_base; | ||
235 | int index = offset / 8; | ||
236 | int mask = 1 << (offset % 8); | ||
237 | |||
238 | ab8500->mask[index] &= ~mask; | ||
239 | } | ||
240 | |||
241 | static struct irq_chip ab8500_irq_chip = { | ||
242 | .name = "ab8500", | ||
243 | .bus_lock = ab8500_irq_lock, | ||
244 | .bus_sync_unlock = ab8500_irq_sync_unlock, | ||
245 | .mask = ab8500_irq_mask, | ||
246 | .unmask = ab8500_irq_unmask, | ||
247 | }; | ||
248 | |||
249 | static irqreturn_t ab8500_irq(int irq, void *dev) | ||
250 | { | ||
251 | struct ab8500 *ab8500 = dev; | ||
252 | int i; | ||
253 | |||
254 | dev_vdbg(ab8500->dev, "interrupt\n"); | ||
255 | |||
256 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) { | ||
257 | int regoffset = ab8500_irq_regoffset[i]; | ||
258 | int status; | ||
259 | |||
260 | status = ab8500_read(ab8500, AB8500_IT_LATCH1_REG + regoffset); | ||
261 | if (status <= 0) | ||
262 | continue; | ||
263 | |||
264 | do { | ||
265 | int bit = __ffs(status); | ||
266 | int line = i * 8 + bit; | ||
267 | |||
268 | handle_nested_irq(ab8500->irq_base + line); | ||
269 | status &= ~(1 << bit); | ||
270 | } while (status); | ||
271 | } | ||
272 | |||
273 | return IRQ_HANDLED; | ||
274 | } | ||
275 | |||
276 | static int ab8500_irq_init(struct ab8500 *ab8500) | ||
277 | { | ||
278 | int base = ab8500->irq_base; | ||
279 | int irq; | ||
280 | |||
281 | for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { | ||
282 | set_irq_chip_data(irq, ab8500); | ||
283 | set_irq_chip_and_handler(irq, &ab8500_irq_chip, | ||
284 | handle_simple_irq); | ||
285 | set_irq_nested_thread(irq, 1); | ||
286 | #ifdef CONFIG_ARM | ||
287 | set_irq_flags(irq, IRQF_VALID); | ||
288 | #else | ||
289 | set_irq_noprobe(irq); | ||
290 | #endif | ||
291 | } | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static void ab8500_irq_remove(struct ab8500 *ab8500) | ||
297 | { | ||
298 | int base = ab8500->irq_base; | ||
299 | int irq; | ||
300 | |||
301 | for (irq = base; irq < base + AB8500_NR_IRQS; irq++) { | ||
302 | #ifdef CONFIG_ARM | ||
303 | set_irq_flags(irq, 0); | ||
304 | #endif | ||
305 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
306 | set_irq_chip_data(irq, NULL); | ||
307 | } | ||
308 | } | ||
309 | |||
310 | static struct resource ab8500_gpadc_resources[] = { | ||
311 | { | ||
312 | .name = "HW_CONV_END", | ||
313 | .start = AB8500_INT_GP_HW_ADC_CONV_END, | ||
314 | .end = AB8500_INT_GP_HW_ADC_CONV_END, | ||
315 | .flags = IORESOURCE_IRQ, | ||
316 | }, | ||
317 | { | ||
318 | .name = "SW_CONV_END", | ||
319 | .start = AB8500_INT_GP_SW_ADC_CONV_END, | ||
320 | .end = AB8500_INT_GP_SW_ADC_CONV_END, | ||
321 | .flags = IORESOURCE_IRQ, | ||
322 | }, | ||
323 | }; | ||
324 | |||
325 | static struct resource ab8500_rtc_resources[] = { | ||
326 | { | ||
327 | .name = "60S", | ||
328 | .start = AB8500_INT_RTC_60S, | ||
329 | .end = AB8500_INT_RTC_60S, | ||
330 | .flags = IORESOURCE_IRQ, | ||
331 | }, | ||
332 | { | ||
333 | .name = "ALARM", | ||
334 | .start = AB8500_INT_RTC_ALARM, | ||
335 | .end = AB8500_INT_RTC_ALARM, | ||
336 | .flags = IORESOURCE_IRQ, | ||
337 | }, | ||
338 | }; | ||
339 | |||
340 | static struct mfd_cell ab8500_devs[] = { | ||
341 | { | ||
342 | .name = "ab8500-gpadc", | ||
343 | .num_resources = ARRAY_SIZE(ab8500_gpadc_resources), | ||
344 | .resources = ab8500_gpadc_resources, | ||
345 | }, | ||
346 | { | ||
347 | .name = "ab8500-rtc", | ||
348 | .num_resources = ARRAY_SIZE(ab8500_rtc_resources), | ||
349 | .resources = ab8500_rtc_resources, | ||
350 | }, | ||
351 | { .name = "ab8500-charger", }, | ||
352 | { .name = "ab8500-audio", }, | ||
353 | { .name = "ab8500-usb", }, | ||
354 | { .name = "ab8500-pwm", }, | ||
355 | }; | ||
356 | |||
357 | int __devinit ab8500_init(struct ab8500 *ab8500) | ||
358 | { | ||
359 | struct ab8500_platform_data *plat = dev_get_platdata(ab8500->dev); | ||
360 | int ret; | ||
361 | int i; | ||
362 | |||
363 | if (plat) | ||
364 | ab8500->irq_base = plat->irq_base; | ||
365 | |||
366 | mutex_init(&ab8500->lock); | ||
367 | mutex_init(&ab8500->irq_lock); | ||
368 | |||
369 | ret = ab8500_read(ab8500, AB8500_REV_REG); | ||
370 | if (ret < 0) | ||
371 | return ret; | ||
372 | |||
373 | /* | ||
374 | * 0x0 - Early Drop | ||
375 | * 0x10 - Cut 1.0 | ||
376 | * 0x11 - Cut 1.1 | ||
377 | */ | ||
378 | if (ret == 0x0 || ret == 0x10 || ret == 0x11) { | ||
379 | ab8500->revision = ret; | ||
380 | dev_info(ab8500->dev, "detected chip, revision: %#x\n", ret); | ||
381 | } else { | ||
382 | dev_err(ab8500->dev, "unknown chip, revision: %#x\n", ret); | ||
383 | return -EINVAL; | ||
384 | } | ||
385 | |||
386 | if (plat && plat->init) | ||
387 | plat->init(ab8500); | ||
388 | |||
389 | /* Clear and mask all interrupts */ | ||
390 | for (i = 0; i < 10; i++) { | ||
391 | ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); | ||
392 | ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); | ||
393 | } | ||
394 | |||
395 | for (i = 18; i < 24; i++) { | ||
396 | ab8500_read(ab8500, AB8500_IT_LATCH1_REG + i); | ||
397 | ab8500_write(ab8500, AB8500_IT_MASK1_REG + i, 0xff); | ||
398 | } | ||
399 | |||
400 | for (i = 0; i < AB8500_NUM_IRQ_REGS; i++) | ||
401 | ab8500->mask[i] = ab8500->oldmask[i] = 0xff; | ||
402 | |||
403 | if (ab8500->irq_base) { | ||
404 | ret = ab8500_irq_init(ab8500); | ||
405 | if (ret) | ||
406 | return ret; | ||
407 | |||
408 | ret = request_threaded_irq(ab8500->irq, NULL, ab8500_irq, | ||
409 | IRQF_ONESHOT, "ab8500", ab8500); | ||
410 | if (ret) | ||
411 | goto out_removeirq; | ||
412 | } | ||
413 | |||
414 | ret = mfd_add_devices(ab8500->dev, -1, ab8500_devs, | ||
415 | ARRAY_SIZE(ab8500_devs), NULL, | ||
416 | ab8500->irq_base); | ||
417 | if (ret) | ||
418 | goto out_freeirq; | ||
419 | |||
420 | return ret; | ||
421 | |||
422 | out_freeirq: | ||
423 | if (ab8500->irq_base) { | ||
424 | free_irq(ab8500->irq, ab8500); | ||
425 | out_removeirq: | ||
426 | ab8500_irq_remove(ab8500); | ||
427 | } | ||
428 | return ret; | ||
429 | } | ||
430 | |||
431 | int __devexit ab8500_exit(struct ab8500 *ab8500) | ||
432 | { | ||
433 | mfd_remove_devices(ab8500->dev); | ||
434 | if (ab8500->irq_base) { | ||
435 | free_irq(ab8500->irq, ab8500); | ||
436 | ab8500_irq_remove(ab8500); | ||
437 | } | ||
438 | |||
439 | return 0; | ||
440 | } | ||
441 | |||
442 | MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent"); | ||
443 | MODULE_DESCRIPTION("AB8500 MFD core"); | ||
444 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/ab8500-spi.c b/drivers/mfd/ab8500-spi.c new file mode 100644 index 000000000000..b81d4f768ef6 --- /dev/null +++ b/drivers/mfd/ab8500-spi.c | |||
@@ -0,0 +1,133 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License v2 | ||
5 | * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | #include <linux/spi/spi.h> | ||
14 | #include <linux/mfd/ab8500.h> | ||
15 | |||
16 | /* | ||
17 | * This funtion writes to any AB8500 registers using | ||
18 | * SPI protocol & before it writes it packs the data | ||
19 | * in the below 24 bit frame format | ||
20 | * | ||
21 | * *|------------------------------------| | ||
22 | * *| 23|22...18|17.......10|9|8|7......0| | ||
23 | * *| r/w bank adr data | | ||
24 | * * ------------------------------------ | ||
25 | * | ||
26 | * This function shouldn't be called from interrupt | ||
27 | * context | ||
28 | */ | ||
29 | static int ab8500_spi_write(struct ab8500 *ab8500, u16 addr, u8 data) | ||
30 | { | ||
31 | struct spi_device *spi = container_of(ab8500->dev, struct spi_device, | ||
32 | dev); | ||
33 | unsigned long spi_data = addr << 10 | data; | ||
34 | struct spi_transfer xfer; | ||
35 | struct spi_message msg; | ||
36 | |||
37 | ab8500->tx_buf[0] = spi_data; | ||
38 | ab8500->rx_buf[0] = 0; | ||
39 | |||
40 | xfer.tx_buf = ab8500->tx_buf; | ||
41 | xfer.rx_buf = NULL; | ||
42 | xfer.len = sizeof(unsigned long); | ||
43 | |||
44 | spi_message_init(&msg); | ||
45 | spi_message_add_tail(&xfer, &msg); | ||
46 | |||
47 | return spi_sync(spi, &msg); | ||
48 | } | ||
49 | |||
50 | static int ab8500_spi_read(struct ab8500 *ab8500, u16 addr) | ||
51 | { | ||
52 | struct spi_device *spi = container_of(ab8500->dev, struct spi_device, | ||
53 | dev); | ||
54 | unsigned long spi_data = 1 << 23 | addr << 10; | ||
55 | struct spi_transfer xfer; | ||
56 | struct spi_message msg; | ||
57 | int ret; | ||
58 | |||
59 | ab8500->tx_buf[0] = spi_data; | ||
60 | ab8500->rx_buf[0] = 0; | ||
61 | |||
62 | xfer.tx_buf = ab8500->tx_buf; | ||
63 | xfer.rx_buf = ab8500->rx_buf; | ||
64 | xfer.len = sizeof(unsigned long); | ||
65 | |||
66 | spi_message_init(&msg); | ||
67 | spi_message_add_tail(&xfer, &msg); | ||
68 | |||
69 | ret = spi_sync(spi, &msg); | ||
70 | if (!ret) | ||
71 | ret = ab8500->rx_buf[0]; | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | static int __devinit ab8500_spi_probe(struct spi_device *spi) | ||
77 | { | ||
78 | struct ab8500 *ab8500; | ||
79 | int ret; | ||
80 | |||
81 | ab8500 = kzalloc(sizeof *ab8500, GFP_KERNEL); | ||
82 | if (!ab8500) | ||
83 | return -ENOMEM; | ||
84 | |||
85 | ab8500->dev = &spi->dev; | ||
86 | ab8500->irq = spi->irq; | ||
87 | |||
88 | ab8500->read = ab8500_spi_read; | ||
89 | ab8500->write = ab8500_spi_write; | ||
90 | |||
91 | spi_set_drvdata(spi, ab8500); | ||
92 | |||
93 | ret = ab8500_init(ab8500); | ||
94 | if (ret) | ||
95 | kfree(ab8500); | ||
96 | |||
97 | return ret; | ||
98 | } | ||
99 | |||
100 | static int __devexit ab8500_spi_remove(struct spi_device *spi) | ||
101 | { | ||
102 | struct ab8500 *ab8500 = spi_get_drvdata(spi); | ||
103 | |||
104 | ab8500_exit(ab8500); | ||
105 | kfree(ab8500); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static struct spi_driver ab8500_spi_driver = { | ||
111 | .driver = { | ||
112 | .name = "ab8500", | ||
113 | .owner = THIS_MODULE, | ||
114 | }, | ||
115 | .probe = ab8500_spi_probe, | ||
116 | .remove = __devexit_p(ab8500_spi_remove) | ||
117 | }; | ||
118 | |||
119 | static int __init ab8500_spi_init(void) | ||
120 | { | ||
121 | return spi_register_driver(&ab8500_spi_driver); | ||
122 | } | ||
123 | subsys_initcall(ab8500_spi_init); | ||
124 | |||
125 | static void __exit ab8500_spi_exit(void) | ||
126 | { | ||
127 | spi_unregister_driver(&ab8500_spi_driver); | ||
128 | } | ||
129 | module_exit(ab8500_spi_exit); | ||
130 | |||
131 | MODULE_AUTHOR("Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com"); | ||
132 | MODULE_DESCRIPTION("AB8500 SPI"); | ||
133 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mfd/abx500-core.c b/drivers/mfd/abx500-core.c new file mode 100644 index 000000000000..3b3b97ec32a7 --- /dev/null +++ b/drivers/mfd/abx500-core.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2007-2010 ST-Ericsson | ||
3 | * License terms: GNU General Public License (GPL) version 2 | ||
4 | * Register access functions for the ABX500 Mixed Signal IC family. | ||
5 | * Author: Mattias Wallin <mattias.wallin@stericsson.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/list.h> | ||
9 | #include <linux/slab.h> | ||
10 | #include <linux/err.h> | ||
11 | #include <linux/mfd/abx500.h> | ||
12 | |||
13 | static LIST_HEAD(abx500_list); | ||
14 | |||
15 | struct abx500_device_entry { | ||
16 | struct list_head list; | ||
17 | struct abx500_ops ops; | ||
18 | struct device *dev; | ||
19 | }; | ||
20 | |||
21 | static void lookup_ops(struct device *dev, struct abx500_ops **ops) | ||
22 | { | ||
23 | struct abx500_device_entry *dev_entry; | ||
24 | |||
25 | *ops = NULL; | ||
26 | list_for_each_entry(dev_entry, &abx500_list, list) { | ||
27 | if (dev_entry->dev == dev) { | ||
28 | *ops = &dev_entry->ops; | ||
29 | return; | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
34 | int abx500_register_ops(struct device *dev, struct abx500_ops *ops) | ||
35 | { | ||
36 | struct abx500_device_entry *dev_entry; | ||
37 | |||
38 | dev_entry = kzalloc(sizeof(struct abx500_device_entry), GFP_KERNEL); | ||
39 | if (IS_ERR(dev_entry)) { | ||
40 | dev_err(dev, "register_ops kzalloc failed"); | ||
41 | return -ENOMEM; | ||
42 | } | ||
43 | dev_entry->dev = dev; | ||
44 | memcpy(&dev_entry->ops, ops, sizeof(struct abx500_ops)); | ||
45 | |||
46 | list_add_tail(&dev_entry->list, &abx500_list); | ||
47 | return 0; | ||
48 | } | ||
49 | EXPORT_SYMBOL(abx500_register_ops); | ||
50 | |||
51 | void abx500_remove_ops(struct device *dev) | ||
52 | { | ||
53 | struct abx500_device_entry *dev_entry, *tmp; | ||
54 | |||
55 | list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list) | ||
56 | { | ||
57 | if (dev_entry->dev == dev) { | ||
58 | list_del(&dev_entry->list); | ||
59 | kfree(dev_entry); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | EXPORT_SYMBOL(abx500_remove_ops); | ||
64 | |||
65 | int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg, | ||
66 | u8 value) | ||
67 | { | ||
68 | struct abx500_ops *ops; | ||
69 | |||
70 | lookup_ops(dev->parent, &ops); | ||
71 | if ((ops != NULL) && (ops->set_register != NULL)) | ||
72 | return ops->set_register(dev, bank, reg, value); | ||
73 | else | ||
74 | return -ENOTSUPP; | ||
75 | } | ||
76 | EXPORT_SYMBOL(abx500_set_register_interruptible); | ||
77 | |||
78 | int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg, | ||
79 | u8 *value) | ||
80 | { | ||
81 | struct abx500_ops *ops; | ||
82 | |||
83 | lookup_ops(dev->parent, &ops); | ||
84 | if ((ops != NULL) && (ops->get_register != NULL)) | ||
85 | return ops->get_register(dev, bank, reg, value); | ||
86 | else | ||
87 | return -ENOTSUPP; | ||
88 | } | ||
89 | EXPORT_SYMBOL(abx500_get_register_interruptible); | ||
90 | |||
91 | int abx500_get_register_page_interruptible(struct device *dev, u8 bank, | ||
92 | u8 first_reg, u8 *regvals, u8 numregs) | ||
93 | { | ||
94 | struct abx500_ops *ops; | ||
95 | |||
96 | lookup_ops(dev->parent, &ops); | ||
97 | if ((ops != NULL) && (ops->get_register_page != NULL)) | ||
98 | return ops->get_register_page(dev, bank, | ||
99 | first_reg, regvals, numregs); | ||
100 | else | ||
101 | return -ENOTSUPP; | ||
102 | } | ||
103 | EXPORT_SYMBOL(abx500_get_register_page_interruptible); | ||
104 | |||
105 | int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank, | ||
106 | u8 reg, u8 bitmask, u8 bitvalues) | ||
107 | { | ||
108 | struct abx500_ops *ops; | ||
109 | |||
110 | lookup_ops(dev->parent, &ops); | ||
111 | if ((ops != NULL) && (ops->mask_and_set_register != NULL)) | ||
112 | return ops->mask_and_set_register(dev, bank, | ||
113 | reg, bitmask, bitvalues); | ||
114 | else | ||
115 | return -ENOTSUPP; | ||
116 | } | ||
117 | EXPORT_SYMBOL(abx500_mask_and_set_register_interruptible); | ||
118 | |||
119 | int abx500_get_chip_id(struct device *dev) | ||
120 | { | ||
121 | struct abx500_ops *ops; | ||
122 | |||
123 | lookup_ops(dev->parent, &ops); | ||
124 | if ((ops != NULL) && (ops->get_chip_id != NULL)) | ||
125 | return ops->get_chip_id(dev); | ||
126 | else | ||
127 | return -ENOTSUPP; | ||
128 | } | ||
129 | EXPORT_SYMBOL(abx500_get_chip_id); | ||
130 | |||
131 | int abx500_event_registers_startup_state_get(struct device *dev, u8 *event) | ||
132 | { | ||
133 | struct abx500_ops *ops; | ||
134 | |||
135 | lookup_ops(dev->parent, &ops); | ||
136 | if ((ops != NULL) && (ops->event_registers_startup_state_get != NULL)) | ||
137 | return ops->event_registers_startup_state_get(dev, event); | ||
138 | else | ||
139 | return -ENOTSUPP; | ||
140 | } | ||
141 | EXPORT_SYMBOL(abx500_event_registers_startup_state_get); | ||
142 | |||
143 | int abx500_startup_irq_enabled(struct device *dev, unsigned int irq) | ||
144 | { | ||
145 | struct abx500_ops *ops; | ||
146 | |||
147 | lookup_ops(dev->parent, &ops); | ||
148 | if ((ops != NULL) && (ops->startup_irq_enabled != NULL)) | ||
149 | return ops->startup_irq_enabled(dev, irq); | ||
150 | else | ||
151 | return -ENOTSUPP; | ||
152 | } | ||
153 | EXPORT_SYMBOL(abx500_startup_irq_enabled); | ||
154 | |||
155 | MODULE_AUTHOR("Mattias Wallin <mattias.wallin@stericsson.com>"); | ||
156 | MODULE_DESCRIPTION("ABX500 core driver"); | ||
157 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 67181b147ab3..3ad915d0589c 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c | |||
@@ -544,6 +544,7 @@ static int __devexit da903x_remove(struct i2c_client *client) | |||
544 | struct da903x_chip *chip = i2c_get_clientdata(client); | 544 | struct da903x_chip *chip = i2c_get_clientdata(client); |
545 | 545 | ||
546 | da903x_remove_subdevs(chip); | 546 | da903x_remove_subdevs(chip); |
547 | i2c_set_clientdata(client, NULL); | ||
547 | kfree(chip); | 548 | kfree(chip); |
548 | return 0; | 549 | return 0; |
549 | } | 550 | } |
diff --git a/drivers/mfd/janz-cmodio.c b/drivers/mfd/janz-cmodio.c new file mode 100644 index 000000000000..9ed630799acc --- /dev/null +++ b/drivers/mfd/janz-cmodio.c | |||
@@ -0,0 +1,304 @@ | |||
1 | /* | ||
2 | * Janz CMOD-IO MODULbus Carrier Board PCI Driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu> | ||
5 | * | ||
6 | * Lots of inspiration and code was copied from drivers/mfd/sm501.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 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/mfd/core.h> | ||
22 | |||
23 | #include <linux/mfd/janz.h> | ||
24 | |||
25 | #define DRV_NAME "janz-cmodio" | ||
26 | |||
27 | /* Size of each MODULbus module in PCI BAR4 */ | ||
28 | #define CMODIO_MODULBUS_SIZE 0x200 | ||
29 | |||
30 | /* Maximum number of MODULbus modules on a CMOD-IO carrier board */ | ||
31 | #define CMODIO_MAX_MODULES 4 | ||
32 | |||
33 | /* Module Parameters */ | ||
34 | static unsigned int num_modules = CMODIO_MAX_MODULES; | ||
35 | static unsigned char *modules[CMODIO_MAX_MODULES] = { | ||
36 | "empty", "empty", "empty", "empty", | ||
37 | }; | ||
38 | |||
39 | module_param_array(modules, charp, &num_modules, S_IRUGO); | ||
40 | MODULE_PARM_DESC(modules, "MODULbus modules attached to the carrier board"); | ||
41 | |||
42 | /* Unique Device Id */ | ||
43 | static unsigned int cmodio_id; | ||
44 | |||
45 | struct cmodio_device { | ||
46 | /* Parent PCI device */ | ||
47 | struct pci_dev *pdev; | ||
48 | |||
49 | /* PLX control registers */ | ||
50 | struct janz_cmodio_onboard_regs __iomem *ctrl; | ||
51 | |||
52 | /* hex switch position */ | ||
53 | u8 hex; | ||
54 | |||
55 | /* mfd-core API */ | ||
56 | struct mfd_cell cells[CMODIO_MAX_MODULES]; | ||
57 | struct resource resources[3 * CMODIO_MAX_MODULES]; | ||
58 | struct janz_platform_data pdata[CMODIO_MAX_MODULES]; | ||
59 | }; | ||
60 | |||
61 | /* | ||
62 | * Subdevices using the mfd-core API | ||
63 | */ | ||
64 | |||
65 | static int __devinit cmodio_setup_subdevice(struct cmodio_device *priv, | ||
66 | char *name, unsigned int devno, | ||
67 | unsigned int modno) | ||
68 | { | ||
69 | struct janz_platform_data *pdata; | ||
70 | struct mfd_cell *cell; | ||
71 | struct resource *res; | ||
72 | struct pci_dev *pci; | ||
73 | |||
74 | pci = priv->pdev; | ||
75 | cell = &priv->cells[devno]; | ||
76 | res = &priv->resources[devno * 3]; | ||
77 | pdata = &priv->pdata[devno]; | ||
78 | |||
79 | cell->name = name; | ||
80 | cell->resources = res; | ||
81 | cell->num_resources = 3; | ||
82 | |||
83 | /* Setup the subdevice ID -- must be unique */ | ||
84 | cell->id = cmodio_id++; | ||
85 | |||
86 | /* Add platform data */ | ||
87 | pdata->modno = modno; | ||
88 | cell->platform_data = pdata; | ||
89 | cell->data_size = sizeof(*pdata); | ||
90 | |||
91 | /* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */ | ||
92 | res->flags = IORESOURCE_MEM; | ||
93 | res->parent = &pci->resource[3]; | ||
94 | res->start = pci->resource[3].start + (CMODIO_MODULBUS_SIZE * modno); | ||
95 | res->end = res->start + CMODIO_MODULBUS_SIZE - 1; | ||
96 | res++; | ||
97 | |||
98 | /* PLX Control Registers -- PCI BAR4 is interrupt and other registers */ | ||
99 | res->flags = IORESOURCE_MEM; | ||
100 | res->parent = &pci->resource[4]; | ||
101 | res->start = pci->resource[4].start; | ||
102 | res->end = pci->resource[4].end; | ||
103 | res++; | ||
104 | |||
105 | /* | ||
106 | * IRQ | ||
107 | * | ||
108 | * The start and end fields are used as an offset to the irq_base | ||
109 | * parameter passed into the mfd_add_devices() function call. All | ||
110 | * devices share the same IRQ. | ||
111 | */ | ||
112 | res->flags = IORESOURCE_IRQ; | ||
113 | res->parent = NULL; | ||
114 | res->start = 0; | ||
115 | res->end = 0; | ||
116 | res++; | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | /* Probe each submodule using kernel parameters */ | ||
122 | static int __devinit cmodio_probe_submodules(struct cmodio_device *priv) | ||
123 | { | ||
124 | struct pci_dev *pdev = priv->pdev; | ||
125 | unsigned int num_probed = 0; | ||
126 | char *name; | ||
127 | int i; | ||
128 | |||
129 | for (i = 0; i < num_modules; i++) { | ||
130 | name = modules[i]; | ||
131 | if (!strcmp(name, "") || !strcmp(name, "empty")) | ||
132 | continue; | ||
133 | |||
134 | dev_dbg(&priv->pdev->dev, "MODULbus %d: name %s\n", i, name); | ||
135 | cmodio_setup_subdevice(priv, name, num_probed, i); | ||
136 | num_probed++; | ||
137 | } | ||
138 | |||
139 | /* print an error message if no modules were probed */ | ||
140 | if (num_probed == 0) { | ||
141 | dev_err(&priv->pdev->dev, "no MODULbus modules specified, " | ||
142 | "please set the ``modules'' kernel " | ||
143 | "parameter according to your " | ||
144 | "hardware configuration\n"); | ||
145 | return -ENODEV; | ||
146 | } | ||
147 | |||
148 | return mfd_add_devices(&pdev->dev, 0, priv->cells, | ||
149 | num_probed, NULL, pdev->irq); | ||
150 | } | ||
151 | |||
152 | /* | ||
153 | * SYSFS Attributes | ||
154 | */ | ||
155 | |||
156 | static ssize_t mbus_show(struct device *dev, struct device_attribute *attr, | ||
157 | char *buf) | ||
158 | { | ||
159 | struct cmodio_device *priv = dev_get_drvdata(dev); | ||
160 | |||
161 | return snprintf(buf, PAGE_SIZE, "%x\n", priv->hex); | ||
162 | } | ||
163 | |||
164 | static DEVICE_ATTR(modulbus_number, S_IRUGO, mbus_show, NULL); | ||
165 | |||
166 | static struct attribute *cmodio_sysfs_attrs[] = { | ||
167 | &dev_attr_modulbus_number.attr, | ||
168 | NULL, | ||
169 | }; | ||
170 | |||
171 | static const struct attribute_group cmodio_sysfs_attr_group = { | ||
172 | .attrs = cmodio_sysfs_attrs, | ||
173 | }; | ||
174 | |||
175 | /* | ||
176 | * PCI Driver | ||
177 | */ | ||
178 | |||
179 | static int __devinit cmodio_pci_probe(struct pci_dev *dev, | ||
180 | const struct pci_device_id *id) | ||
181 | { | ||
182 | struct cmodio_device *priv; | ||
183 | int ret; | ||
184 | |||
185 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
186 | if (!priv) { | ||
187 | dev_err(&dev->dev, "unable to allocate private data\n"); | ||
188 | ret = -ENOMEM; | ||
189 | goto out_return; | ||
190 | } | ||
191 | |||
192 | pci_set_drvdata(dev, priv); | ||
193 | priv->pdev = dev; | ||
194 | |||
195 | /* Hardware Initialization */ | ||
196 | ret = pci_enable_device(dev); | ||
197 | if (ret) { | ||
198 | dev_err(&dev->dev, "unable to enable device\n"); | ||
199 | goto out_free_priv; | ||
200 | } | ||
201 | |||
202 | pci_set_master(dev); | ||
203 | ret = pci_request_regions(dev, DRV_NAME); | ||
204 | if (ret) { | ||
205 | dev_err(&dev->dev, "unable to request regions\n"); | ||
206 | goto out_pci_disable_device; | ||
207 | } | ||
208 | |||
209 | /* Onboard configuration registers */ | ||
210 | priv->ctrl = pci_ioremap_bar(dev, 4); | ||
211 | if (!priv->ctrl) { | ||
212 | dev_err(&dev->dev, "unable to remap onboard regs\n"); | ||
213 | ret = -ENOMEM; | ||
214 | goto out_pci_release_regions; | ||
215 | } | ||
216 | |||
217 | /* Read the hex switch on the carrier board */ | ||
218 | priv->hex = ioread8(&priv->ctrl->int_enable); | ||
219 | |||
220 | /* Add the MODULbus number (hex switch value) to the device's sysfs */ | ||
221 | ret = sysfs_create_group(&dev->dev.kobj, &cmodio_sysfs_attr_group); | ||
222 | if (ret) { | ||
223 | dev_err(&dev->dev, "unable to create sysfs attributes\n"); | ||
224 | goto out_unmap_ctrl; | ||
225 | } | ||
226 | |||
227 | /* | ||
228 | * Disable all interrupt lines, each submodule will enable its | ||
229 | * own interrupt line if needed | ||
230 | */ | ||
231 | iowrite8(0xf, &priv->ctrl->int_disable); | ||
232 | |||
233 | /* Register drivers for all submodules */ | ||
234 | ret = cmodio_probe_submodules(priv); | ||
235 | if (ret) { | ||
236 | dev_err(&dev->dev, "unable to probe submodules\n"); | ||
237 | goto out_sysfs_remove_group; | ||
238 | } | ||
239 | |||
240 | return 0; | ||
241 | |||
242 | out_sysfs_remove_group: | ||
243 | sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group); | ||
244 | out_unmap_ctrl: | ||
245 | iounmap(priv->ctrl); | ||
246 | out_pci_release_regions: | ||
247 | pci_release_regions(dev); | ||
248 | out_pci_disable_device: | ||
249 | pci_disable_device(dev); | ||
250 | out_free_priv: | ||
251 | kfree(priv); | ||
252 | out_return: | ||
253 | return ret; | ||
254 | } | ||
255 | |||
256 | static void __devexit cmodio_pci_remove(struct pci_dev *dev) | ||
257 | { | ||
258 | struct cmodio_device *priv = pci_get_drvdata(dev); | ||
259 | |||
260 | mfd_remove_devices(&dev->dev); | ||
261 | sysfs_remove_group(&dev->dev.kobj, &cmodio_sysfs_attr_group); | ||
262 | iounmap(priv->ctrl); | ||
263 | pci_release_regions(dev); | ||
264 | pci_disable_device(dev); | ||
265 | kfree(priv); | ||
266 | } | ||
267 | |||
268 | #define PCI_VENDOR_ID_JANZ 0x13c3 | ||
269 | |||
270 | /* The list of devices that this module will support */ | ||
271 | static DEFINE_PCI_DEVICE_TABLE(cmodio_pci_ids) = { | ||
272 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, PCI_VENDOR_ID_JANZ, 0x0101 }, | ||
273 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_JANZ, 0x0100 }, | ||
274 | { 0, } | ||
275 | }; | ||
276 | MODULE_DEVICE_TABLE(pci, cmodio_pci_ids); | ||
277 | |||
278 | static struct pci_driver cmodio_pci_driver = { | ||
279 | .name = DRV_NAME, | ||
280 | .id_table = cmodio_pci_ids, | ||
281 | .probe = cmodio_pci_probe, | ||
282 | .remove = __devexit_p(cmodio_pci_remove), | ||
283 | }; | ||
284 | |||
285 | /* | ||
286 | * Module Init / Exit | ||
287 | */ | ||
288 | |||
289 | static int __init cmodio_init(void) | ||
290 | { | ||
291 | return pci_register_driver(&cmodio_pci_driver); | ||
292 | } | ||
293 | |||
294 | static void __exit cmodio_exit(void) | ||
295 | { | ||
296 | pci_unregister_driver(&cmodio_pci_driver); | ||
297 | } | ||
298 | |||
299 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | ||
300 | MODULE_DESCRIPTION("Janz CMOD-IO PCI MODULbus Carrier Board Driver"); | ||
301 | MODULE_LICENSE("GPL"); | ||
302 | |||
303 | module_init(cmodio_init); | ||
304 | module_exit(cmodio_exit); | ||
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index 85d63c04749b..f621bcea3d02 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c | |||
@@ -508,7 +508,7 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq, | |||
508 | max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2); | 508 | max8925_reg_read(chip->i2c, MAX8925_ON_OFF_IRQ2); |
509 | max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ); | 509 | max8925_reg_read(chip->rtc, MAX8925_RTC_IRQ); |
510 | max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); | 510 | max8925_reg_read(chip->adc, MAX8925_TSC_IRQ); |
511 | /* mask all interrupts */ | 511 | /* mask all interrupts except for TSC */ |
512 | max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0); | 512 | max8925_reg_write(chip->rtc, MAX8925_ALARM0_CNTL, 0); |
513 | max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0); | 513 | max8925_reg_write(chip->rtc, MAX8925_ALARM1_CNTL, 0); |
514 | max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff); | 514 | max8925_reg_write(chip->i2c, MAX8925_CHG_IRQ1_MASK, 0xff); |
@@ -516,7 +516,6 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq, | |||
516 | max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff); | 516 | max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ1_MASK, 0xff); |
517 | max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff); | 517 | max8925_reg_write(chip->i2c, MAX8925_ON_OFF_IRQ2_MASK, 0xff); |
518 | max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); | 518 | max8925_reg_write(chip->rtc, MAX8925_RTC_IRQ_MASK, 0xff); |
519 | max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0xff); | ||
520 | 519 | ||
521 | mutex_init(&chip->irq_lock); | 520 | mutex_init(&chip->irq_lock); |
522 | chip->core_irq = irq; | 521 | chip->core_irq = irq; |
@@ -547,7 +546,11 @@ static int max8925_irq_init(struct max8925_chip *chip, int irq, | |||
547 | dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); | 546 | dev_err(chip->dev, "Failed to request core IRQ: %d\n", ret); |
548 | chip->core_irq = 0; | 547 | chip->core_irq = 0; |
549 | } | 548 | } |
549 | |||
550 | tsc_irq: | 550 | tsc_irq: |
551 | /* mask TSC interrupt */ | ||
552 | max8925_reg_write(chip->adc, MAX8925_TSC_IRQ_MASK, 0x0f); | ||
553 | |||
551 | if (!pdata->tsc_irq) { | 554 | if (!pdata->tsc_irq) { |
552 | dev_warn(chip->dev, "No interrupt support on TSC IRQ\n"); | 555 | dev_warn(chip->dev, "No interrupt support on TSC IRQ\n"); |
553 | return 0; | 556 | return 0; |
diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index d9fd8785da4d..e73f3f5252a8 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c | |||
@@ -173,8 +173,6 @@ static int __devexit max8925_remove(struct i2c_client *client) | |||
173 | max8925_device_exit(chip); | 173 | max8925_device_exit(chip); |
174 | i2c_unregister_device(chip->adc); | 174 | i2c_unregister_device(chip->adc); |
175 | i2c_unregister_device(chip->rtc); | 175 | i2c_unregister_device(chip->rtc); |
176 | i2c_set_clientdata(chip->adc, NULL); | ||
177 | i2c_set_clientdata(chip->rtc, NULL); | ||
178 | i2c_set_clientdata(chip->i2c, NULL); | 176 | i2c_set_clientdata(chip->i2c, NULL); |
179 | kfree(chip); | 177 | kfree(chip); |
180 | return 0; | 178 | return 0; |
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/menelaus.c b/drivers/mfd/menelaus.c index a94b131a18ef..721948be12c7 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c | |||
@@ -1228,6 +1228,7 @@ fail2: | |||
1228 | free_irq(client->irq, menelaus); | 1228 | free_irq(client->irq, menelaus); |
1229 | flush_scheduled_work(); | 1229 | flush_scheduled_work(); |
1230 | fail1: | 1230 | fail1: |
1231 | i2c_set_clientdata(client, NULL); | ||
1231 | kfree(menelaus); | 1232 | kfree(menelaus); |
1232 | return err; | 1233 | return err; |
1233 | } | 1234 | } |
@@ -1237,8 +1238,8 @@ static int __exit menelaus_remove(struct i2c_client *client) | |||
1237 | struct menelaus_chip *menelaus = i2c_get_clientdata(client); | 1238 | struct menelaus_chip *menelaus = i2c_get_clientdata(client); |
1238 | 1239 | ||
1239 | free_irq(client->irq, menelaus); | 1240 | free_irq(client->irq, menelaus); |
1240 | kfree(menelaus); | ||
1241 | i2c_set_clientdata(client, NULL); | 1241 | i2c_set_clientdata(client, NULL); |
1242 | kfree(menelaus); | ||
1242 | the_menelaus = NULL; | 1243 | the_menelaus = NULL; |
1243 | return 0; | 1244 | return 0; |
1244 | } | 1245 | } |
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 8ffbb7a85a7e..7dd76bceaae8 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -48,7 +48,7 @@ static int mfd_add_device(struct device *parent, int id, | |||
48 | res[r].flags = cell->resources[r].flags; | 48 | res[r].flags = cell->resources[r].flags; |
49 | 49 | ||
50 | /* Find out base to use */ | 50 | /* Find out base to use */ |
51 | if (cell->resources[r].flags & IORESOURCE_MEM) { | 51 | if ((cell->resources[r].flags & IORESOURCE_MEM) && mem_base) { |
52 | res[r].parent = mem_base; | 52 | res[r].parent = mem_base; |
53 | res[r].start = mem_base->start + | 53 | res[r].start = mem_base->start + |
54 | cell->resources[r].start; | 54 | cell->resources[r].start; |
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c index fe8f922f6654..aed0d2a9b032 100644 --- a/drivers/mfd/pcf50633-adc.c +++ b/drivers/mfd/pcf50633-adc.c | |||
@@ -30,13 +30,13 @@ | |||
30 | struct pcf50633_adc_request { | 30 | struct pcf50633_adc_request { |
31 | int mux; | 31 | int mux; |
32 | int avg; | 32 | int avg; |
33 | int result; | ||
34 | void (*callback)(struct pcf50633 *, void *, int); | 33 | void (*callback)(struct pcf50633 *, void *, int); |
35 | void *callback_param; | 34 | void *callback_param; |
35 | }; | ||
36 | 36 | ||
37 | /* Used in case of sync requests */ | 37 | struct pcf50633_adc_sync_request { |
38 | int result; | ||
38 | struct completion completion; | 39 | struct completion completion; |
39 | |||
40 | }; | 40 | }; |
41 | 41 | ||
42 | #define PCF50633_MAX_ADC_FIFO_DEPTH 8 | 42 | #define PCF50633_MAX_ADC_FIFO_DEPTH 8 |
@@ -109,10 +109,10 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req) | |||
109 | return 0; | 109 | return 0; |
110 | } | 110 | } |
111 | 111 | ||
112 | static void | 112 | static void pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, |
113 | pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) | 113 | int result) |
114 | { | 114 | { |
115 | struct pcf50633_adc_request *req = param; | 115 | struct pcf50633_adc_sync_request *req = param; |
116 | 116 | ||
117 | req->result = result; | 117 | req->result = result; |
118 | complete(&req->completion); | 118 | complete(&req->completion); |
@@ -120,28 +120,19 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) | |||
120 | 120 | ||
121 | int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg) | 121 | int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg) |
122 | { | 122 | { |
123 | struct pcf50633_adc_request *req; | 123 | struct pcf50633_adc_sync_request req; |
124 | int err; | 124 | int ret; |
125 | 125 | ||
126 | /* req is freed when the result is ready, in interrupt handler */ | 126 | init_completion(&req.completion); |
127 | req = kzalloc(sizeof(*req), GFP_KERNEL); | ||
128 | if (!req) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | req->mux = mux; | ||
132 | req->avg = avg; | ||
133 | req->callback = pcf50633_adc_sync_read_callback; | ||
134 | req->callback_param = req; | ||
135 | 127 | ||
136 | init_completion(&req->completion); | 128 | ret = pcf50633_adc_async_read(pcf, mux, avg, |
137 | err = adc_enqueue_request(pcf, req); | 129 | pcf50633_adc_sync_read_callback, &req); |
138 | if (err) | 130 | if (ret) |
139 | return err; | 131 | return ret; |
140 | 132 | ||
141 | wait_for_completion(&req->completion); | 133 | wait_for_completion(&req.completion); |
142 | 134 | ||
143 | /* FIXME by this time req might be already freed */ | 135 | return req.result; |
144 | return req->result; | ||
145 | } | 136 | } |
146 | EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read); | 137 | EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read); |
147 | 138 | ||
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 63a614d696c1..704736e6e9b9 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -21,16 +21,16 @@ | |||
21 | #include <linux/workqueue.h> | 21 | #include <linux/workqueue.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/i2c.h> | 23 | #include <linux/i2c.h> |
24 | #include <linux/irq.h> | ||
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | 25 | ||
27 | #include <linux/mfd/pcf50633/core.h> | 26 | #include <linux/mfd/pcf50633/core.h> |
28 | 27 | ||
29 | /* Two MBCS registers used during cold start */ | 28 | int pcf50633_irq_init(struct pcf50633 *pcf, int irq); |
30 | #define PCF50633_REG_MBCS1 0x4b | 29 | void pcf50633_irq_free(struct pcf50633 *pcf); |
31 | #define PCF50633_REG_MBCS2 0x4c | 30 | #ifdef CONFIG_PM |
32 | #define PCF50633_MBCS1_USBPRES 0x01 | 31 | int pcf50633_irq_suspend(struct pcf50633 *pcf); |
33 | #define PCF50633_MBCS1_ADAPTPRES 0x01 | 32 | int pcf50633_irq_resume(struct pcf50633 *pcf); |
33 | #endif | ||
34 | 34 | ||
35 | static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data) | 35 | static int __pcf50633_read(struct pcf50633 *pcf, u8 reg, int num, u8 *data) |
36 | { | 36 | { |
@@ -215,244 +215,6 @@ static struct attribute_group pcf_attr_group = { | |||
215 | .attrs = pcf_sysfs_entries, | 215 | .attrs = pcf_sysfs_entries, |
216 | }; | 216 | }; |
217 | 217 | ||
218 | int pcf50633_register_irq(struct pcf50633 *pcf, int irq, | ||
219 | void (*handler) (int, void *), void *data) | ||
220 | { | ||
221 | if (irq < 0 || irq > PCF50633_NUM_IRQ || !handler) | ||
222 | return -EINVAL; | ||
223 | |||
224 | if (WARN_ON(pcf->irq_handler[irq].handler)) | ||
225 | return -EBUSY; | ||
226 | |||
227 | mutex_lock(&pcf->lock); | ||
228 | pcf->irq_handler[irq].handler = handler; | ||
229 | pcf->irq_handler[irq].data = data; | ||
230 | mutex_unlock(&pcf->lock); | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(pcf50633_register_irq); | ||
235 | |||
236 | int pcf50633_free_irq(struct pcf50633 *pcf, int irq) | ||
237 | { | ||
238 | if (irq < 0 || irq > PCF50633_NUM_IRQ) | ||
239 | return -EINVAL; | ||
240 | |||
241 | mutex_lock(&pcf->lock); | ||
242 | pcf->irq_handler[irq].handler = NULL; | ||
243 | mutex_unlock(&pcf->lock); | ||
244 | |||
245 | return 0; | ||
246 | } | ||
247 | EXPORT_SYMBOL_GPL(pcf50633_free_irq); | ||
248 | |||
249 | static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask) | ||
250 | { | ||
251 | u8 reg, bits, tmp; | ||
252 | int ret = 0, idx; | ||
253 | |||
254 | idx = irq >> 3; | ||
255 | reg = PCF50633_REG_INT1M + idx; | ||
256 | bits = 1 << (irq & 0x07); | ||
257 | |||
258 | mutex_lock(&pcf->lock); | ||
259 | |||
260 | if (mask) { | ||
261 | ret = __pcf50633_read(pcf, reg, 1, &tmp); | ||
262 | if (ret < 0) | ||
263 | goto out; | ||
264 | |||
265 | tmp |= bits; | ||
266 | |||
267 | ret = __pcf50633_write(pcf, reg, 1, &tmp); | ||
268 | if (ret < 0) | ||
269 | goto out; | ||
270 | |||
271 | pcf->mask_regs[idx] &= ~bits; | ||
272 | pcf->mask_regs[idx] |= bits; | ||
273 | } else { | ||
274 | ret = __pcf50633_read(pcf, reg, 1, &tmp); | ||
275 | if (ret < 0) | ||
276 | goto out; | ||
277 | |||
278 | tmp &= ~bits; | ||
279 | |||
280 | ret = __pcf50633_write(pcf, reg, 1, &tmp); | ||
281 | if (ret < 0) | ||
282 | goto out; | ||
283 | |||
284 | pcf->mask_regs[idx] &= ~bits; | ||
285 | } | ||
286 | out: | ||
287 | mutex_unlock(&pcf->lock); | ||
288 | |||
289 | return ret; | ||
290 | } | ||
291 | |||
292 | int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) | ||
293 | { | ||
294 | dev_dbg(pcf->dev, "Masking IRQ %d\n", irq); | ||
295 | |||
296 | return __pcf50633_irq_mask_set(pcf, irq, 1); | ||
297 | } | ||
298 | EXPORT_SYMBOL_GPL(pcf50633_irq_mask); | ||
299 | |||
300 | int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq) | ||
301 | { | ||
302 | dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq); | ||
303 | |||
304 | return __pcf50633_irq_mask_set(pcf, irq, 0); | ||
305 | } | ||
306 | EXPORT_SYMBOL_GPL(pcf50633_irq_unmask); | ||
307 | |||
308 | int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq) | ||
309 | { | ||
310 | u8 reg, bits; | ||
311 | |||
312 | reg = irq >> 3; | ||
313 | bits = 1 << (irq & 0x07); | ||
314 | |||
315 | return pcf->mask_regs[reg] & bits; | ||
316 | } | ||
317 | EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get); | ||
318 | |||
319 | static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq) | ||
320 | { | ||
321 | if (pcf->irq_handler[irq].handler) | ||
322 | pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data); | ||
323 | } | ||
324 | |||
325 | /* Maximum amount of time ONKEY is held before emergency action is taken */ | ||
326 | #define PCF50633_ONKEY1S_TIMEOUT 8 | ||
327 | |||
328 | static void pcf50633_irq_worker(struct work_struct *work) | ||
329 | { | ||
330 | struct pcf50633 *pcf; | ||
331 | int ret, i, j; | ||
332 | u8 pcf_int[5], chgstat; | ||
333 | |||
334 | pcf = container_of(work, struct pcf50633, irq_work); | ||
335 | |||
336 | /* Read the 5 INT regs in one transaction */ | ||
337 | ret = pcf50633_read_block(pcf, PCF50633_REG_INT1, | ||
338 | ARRAY_SIZE(pcf_int), pcf_int); | ||
339 | if (ret != ARRAY_SIZE(pcf_int)) { | ||
340 | dev_err(pcf->dev, "Error reading INT registers\n"); | ||
341 | |||
342 | /* | ||
343 | * If this doesn't ACK the interrupt to the chip, we'll be | ||
344 | * called once again as we're level triggered. | ||
345 | */ | ||
346 | goto out; | ||
347 | } | ||
348 | |||
349 | /* defeat 8s death from lowsys on A5 */ | ||
350 | pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04); | ||
351 | |||
352 | /* We immediately read the usb and adapter status. We thus make sure | ||
353 | * only of USBINS/USBREM IRQ handlers are called */ | ||
354 | if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) { | ||
355 | chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); | ||
356 | if (chgstat & (0x3 << 4)) | ||
357 | pcf_int[0] &= ~(1 << PCF50633_INT1_USBREM); | ||
358 | else | ||
359 | pcf_int[0] &= ~(1 << PCF50633_INT1_USBINS); | ||
360 | } | ||
361 | |||
362 | /* Make sure only one of ADPINS or ADPREM is set */ | ||
363 | if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) { | ||
364 | chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); | ||
365 | if (chgstat & (0x3 << 4)) | ||
366 | pcf_int[0] &= ~(1 << PCF50633_INT1_ADPREM); | ||
367 | else | ||
368 | pcf_int[0] &= ~(1 << PCF50633_INT1_ADPINS); | ||
369 | } | ||
370 | |||
371 | dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x " | ||
372 | "INT4=0x%02x INT5=0x%02x\n", pcf_int[0], | ||
373 | pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]); | ||
374 | |||
375 | /* Some revisions of the chip don't have a 8s standby mode on | ||
376 | * ONKEY1S press. We try to manually do it in such cases. */ | ||
377 | if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) { | ||
378 | dev_info(pcf->dev, "ONKEY1S held for %d secs\n", | ||
379 | pcf->onkey1s_held); | ||
380 | if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT) | ||
381 | if (pcf->pdata->force_shutdown) | ||
382 | pcf->pdata->force_shutdown(pcf); | ||
383 | } | ||
384 | |||
385 | if (pcf_int[2] & PCF50633_INT3_ONKEY1S) { | ||
386 | dev_info(pcf->dev, "ONKEY1S held\n"); | ||
387 | pcf->onkey1s_held = 1 ; | ||
388 | |||
389 | /* Unmask IRQ_SECOND */ | ||
390 | pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M, | ||
391 | PCF50633_INT1_SECOND); | ||
392 | |||
393 | /* Unmask IRQ_ONKEYR */ | ||
394 | pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M, | ||
395 | PCF50633_INT2_ONKEYR); | ||
396 | } | ||
397 | |||
398 | if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) { | ||
399 | pcf->onkey1s_held = 0; | ||
400 | |||
401 | /* Mask SECOND and ONKEYR interrupts */ | ||
402 | if (pcf->mask_regs[0] & PCF50633_INT1_SECOND) | ||
403 | pcf50633_reg_set_bit_mask(pcf, | ||
404 | PCF50633_REG_INT1M, | ||
405 | PCF50633_INT1_SECOND, | ||
406 | PCF50633_INT1_SECOND); | ||
407 | |||
408 | if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR) | ||
409 | pcf50633_reg_set_bit_mask(pcf, | ||
410 | PCF50633_REG_INT2M, | ||
411 | PCF50633_INT2_ONKEYR, | ||
412 | PCF50633_INT2_ONKEYR); | ||
413 | } | ||
414 | |||
415 | /* Have we just resumed ? */ | ||
416 | if (pcf->is_suspended) { | ||
417 | pcf->is_suspended = 0; | ||
418 | |||
419 | /* Set the resume reason filtering out non resumers */ | ||
420 | for (i = 0; i < ARRAY_SIZE(pcf_int); i++) | ||
421 | pcf->resume_reason[i] = pcf_int[i] & | ||
422 | pcf->pdata->resumers[i]; | ||
423 | |||
424 | /* Make sure we don't pass on any ONKEY events to | ||
425 | * userspace now */ | ||
426 | pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF); | ||
427 | } | ||
428 | |||
429 | for (i = 0; i < ARRAY_SIZE(pcf_int); i++) { | ||
430 | /* Unset masked interrupts */ | ||
431 | pcf_int[i] &= ~pcf->mask_regs[i]; | ||
432 | |||
433 | for (j = 0; j < 8 ; j++) | ||
434 | if (pcf_int[i] & (1 << j)) | ||
435 | pcf50633_irq_call_handler(pcf, (i * 8) + j); | ||
436 | } | ||
437 | |||
438 | out: | ||
439 | put_device(pcf->dev); | ||
440 | enable_irq(pcf->irq); | ||
441 | } | ||
442 | |||
443 | static irqreturn_t pcf50633_irq(int irq, void *data) | ||
444 | { | ||
445 | struct pcf50633 *pcf = data; | ||
446 | |||
447 | dev_dbg(pcf->dev, "pcf50633_irq\n"); | ||
448 | |||
449 | get_device(pcf->dev); | ||
450 | disable_irq_nosync(pcf->irq); | ||
451 | queue_work(pcf->work_queue, &pcf->irq_work); | ||
452 | |||
453 | return IRQ_HANDLED; | ||
454 | } | ||
455 | |||
456 | static void | 218 | static void |
457 | pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, | 219 | pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, |
458 | struct platform_device **pdev) | 220 | struct platform_device **pdev) |
@@ -479,70 +241,17 @@ pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name, | |||
479 | static int pcf50633_suspend(struct i2c_client *client, pm_message_t state) | 241 | static int pcf50633_suspend(struct i2c_client *client, pm_message_t state) |
480 | { | 242 | { |
481 | struct pcf50633 *pcf; | 243 | struct pcf50633 *pcf; |
482 | int ret = 0, i; | ||
483 | u8 res[5]; | ||
484 | |||
485 | pcf = i2c_get_clientdata(client); | 244 | pcf = i2c_get_clientdata(client); |
486 | 245 | ||
487 | /* Make sure our interrupt handlers are not called | 246 | return pcf50633_irq_suspend(pcf); |
488 | * henceforth */ | ||
489 | disable_irq(pcf->irq); | ||
490 | |||
491 | /* Make sure that any running IRQ worker has quit */ | ||
492 | cancel_work_sync(&pcf->irq_work); | ||
493 | |||
494 | /* Save the masks */ | ||
495 | ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M, | ||
496 | ARRAY_SIZE(pcf->suspend_irq_masks), | ||
497 | pcf->suspend_irq_masks); | ||
498 | if (ret < 0) { | ||
499 | dev_err(pcf->dev, "error saving irq masks\n"); | ||
500 | goto out; | ||
501 | } | ||
502 | |||
503 | /* Write wakeup irq masks */ | ||
504 | for (i = 0; i < ARRAY_SIZE(res); i++) | ||
505 | res[i] = ~pcf->pdata->resumers[i]; | ||
506 | |||
507 | ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M, | ||
508 | ARRAY_SIZE(res), &res[0]); | ||
509 | if (ret < 0) { | ||
510 | dev_err(pcf->dev, "error writing wakeup irq masks\n"); | ||
511 | goto out; | ||
512 | } | ||
513 | |||
514 | pcf->is_suspended = 1; | ||
515 | |||
516 | out: | ||
517 | return ret; | ||
518 | } | 247 | } |
519 | 248 | ||
520 | static int pcf50633_resume(struct i2c_client *client) | 249 | static int pcf50633_resume(struct i2c_client *client) |
521 | { | 250 | { |
522 | struct pcf50633 *pcf; | 251 | struct pcf50633 *pcf; |
523 | int ret; | ||
524 | |||
525 | pcf = i2c_get_clientdata(client); | 252 | pcf = i2c_get_clientdata(client); |
526 | 253 | ||
527 | /* Write the saved mask registers */ | 254 | return pcf50633_irq_resume(pcf); |
528 | ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M, | ||
529 | ARRAY_SIZE(pcf->suspend_irq_masks), | ||
530 | pcf->suspend_irq_masks); | ||
531 | if (ret < 0) | ||
532 | dev_err(pcf->dev, "Error restoring saved suspend masks\n"); | ||
533 | |||
534 | /* Restore regulators' state */ | ||
535 | |||
536 | |||
537 | get_device(pcf->dev); | ||
538 | |||
539 | /* | ||
540 | * Clear any pending interrupts and set resume reason if any. | ||
541 | * This will leave with enable_irq() | ||
542 | */ | ||
543 | pcf50633_irq_worker(&pcf->irq_work); | ||
544 | |||
545 | return 0; | ||
546 | } | 255 | } |
547 | #else | 256 | #else |
548 | #define pcf50633_suspend NULL | 257 | #define pcf50633_suspend NULL |
@@ -573,43 +282,19 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
573 | i2c_set_clientdata(client, pcf); | 282 | i2c_set_clientdata(client, pcf); |
574 | pcf->dev = &client->dev; | 283 | pcf->dev = &client->dev; |
575 | pcf->i2c_client = client; | 284 | pcf->i2c_client = client; |
576 | pcf->irq = client->irq; | ||
577 | pcf->work_queue = create_singlethread_workqueue("pcf50633"); | ||
578 | |||
579 | if (!pcf->work_queue) { | ||
580 | dev_err(&client->dev, "Failed to alloc workqueue\n"); | ||
581 | ret = -ENOMEM; | ||
582 | goto err_free; | ||
583 | } | ||
584 | |||
585 | INIT_WORK(&pcf->irq_work, pcf50633_irq_worker); | ||
586 | 285 | ||
587 | version = pcf50633_reg_read(pcf, 0); | 286 | version = pcf50633_reg_read(pcf, 0); |
588 | variant = pcf50633_reg_read(pcf, 1); | 287 | variant = pcf50633_reg_read(pcf, 1); |
589 | if (version < 0 || variant < 0) { | 288 | if (version < 0 || variant < 0) { |
590 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); | 289 | dev_err(pcf->dev, "Unable to probe pcf50633\n"); |
591 | ret = -ENODEV; | 290 | ret = -ENODEV; |
592 | goto err_destroy_workqueue; | 291 | goto err_free; |
593 | } | 292 | } |
594 | 293 | ||
595 | dev_info(pcf->dev, "Probed device version %d variant %d\n", | 294 | dev_info(pcf->dev, "Probed device version %d variant %d\n", |
596 | version, variant); | 295 | version, variant); |
597 | 296 | ||
598 | /* Enable all interrupts except RTC SECOND */ | 297 | pcf50633_irq_init(pcf, client->irq); |
599 | pcf->mask_regs[0] = 0x80; | ||
600 | pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]); | ||
601 | pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00); | ||
602 | pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00); | ||
603 | pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00); | ||
604 | pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00); | ||
605 | |||
606 | ret = request_irq(client->irq, pcf50633_irq, | ||
607 | IRQF_TRIGGER_LOW, "pcf50633", pcf); | ||
608 | |||
609 | if (ret) { | ||
610 | dev_err(pcf->dev, "Failed to request IRQ %d\n", ret); | ||
611 | goto err_destroy_workqueue; | ||
612 | } | ||
613 | 298 | ||
614 | /* Create sub devices */ | 299 | /* Create sub devices */ |
615 | pcf50633_client_dev_register(pcf, "pcf50633-input", | 300 | pcf50633_client_dev_register(pcf, "pcf50633-input", |
@@ -620,6 +305,9 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
620 | &pcf->mbc_pdev); | 305 | &pcf->mbc_pdev); |
621 | pcf50633_client_dev_register(pcf, "pcf50633-adc", | 306 | pcf50633_client_dev_register(pcf, "pcf50633-adc", |
622 | &pcf->adc_pdev); | 307 | &pcf->adc_pdev); |
308 | pcf50633_client_dev_register(pcf, "pcf50633-backlight", | ||
309 | &pcf->bl_pdev); | ||
310 | |||
623 | 311 | ||
624 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { | 312 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) { |
625 | struct platform_device *pdev; | 313 | struct platform_device *pdev; |
@@ -638,10 +326,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
638 | platform_device_add(pdev); | 326 | platform_device_add(pdev); |
639 | } | 327 | } |
640 | 328 | ||
641 | if (enable_irq_wake(client->irq) < 0) | ||
642 | dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source" | ||
643 | "in this hardware revision", client->irq); | ||
644 | |||
645 | ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group); | 329 | ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group); |
646 | if (ret) | 330 | if (ret) |
647 | dev_err(pcf->dev, "error creating sysfs entries\n"); | 331 | dev_err(pcf->dev, "error creating sysfs entries\n"); |
@@ -651,8 +335,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client, | |||
651 | 335 | ||
652 | return 0; | 336 | return 0; |
653 | 337 | ||
654 | err_destroy_workqueue: | ||
655 | destroy_workqueue(pcf->work_queue); | ||
656 | err_free: | 338 | err_free: |
657 | i2c_set_clientdata(client, NULL); | 339 | i2c_set_clientdata(client, NULL); |
658 | kfree(pcf); | 340 | kfree(pcf); |
@@ -665,8 +347,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client) | |||
665 | struct pcf50633 *pcf = i2c_get_clientdata(client); | 347 | struct pcf50633 *pcf = i2c_get_clientdata(client); |
666 | int i; | 348 | int i; |
667 | 349 | ||
668 | free_irq(pcf->irq, pcf); | 350 | pcf50633_irq_free(pcf); |
669 | destroy_workqueue(pcf->work_queue); | ||
670 | 351 | ||
671 | platform_device_unregister(pcf->input_pdev); | 352 | platform_device_unregister(pcf->input_pdev); |
672 | platform_device_unregister(pcf->rtc_pdev); | 353 | platform_device_unregister(pcf->rtc_pdev); |
@@ -676,6 +357,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client) | |||
676 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) | 357 | for (i = 0; i < PCF50633_NUM_REGULATORS; i++) |
677 | platform_device_unregister(pcf->regulator_pdev[i]); | 358 | platform_device_unregister(pcf->regulator_pdev[i]); |
678 | 359 | ||
360 | i2c_set_clientdata(client, NULL); | ||
679 | kfree(pcf); | 361 | kfree(pcf); |
680 | 362 | ||
681 | return 0; | 363 | return 0; |
diff --git a/drivers/mfd/pcf50633-irq.c b/drivers/mfd/pcf50633-irq.c new file mode 100644 index 000000000000..1b0192f1efff --- /dev/null +++ b/drivers/mfd/pcf50633-irq.c | |||
@@ -0,0 +1,318 @@ | |||
1 | /* NXP PCF50633 Power Management Unit (PMU) driver | ||
2 | * | ||
3 | * (C) 2006-2008 by Openmoko, Inc. | ||
4 | * Author: Harald Welte <laforge@openmoko.org> | ||
5 | * Balaji Rao <balajirrao@openmoko.org> | ||
6 | * All rights reserved. | ||
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 | */ | ||
14 | |||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/mutex.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | #include <linux/mfd/pcf50633/core.h> | ||
21 | |||
22 | /* Two MBCS registers used during cold start */ | ||
23 | #define PCF50633_REG_MBCS1 0x4b | ||
24 | #define PCF50633_REG_MBCS2 0x4c | ||
25 | #define PCF50633_MBCS1_USBPRES 0x01 | ||
26 | #define PCF50633_MBCS1_ADAPTPRES 0x01 | ||
27 | |||
28 | int pcf50633_register_irq(struct pcf50633 *pcf, int irq, | ||
29 | void (*handler) (int, void *), void *data) | ||
30 | { | ||
31 | if (irq < 0 || irq >= PCF50633_NUM_IRQ || !handler) | ||
32 | return -EINVAL; | ||
33 | |||
34 | if (WARN_ON(pcf->irq_handler[irq].handler)) | ||
35 | return -EBUSY; | ||
36 | |||
37 | mutex_lock(&pcf->lock); | ||
38 | pcf->irq_handler[irq].handler = handler; | ||
39 | pcf->irq_handler[irq].data = data; | ||
40 | mutex_unlock(&pcf->lock); | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | EXPORT_SYMBOL_GPL(pcf50633_register_irq); | ||
45 | |||
46 | int pcf50633_free_irq(struct pcf50633 *pcf, int irq) | ||
47 | { | ||
48 | if (irq < 0 || irq >= PCF50633_NUM_IRQ) | ||
49 | return -EINVAL; | ||
50 | |||
51 | mutex_lock(&pcf->lock); | ||
52 | pcf->irq_handler[irq].handler = NULL; | ||
53 | mutex_unlock(&pcf->lock); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | EXPORT_SYMBOL_GPL(pcf50633_free_irq); | ||
58 | |||
59 | static int __pcf50633_irq_mask_set(struct pcf50633 *pcf, int irq, u8 mask) | ||
60 | { | ||
61 | u8 reg, bit; | ||
62 | int ret = 0, idx; | ||
63 | |||
64 | idx = irq >> 3; | ||
65 | reg = PCF50633_REG_INT1M + idx; | ||
66 | bit = 1 << (irq & 0x07); | ||
67 | |||
68 | pcf50633_reg_set_bit_mask(pcf, reg, bit, mask ? bit : 0); | ||
69 | |||
70 | mutex_lock(&pcf->lock); | ||
71 | |||
72 | if (mask) | ||
73 | pcf->mask_regs[idx] |= bit; | ||
74 | else | ||
75 | pcf->mask_regs[idx] &= ~bit; | ||
76 | |||
77 | mutex_unlock(&pcf->lock); | ||
78 | |||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | int pcf50633_irq_mask(struct pcf50633 *pcf, int irq) | ||
83 | { | ||
84 | dev_dbg(pcf->dev, "Masking IRQ %d\n", irq); | ||
85 | |||
86 | return __pcf50633_irq_mask_set(pcf, irq, 1); | ||
87 | } | ||
88 | EXPORT_SYMBOL_GPL(pcf50633_irq_mask); | ||
89 | |||
90 | int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq) | ||
91 | { | ||
92 | dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq); | ||
93 | |||
94 | return __pcf50633_irq_mask_set(pcf, irq, 0); | ||
95 | } | ||
96 | EXPORT_SYMBOL_GPL(pcf50633_irq_unmask); | ||
97 | |||
98 | int pcf50633_irq_mask_get(struct pcf50633 *pcf, int irq) | ||
99 | { | ||
100 | u8 reg, bits; | ||
101 | |||
102 | reg = irq >> 3; | ||
103 | bits = 1 << (irq & 0x07); | ||
104 | |||
105 | return pcf->mask_regs[reg] & bits; | ||
106 | } | ||
107 | EXPORT_SYMBOL_GPL(pcf50633_irq_mask_get); | ||
108 | |||
109 | static void pcf50633_irq_call_handler(struct pcf50633 *pcf, int irq) | ||
110 | { | ||
111 | if (pcf->irq_handler[irq].handler) | ||
112 | pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data); | ||
113 | } | ||
114 | |||
115 | /* Maximum amount of time ONKEY is held before emergency action is taken */ | ||
116 | #define PCF50633_ONKEY1S_TIMEOUT 8 | ||
117 | |||
118 | static irqreturn_t pcf50633_irq(int irq, void *data) | ||
119 | { | ||
120 | struct pcf50633 *pcf = data; | ||
121 | int ret, i, j; | ||
122 | u8 pcf_int[5], chgstat; | ||
123 | |||
124 | /* Read the 5 INT regs in one transaction */ | ||
125 | ret = pcf50633_read_block(pcf, PCF50633_REG_INT1, | ||
126 | ARRAY_SIZE(pcf_int), pcf_int); | ||
127 | if (ret != ARRAY_SIZE(pcf_int)) { | ||
128 | dev_err(pcf->dev, "Error reading INT registers\n"); | ||
129 | |||
130 | /* | ||
131 | * If this doesn't ACK the interrupt to the chip, we'll be | ||
132 | * called once again as we're level triggered. | ||
133 | */ | ||
134 | goto out; | ||
135 | } | ||
136 | |||
137 | /* defeat 8s death from lowsys on A5 */ | ||
138 | pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04); | ||
139 | |||
140 | /* We immediately read the usb and adapter status. We thus make sure | ||
141 | * only of USBINS/USBREM IRQ handlers are called */ | ||
142 | if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) { | ||
143 | chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); | ||
144 | if (chgstat & (0x3 << 4)) | ||
145 | pcf_int[0] &= ~PCF50633_INT1_USBREM; | ||
146 | else | ||
147 | pcf_int[0] &= ~PCF50633_INT1_USBINS; | ||
148 | } | ||
149 | |||
150 | /* Make sure only one of ADPINS or ADPREM is set */ | ||
151 | if (pcf_int[0] & (PCF50633_INT1_ADPINS | PCF50633_INT1_ADPREM)) { | ||
152 | chgstat = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2); | ||
153 | if (chgstat & (0x3 << 4)) | ||
154 | pcf_int[0] &= ~PCF50633_INT1_ADPREM; | ||
155 | else | ||
156 | pcf_int[0] &= ~PCF50633_INT1_ADPINS; | ||
157 | } | ||
158 | |||
159 | dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x " | ||
160 | "INT4=0x%02x INT5=0x%02x\n", pcf_int[0], | ||
161 | pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]); | ||
162 | |||
163 | /* Some revisions of the chip don't have a 8s standby mode on | ||
164 | * ONKEY1S press. We try to manually do it in such cases. */ | ||
165 | if ((pcf_int[0] & PCF50633_INT1_SECOND) && pcf->onkey1s_held) { | ||
166 | dev_info(pcf->dev, "ONKEY1S held for %d secs\n", | ||
167 | pcf->onkey1s_held); | ||
168 | if (pcf->onkey1s_held++ == PCF50633_ONKEY1S_TIMEOUT) | ||
169 | if (pcf->pdata->force_shutdown) | ||
170 | pcf->pdata->force_shutdown(pcf); | ||
171 | } | ||
172 | |||
173 | if (pcf_int[2] & PCF50633_INT3_ONKEY1S) { | ||
174 | dev_info(pcf->dev, "ONKEY1S held\n"); | ||
175 | pcf->onkey1s_held = 1 ; | ||
176 | |||
177 | /* Unmask IRQ_SECOND */ | ||
178 | pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT1M, | ||
179 | PCF50633_INT1_SECOND); | ||
180 | |||
181 | /* Unmask IRQ_ONKEYR */ | ||
182 | pcf50633_reg_clear_bits(pcf, PCF50633_REG_INT2M, | ||
183 | PCF50633_INT2_ONKEYR); | ||
184 | } | ||
185 | |||
186 | if ((pcf_int[1] & PCF50633_INT2_ONKEYR) && pcf->onkey1s_held) { | ||
187 | pcf->onkey1s_held = 0; | ||
188 | |||
189 | /* Mask SECOND and ONKEYR interrupts */ | ||
190 | if (pcf->mask_regs[0] & PCF50633_INT1_SECOND) | ||
191 | pcf50633_reg_set_bit_mask(pcf, | ||
192 | PCF50633_REG_INT1M, | ||
193 | PCF50633_INT1_SECOND, | ||
194 | PCF50633_INT1_SECOND); | ||
195 | |||
196 | if (pcf->mask_regs[1] & PCF50633_INT2_ONKEYR) | ||
197 | pcf50633_reg_set_bit_mask(pcf, | ||
198 | PCF50633_REG_INT2M, | ||
199 | PCF50633_INT2_ONKEYR, | ||
200 | PCF50633_INT2_ONKEYR); | ||
201 | } | ||
202 | |||
203 | /* Have we just resumed ? */ | ||
204 | if (pcf->is_suspended) { | ||
205 | pcf->is_suspended = 0; | ||
206 | |||
207 | /* Set the resume reason filtering out non resumers */ | ||
208 | for (i = 0; i < ARRAY_SIZE(pcf_int); i++) | ||
209 | pcf->resume_reason[i] = pcf_int[i] & | ||
210 | pcf->pdata->resumers[i]; | ||
211 | |||
212 | /* Make sure we don't pass on any ONKEY events to | ||
213 | * userspace now */ | ||
214 | pcf_int[1] &= ~(PCF50633_INT2_ONKEYR | PCF50633_INT2_ONKEYF); | ||
215 | } | ||
216 | |||
217 | for (i = 0; i < ARRAY_SIZE(pcf_int); i++) { | ||
218 | /* Unset masked interrupts */ | ||
219 | pcf_int[i] &= ~pcf->mask_regs[i]; | ||
220 | |||
221 | for (j = 0; j < 8 ; j++) | ||
222 | if (pcf_int[i] & (1 << j)) | ||
223 | pcf50633_irq_call_handler(pcf, (i * 8) + j); | ||
224 | } | ||
225 | |||
226 | out: | ||
227 | return IRQ_HANDLED; | ||
228 | } | ||
229 | |||
230 | #ifdef CONFIG_PM | ||
231 | |||
232 | int pcf50633_irq_suspend(struct pcf50633 *pcf) | ||
233 | { | ||
234 | int ret; | ||
235 | int i; | ||
236 | u8 res[5]; | ||
237 | |||
238 | |||
239 | /* Make sure our interrupt handlers are not called | ||
240 | * henceforth */ | ||
241 | disable_irq(pcf->irq); | ||
242 | |||
243 | /* Save the masks */ | ||
244 | ret = pcf50633_read_block(pcf, PCF50633_REG_INT1M, | ||
245 | ARRAY_SIZE(pcf->suspend_irq_masks), | ||
246 | pcf->suspend_irq_masks); | ||
247 | if (ret < 0) { | ||
248 | dev_err(pcf->dev, "error saving irq masks\n"); | ||
249 | goto out; | ||
250 | } | ||
251 | |||
252 | /* Write wakeup irq masks */ | ||
253 | for (i = 0; i < ARRAY_SIZE(res); i++) | ||
254 | res[i] = ~pcf->pdata->resumers[i]; | ||
255 | |||
256 | ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M, | ||
257 | ARRAY_SIZE(res), &res[0]); | ||
258 | if (ret < 0) { | ||
259 | dev_err(pcf->dev, "error writing wakeup irq masks\n"); | ||
260 | goto out; | ||
261 | } | ||
262 | |||
263 | pcf->is_suspended = 1; | ||
264 | |||
265 | out: | ||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | int pcf50633_irq_resume(struct pcf50633 *pcf) | ||
270 | { | ||
271 | int ret; | ||
272 | |||
273 | /* Write the saved mask registers */ | ||
274 | ret = pcf50633_write_block(pcf, PCF50633_REG_INT1M, | ||
275 | ARRAY_SIZE(pcf->suspend_irq_masks), | ||
276 | pcf->suspend_irq_masks); | ||
277 | if (ret < 0) | ||
278 | dev_err(pcf->dev, "Error restoring saved suspend masks\n"); | ||
279 | |||
280 | enable_irq(pcf->irq); | ||
281 | |||
282 | return ret; | ||
283 | } | ||
284 | |||
285 | #endif | ||
286 | |||
287 | int pcf50633_irq_init(struct pcf50633 *pcf, int irq) | ||
288 | { | ||
289 | int ret; | ||
290 | |||
291 | pcf->irq = irq; | ||
292 | |||
293 | /* Enable all interrupts except RTC SECOND */ | ||
294 | pcf->mask_regs[0] = 0x80; | ||
295 | pcf50633_reg_write(pcf, PCF50633_REG_INT1M, pcf->mask_regs[0]); | ||
296 | pcf50633_reg_write(pcf, PCF50633_REG_INT2M, 0x00); | ||
297 | pcf50633_reg_write(pcf, PCF50633_REG_INT3M, 0x00); | ||
298 | pcf50633_reg_write(pcf, PCF50633_REG_INT4M, 0x00); | ||
299 | pcf50633_reg_write(pcf, PCF50633_REG_INT5M, 0x00); | ||
300 | |||
301 | ret = request_threaded_irq(irq, NULL, pcf50633_irq, | ||
302 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
303 | "pcf50633", pcf); | ||
304 | |||
305 | if (ret) | ||
306 | dev_err(pcf->dev, "Failed to request IRQ %d\n", ret); | ||
307 | |||
308 | if (enable_irq_wake(irq) < 0) | ||
309 | dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source" | ||
310 | "in this hardware revision", irq); | ||
311 | |||
312 | return ret; | ||
313 | } | ||
314 | |||
315 | void pcf50633_irq_free(struct pcf50633 *pcf) | ||
316 | { | ||
317 | free_irq(pcf->irq, pcf); | ||
318 | } | ||
diff --git a/drivers/mfd/rdc321x-southbridge.c b/drivers/mfd/rdc321x-southbridge.c new file mode 100644 index 000000000000..50922975bda3 --- /dev/null +++ b/drivers/mfd/rdc321x-southbridge.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * RDC321x MFD southbrige driver | ||
3 | * | ||
4 | * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org> | ||
5 | * Copyright (C) 2010 Bernhard Loos <bernhardloos@googlemail.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, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
20 | * | ||
21 | */ | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/pci.h> | ||
27 | #include <linux/mfd/core.h> | ||
28 | #include <linux/mfd/rdc321x.h> | ||
29 | |||
30 | static struct rdc321x_wdt_pdata rdc321x_wdt_pdata; | ||
31 | |||
32 | static struct resource rdc321x_wdt_resource[] = { | ||
33 | { | ||
34 | .name = "wdt-reg", | ||
35 | .start = RDC321X_WDT_CTRL, | ||
36 | .end = RDC321X_WDT_CTRL + 0x3, | ||
37 | .flags = IORESOURCE_IO, | ||
38 | } | ||
39 | }; | ||
40 | |||
41 | static struct rdc321x_gpio_pdata rdc321x_gpio_pdata = { | ||
42 | .max_gpios = RDC321X_MAX_GPIO, | ||
43 | }; | ||
44 | |||
45 | static struct resource rdc321x_gpio_resources[] = { | ||
46 | { | ||
47 | .name = "gpio-reg1", | ||
48 | .start = RDC321X_GPIO_CTRL_REG1, | ||
49 | .end = RDC321X_GPIO_CTRL_REG1 + 0x7, | ||
50 | .flags = IORESOURCE_IO, | ||
51 | }, { | ||
52 | .name = "gpio-reg2", | ||
53 | .start = RDC321X_GPIO_CTRL_REG2, | ||
54 | .end = RDC321X_GPIO_CTRL_REG2 + 0x7, | ||
55 | .flags = IORESOURCE_IO, | ||
56 | } | ||
57 | }; | ||
58 | |||
59 | static struct mfd_cell rdc321x_sb_cells[] = { | ||
60 | { | ||
61 | .name = "rdc321x-wdt", | ||
62 | .resources = rdc321x_wdt_resource, | ||
63 | .num_resources = ARRAY_SIZE(rdc321x_wdt_resource), | ||
64 | .driver_data = &rdc321x_wdt_pdata, | ||
65 | }, { | ||
66 | .name = "rdc321x-gpio", | ||
67 | .resources = rdc321x_gpio_resources, | ||
68 | .num_resources = ARRAY_SIZE(rdc321x_gpio_resources), | ||
69 | .driver_data = &rdc321x_gpio_pdata, | ||
70 | }, | ||
71 | }; | ||
72 | |||
73 | static int __devinit rdc321x_sb_probe(struct pci_dev *pdev, | ||
74 | const struct pci_device_id *ent) | ||
75 | { | ||
76 | int err; | ||
77 | |||
78 | err = pci_enable_device(pdev); | ||
79 | if (err) { | ||
80 | dev_err(&pdev->dev, "failed to enable device\n"); | ||
81 | return err; | ||
82 | } | ||
83 | |||
84 | rdc321x_gpio_pdata.sb_pdev = pdev; | ||
85 | rdc321x_wdt_pdata.sb_pdev = pdev; | ||
86 | |||
87 | return mfd_add_devices(&pdev->dev, -1, | ||
88 | rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0); | ||
89 | } | ||
90 | |||
91 | static void __devexit rdc321x_sb_remove(struct pci_dev *pdev) | ||
92 | { | ||
93 | mfd_remove_devices(&pdev->dev); | ||
94 | } | ||
95 | |||
96 | static DEFINE_PCI_DEVICE_TABLE(rdc321x_sb_table) = { | ||
97 | { PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) }, | ||
98 | {} | ||
99 | }; | ||
100 | |||
101 | static struct pci_driver rdc321x_sb_driver = { | ||
102 | .name = "RDC321x Southbridge", | ||
103 | .id_table = rdc321x_sb_table, | ||
104 | .probe = rdc321x_sb_probe, | ||
105 | .remove = __devexit_p(rdc321x_sb_remove), | ||
106 | }; | ||
107 | |||
108 | static int __init rdc321x_sb_init(void) | ||
109 | { | ||
110 | return pci_register_driver(&rdc321x_sb_driver); | ||
111 | } | ||
112 | |||
113 | static void __exit rdc321x_sb_exit(void) | ||
114 | { | ||
115 | pci_unregister_driver(&rdc321x_sb_driver); | ||
116 | } | ||
117 | |||
118 | module_init(rdc321x_sb_init); | ||
119 | module_exit(rdc321x_sb_exit); | ||
120 | |||
121 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | ||
122 | MODULE_LICENSE("GPL"); | ||
123 | MODULE_DESCRIPTION("RDC R-321x MFD southbridge driver"); | ||
diff --git a/drivers/mfd/t7l66xb.c b/drivers/mfd/t7l66xb.c index da6383a934ac..5041d33adf0b 100644 --- a/drivers/mfd/t7l66xb.c +++ b/drivers/mfd/t7l66xb.c | |||
@@ -318,6 +318,9 @@ static int t7l66xb_probe(struct platform_device *dev) | |||
318 | struct resource *iomem, *rscr; | 318 | struct resource *iomem, *rscr; |
319 | int ret; | 319 | int ret; |
320 | 320 | ||
321 | if (pdata == NULL) | ||
322 | return -EINVAL; | ||
323 | |||
321 | iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); | 324 | iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); |
322 | if (!iomem) | 325 | if (!iomem) |
323 | return -EINVAL; | 326 | return -EINVAL; |
diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c new file mode 100644 index 000000000000..715f095dd7a6 --- /dev/null +++ b/drivers/mfd/tc35892.c | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson SA 2010 | ||
3 | * | ||
4 | * License Terms: GNU General Public License, version 2 | ||
5 | * Author: Hanumath Prasad <hanumath.prasad@stericsson.com> for ST-Ericsson | ||
6 | * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/interrupt.h> | ||
11 | #include <linux/irq.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/mfd/core.h> | ||
15 | #include <linux/mfd/tc35892.h> | ||
16 | |||
17 | /** | ||
18 | * tc35892_reg_read() - read a single TC35892 register | ||
19 | * @tc35892: Device to read from | ||
20 | * @reg: Register to read | ||
21 | */ | ||
22 | int tc35892_reg_read(struct tc35892 *tc35892, u8 reg) | ||
23 | { | ||
24 | int ret; | ||
25 | |||
26 | ret = i2c_smbus_read_byte_data(tc35892->i2c, reg); | ||
27 | if (ret < 0) | ||
28 | dev_err(tc35892->dev, "failed to read reg %#x: %d\n", | ||
29 | reg, ret); | ||
30 | |||
31 | return ret; | ||
32 | } | ||
33 | EXPORT_SYMBOL_GPL(tc35892_reg_read); | ||
34 | |||
35 | /** | ||
36 | * tc35892_reg_read() - write a single TC35892 register | ||
37 | * @tc35892: Device to write to | ||
38 | * @reg: Register to read | ||
39 | * @data: Value to write | ||
40 | */ | ||
41 | int tc35892_reg_write(struct tc35892 *tc35892, u8 reg, u8 data) | ||
42 | { | ||
43 | int ret; | ||
44 | |||
45 | ret = i2c_smbus_write_byte_data(tc35892->i2c, reg, data); | ||
46 | if (ret < 0) | ||
47 | dev_err(tc35892->dev, "failed to write reg %#x: %d\n", | ||
48 | reg, ret); | ||
49 | |||
50 | return ret; | ||
51 | } | ||
52 | EXPORT_SYMBOL_GPL(tc35892_reg_write); | ||
53 | |||
54 | /** | ||
55 | * tc35892_block_read() - read multiple TC35892 registers | ||
56 | * @tc35892: Device to read from | ||
57 | * @reg: First register | ||
58 | * @length: Number of registers | ||
59 | * @values: Buffer to write to | ||
60 | */ | ||
61 | int tc35892_block_read(struct tc35892 *tc35892, u8 reg, u8 length, u8 *values) | ||
62 | { | ||
63 | int ret; | ||
64 | |||
65 | ret = i2c_smbus_read_i2c_block_data(tc35892->i2c, reg, length, values); | ||
66 | if (ret < 0) | ||
67 | dev_err(tc35892->dev, "failed to read regs %#x: %d\n", | ||
68 | reg, ret); | ||
69 | |||
70 | return ret; | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(tc35892_block_read); | ||
73 | |||
74 | /** | ||
75 | * tc35892_block_write() - write multiple TC35892 registers | ||
76 | * @tc35892: Device to write to | ||
77 | * @reg: First register | ||
78 | * @length: Number of registers | ||
79 | * @values: Values to write | ||
80 | */ | ||
81 | int tc35892_block_write(struct tc35892 *tc35892, u8 reg, u8 length, | ||
82 | const u8 *values) | ||
83 | { | ||
84 | int ret; | ||
85 | |||
86 | ret = i2c_smbus_write_i2c_block_data(tc35892->i2c, reg, length, | ||
87 | values); | ||
88 | if (ret < 0) | ||
89 | dev_err(tc35892->dev, "failed to write regs %#x: %d\n", | ||
90 | reg, ret); | ||
91 | |||
92 | return ret; | ||
93 | } | ||
94 | EXPORT_SYMBOL_GPL(tc35892_block_write); | ||
95 | |||
96 | /** | ||
97 | * tc35892_set_bits() - set the value of a bitfield in a TC35892 register | ||
98 | * @tc35892: Device to write to | ||
99 | * @reg: Register to write | ||
100 | * @mask: Mask of bits to set | ||
101 | * @values: Value to set | ||
102 | */ | ||
103 | int tc35892_set_bits(struct tc35892 *tc35892, u8 reg, u8 mask, u8 val) | ||
104 | { | ||
105 | int ret; | ||
106 | |||
107 | mutex_lock(&tc35892->lock); | ||
108 | |||
109 | ret = tc35892_reg_read(tc35892, reg); | ||
110 | if (ret < 0) | ||
111 | goto out; | ||
112 | |||
113 | ret &= ~mask; | ||
114 | ret |= val; | ||
115 | |||
116 | ret = tc35892_reg_write(tc35892, reg, ret); | ||
117 | |||
118 | out: | ||
119 | mutex_unlock(&tc35892->lock); | ||
120 | return ret; | ||
121 | } | ||
122 | EXPORT_SYMBOL_GPL(tc35892_set_bits); | ||
123 | |||
124 | static struct resource gpio_resources[] = { | ||
125 | { | ||
126 | .start = TC35892_INT_GPIIRQ, | ||
127 | .end = TC35892_INT_GPIIRQ, | ||
128 | .flags = IORESOURCE_IRQ, | ||
129 | }, | ||
130 | }; | ||
131 | |||
132 | static struct mfd_cell tc35892_devs[] = { | ||
133 | { | ||
134 | .name = "tc35892-gpio", | ||
135 | .num_resources = ARRAY_SIZE(gpio_resources), | ||
136 | .resources = &gpio_resources[0], | ||
137 | }, | ||
138 | }; | ||
139 | |||
140 | static irqreturn_t tc35892_irq(int irq, void *data) | ||
141 | { | ||
142 | struct tc35892 *tc35892 = data; | ||
143 | int status; | ||
144 | |||
145 | status = tc35892_reg_read(tc35892, TC35892_IRQST); | ||
146 | if (status < 0) | ||
147 | return IRQ_NONE; | ||
148 | |||
149 | while (status) { | ||
150 | int bit = __ffs(status); | ||
151 | |||
152 | handle_nested_irq(tc35892->irq_base + bit); | ||
153 | status &= ~(1 << bit); | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * A dummy read or write (to any register) appears to be necessary to | ||
158 | * have the last interrupt clear (for example, GPIO IC write) take | ||
159 | * effect. | ||
160 | */ | ||
161 | tc35892_reg_read(tc35892, TC35892_IRQST); | ||
162 | |||
163 | return IRQ_HANDLED; | ||
164 | } | ||
165 | |||
166 | static void tc35892_irq_dummy(unsigned int irq) | ||
167 | { | ||
168 | /* No mask/unmask at this level */ | ||
169 | } | ||
170 | |||
171 | static struct irq_chip tc35892_irq_chip = { | ||
172 | .name = "tc35892", | ||
173 | .mask = tc35892_irq_dummy, | ||
174 | .unmask = tc35892_irq_dummy, | ||
175 | }; | ||
176 | |||
177 | static int tc35892_irq_init(struct tc35892 *tc35892) | ||
178 | { | ||
179 | int base = tc35892->irq_base; | ||
180 | int irq; | ||
181 | |||
182 | for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { | ||
183 | set_irq_chip_data(irq, tc35892); | ||
184 | set_irq_chip_and_handler(irq, &tc35892_irq_chip, | ||
185 | handle_edge_irq); | ||
186 | set_irq_nested_thread(irq, 1); | ||
187 | #ifdef CONFIG_ARM | ||
188 | set_irq_flags(irq, IRQF_VALID); | ||
189 | #else | ||
190 | set_irq_noprobe(irq); | ||
191 | #endif | ||
192 | } | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static void tc35892_irq_remove(struct tc35892 *tc35892) | ||
198 | { | ||
199 | int base = tc35892->irq_base; | ||
200 | int irq; | ||
201 | |||
202 | for (irq = base; irq < base + TC35892_NR_INTERNAL_IRQS; irq++) { | ||
203 | #ifdef CONFIG_ARM | ||
204 | set_irq_flags(irq, 0); | ||
205 | #endif | ||
206 | set_irq_chip_and_handler(irq, NULL, NULL); | ||
207 | set_irq_chip_data(irq, NULL); | ||
208 | } | ||
209 | } | ||
210 | |||
211 | static int tc35892_chip_init(struct tc35892 *tc35892) | ||
212 | { | ||
213 | int manf, ver, ret; | ||
214 | |||
215 | manf = tc35892_reg_read(tc35892, TC35892_MANFCODE); | ||
216 | if (manf < 0) | ||
217 | return manf; | ||
218 | |||
219 | ver = tc35892_reg_read(tc35892, TC35892_VERSION); | ||
220 | if (ver < 0) | ||
221 | return ver; | ||
222 | |||
223 | if (manf != TC35892_MANFCODE_MAGIC) { | ||
224 | dev_err(tc35892->dev, "unknown manufacturer: %#x\n", manf); | ||
225 | return -EINVAL; | ||
226 | } | ||
227 | |||
228 | dev_info(tc35892->dev, "manufacturer: %#x, version: %#x\n", manf, ver); | ||
229 | |||
230 | /* Put everything except the IRQ module into reset */ | ||
231 | ret = tc35892_reg_write(tc35892, TC35892_RSTCTRL, | ||
232 | TC35892_RSTCTRL_TIMRST | ||
233 | | TC35892_RSTCTRL_ROTRST | ||
234 | | TC35892_RSTCTRL_KBDRST | ||
235 | | TC35892_RSTCTRL_GPIRST); | ||
236 | if (ret < 0) | ||
237 | return ret; | ||
238 | |||
239 | /* Clear the reset interrupt. */ | ||
240 | return tc35892_reg_write(tc35892, TC35892_RSTINTCLR, 0x1); | ||
241 | } | ||
242 | |||
243 | static int __devinit tc35892_probe(struct i2c_client *i2c, | ||
244 | const struct i2c_device_id *id) | ||
245 | { | ||
246 | struct tc35892_platform_data *pdata = i2c->dev.platform_data; | ||
247 | struct tc35892 *tc35892; | ||
248 | int ret; | ||
249 | |||
250 | if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA | ||
251 | | I2C_FUNC_SMBUS_I2C_BLOCK)) | ||
252 | return -EIO; | ||
253 | |||
254 | tc35892 = kzalloc(sizeof(struct tc35892), GFP_KERNEL); | ||
255 | if (!tc35892) | ||
256 | return -ENOMEM; | ||
257 | |||
258 | mutex_init(&tc35892->lock); | ||
259 | |||
260 | tc35892->dev = &i2c->dev; | ||
261 | tc35892->i2c = i2c; | ||
262 | tc35892->pdata = pdata; | ||
263 | tc35892->irq_base = pdata->irq_base; | ||
264 | tc35892->num_gpio = id->driver_data; | ||
265 | |||
266 | i2c_set_clientdata(i2c, tc35892); | ||
267 | |||
268 | ret = tc35892_chip_init(tc35892); | ||
269 | if (ret) | ||
270 | goto out_free; | ||
271 | |||
272 | ret = tc35892_irq_init(tc35892); | ||
273 | if (ret) | ||
274 | goto out_free; | ||
275 | |||
276 | ret = request_threaded_irq(tc35892->i2c->irq, NULL, tc35892_irq, | ||
277 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
278 | "tc35892", tc35892); | ||
279 | if (ret) { | ||
280 | dev_err(tc35892->dev, "failed to request IRQ: %d\n", ret); | ||
281 | goto out_removeirq; | ||
282 | } | ||
283 | |||
284 | ret = mfd_add_devices(tc35892->dev, -1, tc35892_devs, | ||
285 | ARRAY_SIZE(tc35892_devs), NULL, | ||
286 | tc35892->irq_base); | ||
287 | if (ret) { | ||
288 | dev_err(tc35892->dev, "failed to add children\n"); | ||
289 | goto out_freeirq; | ||
290 | } | ||
291 | |||
292 | return 0; | ||
293 | |||
294 | out_freeirq: | ||
295 | free_irq(tc35892->i2c->irq, tc35892); | ||
296 | out_removeirq: | ||
297 | tc35892_irq_remove(tc35892); | ||
298 | out_free: | ||
299 | i2c_set_clientdata(i2c, NULL); | ||
300 | kfree(tc35892); | ||
301 | return ret; | ||
302 | } | ||
303 | |||
304 | static int __devexit tc35892_remove(struct i2c_client *client) | ||
305 | { | ||
306 | struct tc35892 *tc35892 = i2c_get_clientdata(client); | ||
307 | |||
308 | mfd_remove_devices(tc35892->dev); | ||
309 | |||
310 | free_irq(tc35892->i2c->irq, tc35892); | ||
311 | tc35892_irq_remove(tc35892); | ||
312 | |||
313 | i2c_set_clientdata(client, NULL); | ||
314 | kfree(tc35892); | ||
315 | |||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | static const struct i2c_device_id tc35892_id[] = { | ||
320 | { "tc35892", 24 }, | ||
321 | { } | ||
322 | }; | ||
323 | MODULE_DEVICE_TABLE(i2c, tc35892_id); | ||
324 | |||
325 | static struct i2c_driver tc35892_driver = { | ||
326 | .driver.name = "tc35892", | ||
327 | .driver.owner = THIS_MODULE, | ||
328 | .probe = tc35892_probe, | ||
329 | .remove = __devexit_p(tc35892_remove), | ||
330 | .id_table = tc35892_id, | ||
331 | }; | ||
332 | |||
333 | static int __init tc35892_init(void) | ||
334 | { | ||
335 | return i2c_add_driver(&tc35892_driver); | ||
336 | } | ||
337 | subsys_initcall(tc35892_init); | ||
338 | |||
339 | static void __exit tc35892_exit(void) | ||
340 | { | ||
341 | i2c_del_driver(&tc35892_driver); | ||
342 | } | ||
343 | module_exit(tc35892_exit); | ||
344 | |||
345 | MODULE_LICENSE("GPL v2"); | ||
346 | MODULE_DESCRIPTION("TC35892 MFD core driver"); | ||
347 | MODULE_AUTHOR("Hanumath Prasad, Rabin Vincent"); | ||
diff --git a/drivers/mfd/timberdale.c b/drivers/mfd/timberdale.c index 7f478ec4184b..ac5995026c88 100644 --- a/drivers/mfd/timberdale.c +++ b/drivers/mfd/timberdale.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/i2c-ocores.h> | 33 | #include <linux/i2c-ocores.h> |
34 | #include <linux/i2c-xiic.h> | ||
34 | #include <linux/i2c/tsc2007.h> | 35 | #include <linux/i2c/tsc2007.h> |
35 | 36 | ||
36 | #include <linux/spi/spi.h> | 37 | #include <linux/spi/spi.h> |
@@ -40,6 +41,8 @@ | |||
40 | 41 | ||
41 | #include <media/timb_radio.h> | 42 | #include <media/timb_radio.h> |
42 | 43 | ||
44 | #include <linux/timb_dma.h> | ||
45 | |||
43 | #include "timberdale.h" | 46 | #include "timberdale.h" |
44 | 47 | ||
45 | #define DRIVER_NAME "timberdale" | 48 | #define DRIVER_NAME "timberdale" |
@@ -69,6 +72,12 @@ static struct i2c_board_info timberdale_i2c_board_info[] = { | |||
69 | }, | 72 | }, |
70 | }; | 73 | }; |
71 | 74 | ||
75 | static __devinitdata struct xiic_i2c_platform_data | ||
76 | timberdale_xiic_platform_data = { | ||
77 | .devices = timberdale_i2c_board_info, | ||
78 | .num_devices = ARRAY_SIZE(timberdale_i2c_board_info) | ||
79 | }; | ||
80 | |||
72 | static __devinitdata struct ocores_i2c_platform_data | 81 | static __devinitdata struct ocores_i2c_platform_data |
73 | timberdale_ocores_platform_data = { | 82 | timberdale_ocores_platform_data = { |
74 | .regstep = 4, | 83 | .regstep = 4, |
@@ -77,7 +86,20 @@ timberdale_ocores_platform_data = { | |||
77 | .num_devices = ARRAY_SIZE(timberdale_i2c_board_info) | 86 | .num_devices = ARRAY_SIZE(timberdale_i2c_board_info) |
78 | }; | 87 | }; |
79 | 88 | ||
80 | const static __devinitconst struct resource timberdale_ocores_resources[] = { | 89 | static const __devinitconst struct resource timberdale_xiic_resources[] = { |
90 | { | ||
91 | .start = XIICOFFSET, | ||
92 | .end = XIICEND, | ||
93 | .flags = IORESOURCE_MEM, | ||
94 | }, | ||
95 | { | ||
96 | .start = IRQ_TIMBERDALE_I2C, | ||
97 | .end = IRQ_TIMBERDALE_I2C, | ||
98 | .flags = IORESOURCE_IRQ, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | static const __devinitconst struct resource timberdale_ocores_resources[] = { | ||
81 | { | 103 | { |
82 | .start = OCORESOFFSET, | 104 | .start = OCORESOFFSET, |
83 | .end = OCORESEND, | 105 | .end = OCORESEND, |
@@ -126,7 +148,7 @@ static __devinitdata struct xspi_platform_data timberdale_xspi_platform_data = { | |||
126 | */ | 148 | */ |
127 | }; | 149 | }; |
128 | 150 | ||
129 | const static __devinitconst struct resource timberdale_spi_resources[] = { | 151 | static const __devinitconst struct resource timberdale_spi_resources[] = { |
130 | { | 152 | { |
131 | .start = SPIOFFSET, | 153 | .start = SPIOFFSET, |
132 | .end = SPIEND, | 154 | .end = SPIEND, |
@@ -139,7 +161,7 @@ const static __devinitconst struct resource timberdale_spi_resources[] = { | |||
139 | }, | 161 | }, |
140 | }; | 162 | }; |
141 | 163 | ||
142 | const static __devinitconst struct resource timberdale_eth_resources[] = { | 164 | static const __devinitconst struct resource timberdale_eth_resources[] = { |
143 | { | 165 | { |
144 | .start = ETHOFFSET, | 166 | .start = ETHOFFSET, |
145 | .end = ETHEND, | 167 | .end = ETHEND, |
@@ -159,7 +181,7 @@ static __devinitdata struct timbgpio_platform_data | |||
159 | .irq_base = 200, | 181 | .irq_base = 200, |
160 | }; | 182 | }; |
161 | 183 | ||
162 | const static __devinitconst struct resource timberdale_gpio_resources[] = { | 184 | static const __devinitconst struct resource timberdale_gpio_resources[] = { |
163 | { | 185 | { |
164 | .start = GPIOOFFSET, | 186 | .start = GPIOOFFSET, |
165 | .end = GPIOEND, | 187 | .end = GPIOEND, |
@@ -172,7 +194,7 @@ const static __devinitconst struct resource timberdale_gpio_resources[] = { | |||
172 | }, | 194 | }, |
173 | }; | 195 | }; |
174 | 196 | ||
175 | const static __devinitconst struct resource timberdale_mlogicore_resources[] = { | 197 | static const __devinitconst struct resource timberdale_mlogicore_resources[] = { |
176 | { | 198 | { |
177 | .start = MLCOREOFFSET, | 199 | .start = MLCOREOFFSET, |
178 | .end = MLCOREEND, | 200 | .end = MLCOREEND, |
@@ -190,7 +212,7 @@ const static __devinitconst struct resource timberdale_mlogicore_resources[] = { | |||
190 | }, | 212 | }, |
191 | }; | 213 | }; |
192 | 214 | ||
193 | const static __devinitconst struct resource timberdale_uart_resources[] = { | 215 | static const __devinitconst struct resource timberdale_uart_resources[] = { |
194 | { | 216 | { |
195 | .start = UARTOFFSET, | 217 | .start = UARTOFFSET, |
196 | .end = UARTEND, | 218 | .end = UARTEND, |
@@ -203,7 +225,7 @@ const static __devinitconst struct resource timberdale_uart_resources[] = { | |||
203 | }, | 225 | }, |
204 | }; | 226 | }; |
205 | 227 | ||
206 | const static __devinitconst struct resource timberdale_uartlite_resources[] = { | 228 | static const __devinitconst struct resource timberdale_uartlite_resources[] = { |
207 | { | 229 | { |
208 | .start = UARTLITEOFFSET, | 230 | .start = UARTLITEOFFSET, |
209 | .end = UARTLITEEND, | 231 | .end = UARTLITEEND, |
@@ -216,7 +238,7 @@ const static __devinitconst struct resource timberdale_uartlite_resources[] = { | |||
216 | }, | 238 | }, |
217 | }; | 239 | }; |
218 | 240 | ||
219 | const static __devinitconst struct resource timberdale_radio_resources[] = { | 241 | static const __devinitconst struct resource timberdale_radio_resources[] = { |
220 | { | 242 | { |
221 | .start = RDSOFFSET, | 243 | .start = RDSOFFSET, |
222 | .end = RDSEND, | 244 | .end = RDSEND, |
@@ -250,7 +272,66 @@ static __devinitdata struct timb_radio_platform_data | |||
250 | } | 272 | } |
251 | }; | 273 | }; |
252 | 274 | ||
253 | const static __devinitconst struct resource timberdale_dma_resources[] = { | 275 | static __devinitdata struct timb_dma_platform_data timb_dma_platform_data = { |
276 | .nr_channels = 10, | ||
277 | .channels = { | ||
278 | { | ||
279 | /* UART RX */ | ||
280 | .rx = true, | ||
281 | .descriptors = 2, | ||
282 | .descriptor_elements = 1 | ||
283 | }, | ||
284 | { | ||
285 | /* UART TX */ | ||
286 | .rx = false, | ||
287 | .descriptors = 2, | ||
288 | .descriptor_elements = 1 | ||
289 | }, | ||
290 | { | ||
291 | /* MLB RX */ | ||
292 | .rx = true, | ||
293 | .descriptors = 2, | ||
294 | .descriptor_elements = 1 | ||
295 | }, | ||
296 | { | ||
297 | /* MLB TX */ | ||
298 | .rx = false, | ||
299 | .descriptors = 2, | ||
300 | .descriptor_elements = 1 | ||
301 | }, | ||
302 | { | ||
303 | /* Video RX */ | ||
304 | .rx = true, | ||
305 | .bytes_per_line = 1440, | ||
306 | .descriptors = 2, | ||
307 | .descriptor_elements = 16 | ||
308 | }, | ||
309 | { | ||
310 | /* Video framedrop */ | ||
311 | }, | ||
312 | { | ||
313 | /* SDHCI RX */ | ||
314 | .rx = true, | ||
315 | }, | ||
316 | { | ||
317 | /* SDHCI TX */ | ||
318 | }, | ||
319 | { | ||
320 | /* ETH RX */ | ||
321 | .rx = true, | ||
322 | .descriptors = 2, | ||
323 | .descriptor_elements = 1 | ||
324 | }, | ||
325 | { | ||
326 | /* ETH TX */ | ||
327 | .rx = false, | ||
328 | .descriptors = 2, | ||
329 | .descriptor_elements = 1 | ||
330 | }, | ||
331 | } | ||
332 | }; | ||
333 | |||
334 | static const __devinitconst struct resource timberdale_dma_resources[] = { | ||
254 | { | 335 | { |
255 | .start = DMAOFFSET, | 336 | .start = DMAOFFSET, |
256 | .end = DMAEND, | 337 | .end = DMAEND, |
@@ -265,11 +346,25 @@ const static __devinitconst struct resource timberdale_dma_resources[] = { | |||
265 | 346 | ||
266 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { | 347 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { |
267 | { | 348 | { |
349 | .name = "timb-dma", | ||
350 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | ||
351 | .resources = timberdale_dma_resources, | ||
352 | .platform_data = &timb_dma_platform_data, | ||
353 | .data_size = sizeof(timb_dma_platform_data), | ||
354 | }, | ||
355 | { | ||
268 | .name = "timb-uart", | 356 | .name = "timb-uart", |
269 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | 357 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), |
270 | .resources = timberdale_uart_resources, | 358 | .resources = timberdale_uart_resources, |
271 | }, | 359 | }, |
272 | { | 360 | { |
361 | .name = "xiic-i2c", | ||
362 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | ||
363 | .resources = timberdale_xiic_resources, | ||
364 | .platform_data = &timberdale_xiic_platform_data, | ||
365 | .data_size = sizeof(timberdale_xiic_platform_data), | ||
366 | }, | ||
367 | { | ||
273 | .name = "timb-gpio", | 368 | .name = "timb-gpio", |
274 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 369 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
275 | .resources = timberdale_gpio_resources, | 370 | .resources = timberdale_gpio_resources, |
@@ -295,14 +390,16 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg0[] = { | |||
295 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 390 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
296 | .resources = timberdale_eth_resources, | 391 | .resources = timberdale_eth_resources, |
297 | }, | 392 | }, |
393 | }; | ||
394 | |||
395 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | ||
298 | { | 396 | { |
299 | .name = "timb-dma", | 397 | .name = "timb-dma", |
300 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 398 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
301 | .resources = timberdale_dma_resources, | 399 | .resources = timberdale_dma_resources, |
400 | .platform_data = &timb_dma_platform_data, | ||
401 | .data_size = sizeof(timb_dma_platform_data), | ||
302 | }, | 402 | }, |
303 | }; | ||
304 | |||
305 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | ||
306 | { | 403 | { |
307 | .name = "timb-uart", | 404 | .name = "timb-uart", |
308 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | 405 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), |
@@ -314,6 +411,13 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
314 | .resources = timberdale_uartlite_resources, | 411 | .resources = timberdale_uartlite_resources, |
315 | }, | 412 | }, |
316 | { | 413 | { |
414 | .name = "xiic-i2c", | ||
415 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | ||
416 | .resources = timberdale_xiic_resources, | ||
417 | .platform_data = &timberdale_xiic_platform_data, | ||
418 | .data_size = sizeof(timberdale_xiic_platform_data), | ||
419 | }, | ||
420 | { | ||
317 | .name = "timb-gpio", | 421 | .name = "timb-gpio", |
318 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 422 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
319 | .resources = timberdale_gpio_resources, | 423 | .resources = timberdale_gpio_resources, |
@@ -344,20 +448,29 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg1[] = { | |||
344 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 448 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
345 | .resources = timberdale_eth_resources, | 449 | .resources = timberdale_eth_resources, |
346 | }, | 450 | }, |
451 | }; | ||
452 | |||
453 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | ||
347 | { | 454 | { |
348 | .name = "timb-dma", | 455 | .name = "timb-dma", |
349 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 456 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
350 | .resources = timberdale_dma_resources, | 457 | .resources = timberdale_dma_resources, |
458 | .platform_data = &timb_dma_platform_data, | ||
459 | .data_size = sizeof(timb_dma_platform_data), | ||
351 | }, | 460 | }, |
352 | }; | ||
353 | |||
354 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | ||
355 | { | 461 | { |
356 | .name = "timb-uart", | 462 | .name = "timb-uart", |
357 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | 463 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), |
358 | .resources = timberdale_uart_resources, | 464 | .resources = timberdale_uart_resources, |
359 | }, | 465 | }, |
360 | { | 466 | { |
467 | .name = "xiic-i2c", | ||
468 | .num_resources = ARRAY_SIZE(timberdale_xiic_resources), | ||
469 | .resources = timberdale_xiic_resources, | ||
470 | .platform_data = &timberdale_xiic_platform_data, | ||
471 | .data_size = sizeof(timberdale_xiic_platform_data), | ||
472 | }, | ||
473 | { | ||
361 | .name = "timb-gpio", | 474 | .name = "timb-gpio", |
362 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), | 475 | .num_resources = ARRAY_SIZE(timberdale_gpio_resources), |
363 | .resources = timberdale_gpio_resources, | 476 | .resources = timberdale_gpio_resources, |
@@ -378,14 +491,16 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg2[] = { | |||
378 | .platform_data = &timberdale_xspi_platform_data, | 491 | .platform_data = &timberdale_xspi_platform_data, |
379 | .data_size = sizeof(timberdale_xspi_platform_data), | 492 | .data_size = sizeof(timberdale_xspi_platform_data), |
380 | }, | 493 | }, |
494 | }; | ||
495 | |||
496 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | ||
381 | { | 497 | { |
382 | .name = "timb-dma", | 498 | .name = "timb-dma", |
383 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | 499 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), |
384 | .resources = timberdale_dma_resources, | 500 | .resources = timberdale_dma_resources, |
501 | .platform_data = &timb_dma_platform_data, | ||
502 | .data_size = sizeof(timb_dma_platform_data), | ||
385 | }, | 503 | }, |
386 | }; | ||
387 | |||
388 | static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | ||
389 | { | 504 | { |
390 | .name = "timb-uart", | 505 | .name = "timb-uart", |
391 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), | 506 | .num_resources = ARRAY_SIZE(timberdale_uart_resources), |
@@ -424,11 +539,6 @@ static __devinitdata struct mfd_cell timberdale_cells_bar0_cfg3[] = { | |||
424 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), | 539 | .num_resources = ARRAY_SIZE(timberdale_eth_resources), |
425 | .resources = timberdale_eth_resources, | 540 | .resources = timberdale_eth_resources, |
426 | }, | 541 | }, |
427 | { | ||
428 | .name = "timb-dma", | ||
429 | .num_resources = ARRAY_SIZE(timberdale_dma_resources), | ||
430 | .resources = timberdale_dma_resources, | ||
431 | }, | ||
432 | }; | 542 | }; |
433 | 543 | ||
434 | static const __devinitconst struct resource timberdale_sdhc_resources[] = { | 544 | static const __devinitconst struct resource timberdale_sdhc_resources[] = { |
diff --git a/drivers/mfd/timberdale.h b/drivers/mfd/timberdale.h index 8d27ffabc25d..c11bf6ebfe00 100644 --- a/drivers/mfd/timberdale.h +++ b/drivers/mfd/timberdale.h | |||
@@ -23,7 +23,7 @@ | |||
23 | #ifndef MFD_TIMBERDALE_H | 23 | #ifndef MFD_TIMBERDALE_H |
24 | #define MFD_TIMBERDALE_H | 24 | #define MFD_TIMBERDALE_H |
25 | 25 | ||
26 | #define DRV_VERSION "0.1" | 26 | #define DRV_VERSION "0.2" |
27 | 27 | ||
28 | /* This driver only support versions >= 3.8 and < 4.0 */ | 28 | /* This driver only support versions >= 3.8 and < 4.0 */ |
29 | #define TIMB_SUPPORTED_MAJOR 3 | 29 | #define TIMB_SUPPORTED_MAJOR 3 |
@@ -66,7 +66,7 @@ | |||
66 | 66 | ||
67 | #define CHIPCTLOFFSET 0x800 | 67 | #define CHIPCTLOFFSET 0x800 |
68 | #define CHIPCTLEND 0x8ff | 68 | #define CHIPCTLEND 0x8ff |
69 | #define CHIPCTLSIZE (CHIPCTLEND - CHIPCTLOFFSET) | 69 | #define CHIPCTLSIZE (CHIPCTLEND - CHIPCTLOFFSET + 1) |
70 | 70 | ||
71 | #define INTCOFFSET 0xc00 | 71 | #define INTCOFFSET 0xc00 |
72 | #define INTCEND 0xfff | 72 | #define INTCEND 0xfff |
@@ -127,4 +127,16 @@ | |||
127 | #define GPIO_PIN_BT_RST 15 | 127 | #define GPIO_PIN_BT_RST 15 |
128 | #define GPIO_NR_PINS 16 | 128 | #define GPIO_NR_PINS 16 |
129 | 129 | ||
130 | /* DMA Channels */ | ||
131 | #define DMA_UART_RX 0 | ||
132 | #define DMA_UART_TX 1 | ||
133 | #define DMA_MLB_RX 2 | ||
134 | #define DMA_MLB_TX 3 | ||
135 | #define DMA_VIDEO_RX 4 | ||
136 | #define DMA_VIDEO_DROP 5 | ||
137 | #define DMA_SDHCI_RX 6 | ||
138 | #define DMA_SDHCI_TX 7 | ||
139 | #define DMA_ETH_RX 8 | ||
140 | #define DMA_ETH_TX 9 | ||
141 | |||
130 | #endif | 142 | #endif |
diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index e5955306c2fa..9b22a77f70f5 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c | |||
@@ -530,8 +530,8 @@ static int __exit tps65010_remove(struct i2c_client *client) | |||
530 | cancel_delayed_work(&tps->work); | 530 | cancel_delayed_work(&tps->work); |
531 | flush_scheduled_work(); | 531 | flush_scheduled_work(); |
532 | debugfs_remove(tps->file); | 532 | debugfs_remove(tps->file); |
533 | kfree(tps); | ||
534 | i2c_set_clientdata(client, NULL); | 533 | i2c_set_clientdata(client, NULL); |
534 | kfree(tps); | ||
535 | the_tps = NULL; | 535 | the_tps = NULL; |
536 | return 0; | 536 | return 0; |
537 | } | 537 | } |
diff --git a/drivers/mfd/tps6507x.c b/drivers/mfd/tps6507x.c new file mode 100644 index 000000000000..d859dffed39f --- /dev/null +++ b/drivers/mfd/tps6507x.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * tps6507x.c -- TPS6507x chip family multi-function driver | ||
3 | * | ||
4 | * Copyright (c) 2010 RidgeRun (todd.fischer@ridgerun.com) | ||
5 | * | ||
6 | * Author: Todd Fischer | ||
7 | * todd.fischer@ridgerun.com | ||
8 | * | ||
9 | * Credits: | ||
10 | * | ||
11 | * Using code from wm831x-*.c, wm8400-core, Wolfson Microelectronics PLC. | ||
12 | * | ||
13 | * For licencing details see kernel-base/COPYING | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/moduleparam.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/mfd/core.h> | ||
23 | #include <linux/mfd/tps6507x.h> | ||
24 | |||
25 | static struct mfd_cell tps6507x_devs[] = { | ||
26 | { | ||
27 | .name = "tps6507x-pmic", | ||
28 | }, | ||
29 | { | ||
30 | .name = "tps6507x-ts", | ||
31 | }, | ||
32 | }; | ||
33 | |||
34 | |||
35 | static int tps6507x_i2c_read_device(struct tps6507x_dev *tps6507x, char reg, | ||
36 | int bytes, void *dest) | ||
37 | { | ||
38 | struct i2c_client *i2c = tps6507x->i2c_client; | ||
39 | struct i2c_msg xfer[2]; | ||
40 | int ret; | ||
41 | |||
42 | /* Write register */ | ||
43 | xfer[0].addr = i2c->addr; | ||
44 | xfer[0].flags = 0; | ||
45 | xfer[0].len = 1; | ||
46 | xfer[0].buf = ® | ||
47 | |||
48 | /* Read data */ | ||
49 | xfer[1].addr = i2c->addr; | ||
50 | xfer[1].flags = I2C_M_RD; | ||
51 | xfer[1].len = bytes; | ||
52 | xfer[1].buf = dest; | ||
53 | |||
54 | ret = i2c_transfer(i2c->adapter, xfer, 2); | ||
55 | if (ret == 2) | ||
56 | ret = 0; | ||
57 | else if (ret >= 0) | ||
58 | ret = -EIO; | ||
59 | |||
60 | return ret; | ||
61 | } | ||
62 | |||
63 | static int tps6507x_i2c_write_device(struct tps6507x_dev *tps6507x, char reg, | ||
64 | int bytes, void *src) | ||
65 | { | ||
66 | struct i2c_client *i2c = tps6507x->i2c_client; | ||
67 | /* we add 1 byte for device register */ | ||
68 | u8 msg[TPS6507X_MAX_REGISTER + 1]; | ||
69 | int ret; | ||
70 | |||
71 | if (bytes > (TPS6507X_MAX_REGISTER + 1)) | ||
72 | return -EINVAL; | ||
73 | |||
74 | msg[0] = reg; | ||
75 | memcpy(&msg[1], src, bytes); | ||
76 | |||
77 | ret = i2c_master_send(i2c, msg, bytes + 1); | ||
78 | if (ret < 0) | ||
79 | return ret; | ||
80 | if (ret != bytes + 1) | ||
81 | return -EIO; | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static int tps6507x_i2c_probe(struct i2c_client *i2c, | ||
86 | const struct i2c_device_id *id) | ||
87 | { | ||
88 | struct tps6507x_dev *tps6507x; | ||
89 | int ret = 0; | ||
90 | |||
91 | tps6507x = kzalloc(sizeof(struct tps6507x_dev), GFP_KERNEL); | ||
92 | if (tps6507x == NULL) { | ||
93 | kfree(i2c); | ||
94 | return -ENOMEM; | ||
95 | } | ||
96 | |||
97 | i2c_set_clientdata(i2c, tps6507x); | ||
98 | tps6507x->dev = &i2c->dev; | ||
99 | tps6507x->i2c_client = i2c; | ||
100 | tps6507x->read_dev = tps6507x_i2c_read_device; | ||
101 | tps6507x->write_dev = tps6507x_i2c_write_device; | ||
102 | |||
103 | ret = mfd_add_devices(tps6507x->dev, -1, | ||
104 | tps6507x_devs, ARRAY_SIZE(tps6507x_devs), | ||
105 | NULL, 0); | ||
106 | |||
107 | if (ret < 0) | ||
108 | goto err; | ||
109 | |||
110 | return ret; | ||
111 | |||
112 | err: | ||
113 | mfd_remove_devices(tps6507x->dev); | ||
114 | kfree(tps6507x); | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | static int tps6507x_i2c_remove(struct i2c_client *i2c) | ||
119 | { | ||
120 | struct tps6507x_dev *tps6507x = i2c_get_clientdata(i2c); | ||
121 | |||
122 | mfd_remove_devices(tps6507x->dev); | ||
123 | kfree(tps6507x); | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | static const struct i2c_device_id tps6507x_i2c_id[] = { | ||
129 | { "tps6507x", 0 }, | ||
130 | { } | ||
131 | }; | ||
132 | MODULE_DEVICE_TABLE(i2c, tps6507x_i2c_id); | ||
133 | |||
134 | |||
135 | static struct i2c_driver tps6507x_i2c_driver = { | ||
136 | .driver = { | ||
137 | .name = "tps6507x", | ||
138 | .owner = THIS_MODULE, | ||
139 | }, | ||
140 | .probe = tps6507x_i2c_probe, | ||
141 | .remove = tps6507x_i2c_remove, | ||
142 | .id_table = tps6507x_i2c_id, | ||
143 | }; | ||
144 | |||
145 | static int __init tps6507x_i2c_init(void) | ||
146 | { | ||
147 | return i2c_add_driver(&tps6507x_i2c_driver); | ||
148 | } | ||
149 | /* init early so consumer devices can complete system boot */ | ||
150 | subsys_initcall(tps6507x_i2c_init); | ||
151 | |||
152 | static void __exit tps6507x_i2c_exit(void) | ||
153 | { | ||
154 | i2c_del_driver(&tps6507x_i2c_driver); | ||
155 | } | ||
156 | module_exit(tps6507x_i2c_exit); | ||
157 | |||
158 | MODULE_DESCRIPTION("TPS6507x chip family multi-function driver"); | ||
159 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 202bdd59632d..097f24d8bceb 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -232,10 +232,11 @@ static const struct sih sih_modules_twl5031[8] = { | |||
232 | }, | 232 | }, |
233 | [6] = { | 233 | [6] = { |
234 | /* | 234 | /* |
235 | * ACI doesn't use the same SIH organization. | 235 | * ECI/DBI doesn't use the same SIH organization. |
236 | * For example, it supports only one interrupt line | 236 | * For example, it supports only one interrupt output line. |
237 | * That is, the interrupts are seen on both INT1 and INT2 lines. | ||
237 | */ | 238 | */ |
238 | .name = "aci", | 239 | .name = "eci_dbi", |
239 | .module = TWL5031_MODULE_ACCESSORY, | 240 | .module = TWL5031_MODULE_ACCESSORY, |
240 | .bits = 9, | 241 | .bits = 9, |
241 | .bytes_ixr = 2, | 242 | .bytes_ixr = 2, |
@@ -247,8 +248,8 @@ static const struct sih sih_modules_twl5031[8] = { | |||
247 | 248 | ||
248 | }, | 249 | }, |
249 | [7] = { | 250 | [7] = { |
250 | /* Accessory */ | 251 | /* Audio accessory */ |
251 | .name = "acc", | 252 | .name = "audio", |
252 | .module = TWL5031_MODULE_ACCESSORY, | 253 | .module = TWL5031_MODULE_ACCESSORY, |
253 | .control_offset = TWL5031_ACCSIHCTRL, | 254 | .control_offset = TWL5031_ACCSIHCTRL, |
254 | .bits = 2, | 255 | .bits = 2, |
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index f2ab025ad97a..1a968f34d679 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
@@ -322,7 +322,11 @@ EXPORT_SYMBOL_GPL(wm831x_set_bits); | |||
322 | */ | 322 | */ |
323 | int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) | 323 | int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) |
324 | { | 324 | { |
325 | int ret, src; | 325 | int ret, src, irq_masked, timeout; |
326 | |||
327 | /* Are we using the interrupt? */ | ||
328 | irq_masked = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_1_MASK); | ||
329 | irq_masked &= WM831X_AUXADC_DATA_EINT; | ||
326 | 330 | ||
327 | mutex_lock(&wm831x->auxadc_lock); | 331 | mutex_lock(&wm831x->auxadc_lock); |
328 | 332 | ||
@@ -342,6 +346,9 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) | |||
342 | goto out; | 346 | goto out; |
343 | } | 347 | } |
344 | 348 | ||
349 | /* Clear any notification from a very late arriving interrupt */ | ||
350 | try_wait_for_completion(&wm831x->auxadc_done); | ||
351 | |||
345 | ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, | 352 | ret = wm831x_set_bits(wm831x, WM831X_AUXADC_CONTROL, |
346 | WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA); | 353 | WM831X_AUX_CVT_ENA, WM831X_AUX_CVT_ENA); |
347 | if (ret < 0) { | 354 | if (ret < 0) { |
@@ -349,22 +356,46 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) | |||
349 | goto disable; | 356 | goto disable; |
350 | } | 357 | } |
351 | 358 | ||
352 | /* If an interrupt arrived late clean up after it */ | 359 | if (irq_masked) { |
353 | try_wait_for_completion(&wm831x->auxadc_done); | 360 | /* If we're not using interrupts then poll the |
354 | 361 | * interrupt status register */ | |
355 | /* Ignore the result to allow us to soldier on without IRQ hookup */ | 362 | timeout = 5; |
356 | wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); | 363 | while (timeout) { |
357 | 364 | msleep(1); | |
358 | ret = wm831x_reg_read(wm831x, WM831X_AUXADC_CONTROL); | 365 | |
359 | if (ret < 0) { | 366 | ret = wm831x_reg_read(wm831x, |
360 | dev_err(wm831x->dev, "AUXADC status read failed: %d\n", ret); | 367 | WM831X_INTERRUPT_STATUS_1); |
361 | goto disable; | 368 | if (ret < 0) { |
362 | } | 369 | dev_err(wm831x->dev, |
363 | 370 | "ISR 1 read failed: %d\n", ret); | |
364 | if (ret & WM831X_AUX_CVT_ENA) { | 371 | goto disable; |
365 | dev_err(wm831x->dev, "Timed out reading AUXADC\n"); | 372 | } |
366 | ret = -EBUSY; | 373 | |
367 | goto disable; | 374 | /* Did it complete? */ |
375 | if (ret & WM831X_AUXADC_DATA_EINT) { | ||
376 | wm831x_reg_write(wm831x, | ||
377 | WM831X_INTERRUPT_STATUS_1, | ||
378 | WM831X_AUXADC_DATA_EINT); | ||
379 | break; | ||
380 | } else { | ||
381 | dev_err(wm831x->dev, | ||
382 | "AUXADC conversion timeout\n"); | ||
383 | ret = -EBUSY; | ||
384 | goto disable; | ||
385 | } | ||
386 | } | ||
387 | } else { | ||
388 | /* If we are using interrupts then wait for the | ||
389 | * interrupt to complete. Use an extremely long | ||
390 | * timeout to handle situations with heavy load where | ||
391 | * the notification of the interrupt may be delayed by | ||
392 | * threaded IRQ handling. */ | ||
393 | if (!wait_for_completion_timeout(&wm831x->auxadc_done, | ||
394 | msecs_to_jiffies(500))) { | ||
395 | dev_err(wm831x->dev, "Timed out waiting for AUXADC\n"); | ||
396 | ret = -EBUSY; | ||
397 | goto disable; | ||
398 | } | ||
368 | } | 399 | } |
369 | 400 | ||
370 | ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); | 401 | ret = wm831x_reg_read(wm831x, WM831X_AUXADC_DATA); |
@@ -1463,6 +1494,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1463 | case WM8310: | 1494 | case WM8310: |
1464 | parent = WM8310; | 1495 | parent = WM8310; |
1465 | wm831x->num_gpio = 16; | 1496 | wm831x->num_gpio = 16; |
1497 | wm831x->charger_irq_wake = 1; | ||
1466 | if (rev > 0) { | 1498 | if (rev > 0) { |
1467 | wm831x->has_gpio_ena = 1; | 1499 | wm831x->has_gpio_ena = 1; |
1468 | wm831x->has_cs_sts = 1; | 1500 | wm831x->has_cs_sts = 1; |
@@ -1474,6 +1506,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1474 | case WM8311: | 1506 | case WM8311: |
1475 | parent = WM8311; | 1507 | parent = WM8311; |
1476 | wm831x->num_gpio = 16; | 1508 | wm831x->num_gpio = 16; |
1509 | wm831x->charger_irq_wake = 1; | ||
1477 | if (rev > 0) { | 1510 | if (rev > 0) { |
1478 | wm831x->has_gpio_ena = 1; | 1511 | wm831x->has_gpio_ena = 1; |
1479 | wm831x->has_cs_sts = 1; | 1512 | wm831x->has_cs_sts = 1; |
@@ -1485,6 +1518,7 @@ static int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq) | |||
1485 | case WM8312: | 1518 | case WM8312: |
1486 | parent = WM8312; | 1519 | parent = WM8312; |
1487 | wm831x->num_gpio = 16; | 1520 | wm831x->num_gpio = 16; |
1521 | wm831x->charger_irq_wake = 1; | ||
1488 | if (rev > 0) { | 1522 | if (rev > 0) { |
1489 | wm831x->has_gpio_ena = 1; | 1523 | wm831x->has_gpio_ena = 1; |
1490 | wm831x->has_cs_sts = 1; | 1524 | wm831x->has_cs_sts = 1; |
@@ -1623,6 +1657,42 @@ static void wm831x_device_exit(struct wm831x *wm831x) | |||
1623 | kfree(wm831x); | 1657 | kfree(wm831x); |
1624 | } | 1658 | } |
1625 | 1659 | ||
1660 | static int wm831x_device_suspend(struct wm831x *wm831x) | ||
1661 | { | ||
1662 | int reg, mask; | ||
1663 | |||
1664 | /* If the charger IRQs are a wake source then make sure we ack | ||
1665 | * them even if they're not actively being used (eg, no power | ||
1666 | * driver or no IRQ line wired up) then acknowledge the | ||
1667 | * interrupts otherwise suspend won't last very long. | ||
1668 | */ | ||
1669 | if (wm831x->charger_irq_wake) { | ||
1670 | reg = wm831x_reg_read(wm831x, WM831X_INTERRUPT_STATUS_2_MASK); | ||
1671 | |||
1672 | mask = WM831X_CHG_BATT_HOT_EINT | | ||
1673 | WM831X_CHG_BATT_COLD_EINT | | ||
1674 | WM831X_CHG_BATT_FAIL_EINT | | ||
1675 | WM831X_CHG_OV_EINT | WM831X_CHG_END_EINT | | ||
1676 | WM831X_CHG_TO_EINT | WM831X_CHG_MODE_EINT | | ||
1677 | WM831X_CHG_START_EINT; | ||
1678 | |||
1679 | /* If any of the interrupts are masked read the statuses */ | ||
1680 | if (reg & mask) | ||
1681 | reg = wm831x_reg_read(wm831x, | ||
1682 | WM831X_INTERRUPT_STATUS_2); | ||
1683 | |||
1684 | if (reg & mask) { | ||
1685 | dev_info(wm831x->dev, | ||
1686 | "Acknowledging masked charger IRQs: %x\n", | ||
1687 | reg & mask); | ||
1688 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_2, | ||
1689 | reg & mask); | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | return 0; | ||
1694 | } | ||
1695 | |||
1626 | static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, | 1696 | static int wm831x_i2c_read_device(struct wm831x *wm831x, unsigned short reg, |
1627 | int bytes, void *dest) | 1697 | int bytes, void *dest) |
1628 | { | 1698 | { |
@@ -1697,6 +1767,13 @@ static int wm831x_i2c_remove(struct i2c_client *i2c) | |||
1697 | return 0; | 1767 | return 0; |
1698 | } | 1768 | } |
1699 | 1769 | ||
1770 | static int wm831x_i2c_suspend(struct i2c_client *i2c, pm_message_t mesg) | ||
1771 | { | ||
1772 | struct wm831x *wm831x = i2c_get_clientdata(i2c); | ||
1773 | |||
1774 | return wm831x_device_suspend(wm831x); | ||
1775 | } | ||
1776 | |||
1700 | static const struct i2c_device_id wm831x_i2c_id[] = { | 1777 | static const struct i2c_device_id wm831x_i2c_id[] = { |
1701 | { "wm8310", WM8310 }, | 1778 | { "wm8310", WM8310 }, |
1702 | { "wm8311", WM8311 }, | 1779 | { "wm8311", WM8311 }, |
@@ -1714,6 +1791,7 @@ static struct i2c_driver wm831x_i2c_driver = { | |||
1714 | }, | 1791 | }, |
1715 | .probe = wm831x_i2c_probe, | 1792 | .probe = wm831x_i2c_probe, |
1716 | .remove = wm831x_i2c_remove, | 1793 | .remove = wm831x_i2c_remove, |
1794 | .suspend = wm831x_i2c_suspend, | ||
1717 | .id_table = wm831x_i2c_id, | 1795 | .id_table = wm831x_i2c_id, |
1718 | }; | 1796 | }; |
1719 | 1797 | ||
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c index 4c1122ceb443..7dabe4dbd373 100644 --- a/drivers/mfd/wm831x-irq.c +++ b/drivers/mfd/wm831x-irq.c | |||
@@ -39,8 +39,6 @@ struct wm831x_irq_data { | |||
39 | int primary; | 39 | int primary; |
40 | int reg; | 40 | int reg; |
41 | int mask; | 41 | int mask; |
42 | irq_handler_t handler; | ||
43 | void *handler_data; | ||
44 | }; | 42 | }; |
45 | 43 | ||
46 | static struct wm831x_irq_data wm831x_irqs[] = { | 44 | static struct wm831x_irq_data wm831x_irqs[] = { |
@@ -492,6 +490,14 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
492 | 490 | ||
493 | mutex_init(&wm831x->irq_lock); | 491 | mutex_init(&wm831x->irq_lock); |
494 | 492 | ||
493 | /* Mask the individual interrupt sources */ | ||
494 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { | ||
495 | wm831x->irq_masks_cur[i] = 0xffff; | ||
496 | wm831x->irq_masks_cache[i] = 0xffff; | ||
497 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, | ||
498 | 0xffff); | ||
499 | } | ||
500 | |||
495 | if (!irq) { | 501 | if (!irq) { |
496 | dev_warn(wm831x->dev, | 502 | dev_warn(wm831x->dev, |
497 | "No interrupt specified - functionality limited\n"); | 503 | "No interrupt specified - functionality limited\n"); |
@@ -507,14 +513,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) | |||
507 | wm831x->irq = irq; | 513 | wm831x->irq = irq; |
508 | wm831x->irq_base = pdata->irq_base; | 514 | wm831x->irq_base = pdata->irq_base; |
509 | 515 | ||
510 | /* Mask the individual interrupt sources */ | ||
511 | for (i = 0; i < ARRAY_SIZE(wm831x->irq_masks_cur); i++) { | ||
512 | wm831x->irq_masks_cur[i] = 0xffff; | ||
513 | wm831x->irq_masks_cache[i] = 0xffff; | ||
514 | wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1_MASK + i, | ||
515 | 0xffff); | ||
516 | } | ||
517 | |||
518 | /* Register them with genirq */ | 516 | /* Register them with genirq */ |
519 | for (cur_irq = wm831x->irq_base; | 517 | for (cur_irq = wm831x->irq_base; |
520 | cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; | 518 | cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base; |
diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index 65830f57c093..7795af4b1fe1 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c | |||
@@ -64,10 +64,8 @@ static int wm8350_i2c_probe(struct i2c_client *i2c, | |||
64 | int ret = 0; | 64 | int ret = 0; |
65 | 65 | ||
66 | wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL); | 66 | wm8350 = kzalloc(sizeof(struct wm8350), GFP_KERNEL); |
67 | if (wm8350 == NULL) { | 67 | if (wm8350 == NULL) |
68 | kfree(i2c); | ||
69 | return -ENOMEM; | 68 | return -ENOMEM; |
70 | } | ||
71 | 69 | ||
72 | i2c_set_clientdata(i2c, wm8350); | 70 | i2c_set_clientdata(i2c, wm8350); |
73 | wm8350->dev = &i2c->dev; | 71 | wm8350->dev = &i2c->dev; |
@@ -82,6 +80,7 @@ static int wm8350_i2c_probe(struct i2c_client *i2c, | |||
82 | return ret; | 80 | return ret; |
83 | 81 | ||
84 | err: | 82 | err: |
83 | i2c_set_clientdata(i2c, NULL); | ||
85 | kfree(wm8350); | 84 | kfree(wm8350); |
86 | return ret; | 85 | return ret; |
87 | } | 86 | } |
@@ -91,6 +90,7 @@ static int wm8350_i2c_remove(struct i2c_client *i2c) | |||
91 | struct wm8350 *wm8350 = i2c_get_clientdata(i2c); | 90 | struct wm8350 *wm8350 = i2c_get_clientdata(i2c); |
92 | 91 | ||
93 | wm8350_device_exit(wm8350); | 92 | wm8350_device_exit(wm8350); |
93 | i2c_set_clientdata(i2c, NULL); | ||
94 | kfree(wm8350); | 94 | kfree(wm8350); |
95 | 95 | ||
96 | return 0; | 96 | return 0; |
diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index 865ce013a821..e08aafa663dc 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c | |||
@@ -118,7 +118,7 @@ static int wm8400_read(struct wm8400 *wm8400, u8 reg, int num_regs, u16 *dest) | |||
118 | { | 118 | { |
119 | int i, ret = 0; | 119 | int i, ret = 0; |
120 | 120 | ||
121 | BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache)); | 121 | BUG_ON(reg + num_regs > ARRAY_SIZE(wm8400->reg_cache)); |
122 | 122 | ||
123 | /* If there are any volatile reads then read back the entire block */ | 123 | /* If there are any volatile reads then read back the entire block */ |
124 | for (i = reg; i < reg + num_regs; i++) | 124 | for (i = reg; i < reg + num_regs; i++) |
@@ -144,7 +144,7 @@ static int wm8400_write(struct wm8400 *wm8400, u8 reg, int num_regs, | |||
144 | { | 144 | { |
145 | int ret, i; | 145 | int ret, i; |
146 | 146 | ||
147 | BUG_ON(reg + num_regs - 1 > ARRAY_SIZE(wm8400->reg_cache)); | 147 | BUG_ON(reg + num_regs > ARRAY_SIZE(wm8400->reg_cache)); |
148 | 148 | ||
149 | for (i = 0; i < num_regs; i++) { | 149 | for (i = 0; i < num_regs; i++) { |
150 | BUG_ON(!reg_data[reg + i].writable); | 150 | BUG_ON(!reg_data[reg + i].writable); |
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 74c87e023866..fdf33e837a73 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
@@ -942,7 +942,7 @@ static int mxcmci_suspend(struct platform_device *dev, pm_message_t state) | |||
942 | int ret = 0; | 942 | int ret = 0; |
943 | 943 | ||
944 | if (mmc) | 944 | if (mmc) |
945 | ret = mmc_suspend_host(mmc, state); | 945 | ret = mmc_suspend_host(mmc); |
946 | 946 | ||
947 | return ret; | 947 | return ret; |
948 | } | 948 | } |
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/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 72ebb3f06b86..4dfa6b90c21c 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c | |||
@@ -189,8 +189,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin) | |||
189 | return new_offset; | 189 | return new_offset; |
190 | } | 190 | } |
191 | 191 | ||
192 | static int vol_cdev_fsync(struct file *file, struct dentry *dentry, | 192 | static int vol_cdev_fsync(struct file *file, int datasync) |
193 | int datasync) | ||
194 | { | 193 | { |
195 | struct ubi_volume_desc *desc = file->private_data; | 194 | struct ubi_volume_desc *desc = file->private_data; |
196 | struct ubi_device *ubi = desc->vol->ubi; | 195 | struct ubi_device *ubi = desc->vol->ubi; |
diff --git a/drivers/net/3c507.c b/drivers/net/3c507.c index 82eaf65d2d85..ea9b7a098c9b 100644 --- a/drivers/net/3c507.c +++ b/drivers/net/3c507.c | |||
@@ -551,8 +551,7 @@ static irqreturn_t el16_interrupt(int irq, void *dev_id) | |||
551 | void __iomem *shmem; | 551 | void __iomem *shmem; |
552 | 552 | ||
553 | if (dev == NULL) { | 553 | if (dev == NULL) { |
554 | pr_err("%s: net_interrupt(): irq %d for unknown device.\n", | 554 | pr_err("net_interrupt(): irq %d for unknown device.\n", irq); |
555 | dev->name, irq); | ||
556 | return IRQ_NONE; | 555 | return IRQ_NONE; |
557 | } | 556 | } |
558 | 557 | ||
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index c911bfb55b19..9d11dbf5e4da 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c | |||
@@ -294,7 +294,7 @@ int be_cmd_POST(struct be_adapter *adapter) | |||
294 | } else { | 294 | } else { |
295 | return 0; | 295 | return 0; |
296 | } | 296 | } |
297 | } while (timeout < 20); | 297 | } while (timeout < 40); |
298 | 298 | ||
299 | dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage); | 299 | dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage); |
300 | return -1; | 300 | return -1; |
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index aa065c71ddd8..54b14272f333 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c | |||
@@ -1861,7 +1861,7 @@ static int be_setup(struct be_adapter *adapter) | |||
1861 | goto if_destroy; | 1861 | goto if_destroy; |
1862 | } | 1862 | } |
1863 | vf++; | 1863 | vf++; |
1864 | } while (vf < num_vfs); | 1864 | } |
1865 | } else if (!be_physfn(adapter)) { | 1865 | } else if (!be_physfn(adapter)) { |
1866 | status = be_cmd_mac_addr_query(adapter, mac, | 1866 | status = be_cmd_mac_addr_query(adapter, mac, |
1867 | MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); | 1867 | MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle); |
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 05b751719bd5..2c5227c02fa0 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig | |||
@@ -63,6 +63,16 @@ config CAN_BFIN | |||
63 | To compile this driver as a module, choose M here: the | 63 | To compile this driver as a module, choose M here: the |
64 | module will be called bfin_can. | 64 | module will be called bfin_can. |
65 | 65 | ||
66 | config CAN_JANZ_ICAN3 | ||
67 | tristate "Janz VMOD-ICAN3 Intelligent CAN controller" | ||
68 | depends on CAN_DEV && MFD_JANZ_CMODIO | ||
69 | ---help--- | ||
70 | Driver for Janz VMOD-ICAN3 Intelligent CAN controller module, which | ||
71 | connects to a MODULbus carrier board. | ||
72 | |||
73 | This driver can also be built as a module. If so, the module will be | ||
74 | called janz-ican3.ko. | ||
75 | |||
66 | source "drivers/net/can/mscan/Kconfig" | 76 | source "drivers/net/can/mscan/Kconfig" |
67 | 77 | ||
68 | source "drivers/net/can/sja1000/Kconfig" | 78 | source "drivers/net/can/sja1000/Kconfig" |
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile index 7a702f28d01c..9047cd066fea 100644 --- a/drivers/net/can/Makefile +++ b/drivers/net/can/Makefile | |||
@@ -15,5 +15,6 @@ obj-$(CONFIG_CAN_AT91) += at91_can.o | |||
15 | obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o | 15 | obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o |
16 | obj-$(CONFIG_CAN_MCP251X) += mcp251x.o | 16 | obj-$(CONFIG_CAN_MCP251X) += mcp251x.o |
17 | obj-$(CONFIG_CAN_BFIN) += bfin_can.o | 17 | obj-$(CONFIG_CAN_BFIN) += bfin_can.o |
18 | obj-$(CONFIG_CAN_JANZ_ICAN3) += janz-ican3.o | ||
18 | 19 | ||
19 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG | 20 | ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG |
diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c new file mode 100644 index 000000000000..6e533dcc36c0 --- /dev/null +++ b/drivers/net/can/janz-ican3.c | |||
@@ -0,0 +1,1830 @@ | |||
1 | /* | ||
2 | * Janz MODULbus VMOD-ICAN3 CAN Interface Driver | ||
3 | * | ||
4 | * Copyright (c) 2010 Ira W. Snyder <iws@ovro.caltech.edu> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <linux/netdevice.h> | ||
20 | #include <linux/can.h> | ||
21 | #include <linux/can/dev.h> | ||
22 | #include <linux/can/error.h> | ||
23 | |||
24 | #include <linux/mfd/janz.h> | ||
25 | |||
26 | /* the DPM has 64k of memory, organized into 256x 256 byte pages */ | ||
27 | #define DPM_NUM_PAGES 256 | ||
28 | #define DPM_PAGE_SIZE 256 | ||
29 | #define DPM_PAGE_ADDR(p) ((p) * DPM_PAGE_SIZE) | ||
30 | |||
31 | /* JANZ ICAN3 "old-style" host interface queue page numbers */ | ||
32 | #define QUEUE_OLD_CONTROL 0 | ||
33 | #define QUEUE_OLD_RB0 1 | ||
34 | #define QUEUE_OLD_RB1 2 | ||
35 | #define QUEUE_OLD_WB0 3 | ||
36 | #define QUEUE_OLD_WB1 4 | ||
37 | |||
38 | /* Janz ICAN3 "old-style" host interface control registers */ | ||
39 | #define MSYNC_PEER 0x00 /* ICAN only */ | ||
40 | #define MSYNC_LOCL 0x01 /* host only */ | ||
41 | #define TARGET_RUNNING 0x02 | ||
42 | |||
43 | #define MSYNC_RB0 0x01 | ||
44 | #define MSYNC_RB1 0x02 | ||
45 | #define MSYNC_RBLW 0x04 | ||
46 | #define MSYNC_RB_MASK (MSYNC_RB0 | MSYNC_RB1) | ||
47 | |||
48 | #define MSYNC_WB0 0x10 | ||
49 | #define MSYNC_WB1 0x20 | ||
50 | #define MSYNC_WBLW 0x40 | ||
51 | #define MSYNC_WB_MASK (MSYNC_WB0 | MSYNC_WB1) | ||
52 | |||
53 | /* Janz ICAN3 "new-style" host interface queue page numbers */ | ||
54 | #define QUEUE_TOHOST 5 | ||
55 | #define QUEUE_FROMHOST_MID 6 | ||
56 | #define QUEUE_FROMHOST_HIGH 7 | ||
57 | #define QUEUE_FROMHOST_LOW 8 | ||
58 | |||
59 | /* The first free page in the DPM is #9 */ | ||
60 | #define DPM_FREE_START 9 | ||
61 | |||
62 | /* Janz ICAN3 "new-style" and "fast" host interface descriptor flags */ | ||
63 | #define DESC_VALID 0x80 | ||
64 | #define DESC_WRAP 0x40 | ||
65 | #define DESC_INTERRUPT 0x20 | ||
66 | #define DESC_IVALID 0x10 | ||
67 | #define DESC_LEN(len) (len) | ||
68 | |||
69 | /* Janz ICAN3 Firmware Messages */ | ||
70 | #define MSG_CONNECTI 0x02 | ||
71 | #define MSG_DISCONNECT 0x03 | ||
72 | #define MSG_IDVERS 0x04 | ||
73 | #define MSG_MSGLOST 0x05 | ||
74 | #define MSG_NEWHOSTIF 0x08 | ||
75 | #define MSG_INQUIRY 0x0a | ||
76 | #define MSG_SETAFILMASK 0x10 | ||
77 | #define MSG_INITFDPMQUEUE 0x11 | ||
78 | #define MSG_HWCONF 0x12 | ||
79 | #define MSG_FMSGLOST 0x15 | ||
80 | #define MSG_CEVTIND 0x37 | ||
81 | #define MSG_CBTRREQ 0x41 | ||
82 | #define MSG_COFFREQ 0x42 | ||
83 | #define MSG_CONREQ 0x43 | ||
84 | #define MSG_CCONFREQ 0x47 | ||
85 | |||
86 | /* | ||
87 | * Janz ICAN3 CAN Inquiry Message Types | ||
88 | * | ||
89 | * NOTE: there appears to be a firmware bug here. You must send | ||
90 | * NOTE: INQUIRY_STATUS and expect to receive an INQUIRY_EXTENDED | ||
91 | * NOTE: response. The controller never responds to a message with | ||
92 | * NOTE: the INQUIRY_EXTENDED subspec :( | ||
93 | */ | ||
94 | #define INQUIRY_STATUS 0x00 | ||
95 | #define INQUIRY_TERMINATION 0x01 | ||
96 | #define INQUIRY_EXTENDED 0x04 | ||
97 | |||
98 | /* Janz ICAN3 CAN Set Acceptance Filter Mask Message Types */ | ||
99 | #define SETAFILMASK_REJECT 0x00 | ||
100 | #define SETAFILMASK_FASTIF 0x02 | ||
101 | |||
102 | /* Janz ICAN3 CAN Hardware Configuration Message Types */ | ||
103 | #define HWCONF_TERMINATE_ON 0x01 | ||
104 | #define HWCONF_TERMINATE_OFF 0x00 | ||
105 | |||
106 | /* Janz ICAN3 CAN Event Indication Message Types */ | ||
107 | #define CEVTIND_EI 0x01 | ||
108 | #define CEVTIND_DOI 0x02 | ||
109 | #define CEVTIND_LOST 0x04 | ||
110 | #define CEVTIND_FULL 0x08 | ||
111 | #define CEVTIND_BEI 0x10 | ||
112 | |||
113 | #define CEVTIND_CHIP_SJA1000 0x02 | ||
114 | |||
115 | #define ICAN3_BUSERR_QUOTA_MAX 255 | ||
116 | |||
117 | /* Janz ICAN3 CAN Frame Conversion */ | ||
118 | #define ICAN3_ECHO 0x10 | ||
119 | #define ICAN3_EFF_RTR 0x40 | ||
120 | #define ICAN3_SFF_RTR 0x10 | ||
121 | #define ICAN3_EFF 0x80 | ||
122 | |||
123 | #define ICAN3_CAN_TYPE_MASK 0x0f | ||
124 | #define ICAN3_CAN_TYPE_SFF 0x00 | ||
125 | #define ICAN3_CAN_TYPE_EFF 0x01 | ||
126 | |||
127 | #define ICAN3_CAN_DLC_MASK 0x0f | ||
128 | |||
129 | /* | ||
130 | * SJA1000 Status and Error Register Definitions | ||
131 | * | ||
132 | * Copied from drivers/net/can/sja1000/sja1000.h | ||
133 | */ | ||
134 | |||
135 | /* status register content */ | ||
136 | #define SR_BS 0x80 | ||
137 | #define SR_ES 0x40 | ||
138 | #define SR_TS 0x20 | ||
139 | #define SR_RS 0x10 | ||
140 | #define SR_TCS 0x08 | ||
141 | #define SR_TBS 0x04 | ||
142 | #define SR_DOS 0x02 | ||
143 | #define SR_RBS 0x01 | ||
144 | |||
145 | #define SR_CRIT (SR_BS|SR_ES) | ||
146 | |||
147 | /* ECC register */ | ||
148 | #define ECC_SEG 0x1F | ||
149 | #define ECC_DIR 0x20 | ||
150 | #define ECC_ERR 6 | ||
151 | #define ECC_BIT 0x00 | ||
152 | #define ECC_FORM 0x40 | ||
153 | #define ECC_STUFF 0x80 | ||
154 | #define ECC_MASK 0xc0 | ||
155 | |||
156 | /* Number of buffers for use in the "new-style" host interface */ | ||
157 | #define ICAN3_NEW_BUFFERS 16 | ||
158 | |||
159 | /* Number of buffers for use in the "fast" host interface */ | ||
160 | #define ICAN3_TX_BUFFERS 512 | ||
161 | #define ICAN3_RX_BUFFERS 1024 | ||
162 | |||
163 | /* SJA1000 Clock Input */ | ||
164 | #define ICAN3_CAN_CLOCK 8000000 | ||
165 | |||
166 | /* Driver Name */ | ||
167 | #define DRV_NAME "janz-ican3" | ||
168 | |||
169 | /* DPM Control Registers -- starts at offset 0x100 in the MODULbus registers */ | ||
170 | struct ican3_dpm_control { | ||
171 | /* window address register */ | ||
172 | u8 window_address; | ||
173 | u8 unused1; | ||
174 | |||
175 | /* | ||
176 | * Read access: clear interrupt from microcontroller | ||
177 | * Write access: send interrupt to microcontroller | ||
178 | */ | ||
179 | u8 interrupt; | ||
180 | u8 unused2; | ||
181 | |||
182 | /* write-only: reset all hardware on the module */ | ||
183 | u8 hwreset; | ||
184 | u8 unused3; | ||
185 | |||
186 | /* write-only: generate an interrupt to the TPU */ | ||
187 | u8 tpuinterrupt; | ||
188 | }; | ||
189 | |||
190 | struct ican3_dev { | ||
191 | |||
192 | /* must be the first member */ | ||
193 | struct can_priv can; | ||
194 | |||
195 | /* CAN network device */ | ||
196 | struct net_device *ndev; | ||
197 | struct napi_struct napi; | ||
198 | |||
199 | /* Device for printing */ | ||
200 | struct device *dev; | ||
201 | |||
202 | /* module number */ | ||
203 | unsigned int num; | ||
204 | |||
205 | /* base address of registers and IRQ */ | ||
206 | struct janz_cmodio_onboard_regs __iomem *ctrl; | ||
207 | struct ican3_dpm_control __iomem *dpmctrl; | ||
208 | void __iomem *dpm; | ||
209 | int irq; | ||
210 | |||
211 | /* CAN bus termination status */ | ||
212 | struct completion termination_comp; | ||
213 | bool termination_enabled; | ||
214 | |||
215 | /* CAN bus error status registers */ | ||
216 | struct completion buserror_comp; | ||
217 | struct can_berr_counter bec; | ||
218 | |||
219 | /* old and new style host interface */ | ||
220 | unsigned int iftype; | ||
221 | |||
222 | /* | ||
223 | * Any function which changes the current DPM page must hold this | ||
224 | * lock while it is performing data accesses. This ensures that the | ||
225 | * function will not be preempted and end up reading data from a | ||
226 | * different DPM page than it expects. | ||
227 | */ | ||
228 | spinlock_t lock; | ||
229 | |||
230 | /* new host interface */ | ||
231 | unsigned int rx_int; | ||
232 | unsigned int rx_num; | ||
233 | unsigned int tx_num; | ||
234 | |||
235 | /* fast host interface */ | ||
236 | unsigned int fastrx_start; | ||
237 | unsigned int fastrx_int; | ||
238 | unsigned int fastrx_num; | ||
239 | unsigned int fasttx_start; | ||
240 | unsigned int fasttx_num; | ||
241 | |||
242 | /* first free DPM page */ | ||
243 | unsigned int free_page; | ||
244 | }; | ||
245 | |||
246 | struct ican3_msg { | ||
247 | u8 control; | ||
248 | u8 spec; | ||
249 | __le16 len; | ||
250 | u8 data[252]; | ||
251 | }; | ||
252 | |||
253 | struct ican3_new_desc { | ||
254 | u8 control; | ||
255 | u8 pointer; | ||
256 | }; | ||
257 | |||
258 | struct ican3_fast_desc { | ||
259 | u8 control; | ||
260 | u8 command; | ||
261 | u8 data[14]; | ||
262 | }; | ||
263 | |||
264 | /* write to the window basic address register */ | ||
265 | static inline void ican3_set_page(struct ican3_dev *mod, unsigned int page) | ||
266 | { | ||
267 | BUG_ON(page >= DPM_NUM_PAGES); | ||
268 | iowrite8(page, &mod->dpmctrl->window_address); | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * ICAN3 "old-style" host interface | ||
273 | */ | ||
274 | |||
275 | /* | ||
276 | * Recieve a message from the ICAN3 "old-style" firmware interface | ||
277 | * | ||
278 | * LOCKING: must hold mod->lock | ||
279 | * | ||
280 | * returns 0 on success, -ENOMEM when no message exists | ||
281 | */ | ||
282 | static int ican3_old_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg) | ||
283 | { | ||
284 | unsigned int mbox, mbox_page; | ||
285 | u8 locl, peer, xord; | ||
286 | |||
287 | /* get the MSYNC registers */ | ||
288 | ican3_set_page(mod, QUEUE_OLD_CONTROL); | ||
289 | peer = ioread8(mod->dpm + MSYNC_PEER); | ||
290 | locl = ioread8(mod->dpm + MSYNC_LOCL); | ||
291 | xord = locl ^ peer; | ||
292 | |||
293 | if ((xord & MSYNC_RB_MASK) == 0x00) { | ||
294 | dev_dbg(mod->dev, "no mbox for reading\n"); | ||
295 | return -ENOMEM; | ||
296 | } | ||
297 | |||
298 | /* find the first free mbox to read */ | ||
299 | if ((xord & MSYNC_RB_MASK) == MSYNC_RB_MASK) | ||
300 | mbox = (xord & MSYNC_RBLW) ? MSYNC_RB0 : MSYNC_RB1; | ||
301 | else | ||
302 | mbox = (xord & MSYNC_RB0) ? MSYNC_RB0 : MSYNC_RB1; | ||
303 | |||
304 | /* copy the message */ | ||
305 | mbox_page = (mbox == MSYNC_RB0) ? QUEUE_OLD_RB0 : QUEUE_OLD_RB1; | ||
306 | ican3_set_page(mod, mbox_page); | ||
307 | memcpy_fromio(msg, mod->dpm, sizeof(*msg)); | ||
308 | |||
309 | /* | ||
310 | * notify the firmware that the read buffer is available | ||
311 | * for it to fill again | ||
312 | */ | ||
313 | locl ^= mbox; | ||
314 | |||
315 | ican3_set_page(mod, QUEUE_OLD_CONTROL); | ||
316 | iowrite8(locl, mod->dpm + MSYNC_LOCL); | ||
317 | return 0; | ||
318 | } | ||
319 | |||
320 | /* | ||
321 | * Send a message through the "old-style" firmware interface | ||
322 | * | ||
323 | * LOCKING: must hold mod->lock | ||
324 | * | ||
325 | * returns 0 on success, -ENOMEM when no free space exists | ||
326 | */ | ||
327 | static int ican3_old_send_msg(struct ican3_dev *mod, struct ican3_msg *msg) | ||
328 | { | ||
329 | unsigned int mbox, mbox_page; | ||
330 | u8 locl, peer, xord; | ||
331 | |||
332 | /* get the MSYNC registers */ | ||
333 | ican3_set_page(mod, QUEUE_OLD_CONTROL); | ||
334 | peer = ioread8(mod->dpm + MSYNC_PEER); | ||
335 | locl = ioread8(mod->dpm + MSYNC_LOCL); | ||
336 | xord = locl ^ peer; | ||
337 | |||
338 | if ((xord & MSYNC_WB_MASK) == MSYNC_WB_MASK) { | ||
339 | dev_err(mod->dev, "no mbox for writing\n"); | ||
340 | return -ENOMEM; | ||
341 | } | ||
342 | |||
343 | /* calculate a free mbox to use */ | ||
344 | mbox = (xord & MSYNC_WB0) ? MSYNC_WB1 : MSYNC_WB0; | ||
345 | |||
346 | /* copy the message to the DPM */ | ||
347 | mbox_page = (mbox == MSYNC_WB0) ? QUEUE_OLD_WB0 : QUEUE_OLD_WB1; | ||
348 | ican3_set_page(mod, mbox_page); | ||
349 | memcpy_toio(mod->dpm, msg, sizeof(*msg)); | ||
350 | |||
351 | locl ^= mbox; | ||
352 | if (mbox == MSYNC_WB1) | ||
353 | locl |= MSYNC_WBLW; | ||
354 | |||
355 | ican3_set_page(mod, QUEUE_OLD_CONTROL); | ||
356 | iowrite8(locl, mod->dpm + MSYNC_LOCL); | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * ICAN3 "new-style" Host Interface Setup | ||
362 | */ | ||
363 | |||
364 | static void __devinit ican3_init_new_host_interface(struct ican3_dev *mod) | ||
365 | { | ||
366 | struct ican3_new_desc desc; | ||
367 | unsigned long flags; | ||
368 | void __iomem *dst; | ||
369 | int i; | ||
370 | |||
371 | spin_lock_irqsave(&mod->lock, flags); | ||
372 | |||
373 | /* setup the internal datastructures for RX */ | ||
374 | mod->rx_num = 0; | ||
375 | mod->rx_int = 0; | ||
376 | |||
377 | /* tohost queue descriptors are in page 5 */ | ||
378 | ican3_set_page(mod, QUEUE_TOHOST); | ||
379 | dst = mod->dpm; | ||
380 | |||
381 | /* initialize the tohost (rx) queue descriptors: pages 9-24 */ | ||
382 | for (i = 0; i < ICAN3_NEW_BUFFERS; i++) { | ||
383 | desc.control = DESC_INTERRUPT | DESC_LEN(1); /* I L=1 */ | ||
384 | desc.pointer = mod->free_page; | ||
385 | |||
386 | /* set wrap flag on last buffer */ | ||
387 | if (i == ICAN3_NEW_BUFFERS - 1) | ||
388 | desc.control |= DESC_WRAP; | ||
389 | |||
390 | memcpy_toio(dst, &desc, sizeof(desc)); | ||
391 | dst += sizeof(desc); | ||
392 | mod->free_page++; | ||
393 | } | ||
394 | |||
395 | /* fromhost (tx) mid queue descriptors are in page 6 */ | ||
396 | ican3_set_page(mod, QUEUE_FROMHOST_MID); | ||
397 | dst = mod->dpm; | ||
398 | |||
399 | /* setup the internal datastructures for TX */ | ||
400 | mod->tx_num = 0; | ||
401 | |||
402 | /* initialize the fromhost mid queue descriptors: pages 25-40 */ | ||
403 | for (i = 0; i < ICAN3_NEW_BUFFERS; i++) { | ||
404 | desc.control = DESC_VALID | DESC_LEN(1); /* V L=1 */ | ||
405 | desc.pointer = mod->free_page; | ||
406 | |||
407 | /* set wrap flag on last buffer */ | ||
408 | if (i == ICAN3_NEW_BUFFERS - 1) | ||
409 | desc.control |= DESC_WRAP; | ||
410 | |||
411 | memcpy_toio(dst, &desc, sizeof(desc)); | ||
412 | dst += sizeof(desc); | ||
413 | mod->free_page++; | ||
414 | } | ||
415 | |||
416 | /* fromhost hi queue descriptors are in page 7 */ | ||
417 | ican3_set_page(mod, QUEUE_FROMHOST_HIGH); | ||
418 | dst = mod->dpm; | ||
419 | |||
420 | /* initialize only a single buffer in the fromhost hi queue (unused) */ | ||
421 | desc.control = DESC_VALID | DESC_WRAP | DESC_LEN(1); /* VW L=1 */ | ||
422 | desc.pointer = mod->free_page; | ||
423 | memcpy_toio(dst, &desc, sizeof(desc)); | ||
424 | mod->free_page++; | ||
425 | |||
426 | /* fromhost low queue descriptors are in page 8 */ | ||
427 | ican3_set_page(mod, QUEUE_FROMHOST_LOW); | ||
428 | dst = mod->dpm; | ||
429 | |||
430 | /* initialize only a single buffer in the fromhost low queue (unused) */ | ||
431 | desc.control = DESC_VALID | DESC_WRAP | DESC_LEN(1); /* VW L=1 */ | ||
432 | desc.pointer = mod->free_page; | ||
433 | memcpy_toio(dst, &desc, sizeof(desc)); | ||
434 | mod->free_page++; | ||
435 | |||
436 | spin_unlock_irqrestore(&mod->lock, flags); | ||
437 | } | ||
438 | |||
439 | /* | ||
440 | * ICAN3 Fast Host Interface Setup | ||
441 | */ | ||
442 | |||
443 | static void __devinit ican3_init_fast_host_interface(struct ican3_dev *mod) | ||
444 | { | ||
445 | struct ican3_fast_desc desc; | ||
446 | unsigned long flags; | ||
447 | unsigned int addr; | ||
448 | void __iomem *dst; | ||
449 | int i; | ||
450 | |||
451 | spin_lock_irqsave(&mod->lock, flags); | ||
452 | |||
453 | /* save the start recv page */ | ||
454 | mod->fastrx_start = mod->free_page; | ||
455 | mod->fastrx_num = 0; | ||
456 | mod->fastrx_int = 0; | ||
457 | |||
458 | /* build a single fast tohost queue descriptor */ | ||
459 | memset(&desc, 0, sizeof(desc)); | ||
460 | desc.control = 0x00; | ||
461 | desc.command = 1; | ||
462 | |||
463 | /* build the tohost queue descriptor ring in memory */ | ||
464 | addr = 0; | ||
465 | for (i = 0; i < ICAN3_RX_BUFFERS; i++) { | ||
466 | |||
467 | /* set the wrap bit on the last buffer */ | ||
468 | if (i == ICAN3_RX_BUFFERS - 1) | ||
469 | desc.control |= DESC_WRAP; | ||
470 | |||
471 | /* switch to the correct page */ | ||
472 | ican3_set_page(mod, mod->free_page); | ||
473 | |||
474 | /* copy the descriptor to the DPM */ | ||
475 | dst = mod->dpm + addr; | ||
476 | memcpy_toio(dst, &desc, sizeof(desc)); | ||
477 | addr += sizeof(desc); | ||
478 | |||
479 | /* move to the next page if necessary */ | ||
480 | if (addr >= DPM_PAGE_SIZE) { | ||
481 | addr = 0; | ||
482 | mod->free_page++; | ||
483 | } | ||
484 | } | ||
485 | |||
486 | /* make sure we page-align the next queue */ | ||
487 | if (addr != 0) | ||
488 | mod->free_page++; | ||
489 | |||
490 | /* save the start xmit page */ | ||
491 | mod->fasttx_start = mod->free_page; | ||
492 | mod->fasttx_num = 0; | ||
493 | |||
494 | /* build a single fast fromhost queue descriptor */ | ||
495 | memset(&desc, 0, sizeof(desc)); | ||
496 | desc.control = DESC_VALID; | ||
497 | desc.command = 1; | ||
498 | |||
499 | /* build the fromhost queue descriptor ring in memory */ | ||
500 | addr = 0; | ||
501 | for (i = 0; i < ICAN3_TX_BUFFERS; i++) { | ||
502 | |||
503 | /* set the wrap bit on the last buffer */ | ||
504 | if (i == ICAN3_TX_BUFFERS - 1) | ||
505 | desc.control |= DESC_WRAP; | ||
506 | |||
507 | /* switch to the correct page */ | ||
508 | ican3_set_page(mod, mod->free_page); | ||
509 | |||
510 | /* copy the descriptor to the DPM */ | ||
511 | dst = mod->dpm + addr; | ||
512 | memcpy_toio(dst, &desc, sizeof(desc)); | ||
513 | addr += sizeof(desc); | ||
514 | |||
515 | /* move to the next page if necessary */ | ||
516 | if (addr >= DPM_PAGE_SIZE) { | ||
517 | addr = 0; | ||
518 | mod->free_page++; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | spin_unlock_irqrestore(&mod->lock, flags); | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * ICAN3 "new-style" Host Interface Message Helpers | ||
527 | */ | ||
528 | |||
529 | /* | ||
530 | * LOCKING: must hold mod->lock | ||
531 | */ | ||
532 | static int ican3_new_send_msg(struct ican3_dev *mod, struct ican3_msg *msg) | ||
533 | { | ||
534 | struct ican3_new_desc desc; | ||
535 | void __iomem *desc_addr = mod->dpm + (mod->tx_num * sizeof(desc)); | ||
536 | |||
537 | /* switch to the fromhost mid queue, and read the buffer descriptor */ | ||
538 | ican3_set_page(mod, QUEUE_FROMHOST_MID); | ||
539 | memcpy_fromio(&desc, desc_addr, sizeof(desc)); | ||
540 | |||
541 | if (!(desc.control & DESC_VALID)) { | ||
542 | dev_dbg(mod->dev, "%s: no free buffers\n", __func__); | ||
543 | return -ENOMEM; | ||
544 | } | ||
545 | |||
546 | /* switch to the data page, copy the data */ | ||
547 | ican3_set_page(mod, desc.pointer); | ||
548 | memcpy_toio(mod->dpm, msg, sizeof(*msg)); | ||
549 | |||
550 | /* switch back to the descriptor, set the valid bit, write it back */ | ||
551 | ican3_set_page(mod, QUEUE_FROMHOST_MID); | ||
552 | desc.control ^= DESC_VALID; | ||
553 | memcpy_toio(desc_addr, &desc, sizeof(desc)); | ||
554 | |||
555 | /* update the tx number */ | ||
556 | mod->tx_num = (desc.control & DESC_WRAP) ? 0 : (mod->tx_num + 1); | ||
557 | return 0; | ||
558 | } | ||
559 | |||
560 | /* | ||
561 | * LOCKING: must hold mod->lock | ||
562 | */ | ||
563 | static int ican3_new_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg) | ||
564 | { | ||
565 | struct ican3_new_desc desc; | ||
566 | void __iomem *desc_addr = mod->dpm + (mod->rx_num * sizeof(desc)); | ||
567 | |||
568 | /* switch to the tohost queue, and read the buffer descriptor */ | ||
569 | ican3_set_page(mod, QUEUE_TOHOST); | ||
570 | memcpy_fromio(&desc, desc_addr, sizeof(desc)); | ||
571 | |||
572 | if (!(desc.control & DESC_VALID)) { | ||
573 | dev_dbg(mod->dev, "%s: no buffers to recv\n", __func__); | ||
574 | return -ENOMEM; | ||
575 | } | ||
576 | |||
577 | /* switch to the data page, copy the data */ | ||
578 | ican3_set_page(mod, desc.pointer); | ||
579 | memcpy_fromio(msg, mod->dpm, sizeof(*msg)); | ||
580 | |||
581 | /* switch back to the descriptor, toggle the valid bit, write it back */ | ||
582 | ican3_set_page(mod, QUEUE_TOHOST); | ||
583 | desc.control ^= DESC_VALID; | ||
584 | memcpy_toio(desc_addr, &desc, sizeof(desc)); | ||
585 | |||
586 | /* update the rx number */ | ||
587 | mod->rx_num = (desc.control & DESC_WRAP) ? 0 : (mod->rx_num + 1); | ||
588 | return 0; | ||
589 | } | ||
590 | |||
591 | /* | ||
592 | * Message Send / Recv Helpers | ||
593 | */ | ||
594 | |||
595 | static int ican3_send_msg(struct ican3_dev *mod, struct ican3_msg *msg) | ||
596 | { | ||
597 | unsigned long flags; | ||
598 | int ret; | ||
599 | |||
600 | spin_lock_irqsave(&mod->lock, flags); | ||
601 | |||
602 | if (mod->iftype == 0) | ||
603 | ret = ican3_old_send_msg(mod, msg); | ||
604 | else | ||
605 | ret = ican3_new_send_msg(mod, msg); | ||
606 | |||
607 | spin_unlock_irqrestore(&mod->lock, flags); | ||
608 | return ret; | ||
609 | } | ||
610 | |||
611 | static int ican3_recv_msg(struct ican3_dev *mod, struct ican3_msg *msg) | ||
612 | { | ||
613 | unsigned long flags; | ||
614 | int ret; | ||
615 | |||
616 | spin_lock_irqsave(&mod->lock, flags); | ||
617 | |||
618 | if (mod->iftype == 0) | ||
619 | ret = ican3_old_recv_msg(mod, msg); | ||
620 | else | ||
621 | ret = ican3_new_recv_msg(mod, msg); | ||
622 | |||
623 | spin_unlock_irqrestore(&mod->lock, flags); | ||
624 | return ret; | ||
625 | } | ||
626 | |||
627 | /* | ||
628 | * Quick Pre-constructed Messages | ||
629 | */ | ||
630 | |||
631 | static int __devinit ican3_msg_connect(struct ican3_dev *mod) | ||
632 | { | ||
633 | struct ican3_msg msg; | ||
634 | |||
635 | memset(&msg, 0, sizeof(msg)); | ||
636 | msg.spec = MSG_CONNECTI; | ||
637 | msg.len = cpu_to_le16(0); | ||
638 | |||
639 | return ican3_send_msg(mod, &msg); | ||
640 | } | ||
641 | |||
642 | static int __devexit ican3_msg_disconnect(struct ican3_dev *mod) | ||
643 | { | ||
644 | struct ican3_msg msg; | ||
645 | |||
646 | memset(&msg, 0, sizeof(msg)); | ||
647 | msg.spec = MSG_DISCONNECT; | ||
648 | msg.len = cpu_to_le16(0); | ||
649 | |||
650 | return ican3_send_msg(mod, &msg); | ||
651 | } | ||
652 | |||
653 | static int __devinit ican3_msg_newhostif(struct ican3_dev *mod) | ||
654 | { | ||
655 | struct ican3_msg msg; | ||
656 | int ret; | ||
657 | |||
658 | memset(&msg, 0, sizeof(msg)); | ||
659 | msg.spec = MSG_NEWHOSTIF; | ||
660 | msg.len = cpu_to_le16(0); | ||
661 | |||
662 | /* If we're not using the old interface, switching seems bogus */ | ||
663 | WARN_ON(mod->iftype != 0); | ||
664 | |||
665 | ret = ican3_send_msg(mod, &msg); | ||
666 | if (ret) | ||
667 | return ret; | ||
668 | |||
669 | /* mark the module as using the new host interface */ | ||
670 | mod->iftype = 1; | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static int __devinit ican3_msg_fasthostif(struct ican3_dev *mod) | ||
675 | { | ||
676 | struct ican3_msg msg; | ||
677 | unsigned int addr; | ||
678 | |||
679 | memset(&msg, 0, sizeof(msg)); | ||
680 | msg.spec = MSG_INITFDPMQUEUE; | ||
681 | msg.len = cpu_to_le16(8); | ||
682 | |||
683 | /* write the tohost queue start address */ | ||
684 | addr = DPM_PAGE_ADDR(mod->fastrx_start); | ||
685 | msg.data[0] = addr & 0xff; | ||
686 | msg.data[1] = (addr >> 8) & 0xff; | ||
687 | msg.data[2] = (addr >> 16) & 0xff; | ||
688 | msg.data[3] = (addr >> 24) & 0xff; | ||
689 | |||
690 | /* write the fromhost queue start address */ | ||
691 | addr = DPM_PAGE_ADDR(mod->fasttx_start); | ||
692 | msg.data[4] = addr & 0xff; | ||
693 | msg.data[5] = (addr >> 8) & 0xff; | ||
694 | msg.data[6] = (addr >> 16) & 0xff; | ||
695 | msg.data[7] = (addr >> 24) & 0xff; | ||
696 | |||
697 | /* If we're not using the new interface yet, we cannot do this */ | ||
698 | WARN_ON(mod->iftype != 1); | ||
699 | |||
700 | return ican3_send_msg(mod, &msg); | ||
701 | } | ||
702 | |||
703 | /* | ||
704 | * Setup the CAN filter to either accept or reject all | ||
705 | * messages from the CAN bus. | ||
706 | */ | ||
707 | static int __devinit ican3_set_id_filter(struct ican3_dev *mod, bool accept) | ||
708 | { | ||
709 | struct ican3_msg msg; | ||
710 | int ret; | ||
711 | |||
712 | /* Standard Frame Format */ | ||
713 | memset(&msg, 0, sizeof(msg)); | ||
714 | msg.spec = MSG_SETAFILMASK; | ||
715 | msg.len = cpu_to_le16(5); | ||
716 | msg.data[0] = 0x00; /* IDLo LSB */ | ||
717 | msg.data[1] = 0x00; /* IDLo MSB */ | ||
718 | msg.data[2] = 0xff; /* IDHi LSB */ | ||
719 | msg.data[3] = 0x07; /* IDHi MSB */ | ||
720 | |||
721 | /* accept all frames for fast host if, or reject all frames */ | ||
722 | msg.data[4] = accept ? SETAFILMASK_FASTIF : SETAFILMASK_REJECT; | ||
723 | |||
724 | ret = ican3_send_msg(mod, &msg); | ||
725 | if (ret) | ||
726 | return ret; | ||
727 | |||
728 | /* Extended Frame Format */ | ||
729 | memset(&msg, 0, sizeof(msg)); | ||
730 | msg.spec = MSG_SETAFILMASK; | ||
731 | msg.len = cpu_to_le16(13); | ||
732 | msg.data[0] = 0; /* MUX = 0 */ | ||
733 | msg.data[1] = 0x00; /* IDLo LSB */ | ||
734 | msg.data[2] = 0x00; | ||
735 | msg.data[3] = 0x00; | ||
736 | msg.data[4] = 0x20; /* IDLo MSB */ | ||
737 | msg.data[5] = 0xff; /* IDHi LSB */ | ||
738 | msg.data[6] = 0xff; | ||
739 | msg.data[7] = 0xff; | ||
740 | msg.data[8] = 0x3f; /* IDHi MSB */ | ||
741 | |||
742 | /* accept all frames for fast host if, or reject all frames */ | ||
743 | msg.data[9] = accept ? SETAFILMASK_FASTIF : SETAFILMASK_REJECT; | ||
744 | |||
745 | return ican3_send_msg(mod, &msg); | ||
746 | } | ||
747 | |||
748 | /* | ||
749 | * Bring the CAN bus online or offline | ||
750 | */ | ||
751 | static int ican3_set_bus_state(struct ican3_dev *mod, bool on) | ||
752 | { | ||
753 | struct ican3_msg msg; | ||
754 | |||
755 | memset(&msg, 0, sizeof(msg)); | ||
756 | msg.spec = on ? MSG_CONREQ : MSG_COFFREQ; | ||
757 | msg.len = cpu_to_le16(0); | ||
758 | |||
759 | return ican3_send_msg(mod, &msg); | ||
760 | } | ||
761 | |||
762 | static int ican3_set_termination(struct ican3_dev *mod, bool on) | ||
763 | { | ||
764 | struct ican3_msg msg; | ||
765 | |||
766 | memset(&msg, 0, sizeof(msg)); | ||
767 | msg.spec = MSG_HWCONF; | ||
768 | msg.len = cpu_to_le16(2); | ||
769 | msg.data[0] = 0x00; | ||
770 | msg.data[1] = on ? HWCONF_TERMINATE_ON : HWCONF_TERMINATE_OFF; | ||
771 | |||
772 | return ican3_send_msg(mod, &msg); | ||
773 | } | ||
774 | |||
775 | static int ican3_send_inquiry(struct ican3_dev *mod, u8 subspec) | ||
776 | { | ||
777 | struct ican3_msg msg; | ||
778 | |||
779 | memset(&msg, 0, sizeof(msg)); | ||
780 | msg.spec = MSG_INQUIRY; | ||
781 | msg.len = cpu_to_le16(2); | ||
782 | msg.data[0] = subspec; | ||
783 | msg.data[1] = 0x00; | ||
784 | |||
785 | return ican3_send_msg(mod, &msg); | ||
786 | } | ||
787 | |||
788 | static int ican3_set_buserror(struct ican3_dev *mod, u8 quota) | ||
789 | { | ||
790 | struct ican3_msg msg; | ||
791 | |||
792 | memset(&msg, 0, sizeof(msg)); | ||
793 | msg.spec = MSG_CCONFREQ; | ||
794 | msg.len = cpu_to_le16(2); | ||
795 | msg.data[0] = 0x00; | ||
796 | msg.data[1] = quota; | ||
797 | |||
798 | return ican3_send_msg(mod, &msg); | ||
799 | } | ||
800 | |||
801 | /* | ||
802 | * ICAN3 to Linux CAN Frame Conversion | ||
803 | */ | ||
804 | |||
805 | static void ican3_to_can_frame(struct ican3_dev *mod, | ||
806 | struct ican3_fast_desc *desc, | ||
807 | struct can_frame *cf) | ||
808 | { | ||
809 | if ((desc->command & ICAN3_CAN_TYPE_MASK) == ICAN3_CAN_TYPE_SFF) { | ||
810 | if (desc->data[1] & ICAN3_SFF_RTR) | ||
811 | cf->can_id |= CAN_RTR_FLAG; | ||
812 | |||
813 | cf->can_id |= desc->data[0] << 3; | ||
814 | cf->can_id |= (desc->data[1] & 0xe0) >> 5; | ||
815 | cf->can_dlc = desc->data[1] & ICAN3_CAN_DLC_MASK; | ||
816 | memcpy(cf->data, &desc->data[2], sizeof(cf->data)); | ||
817 | } else { | ||
818 | cf->can_dlc = desc->data[0] & ICAN3_CAN_DLC_MASK; | ||
819 | if (desc->data[0] & ICAN3_EFF_RTR) | ||
820 | cf->can_id |= CAN_RTR_FLAG; | ||
821 | |||
822 | if (desc->data[0] & ICAN3_EFF) { | ||
823 | cf->can_id |= CAN_EFF_FLAG; | ||
824 | cf->can_id |= desc->data[2] << 21; /* 28-21 */ | ||
825 | cf->can_id |= desc->data[3] << 13; /* 20-13 */ | ||
826 | cf->can_id |= desc->data[4] << 5; /* 12-5 */ | ||
827 | cf->can_id |= (desc->data[5] & 0xf8) >> 3; | ||
828 | } else { | ||
829 | cf->can_id |= desc->data[2] << 3; /* 10-3 */ | ||
830 | cf->can_id |= desc->data[3] >> 5; /* 2-0 */ | ||
831 | } | ||
832 | |||
833 | memcpy(cf->data, &desc->data[6], sizeof(cf->data)); | ||
834 | } | ||
835 | } | ||
836 | |||
837 | static void can_frame_to_ican3(struct ican3_dev *mod, | ||
838 | struct can_frame *cf, | ||
839 | struct ican3_fast_desc *desc) | ||
840 | { | ||
841 | /* clear out any stale data in the descriptor */ | ||
842 | memset(desc->data, 0, sizeof(desc->data)); | ||
843 | |||
844 | /* we always use the extended format, with the ECHO flag set */ | ||
845 | desc->command = ICAN3_CAN_TYPE_EFF; | ||
846 | desc->data[0] |= cf->can_dlc; | ||
847 | desc->data[1] |= ICAN3_ECHO; | ||
848 | |||
849 | if (cf->can_id & CAN_RTR_FLAG) | ||
850 | desc->data[0] |= ICAN3_EFF_RTR; | ||
851 | |||
852 | /* pack the id into the correct places */ | ||
853 | if (cf->can_id & CAN_EFF_FLAG) { | ||
854 | desc->data[0] |= ICAN3_EFF; | ||
855 | desc->data[2] = (cf->can_id & 0x1fe00000) >> 21; /* 28-21 */ | ||
856 | desc->data[3] = (cf->can_id & 0x001fe000) >> 13; /* 20-13 */ | ||
857 | desc->data[4] = (cf->can_id & 0x00001fe0) >> 5; /* 12-5 */ | ||
858 | desc->data[5] = (cf->can_id & 0x0000001f) << 3; /* 4-0 */ | ||
859 | } else { | ||
860 | desc->data[2] = (cf->can_id & 0x7F8) >> 3; /* bits 10-3 */ | ||
861 | desc->data[3] = (cf->can_id & 0x007) << 5; /* bits 2-0 */ | ||
862 | } | ||
863 | |||
864 | /* copy the data bits into the descriptor */ | ||
865 | memcpy(&desc->data[6], cf->data, sizeof(cf->data)); | ||
866 | } | ||
867 | |||
868 | /* | ||
869 | * Interrupt Handling | ||
870 | */ | ||
871 | |||
872 | /* | ||
873 | * Handle an ID + Version message response from the firmware. We never generate | ||
874 | * this message in production code, but it is very useful when debugging to be | ||
875 | * able to display this message. | ||
876 | */ | ||
877 | static void ican3_handle_idvers(struct ican3_dev *mod, struct ican3_msg *msg) | ||
878 | { | ||
879 | dev_dbg(mod->dev, "IDVERS response: %s\n", msg->data); | ||
880 | } | ||
881 | |||
882 | static void ican3_handle_msglost(struct ican3_dev *mod, struct ican3_msg *msg) | ||
883 | { | ||
884 | struct net_device *dev = mod->ndev; | ||
885 | struct net_device_stats *stats = &dev->stats; | ||
886 | struct can_frame *cf; | ||
887 | struct sk_buff *skb; | ||
888 | |||
889 | /* | ||
890 | * Report that communication messages with the microcontroller firmware | ||
891 | * are being lost. These are never CAN frames, so we do not generate an | ||
892 | * error frame for userspace | ||
893 | */ | ||
894 | if (msg->spec == MSG_MSGLOST) { | ||
895 | dev_err(mod->dev, "lost %d control messages\n", msg->data[0]); | ||
896 | return; | ||
897 | } | ||
898 | |||
899 | /* | ||
900 | * Oops, this indicates that we have lost messages in the fast queue, | ||
901 | * which are exclusively CAN messages. Our driver isn't reading CAN | ||
902 | * frames fast enough. | ||
903 | * | ||
904 | * We'll pretend that the SJA1000 told us that it ran out of buffer | ||
905 | * space, because there is not a better message for this. | ||
906 | */ | ||
907 | skb = alloc_can_err_skb(dev, &cf); | ||
908 | if (skb) { | ||
909 | cf->can_id |= CAN_ERR_CRTL; | ||
910 | cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | ||
911 | stats->rx_errors++; | ||
912 | stats->rx_bytes += cf->can_dlc; | ||
913 | netif_rx(skb); | ||
914 | } | ||
915 | } | ||
916 | |||
917 | /* | ||
918 | * Handle CAN Event Indication Messages from the firmware | ||
919 | * | ||
920 | * The ICAN3 firmware provides the values of some SJA1000 registers when it | ||
921 | * generates this message. The code below is largely copied from the | ||
922 | * drivers/net/can/sja1000/sja1000.c file, and adapted as necessary | ||
923 | */ | ||
924 | static int ican3_handle_cevtind(struct ican3_dev *mod, struct ican3_msg *msg) | ||
925 | { | ||
926 | struct net_device *dev = mod->ndev; | ||
927 | struct net_device_stats *stats = &dev->stats; | ||
928 | enum can_state state = mod->can.state; | ||
929 | u8 status, isrc, rxerr, txerr; | ||
930 | struct can_frame *cf; | ||
931 | struct sk_buff *skb; | ||
932 | |||
933 | /* we can only handle the SJA1000 part */ | ||
934 | if (msg->data[1] != CEVTIND_CHIP_SJA1000) { | ||
935 | dev_err(mod->dev, "unable to handle errors on non-SJA1000\n"); | ||
936 | return -ENODEV; | ||
937 | } | ||
938 | |||
939 | /* check the message length for sanity */ | ||
940 | if (le16_to_cpu(msg->len) < 6) { | ||
941 | dev_err(mod->dev, "error message too short\n"); | ||
942 | return -EINVAL; | ||
943 | } | ||
944 | |||
945 | skb = alloc_can_err_skb(dev, &cf); | ||
946 | if (skb == NULL) | ||
947 | return -ENOMEM; | ||
948 | |||
949 | isrc = msg->data[0]; | ||
950 | status = msg->data[3]; | ||
951 | rxerr = msg->data[4]; | ||
952 | txerr = msg->data[5]; | ||
953 | |||
954 | /* data overrun interrupt */ | ||
955 | if (isrc == CEVTIND_DOI || isrc == CEVTIND_LOST) { | ||
956 | dev_dbg(mod->dev, "data overrun interrupt\n"); | ||
957 | cf->can_id |= CAN_ERR_CRTL; | ||
958 | cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; | ||
959 | stats->rx_over_errors++; | ||
960 | stats->rx_errors++; | ||
961 | } | ||
962 | |||
963 | /* error warning + passive interrupt */ | ||
964 | if (isrc == CEVTIND_EI) { | ||
965 | dev_dbg(mod->dev, "error warning + passive interrupt\n"); | ||
966 | if (status & SR_BS) { | ||
967 | state = CAN_STATE_BUS_OFF; | ||
968 | cf->can_id |= CAN_ERR_BUSOFF; | ||
969 | can_bus_off(dev); | ||
970 | } else if (status & SR_ES) { | ||
971 | if (rxerr >= 128 || txerr >= 128) | ||
972 | state = CAN_STATE_ERROR_PASSIVE; | ||
973 | else | ||
974 | state = CAN_STATE_ERROR_WARNING; | ||
975 | } else { | ||
976 | state = CAN_STATE_ERROR_ACTIVE; | ||
977 | } | ||
978 | } | ||
979 | |||
980 | /* bus error interrupt */ | ||
981 | if (isrc == CEVTIND_BEI) { | ||
982 | u8 ecc = msg->data[2]; | ||
983 | |||
984 | dev_dbg(mod->dev, "bus error interrupt\n"); | ||
985 | mod->can.can_stats.bus_error++; | ||
986 | stats->rx_errors++; | ||
987 | cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; | ||
988 | |||
989 | switch (ecc & ECC_MASK) { | ||
990 | case ECC_BIT: | ||
991 | cf->data[2] |= CAN_ERR_PROT_BIT; | ||
992 | break; | ||
993 | case ECC_FORM: | ||
994 | cf->data[2] |= CAN_ERR_PROT_FORM; | ||
995 | break; | ||
996 | case ECC_STUFF: | ||
997 | cf->data[2] |= CAN_ERR_PROT_STUFF; | ||
998 | break; | ||
999 | default: | ||
1000 | cf->data[2] |= CAN_ERR_PROT_UNSPEC; | ||
1001 | cf->data[3] = ecc & ECC_SEG; | ||
1002 | break; | ||
1003 | } | ||
1004 | |||
1005 | if ((ecc & ECC_DIR) == 0) | ||
1006 | cf->data[2] |= CAN_ERR_PROT_TX; | ||
1007 | |||
1008 | cf->data[6] = txerr; | ||
1009 | cf->data[7] = rxerr; | ||
1010 | } | ||
1011 | |||
1012 | if (state != mod->can.state && (state == CAN_STATE_ERROR_WARNING || | ||
1013 | state == CAN_STATE_ERROR_PASSIVE)) { | ||
1014 | cf->can_id |= CAN_ERR_CRTL; | ||
1015 | if (state == CAN_STATE_ERROR_WARNING) { | ||
1016 | mod->can.can_stats.error_warning++; | ||
1017 | cf->data[1] = (txerr > rxerr) ? | ||
1018 | CAN_ERR_CRTL_TX_WARNING : | ||
1019 | CAN_ERR_CRTL_RX_WARNING; | ||
1020 | } else { | ||
1021 | mod->can.can_stats.error_passive++; | ||
1022 | cf->data[1] = (txerr > rxerr) ? | ||
1023 | CAN_ERR_CRTL_TX_PASSIVE : | ||
1024 | CAN_ERR_CRTL_RX_PASSIVE; | ||
1025 | } | ||
1026 | |||
1027 | cf->data[6] = txerr; | ||
1028 | cf->data[7] = rxerr; | ||
1029 | } | ||
1030 | |||
1031 | mod->can.state = state; | ||
1032 | stats->rx_errors++; | ||
1033 | stats->rx_bytes += cf->can_dlc; | ||
1034 | netif_rx(skb); | ||
1035 | return 0; | ||
1036 | } | ||
1037 | |||
1038 | static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg) | ||
1039 | { | ||
1040 | switch (msg->data[0]) { | ||
1041 | case INQUIRY_STATUS: | ||
1042 | case INQUIRY_EXTENDED: | ||
1043 | mod->bec.rxerr = msg->data[5]; | ||
1044 | mod->bec.txerr = msg->data[6]; | ||
1045 | complete(&mod->buserror_comp); | ||
1046 | break; | ||
1047 | case INQUIRY_TERMINATION: | ||
1048 | mod->termination_enabled = msg->data[6] & HWCONF_TERMINATE_ON; | ||
1049 | complete(&mod->termination_comp); | ||
1050 | break; | ||
1051 | default: | ||
1052 | dev_err(mod->dev, "recieved an unknown inquiry response\n"); | ||
1053 | break; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | static void ican3_handle_unknown_message(struct ican3_dev *mod, | ||
1058 | struct ican3_msg *msg) | ||
1059 | { | ||
1060 | dev_warn(mod->dev, "recieved unknown message: spec 0x%.2x length %d\n", | ||
1061 | msg->spec, le16_to_cpu(msg->len)); | ||
1062 | } | ||
1063 | |||
1064 | /* | ||
1065 | * Handle a control message from the firmware | ||
1066 | */ | ||
1067 | static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg) | ||
1068 | { | ||
1069 | dev_dbg(mod->dev, "%s: modno %d spec 0x%.2x len %d bytes\n", __func__, | ||
1070 | mod->num, msg->spec, le16_to_cpu(msg->len)); | ||
1071 | |||
1072 | switch (msg->spec) { | ||
1073 | case MSG_IDVERS: | ||
1074 | ican3_handle_idvers(mod, msg); | ||
1075 | break; | ||
1076 | case MSG_MSGLOST: | ||
1077 | case MSG_FMSGLOST: | ||
1078 | ican3_handle_msglost(mod, msg); | ||
1079 | break; | ||
1080 | case MSG_CEVTIND: | ||
1081 | ican3_handle_cevtind(mod, msg); | ||
1082 | break; | ||
1083 | case MSG_INQUIRY: | ||
1084 | ican3_handle_inquiry(mod, msg); | ||
1085 | break; | ||
1086 | default: | ||
1087 | ican3_handle_unknown_message(mod, msg); | ||
1088 | break; | ||
1089 | } | ||
1090 | } | ||
1091 | |||
1092 | /* | ||
1093 | * Check that there is room in the TX ring to transmit another skb | ||
1094 | * | ||
1095 | * LOCKING: must hold mod->lock | ||
1096 | */ | ||
1097 | static bool ican3_txok(struct ican3_dev *mod) | ||
1098 | { | ||
1099 | struct ican3_fast_desc __iomem *desc; | ||
1100 | u8 control; | ||
1101 | |||
1102 | /* copy the control bits of the descriptor */ | ||
1103 | ican3_set_page(mod, mod->fasttx_start + (mod->fasttx_num / 16)); | ||
1104 | desc = mod->dpm + ((mod->fasttx_num % 16) * sizeof(*desc)); | ||
1105 | control = ioread8(&desc->control); | ||
1106 | |||
1107 | /* if the control bits are not valid, then we have no more space */ | ||
1108 | if (!(control & DESC_VALID)) | ||
1109 | return false; | ||
1110 | |||
1111 | return true; | ||
1112 | } | ||
1113 | |||
1114 | /* | ||
1115 | * Recieve one CAN frame from the hardware | ||
1116 | * | ||
1117 | * This works like the core of a NAPI function, but is intended to be called | ||
1118 | * from workqueue context instead. This driver already needs a workqueue to | ||
1119 | * process control messages, so we use the workqueue instead of using NAPI. | ||
1120 | * This was done to simplify locking. | ||
1121 | * | ||
1122 | * CONTEXT: must be called from user context | ||
1123 | */ | ||
1124 | static int ican3_recv_skb(struct ican3_dev *mod) | ||
1125 | { | ||
1126 | struct net_device *ndev = mod->ndev; | ||
1127 | struct net_device_stats *stats = &ndev->stats; | ||
1128 | struct ican3_fast_desc desc; | ||
1129 | void __iomem *desc_addr; | ||
1130 | struct can_frame *cf; | ||
1131 | struct sk_buff *skb; | ||
1132 | unsigned long flags; | ||
1133 | |||
1134 | spin_lock_irqsave(&mod->lock, flags); | ||
1135 | |||
1136 | /* copy the whole descriptor */ | ||
1137 | ican3_set_page(mod, mod->fastrx_start + (mod->fastrx_num / 16)); | ||
1138 | desc_addr = mod->dpm + ((mod->fastrx_num % 16) * sizeof(desc)); | ||
1139 | memcpy_fromio(&desc, desc_addr, sizeof(desc)); | ||
1140 | |||
1141 | spin_unlock_irqrestore(&mod->lock, flags); | ||
1142 | |||
1143 | /* check that we actually have a CAN frame */ | ||
1144 | if (!(desc.control & DESC_VALID)) | ||
1145 | return -ENOBUFS; | ||
1146 | |||
1147 | /* allocate an skb */ | ||
1148 | skb = alloc_can_skb(ndev, &cf); | ||
1149 | if (unlikely(skb == NULL)) { | ||
1150 | stats->rx_dropped++; | ||
1151 | goto err_noalloc; | ||
1152 | } | ||
1153 | |||
1154 | /* convert the ICAN3 frame into Linux CAN format */ | ||
1155 | ican3_to_can_frame(mod, &desc, cf); | ||
1156 | |||
1157 | /* receive the skb, update statistics */ | ||
1158 | netif_receive_skb(skb); | ||
1159 | stats->rx_packets++; | ||
1160 | stats->rx_bytes += cf->can_dlc; | ||
1161 | |||
1162 | err_noalloc: | ||
1163 | /* toggle the valid bit and return the descriptor to the ring */ | ||
1164 | desc.control ^= DESC_VALID; | ||
1165 | |||
1166 | spin_lock_irqsave(&mod->lock, flags); | ||
1167 | |||
1168 | ican3_set_page(mod, mod->fastrx_start + (mod->fastrx_num / 16)); | ||
1169 | memcpy_toio(desc_addr, &desc, 1); | ||
1170 | |||
1171 | /* update the next buffer pointer */ | ||
1172 | mod->fastrx_num = (desc.control & DESC_WRAP) ? 0 | ||
1173 | : (mod->fastrx_num + 1); | ||
1174 | |||
1175 | /* there are still more buffers to process */ | ||
1176 | spin_unlock_irqrestore(&mod->lock, flags); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | static int ican3_napi(struct napi_struct *napi, int budget) | ||
1181 | { | ||
1182 | struct ican3_dev *mod = container_of(napi, struct ican3_dev, napi); | ||
1183 | struct ican3_msg msg; | ||
1184 | unsigned long flags; | ||
1185 | int received = 0; | ||
1186 | int ret; | ||
1187 | |||
1188 | /* process all communication messages */ | ||
1189 | while (true) { | ||
1190 | ret = ican3_recv_msg(mod, &msg); | ||
1191 | if (ret) | ||
1192 | break; | ||
1193 | |||
1194 | ican3_handle_message(mod, &msg); | ||
1195 | } | ||
1196 | |||
1197 | /* process all CAN frames from the fast interface */ | ||
1198 | while (received < budget) { | ||
1199 | ret = ican3_recv_skb(mod); | ||
1200 | if (ret) | ||
1201 | break; | ||
1202 | |||
1203 | received++; | ||
1204 | } | ||
1205 | |||
1206 | /* We have processed all packets that the adapter had, but it | ||
1207 | * was less than our budget, stop polling */ | ||
1208 | if (received < budget) | ||
1209 | napi_complete(napi); | ||
1210 | |||
1211 | spin_lock_irqsave(&mod->lock, flags); | ||
1212 | |||
1213 | /* Wake up the transmit queue if necessary */ | ||
1214 | if (netif_queue_stopped(mod->ndev) && ican3_txok(mod)) | ||
1215 | netif_wake_queue(mod->ndev); | ||
1216 | |||
1217 | spin_unlock_irqrestore(&mod->lock, flags); | ||
1218 | |||
1219 | /* re-enable interrupt generation */ | ||
1220 | iowrite8(1 << mod->num, &mod->ctrl->int_enable); | ||
1221 | return received; | ||
1222 | } | ||
1223 | |||
1224 | static irqreturn_t ican3_irq(int irq, void *dev_id) | ||
1225 | { | ||
1226 | struct ican3_dev *mod = dev_id; | ||
1227 | u8 stat; | ||
1228 | |||
1229 | /* | ||
1230 | * The interrupt status register on this device reports interrupts | ||
1231 | * as zeroes instead of using ones like most other devices | ||
1232 | */ | ||
1233 | stat = ioread8(&mod->ctrl->int_disable) & (1 << mod->num); | ||
1234 | if (stat == (1 << mod->num)) | ||
1235 | return IRQ_NONE; | ||
1236 | |||
1237 | /* clear the MODULbus interrupt from the microcontroller */ | ||
1238 | ioread8(&mod->dpmctrl->interrupt); | ||
1239 | |||
1240 | /* disable interrupt generation, schedule the NAPI poller */ | ||
1241 | iowrite8(1 << mod->num, &mod->ctrl->int_disable); | ||
1242 | napi_schedule(&mod->napi); | ||
1243 | return IRQ_HANDLED; | ||
1244 | } | ||
1245 | |||
1246 | /* | ||
1247 | * Firmware reset, startup, and shutdown | ||
1248 | */ | ||
1249 | |||
1250 | /* | ||
1251 | * Reset an ICAN module to its power-on state | ||
1252 | * | ||
1253 | * CONTEXT: no network device registered | ||
1254 | * LOCKING: work function disabled | ||
1255 | */ | ||
1256 | static int ican3_reset_module(struct ican3_dev *mod) | ||
1257 | { | ||
1258 | u8 val = 1 << mod->num; | ||
1259 | unsigned long start; | ||
1260 | u8 runold, runnew; | ||
1261 | |||
1262 | /* disable interrupts so no more work is scheduled */ | ||
1263 | iowrite8(1 << mod->num, &mod->ctrl->int_disable); | ||
1264 | |||
1265 | /* flush any pending work */ | ||
1266 | flush_scheduled_work(); | ||
1267 | |||
1268 | /* the first unallocated page in the DPM is #9 */ | ||
1269 | mod->free_page = DPM_FREE_START; | ||
1270 | |||
1271 | ican3_set_page(mod, QUEUE_OLD_CONTROL); | ||
1272 | runold = ioread8(mod->dpm + TARGET_RUNNING); | ||
1273 | |||
1274 | /* reset the module */ | ||
1275 | iowrite8(val, &mod->ctrl->reset_assert); | ||
1276 | iowrite8(val, &mod->ctrl->reset_deassert); | ||
1277 | |||
1278 | /* wait until the module has finished resetting and is running */ | ||
1279 | start = jiffies; | ||
1280 | do { | ||
1281 | ican3_set_page(mod, QUEUE_OLD_CONTROL); | ||
1282 | runnew = ioread8(mod->dpm + TARGET_RUNNING); | ||
1283 | if (runnew == (runold ^ 0xff)) | ||
1284 | return 0; | ||
1285 | |||
1286 | msleep(10); | ||
1287 | } while (time_before(jiffies, start + HZ / 4)); | ||
1288 | |||
1289 | dev_err(mod->dev, "failed to reset CAN module\n"); | ||
1290 | return -ETIMEDOUT; | ||
1291 | } | ||
1292 | |||
1293 | static void __devexit ican3_shutdown_module(struct ican3_dev *mod) | ||
1294 | { | ||
1295 | ican3_msg_disconnect(mod); | ||
1296 | ican3_reset_module(mod); | ||
1297 | } | ||
1298 | |||
1299 | /* | ||
1300 | * Startup an ICAN module, bringing it into fast mode | ||
1301 | */ | ||
1302 | static int __devinit ican3_startup_module(struct ican3_dev *mod) | ||
1303 | { | ||
1304 | int ret; | ||
1305 | |||
1306 | ret = ican3_reset_module(mod); | ||
1307 | if (ret) { | ||
1308 | dev_err(mod->dev, "unable to reset module\n"); | ||
1309 | return ret; | ||
1310 | } | ||
1311 | |||
1312 | /* re-enable interrupts so we can send messages */ | ||
1313 | iowrite8(1 << mod->num, &mod->ctrl->int_enable); | ||
1314 | |||
1315 | ret = ican3_msg_connect(mod); | ||
1316 | if (ret) { | ||
1317 | dev_err(mod->dev, "unable to connect to module\n"); | ||
1318 | return ret; | ||
1319 | } | ||
1320 | |||
1321 | ican3_init_new_host_interface(mod); | ||
1322 | ret = ican3_msg_newhostif(mod); | ||
1323 | if (ret) { | ||
1324 | dev_err(mod->dev, "unable to switch to new-style interface\n"); | ||
1325 | return ret; | ||
1326 | } | ||
1327 | |||
1328 | /* default to "termination on" */ | ||
1329 | ret = ican3_set_termination(mod, true); | ||
1330 | if (ret) { | ||
1331 | dev_err(mod->dev, "unable to enable termination\n"); | ||
1332 | return ret; | ||
1333 | } | ||
1334 | |||
1335 | /* default to "bus errors enabled" */ | ||
1336 | ret = ican3_set_buserror(mod, ICAN3_BUSERR_QUOTA_MAX); | ||
1337 | if (ret) { | ||
1338 | dev_err(mod->dev, "unable to set bus-error\n"); | ||
1339 | return ret; | ||
1340 | } | ||
1341 | |||
1342 | ican3_init_fast_host_interface(mod); | ||
1343 | ret = ican3_msg_fasthostif(mod); | ||
1344 | if (ret) { | ||
1345 | dev_err(mod->dev, "unable to switch to fast host interface\n"); | ||
1346 | return ret; | ||
1347 | } | ||
1348 | |||
1349 | ret = ican3_set_id_filter(mod, true); | ||
1350 | if (ret) { | ||
1351 | dev_err(mod->dev, "unable to set acceptance filter\n"); | ||
1352 | return ret; | ||
1353 | } | ||
1354 | |||
1355 | return 0; | ||
1356 | } | ||
1357 | |||
1358 | /* | ||
1359 | * CAN Network Device | ||
1360 | */ | ||
1361 | |||
1362 | static int ican3_open(struct net_device *ndev) | ||
1363 | { | ||
1364 | struct ican3_dev *mod = netdev_priv(ndev); | ||
1365 | u8 quota; | ||
1366 | int ret; | ||
1367 | |||
1368 | /* open the CAN layer */ | ||
1369 | ret = open_candev(ndev); | ||
1370 | if (ret) { | ||
1371 | dev_err(mod->dev, "unable to start CAN layer\n"); | ||
1372 | return ret; | ||
1373 | } | ||
1374 | |||
1375 | /* set the bus error generation state appropriately */ | ||
1376 | if (mod->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) | ||
1377 | quota = ICAN3_BUSERR_QUOTA_MAX; | ||
1378 | else | ||
1379 | quota = 0; | ||
1380 | |||
1381 | ret = ican3_set_buserror(mod, quota); | ||
1382 | if (ret) { | ||
1383 | dev_err(mod->dev, "unable to set bus-error\n"); | ||
1384 | close_candev(ndev); | ||
1385 | return ret; | ||
1386 | } | ||
1387 | |||
1388 | /* bring the bus online */ | ||
1389 | ret = ican3_set_bus_state(mod, true); | ||
1390 | if (ret) { | ||
1391 | dev_err(mod->dev, "unable to set bus-on\n"); | ||
1392 | close_candev(ndev); | ||
1393 | return ret; | ||
1394 | } | ||
1395 | |||
1396 | /* start up the network device */ | ||
1397 | mod->can.state = CAN_STATE_ERROR_ACTIVE; | ||
1398 | netif_start_queue(ndev); | ||
1399 | |||
1400 | return 0; | ||
1401 | } | ||
1402 | |||
1403 | static int ican3_stop(struct net_device *ndev) | ||
1404 | { | ||
1405 | struct ican3_dev *mod = netdev_priv(ndev); | ||
1406 | int ret; | ||
1407 | |||
1408 | /* stop the network device xmit routine */ | ||
1409 | netif_stop_queue(ndev); | ||
1410 | mod->can.state = CAN_STATE_STOPPED; | ||
1411 | |||
1412 | /* bring the bus offline, stop receiving packets */ | ||
1413 | ret = ican3_set_bus_state(mod, false); | ||
1414 | if (ret) { | ||
1415 | dev_err(mod->dev, "unable to set bus-off\n"); | ||
1416 | return ret; | ||
1417 | } | ||
1418 | |||
1419 | /* close the CAN layer */ | ||
1420 | close_candev(ndev); | ||
1421 | return 0; | ||
1422 | } | ||
1423 | |||
1424 | static int ican3_xmit(struct sk_buff *skb, struct net_device *ndev) | ||
1425 | { | ||
1426 | struct ican3_dev *mod = netdev_priv(ndev); | ||
1427 | struct net_device_stats *stats = &ndev->stats; | ||
1428 | struct can_frame *cf = (struct can_frame *)skb->data; | ||
1429 | struct ican3_fast_desc desc; | ||
1430 | void __iomem *desc_addr; | ||
1431 | unsigned long flags; | ||
1432 | |||
1433 | spin_lock_irqsave(&mod->lock, flags); | ||
1434 | |||
1435 | /* check that we can actually transmit */ | ||
1436 | if (!ican3_txok(mod)) { | ||
1437 | dev_err(mod->dev, "no free descriptors, stopping queue\n"); | ||
1438 | netif_stop_queue(ndev); | ||
1439 | spin_unlock_irqrestore(&mod->lock, flags); | ||
1440 | return NETDEV_TX_BUSY; | ||
1441 | } | ||
1442 | |||
1443 | /* copy the control bits of the descriptor */ | ||
1444 | ican3_set_page(mod, mod->fasttx_start + (mod->fasttx_num / 16)); | ||
1445 | desc_addr = mod->dpm + ((mod->fasttx_num % 16) * sizeof(desc)); | ||
1446 | memset(&desc, 0, sizeof(desc)); | ||
1447 | memcpy_fromio(&desc, desc_addr, 1); | ||
1448 | |||
1449 | /* convert the Linux CAN frame into ICAN3 format */ | ||
1450 | can_frame_to_ican3(mod, cf, &desc); | ||
1451 | |||
1452 | /* | ||
1453 | * the programming manual says that you must set the IVALID bit, then | ||
1454 | * interrupt, then set the valid bit. Quite weird, but it seems to be | ||
1455 | * required for this to work | ||
1456 | */ | ||
1457 | desc.control |= DESC_IVALID; | ||
1458 | memcpy_toio(desc_addr, &desc, sizeof(desc)); | ||
1459 | |||
1460 | /* generate a MODULbus interrupt to the microcontroller */ | ||
1461 | iowrite8(0x01, &mod->dpmctrl->interrupt); | ||
1462 | |||
1463 | desc.control ^= DESC_VALID; | ||
1464 | memcpy_toio(desc_addr, &desc, sizeof(desc)); | ||
1465 | |||
1466 | /* update the next buffer pointer */ | ||
1467 | mod->fasttx_num = (desc.control & DESC_WRAP) ? 0 | ||
1468 | : (mod->fasttx_num + 1); | ||
1469 | |||
1470 | /* update statistics */ | ||
1471 | stats->tx_packets++; | ||
1472 | stats->tx_bytes += cf->can_dlc; | ||
1473 | kfree_skb(skb); | ||
1474 | |||
1475 | /* | ||
1476 | * This hardware doesn't have TX-done notifications, so we'll try and | ||
1477 | * emulate it the best we can using ECHO skbs. Get the next TX | ||
1478 | * descriptor, and see if we have room to send. If not, stop the queue. | ||
1479 | * It will be woken when the ECHO skb for the current packet is recv'd. | ||
1480 | */ | ||
1481 | |||
1482 | /* copy the control bits of the descriptor */ | ||
1483 | if (!ican3_txok(mod)) | ||
1484 | netif_stop_queue(ndev); | ||
1485 | |||
1486 | spin_unlock_irqrestore(&mod->lock, flags); | ||
1487 | return NETDEV_TX_OK; | ||
1488 | } | ||
1489 | |||
1490 | static const struct net_device_ops ican3_netdev_ops = { | ||
1491 | .ndo_open = ican3_open, | ||
1492 | .ndo_stop = ican3_stop, | ||
1493 | .ndo_start_xmit = ican3_xmit, | ||
1494 | }; | ||
1495 | |||
1496 | /* | ||
1497 | * Low-level CAN Device | ||
1498 | */ | ||
1499 | |||
1500 | /* This structure was stolen from drivers/net/can/sja1000/sja1000.c */ | ||
1501 | static struct can_bittiming_const ican3_bittiming_const = { | ||
1502 | .name = DRV_NAME, | ||
1503 | .tseg1_min = 1, | ||
1504 | .tseg1_max = 16, | ||
1505 | .tseg2_min = 1, | ||
1506 | .tseg2_max = 8, | ||
1507 | .sjw_max = 4, | ||
1508 | .brp_min = 1, | ||
1509 | .brp_max = 64, | ||
1510 | .brp_inc = 1, | ||
1511 | }; | ||
1512 | |||
1513 | /* | ||
1514 | * This routine was stolen from drivers/net/can/sja1000/sja1000.c | ||
1515 | * | ||
1516 | * The bittiming register command for the ICAN3 just sets the bit timing | ||
1517 | * registers on the SJA1000 chip directly | ||
1518 | */ | ||
1519 | static int ican3_set_bittiming(struct net_device *ndev) | ||
1520 | { | ||
1521 | struct ican3_dev *mod = netdev_priv(ndev); | ||
1522 | struct can_bittiming *bt = &mod->can.bittiming; | ||
1523 | struct ican3_msg msg; | ||
1524 | u8 btr0, btr1; | ||
1525 | |||
1526 | btr0 = ((bt->brp - 1) & 0x3f) | (((bt->sjw - 1) & 0x3) << 6); | ||
1527 | btr1 = ((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) | | ||
1528 | (((bt->phase_seg2 - 1) & 0x7) << 4); | ||
1529 | if (mod->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) | ||
1530 | btr1 |= 0x80; | ||
1531 | |||
1532 | memset(&msg, 0, sizeof(msg)); | ||
1533 | msg.spec = MSG_CBTRREQ; | ||
1534 | msg.len = cpu_to_le16(4); | ||
1535 | msg.data[0] = 0x00; | ||
1536 | msg.data[1] = 0x00; | ||
1537 | msg.data[2] = btr0; | ||
1538 | msg.data[3] = btr1; | ||
1539 | |||
1540 | return ican3_send_msg(mod, &msg); | ||
1541 | } | ||
1542 | |||
1543 | static int ican3_set_mode(struct net_device *ndev, enum can_mode mode) | ||
1544 | { | ||
1545 | struct ican3_dev *mod = netdev_priv(ndev); | ||
1546 | int ret; | ||
1547 | |||
1548 | if (mode != CAN_MODE_START) | ||
1549 | return -ENOTSUPP; | ||
1550 | |||
1551 | /* bring the bus online */ | ||
1552 | ret = ican3_set_bus_state(mod, true); | ||
1553 | if (ret) { | ||
1554 | dev_err(mod->dev, "unable to set bus-on\n"); | ||
1555 | return ret; | ||
1556 | } | ||
1557 | |||
1558 | /* start up the network device */ | ||
1559 | mod->can.state = CAN_STATE_ERROR_ACTIVE; | ||
1560 | |||
1561 | if (netif_queue_stopped(ndev)) | ||
1562 | netif_wake_queue(ndev); | ||
1563 | |||
1564 | return 0; | ||
1565 | } | ||
1566 | |||
1567 | static int ican3_get_berr_counter(const struct net_device *ndev, | ||
1568 | struct can_berr_counter *bec) | ||
1569 | { | ||
1570 | struct ican3_dev *mod = netdev_priv(ndev); | ||
1571 | int ret; | ||
1572 | |||
1573 | ret = ican3_send_inquiry(mod, INQUIRY_STATUS); | ||
1574 | if (ret) | ||
1575 | return ret; | ||
1576 | |||
1577 | ret = wait_for_completion_timeout(&mod->buserror_comp, HZ); | ||
1578 | if (ret <= 0) { | ||
1579 | dev_info(mod->dev, "%s timed out\n", __func__); | ||
1580 | return -ETIMEDOUT; | ||
1581 | } | ||
1582 | |||
1583 | bec->rxerr = mod->bec.rxerr; | ||
1584 | bec->txerr = mod->bec.txerr; | ||
1585 | return 0; | ||
1586 | } | ||
1587 | |||
1588 | /* | ||
1589 | * Sysfs Attributes | ||
1590 | */ | ||
1591 | |||
1592 | static ssize_t ican3_sysfs_show_term(struct device *dev, | ||
1593 | struct device_attribute *attr, | ||
1594 | char *buf) | ||
1595 | { | ||
1596 | struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); | ||
1597 | int ret; | ||
1598 | |||
1599 | ret = ican3_send_inquiry(mod, INQUIRY_TERMINATION); | ||
1600 | if (ret) | ||
1601 | return ret; | ||
1602 | |||
1603 | ret = wait_for_completion_timeout(&mod->termination_comp, HZ); | ||
1604 | if (ret <= 0) { | ||
1605 | dev_info(mod->dev, "%s timed out\n", __func__); | ||
1606 | return -ETIMEDOUT; | ||
1607 | } | ||
1608 | |||
1609 | return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled); | ||
1610 | } | ||
1611 | |||
1612 | static ssize_t ican3_sysfs_set_term(struct device *dev, | ||
1613 | struct device_attribute *attr, | ||
1614 | const char *buf, size_t count) | ||
1615 | { | ||
1616 | struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); | ||
1617 | unsigned long enable; | ||
1618 | int ret; | ||
1619 | |||
1620 | if (strict_strtoul(buf, 0, &enable)) | ||
1621 | return -EINVAL; | ||
1622 | |||
1623 | ret = ican3_set_termination(mod, enable); | ||
1624 | if (ret) | ||
1625 | return ret; | ||
1626 | |||
1627 | return count; | ||
1628 | } | ||
1629 | |||
1630 | static DEVICE_ATTR(termination, S_IWUGO | S_IRUGO, ican3_sysfs_show_term, | ||
1631 | ican3_sysfs_set_term); | ||
1632 | |||
1633 | static struct attribute *ican3_sysfs_attrs[] = { | ||
1634 | &dev_attr_termination.attr, | ||
1635 | NULL, | ||
1636 | }; | ||
1637 | |||
1638 | static struct attribute_group ican3_sysfs_attr_group = { | ||
1639 | .attrs = ican3_sysfs_attrs, | ||
1640 | }; | ||
1641 | |||
1642 | /* | ||
1643 | * PCI Subsystem | ||
1644 | */ | ||
1645 | |||
1646 | static int __devinit ican3_probe(struct platform_device *pdev) | ||
1647 | { | ||
1648 | struct janz_platform_data *pdata; | ||
1649 | struct net_device *ndev; | ||
1650 | struct ican3_dev *mod; | ||
1651 | struct resource *res; | ||
1652 | struct device *dev; | ||
1653 | int ret; | ||
1654 | |||
1655 | pdata = pdev->dev.platform_data; | ||
1656 | if (!pdata) | ||
1657 | return -ENXIO; | ||
1658 | |||
1659 | dev_dbg(&pdev->dev, "probe: module number %d\n", pdata->modno); | ||
1660 | |||
1661 | /* save the struct device for printing */ | ||
1662 | dev = &pdev->dev; | ||
1663 | |||
1664 | /* allocate the CAN device and private data */ | ||
1665 | ndev = alloc_candev(sizeof(*mod), 0); | ||
1666 | if (!ndev) { | ||
1667 | dev_err(dev, "unable to allocate CANdev\n"); | ||
1668 | ret = -ENOMEM; | ||
1669 | goto out_return; | ||
1670 | } | ||
1671 | |||
1672 | platform_set_drvdata(pdev, ndev); | ||
1673 | mod = netdev_priv(ndev); | ||
1674 | mod->ndev = ndev; | ||
1675 | mod->dev = &pdev->dev; | ||
1676 | mod->num = pdata->modno; | ||
1677 | netif_napi_add(ndev, &mod->napi, ican3_napi, ICAN3_RX_BUFFERS); | ||
1678 | spin_lock_init(&mod->lock); | ||
1679 | init_completion(&mod->termination_comp); | ||
1680 | init_completion(&mod->buserror_comp); | ||
1681 | |||
1682 | /* setup device-specific sysfs attributes */ | ||
1683 | ndev->sysfs_groups[0] = &ican3_sysfs_attr_group; | ||
1684 | |||
1685 | /* the first unallocated page in the DPM is 9 */ | ||
1686 | mod->free_page = DPM_FREE_START; | ||
1687 | |||
1688 | ndev->netdev_ops = &ican3_netdev_ops; | ||
1689 | ndev->flags |= IFF_ECHO; | ||
1690 | SET_NETDEV_DEV(ndev, &pdev->dev); | ||
1691 | |||
1692 | mod->can.clock.freq = ICAN3_CAN_CLOCK; | ||
1693 | mod->can.bittiming_const = &ican3_bittiming_const; | ||
1694 | mod->can.do_set_bittiming = ican3_set_bittiming; | ||
1695 | mod->can.do_set_mode = ican3_set_mode; | ||
1696 | mod->can.do_get_berr_counter = ican3_get_berr_counter; | ||
1697 | mod->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES | ||
1698 | | CAN_CTRLMODE_BERR_REPORTING; | ||
1699 | |||
1700 | /* find our IRQ number */ | ||
1701 | mod->irq = platform_get_irq(pdev, 0); | ||
1702 | if (mod->irq < 0) { | ||
1703 | dev_err(dev, "IRQ line not found\n"); | ||
1704 | ret = -ENODEV; | ||
1705 | goto out_free_ndev; | ||
1706 | } | ||
1707 | |||
1708 | ndev->irq = mod->irq; | ||
1709 | |||
1710 | /* get access to the MODULbus registers for this module */ | ||
1711 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1712 | if (!res) { | ||
1713 | dev_err(dev, "MODULbus registers not found\n"); | ||
1714 | ret = -ENODEV; | ||
1715 | goto out_free_ndev; | ||
1716 | } | ||
1717 | |||
1718 | mod->dpm = ioremap(res->start, resource_size(res)); | ||
1719 | if (!mod->dpm) { | ||
1720 | dev_err(dev, "MODULbus registers not ioremap\n"); | ||
1721 | ret = -ENOMEM; | ||
1722 | goto out_free_ndev; | ||
1723 | } | ||
1724 | |||
1725 | mod->dpmctrl = mod->dpm + DPM_PAGE_SIZE; | ||
1726 | |||
1727 | /* get access to the control registers for this module */ | ||
1728 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
1729 | if (!res) { | ||
1730 | dev_err(dev, "CONTROL registers not found\n"); | ||
1731 | ret = -ENODEV; | ||
1732 | goto out_iounmap_dpm; | ||
1733 | } | ||
1734 | |||
1735 | mod->ctrl = ioremap(res->start, resource_size(res)); | ||
1736 | if (!mod->ctrl) { | ||
1737 | dev_err(dev, "CONTROL registers not ioremap\n"); | ||
1738 | ret = -ENOMEM; | ||
1739 | goto out_iounmap_dpm; | ||
1740 | } | ||
1741 | |||
1742 | /* disable our IRQ, then hookup the IRQ handler */ | ||
1743 | iowrite8(1 << mod->num, &mod->ctrl->int_disable); | ||
1744 | ret = request_irq(mod->irq, ican3_irq, IRQF_SHARED, DRV_NAME, mod); | ||
1745 | if (ret) { | ||
1746 | dev_err(dev, "unable to request IRQ\n"); | ||
1747 | goto out_iounmap_ctrl; | ||
1748 | } | ||
1749 | |||
1750 | /* reset and initialize the CAN controller into fast mode */ | ||
1751 | napi_enable(&mod->napi); | ||
1752 | ret = ican3_startup_module(mod); | ||
1753 | if (ret) { | ||
1754 | dev_err(dev, "%s: unable to start CANdev\n", __func__); | ||
1755 | goto out_free_irq; | ||
1756 | } | ||
1757 | |||
1758 | /* register with the Linux CAN layer */ | ||
1759 | ret = register_candev(ndev); | ||
1760 | if (ret) { | ||
1761 | dev_err(dev, "%s: unable to register CANdev\n", __func__); | ||
1762 | goto out_free_irq; | ||
1763 | } | ||
1764 | |||
1765 | dev_info(dev, "module %d: registered CAN device\n", pdata->modno); | ||
1766 | return 0; | ||
1767 | |||
1768 | out_free_irq: | ||
1769 | napi_disable(&mod->napi); | ||
1770 | iowrite8(1 << mod->num, &mod->ctrl->int_disable); | ||
1771 | free_irq(mod->irq, mod); | ||
1772 | out_iounmap_ctrl: | ||
1773 | iounmap(mod->ctrl); | ||
1774 | out_iounmap_dpm: | ||
1775 | iounmap(mod->dpm); | ||
1776 | out_free_ndev: | ||
1777 | free_candev(ndev); | ||
1778 | out_return: | ||
1779 | return ret; | ||
1780 | } | ||
1781 | |||
1782 | static int __devexit ican3_remove(struct platform_device *pdev) | ||
1783 | { | ||
1784 | struct net_device *ndev = platform_get_drvdata(pdev); | ||
1785 | struct ican3_dev *mod = netdev_priv(ndev); | ||
1786 | |||
1787 | /* unregister the netdevice, stop interrupts */ | ||
1788 | unregister_netdev(ndev); | ||
1789 | napi_disable(&mod->napi); | ||
1790 | iowrite8(1 << mod->num, &mod->ctrl->int_disable); | ||
1791 | free_irq(mod->irq, mod); | ||
1792 | |||
1793 | /* put the module into reset */ | ||
1794 | ican3_shutdown_module(mod); | ||
1795 | |||
1796 | /* unmap all registers */ | ||
1797 | iounmap(mod->ctrl); | ||
1798 | iounmap(mod->dpm); | ||
1799 | |||
1800 | free_candev(ndev); | ||
1801 | |||
1802 | return 0; | ||
1803 | } | ||
1804 | |||
1805 | static struct platform_driver ican3_driver = { | ||
1806 | .driver = { | ||
1807 | .name = DRV_NAME, | ||
1808 | .owner = THIS_MODULE, | ||
1809 | }, | ||
1810 | .probe = ican3_probe, | ||
1811 | .remove = __devexit_p(ican3_remove), | ||
1812 | }; | ||
1813 | |||
1814 | static int __init ican3_init(void) | ||
1815 | { | ||
1816 | return platform_driver_register(&ican3_driver); | ||
1817 | } | ||
1818 | |||
1819 | static void __exit ican3_exit(void) | ||
1820 | { | ||
1821 | platform_driver_unregister(&ican3_driver); | ||
1822 | } | ||
1823 | |||
1824 | MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>"); | ||
1825 | MODULE_DESCRIPTION("Janz MODULbus VMOD-ICAN3 Driver"); | ||
1826 | MODULE_LICENSE("GPL"); | ||
1827 | MODULE_ALIAS("platform:janz-ican3"); | ||
1828 | |||
1829 | module_init(ican3_init); | ||
1830 | module_exit(ican3_exit); | ||
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index be90d3598bca..fe925663d39a 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
@@ -3367,13 +3367,9 @@ static int cnic_cm_shutdown(struct cnic_dev *dev) | |||
3367 | 3367 | ||
3368 | static void cnic_init_context(struct cnic_dev *dev, u32 cid) | 3368 | static void cnic_init_context(struct cnic_dev *dev, u32 cid) |
3369 | { | 3369 | { |
3370 | struct cnic_local *cp = dev->cnic_priv; | ||
3371 | u32 cid_addr; | 3370 | u32 cid_addr; |
3372 | int i; | 3371 | int i; |
3373 | 3372 | ||
3374 | if (CHIP_NUM(cp) == CHIP_NUM_5709) | ||
3375 | return; | ||
3376 | |||
3377 | cid_addr = GET_CID_ADDR(cid); | 3373 | cid_addr = GET_CID_ADDR(cid); |
3378 | 3374 | ||
3379 | for (i = 0; i < CTX_SIZE; i += 4) | 3375 | for (i = 0; i < CTX_SIZE; i += 4) |
@@ -3530,14 +3526,11 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) | |||
3530 | 3526 | ||
3531 | sb_id = cp->status_blk_num; | 3527 | sb_id = cp->status_blk_num; |
3532 | tx_cid = 20; | 3528 | tx_cid = 20; |
3533 | cnic_init_context(dev, tx_cid); | ||
3534 | cnic_init_context(dev, tx_cid + 1); | ||
3535 | cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2; | 3529 | cp->tx_cons_ptr = &s_blk->status_tx_quick_consumer_index2; |
3536 | if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { | 3530 | if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) { |
3537 | struct status_block_msix *sblk = cp->status_blk.bnx2; | 3531 | struct status_block_msix *sblk = cp->status_blk.bnx2; |
3538 | 3532 | ||
3539 | tx_cid = TX_TSS_CID + sb_id - 1; | 3533 | tx_cid = TX_TSS_CID + sb_id - 1; |
3540 | cnic_init_context(dev, tx_cid); | ||
3541 | CNIC_WR(dev, BNX2_TSCH_TSS_CFG, (sb_id << 24) | | 3534 | CNIC_WR(dev, BNX2_TSCH_TSS_CFG, (sb_id << 24) | |
3542 | (TX_TSS_CID << 7)); | 3535 | (TX_TSS_CID << 7)); |
3543 | cp->tx_cons_ptr = &sblk->status_tx_quick_consumer_index; | 3536 | cp->tx_cons_ptr = &sblk->status_tx_quick_consumer_index; |
@@ -3556,6 +3549,9 @@ static void cnic_init_bnx2_tx_ring(struct cnic_dev *dev) | |||
3556 | offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI; | 3549 | offset2 = BNX2_L2CTX_TBDR_BHADDR_HI_XI; |
3557 | offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI; | 3550 | offset3 = BNX2_L2CTX_TBDR_BHADDR_LO_XI; |
3558 | } else { | 3551 | } else { |
3552 | cnic_init_context(dev, tx_cid); | ||
3553 | cnic_init_context(dev, tx_cid + 1); | ||
3554 | |||
3559 | offset0 = BNX2_L2CTX_TYPE; | 3555 | offset0 = BNX2_L2CTX_TYPE; |
3560 | offset1 = BNX2_L2CTX_CMD_TYPE; | 3556 | offset1 = BNX2_L2CTX_CMD_TYPE; |
3561 | offset2 = BNX2_L2CTX_TBDR_BHADDR_HI; | 3557 | offset2 = BNX2_L2CTX_TBDR_BHADDR_HI; |
diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h index 110c62072e6f..0c55177db046 100644 --- a/drivers/net/cnic_if.h +++ b/drivers/net/cnic_if.h | |||
@@ -12,8 +12,8 @@ | |||
12 | #ifndef CNIC_IF_H | 12 | #ifndef CNIC_IF_H |
13 | #define CNIC_IF_H | 13 | #define CNIC_IF_H |
14 | 14 | ||
15 | #define CNIC_MODULE_VERSION "2.1.1" | 15 | #define CNIC_MODULE_VERSION "2.1.2" |
16 | #define CNIC_MODULE_RELDATE "Feb 22, 2010" | 16 | #define CNIC_MODULE_RELDATE "May 26, 2010" |
17 | 17 | ||
18 | #define CNIC_ULP_RDMA 0 | 18 | #define CNIC_ULP_RDMA 0 |
19 | #define CNIC_ULP_ISCSI 1 | 19 | #define CNIC_ULP_ISCSI 1 |
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 326465ffbb23..ddf7a86cd466 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
@@ -681,6 +681,8 @@ static int fec_enet_mii_probe(struct net_device *dev) | |||
681 | struct phy_device *phy_dev = NULL; | 681 | struct phy_device *phy_dev = NULL; |
682 | int phy_addr; | 682 | int phy_addr; |
683 | 683 | ||
684 | fep->phy_dev = NULL; | ||
685 | |||
684 | /* find the first phy */ | 686 | /* find the first phy */ |
685 | for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { | 687 | for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { |
686 | if (fep->mii_bus->phy_map[phy_addr]) { | 688 | if (fep->mii_bus->phy_map[phy_addr]) { |
@@ -711,6 +713,11 @@ static int fec_enet_mii_probe(struct net_device *dev) | |||
711 | fep->link = 0; | 713 | fep->link = 0; |
712 | fep->full_duplex = 0; | 714 | fep->full_duplex = 0; |
713 | 715 | ||
716 | printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " | ||
717 | "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, | ||
718 | fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), | ||
719 | fep->phy_dev->irq); | ||
720 | |||
714 | return 0; | 721 | return 0; |
715 | } | 722 | } |
716 | 723 | ||
@@ -756,13 +763,8 @@ static int fec_enet_mii_init(struct platform_device *pdev) | |||
756 | if (mdiobus_register(fep->mii_bus)) | 763 | if (mdiobus_register(fep->mii_bus)) |
757 | goto err_out_free_mdio_irq; | 764 | goto err_out_free_mdio_irq; |
758 | 765 | ||
759 | if (fec_enet_mii_probe(dev) != 0) | ||
760 | goto err_out_unregister_bus; | ||
761 | |||
762 | return 0; | 766 | return 0; |
763 | 767 | ||
764 | err_out_unregister_bus: | ||
765 | mdiobus_unregister(fep->mii_bus); | ||
766 | err_out_free_mdio_irq: | 768 | err_out_free_mdio_irq: |
767 | kfree(fep->mii_bus->irq); | 769 | kfree(fep->mii_bus->irq); |
768 | err_out_free_mdiobus: | 770 | err_out_free_mdiobus: |
@@ -915,7 +917,12 @@ fec_enet_open(struct net_device *dev) | |||
915 | if (ret) | 917 | if (ret) |
916 | return ret; | 918 | return ret; |
917 | 919 | ||
918 | /* schedule a link state check */ | 920 | /* Probe and connect to PHY when open the interface */ |
921 | ret = fec_enet_mii_probe(dev); | ||
922 | if (ret) { | ||
923 | fec_enet_free_buffers(dev); | ||
924 | return ret; | ||
925 | } | ||
919 | phy_start(fep->phy_dev); | 926 | phy_start(fep->phy_dev); |
920 | netif_start_queue(dev); | 927 | netif_start_queue(dev); |
921 | fep->opened = 1; | 928 | fep->opened = 1; |
@@ -929,10 +936,12 @@ fec_enet_close(struct net_device *dev) | |||
929 | 936 | ||
930 | /* Don't know what to do yet. */ | 937 | /* Don't know what to do yet. */ |
931 | fep->opened = 0; | 938 | fep->opened = 0; |
932 | phy_stop(fep->phy_dev); | ||
933 | netif_stop_queue(dev); | 939 | netif_stop_queue(dev); |
934 | fec_stop(dev); | 940 | fec_stop(dev); |
935 | 941 | ||
942 | if (fep->phy_dev) | ||
943 | phy_disconnect(fep->phy_dev); | ||
944 | |||
936 | fec_enet_free_buffers(dev); | 945 | fec_enet_free_buffers(dev); |
937 | 946 | ||
938 | return 0; | 947 | return 0; |
@@ -1316,11 +1325,6 @@ fec_probe(struct platform_device *pdev) | |||
1316 | if (ret) | 1325 | if (ret) |
1317 | goto failed_register; | 1326 | goto failed_register; |
1318 | 1327 | ||
1319 | printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] " | ||
1320 | "(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name, | ||
1321 | fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev), | ||
1322 | fep->phy_dev->irq); | ||
1323 | |||
1324 | return 0; | 1328 | return 0; |
1325 | 1329 | ||
1326 | failed_register: | 1330 | failed_register: |
diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 694132e04af6..4e7d1d0a2340 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c | |||
@@ -1151,8 +1151,7 @@ static int __init yam_init_driver(void) | |||
1151 | dev = alloc_netdev(sizeof(struct yam_port), name, | 1151 | dev = alloc_netdev(sizeof(struct yam_port), name, |
1152 | yam_setup); | 1152 | yam_setup); |
1153 | if (!dev) { | 1153 | if (!dev) { |
1154 | printk(KERN_ERR "yam: cannot allocate net device %s\n", | 1154 | pr_err("yam: cannot allocate net device\n"); |
1155 | dev->name); | ||
1156 | err = -ENOMEM; | 1155 | err = -ENOMEM; |
1157 | goto error; | 1156 | goto error; |
1158 | } | 1157 | } |
diff --git a/drivers/net/ll_temac.h b/drivers/net/ll_temac.h index c03358434acb..522abe2ff25a 100644 --- a/drivers/net/ll_temac.h +++ b/drivers/net/ll_temac.h | |||
@@ -295,6 +295,10 @@ This option defaults to enabled (set) */ | |||
295 | 295 | ||
296 | #define MULTICAST_CAM_TABLE_NUM 4 | 296 | #define MULTICAST_CAM_TABLE_NUM 4 |
297 | 297 | ||
298 | /* TEMAC Synthesis features */ | ||
299 | #define TEMAC_FEATURE_RX_CSUM (1 << 0) | ||
300 | #define TEMAC_FEATURE_TX_CSUM (1 << 1) | ||
301 | |||
298 | /* TX/RX CURDESC_PTR points to first descriptor */ | 302 | /* TX/RX CURDESC_PTR points to first descriptor */ |
299 | /* TX/RX TAILDESC_PTR points to last descriptor in linked list */ | 303 | /* TX/RX TAILDESC_PTR points to last descriptor in linked list */ |
300 | 304 | ||
@@ -353,6 +357,7 @@ struct temac_local { | |||
353 | struct mutex indirect_mutex; | 357 | struct mutex indirect_mutex; |
354 | u32 options; /* Current options word */ | 358 | u32 options; /* Current options word */ |
355 | int last_link; | 359 | int last_link; |
360 | unsigned int temac_features; | ||
356 | 361 | ||
357 | /* Buffer descriptors */ | 362 | /* Buffer descriptors */ |
358 | struct cdmac_bd *tx_bd_v; | 363 | struct cdmac_bd *tx_bd_v; |
diff --git a/drivers/net/ll_temac_main.c b/drivers/net/ll_temac_main.c index fa7620e28404..52dcc8495647 100644 --- a/drivers/net/ll_temac_main.c +++ b/drivers/net/ll_temac_main.c | |||
@@ -245,7 +245,7 @@ static int temac_dma_bd_init(struct net_device *ndev) | |||
245 | CHNL_CTRL_IRQ_COAL_EN); | 245 | CHNL_CTRL_IRQ_COAL_EN); |
246 | /* 0x10220483 */ | 246 | /* 0x10220483 */ |
247 | /* 0x00100483 */ | 247 | /* 0x00100483 */ |
248 | lp->dma_out(lp, RX_CHNL_CTRL, 0xff010000 | | 248 | lp->dma_out(lp, RX_CHNL_CTRL, 0xff070000 | |
249 | CHNL_CTRL_IRQ_EN | | 249 | CHNL_CTRL_IRQ_EN | |
250 | CHNL_CTRL_IRQ_DLY_EN | | 250 | CHNL_CTRL_IRQ_DLY_EN | |
251 | CHNL_CTRL_IRQ_COAL_EN | | 251 | CHNL_CTRL_IRQ_COAL_EN | |
@@ -574,6 +574,10 @@ static void temac_start_xmit_done(struct net_device *ndev) | |||
574 | if (cur_p->app4) | 574 | if (cur_p->app4) |
575 | dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); | 575 | dev_kfree_skb_irq((struct sk_buff *)cur_p->app4); |
576 | cur_p->app0 = 0; | 576 | cur_p->app0 = 0; |
577 | cur_p->app1 = 0; | ||
578 | cur_p->app2 = 0; | ||
579 | cur_p->app3 = 0; | ||
580 | cur_p->app4 = 0; | ||
577 | 581 | ||
578 | ndev->stats.tx_packets++; | 582 | ndev->stats.tx_packets++; |
579 | ndev->stats.tx_bytes += cur_p->len; | 583 | ndev->stats.tx_bytes += cur_p->len; |
@@ -589,6 +593,29 @@ static void temac_start_xmit_done(struct net_device *ndev) | |||
589 | netif_wake_queue(ndev); | 593 | netif_wake_queue(ndev); |
590 | } | 594 | } |
591 | 595 | ||
596 | static inline int temac_check_tx_bd_space(struct temac_local *lp, int num_frag) | ||
597 | { | ||
598 | struct cdmac_bd *cur_p; | ||
599 | int tail; | ||
600 | |||
601 | tail = lp->tx_bd_tail; | ||
602 | cur_p = &lp->tx_bd_v[tail]; | ||
603 | |||
604 | do { | ||
605 | if (cur_p->app0) | ||
606 | return NETDEV_TX_BUSY; | ||
607 | |||
608 | tail++; | ||
609 | if (tail >= TX_BD_NUM) | ||
610 | tail = 0; | ||
611 | |||
612 | cur_p = &lp->tx_bd_v[tail]; | ||
613 | num_frag--; | ||
614 | } while (num_frag >= 0); | ||
615 | |||
616 | return 0; | ||
617 | } | ||
618 | |||
592 | static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) | 619 | static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) |
593 | { | 620 | { |
594 | struct temac_local *lp = netdev_priv(ndev); | 621 | struct temac_local *lp = netdev_priv(ndev); |
@@ -603,7 +630,7 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
603 | start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; | 630 | start_p = lp->tx_bd_p + sizeof(*lp->tx_bd_v) * lp->tx_bd_tail; |
604 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; | 631 | cur_p = &lp->tx_bd_v[lp->tx_bd_tail]; |
605 | 632 | ||
606 | if (cur_p->app0 & STS_CTRL_APP0_CMPLT) { | 633 | if (temac_check_tx_bd_space(lp, num_frag)) { |
607 | if (!netif_queue_stopped(ndev)) { | 634 | if (!netif_queue_stopped(ndev)) { |
608 | netif_stop_queue(ndev); | 635 | netif_stop_queue(ndev); |
609 | return NETDEV_TX_BUSY; | 636 | return NETDEV_TX_BUSY; |
@@ -613,29 +640,14 @@ static int temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
613 | 640 | ||
614 | cur_p->app0 = 0; | 641 | cur_p->app0 = 0; |
615 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 642 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
616 | const struct iphdr *ip = ip_hdr(skb); | 643 | unsigned int csum_start_off = skb_transport_offset(skb); |
617 | int length = 0, start = 0, insert = 0; | 644 | unsigned int csum_index_off = csum_start_off + skb->csum_offset; |
618 | 645 | ||
619 | switch (ip->protocol) { | 646 | cur_p->app0 |= 1; /* TX Checksum Enabled */ |
620 | case IPPROTO_TCP: | 647 | cur_p->app1 = (csum_start_off << 16) | csum_index_off; |
621 | start = sizeof(struct iphdr) + ETH_HLEN; | 648 | cur_p->app2 = 0; /* initial checksum seed */ |
622 | insert = sizeof(struct iphdr) + ETH_HLEN + 16; | ||
623 | length = ip->tot_len - sizeof(struct iphdr); | ||
624 | break; | ||
625 | case IPPROTO_UDP: | ||
626 | start = sizeof(struct iphdr) + ETH_HLEN; | ||
627 | insert = sizeof(struct iphdr) + ETH_HLEN + 6; | ||
628 | length = ip->tot_len - sizeof(struct iphdr); | ||
629 | break; | ||
630 | default: | ||
631 | break; | ||
632 | } | ||
633 | cur_p->app1 = ((start << 16) | insert); | ||
634 | cur_p->app2 = csum_tcpudp_magic(ip->saddr, ip->daddr, | ||
635 | length, ip->protocol, 0); | ||
636 | skb->data[insert] = 0; | ||
637 | skb->data[insert + 1] = 0; | ||
638 | } | 649 | } |
650 | |||
639 | cur_p->app0 |= STS_CTRL_APP0_SOP; | 651 | cur_p->app0 |= STS_CTRL_APP0_SOP; |
640 | cur_p->len = skb_headlen(skb); | 652 | cur_p->len = skb_headlen(skb); |
641 | cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len, | 653 | cur_p->phys = dma_map_single(ndev->dev.parent, skb->data, skb->len, |
@@ -699,6 +711,15 @@ static void ll_temac_recv(struct net_device *ndev) | |||
699 | skb->protocol = eth_type_trans(skb, ndev); | 711 | skb->protocol = eth_type_trans(skb, ndev); |
700 | skb->ip_summed = CHECKSUM_NONE; | 712 | skb->ip_summed = CHECKSUM_NONE; |
701 | 713 | ||
714 | /* if we're doing rx csum offload, set it up */ | ||
715 | if (((lp->temac_features & TEMAC_FEATURE_RX_CSUM) != 0) && | ||
716 | (skb->protocol == __constant_htons(ETH_P_IP)) && | ||
717 | (skb->len > 64)) { | ||
718 | |||
719 | skb->csum = cur_p->app3 & 0xFFFF; | ||
720 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
721 | } | ||
722 | |||
702 | netif_rx(skb); | 723 | netif_rx(skb); |
703 | 724 | ||
704 | ndev->stats.rx_packets++; | 725 | ndev->stats.rx_packets++; |
@@ -883,6 +904,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) | |||
883 | struct temac_local *lp; | 904 | struct temac_local *lp; |
884 | struct net_device *ndev; | 905 | struct net_device *ndev; |
885 | const void *addr; | 906 | const void *addr; |
907 | __be32 *p; | ||
886 | int size, rc = 0; | 908 | int size, rc = 0; |
887 | 909 | ||
888 | /* Init network device structure */ | 910 | /* Init network device structure */ |
@@ -926,6 +948,18 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) | |||
926 | goto nodev; | 948 | goto nodev; |
927 | } | 949 | } |
928 | 950 | ||
951 | /* Setup checksum offload, but default to off if not specified */ | ||
952 | lp->temac_features = 0; | ||
953 | p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,txcsum", NULL); | ||
954 | if (p && be32_to_cpu(*p)) { | ||
955 | lp->temac_features |= TEMAC_FEATURE_TX_CSUM; | ||
956 | /* Can checksum TCP/UDP over IPv4. */ | ||
957 | ndev->features |= NETIF_F_IP_CSUM; | ||
958 | } | ||
959 | p = (__be32 *)of_get_property(op->dev.of_node, "xlnx,rxcsum", NULL); | ||
960 | if (p && be32_to_cpu(*p)) | ||
961 | lp->temac_features |= TEMAC_FEATURE_RX_CSUM; | ||
962 | |||
929 | /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ | 963 | /* Find the DMA node, map the DMA registers, and decode the DMA IRQs */ |
930 | np = of_parse_phandle(op->dev.of_node, "llink-connected", 0); | 964 | np = of_parse_phandle(op->dev.of_node, "llink-connected", 0); |
931 | if (!np) { | 965 | if (!np) { |
@@ -950,7 +984,7 @@ temac_of_probe(struct of_device *op, const struct of_device_id *match) | |||
950 | 984 | ||
951 | lp->rx_irq = irq_of_parse_and_map(np, 0); | 985 | lp->rx_irq = irq_of_parse_and_map(np, 0); |
952 | lp->tx_irq = irq_of_parse_and_map(np, 1); | 986 | lp->tx_irq = irq_of_parse_and_map(np, 1); |
953 | if (!lp->rx_irq || !lp->tx_irq) { | 987 | if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { |
954 | dev_err(&op->dev, "could not determine irqs\n"); | 988 | dev_err(&op->dev, "could not determine irqs\n"); |
955 | rc = -ENOMEM; | 989 | rc = -ENOMEM; |
956 | goto nodev; | 990 | goto nodev; |
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/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h index 7aaae2d2bd67..80c11d131499 100644 --- a/drivers/pci/pcie/aer/aerdrv.h +++ b/drivers/pci/pcie/aer/aerdrv.h | |||
@@ -130,4 +130,21 @@ static inline int aer_osc_setup(struct pcie_device *pciedev) | |||
130 | } | 130 | } |
131 | #endif | 131 | #endif |
132 | 132 | ||
133 | #ifdef CONFIG_ACPI_APEI | ||
134 | extern int pcie_aer_get_firmware_first(struct pci_dev *pci_dev); | ||
135 | #else | ||
136 | static inline int pcie_aer_get_firmware_first(struct pci_dev *pci_dev) | ||
137 | { | ||
138 | if (pci_dev->__aer_firmware_first_valid) | ||
139 | return pci_dev->__aer_firmware_first; | ||
140 | return 0; | ||
141 | } | ||
142 | #endif | ||
143 | |||
144 | static inline void pcie_aer_force_firmware_first(struct pci_dev *pci_dev, | ||
145 | int enable) | ||
146 | { | ||
147 | pci_dev->__aer_firmware_first = !!enable; | ||
148 | pci_dev->__aer_firmware_first_valid = 1; | ||
149 | } | ||
133 | #endif /* _AERDRV_H_ */ | 150 | #endif /* _AERDRV_H_ */ |
diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 04814087658d..f278d7b0d95d 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
17 | #include <linux/pci-acpi.h> | 17 | #include <linux/pci-acpi.h> |
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <acpi/apei.h> | ||
19 | #include "aerdrv.h" | 20 | #include "aerdrv.h" |
20 | 21 | ||
21 | /** | 22 | /** |
@@ -53,3 +54,79 @@ int aer_osc_setup(struct pcie_device *pciedev) | |||
53 | 54 | ||
54 | return 0; | 55 | return 0; |
55 | } | 56 | } |
57 | |||
58 | #ifdef CONFIG_ACPI_APEI | ||
59 | static inline int hest_match_pci(struct acpi_hest_aer_common *p, | ||
60 | struct pci_dev *pci) | ||
61 | { | ||
62 | return (0 == pci_domain_nr(pci->bus) && | ||
63 | p->bus == pci->bus->number && | ||
64 | p->device == PCI_SLOT(pci->devfn) && | ||
65 | p->function == PCI_FUNC(pci->devfn)); | ||
66 | } | ||
67 | |||
68 | struct aer_hest_parse_info { | ||
69 | struct pci_dev *pci_dev; | ||
70 | int firmware_first; | ||
71 | }; | ||
72 | |||
73 | static int aer_hest_parse(struct acpi_hest_header *hest_hdr, void *data) | ||
74 | { | ||
75 | struct aer_hest_parse_info *info = data; | ||
76 | struct acpi_hest_aer_common *p; | ||
77 | u8 pcie_type = 0; | ||
78 | u8 bridge = 0; | ||
79 | int ff = 0; | ||
80 | |||
81 | switch (hest_hdr->type) { | ||
82 | case ACPI_HEST_TYPE_AER_ROOT_PORT: | ||
83 | pcie_type = PCI_EXP_TYPE_ROOT_PORT; | ||
84 | break; | ||
85 | case ACPI_HEST_TYPE_AER_ENDPOINT: | ||
86 | pcie_type = PCI_EXP_TYPE_ENDPOINT; | ||
87 | break; | ||
88 | case ACPI_HEST_TYPE_AER_BRIDGE: | ||
89 | if ((info->pci_dev->class >> 16) == PCI_BASE_CLASS_BRIDGE) | ||
90 | bridge = 1; | ||
91 | break; | ||
92 | default: | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | p = (struct acpi_hest_aer_common *)(hest_hdr + 1); | ||
97 | if (p->flags & ACPI_HEST_GLOBAL) { | ||
98 | if ((info->pci_dev->is_pcie && | ||
99 | info->pci_dev->pcie_type == pcie_type) || bridge) | ||
100 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
101 | } else | ||
102 | if (hest_match_pci(p, info->pci_dev)) | ||
103 | ff = !!(p->flags & ACPI_HEST_FIRMWARE_FIRST); | ||
104 | info->firmware_first = ff; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void aer_set_firmware_first(struct pci_dev *pci_dev) | ||
110 | { | ||
111 | int rc; | ||
112 | struct aer_hest_parse_info info = { | ||
113 | .pci_dev = pci_dev, | ||
114 | .firmware_first = 0, | ||
115 | }; | ||
116 | |||
117 | rc = apei_hest_parse(aer_hest_parse, &info); | ||
118 | |||
119 | if (rc) | ||
120 | pci_dev->__aer_firmware_first = 0; | ||
121 | else | ||
122 | pci_dev->__aer_firmware_first = info.firmware_first; | ||
123 | pci_dev->__aer_firmware_first_valid = 1; | ||
124 | } | ||
125 | |||
126 | int pcie_aer_get_firmware_first(struct pci_dev *dev) | ||
127 | { | ||
128 | if (!dev->__aer_firmware_first_valid) | ||
129 | aer_set_firmware_first(dev); | ||
130 | return dev->__aer_firmware_first; | ||
131 | } | ||
132 | #endif | ||
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index df2d686fe3dd..8af4f619bba2 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -36,7 +36,7 @@ int pci_enable_pcie_error_reporting(struct pci_dev *dev) | |||
36 | u16 reg16 = 0; | 36 | u16 reg16 = 0; |
37 | int pos; | 37 | int pos; |
38 | 38 | ||
39 | if (dev->aer_firmware_first) | 39 | if (pcie_aer_get_firmware_first(dev)) |
40 | return -EIO; | 40 | return -EIO; |
41 | 41 | ||
42 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); | 42 | pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR); |
@@ -63,7 +63,7 @@ int pci_disable_pcie_error_reporting(struct pci_dev *dev) | |||
63 | u16 reg16 = 0; | 63 | u16 reg16 = 0; |
64 | int pos; | 64 | int pos; |
65 | 65 | ||
66 | if (dev->aer_firmware_first) | 66 | if (pcie_aer_get_firmware_first(dev)) |
67 | return -EIO; | 67 | return -EIO; |
68 | 68 | ||
69 | pos = pci_pcie_cap(dev); | 69 | pos = pci_pcie_cap(dev); |
@@ -771,7 +771,7 @@ void aer_isr(struct work_struct *work) | |||
771 | */ | 771 | */ |
772 | int aer_init(struct pcie_device *dev) | 772 | int aer_init(struct pcie_device *dev) |
773 | { | 773 | { |
774 | if (dev->port->aer_firmware_first) { | 774 | if (pcie_aer_get_firmware_first(dev->port)) { |
775 | dev_printk(KERN_DEBUG, &dev->device, | 775 | dev_printk(KERN_DEBUG, &dev->device, |
776 | "PCIe errors handled by platform firmware.\n"); | 776 | "PCIe errors handled by platform firmware.\n"); |
777 | goto out; | 777 | goto out; |
@@ -785,7 +785,7 @@ out: | |||
785 | if (forceload) { | 785 | if (forceload) { |
786 | dev_printk(KERN_DEBUG, &dev->device, | 786 | dev_printk(KERN_DEBUG, &dev->device, |
787 | "aerdrv forceload requested.\n"); | 787 | "aerdrv forceload requested.\n"); |
788 | dev->port->aer_firmware_first = 0; | 788 | pcie_aer_force_firmware_first(dev->port, 0); |
789 | return 0; | 789 | return 0; |
790 | } | 790 | } |
791 | return -ENXIO; | 791 | return -ENXIO; |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index c82548afcd5c..f4adba2d1dd3 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/cpumask.h> | 11 | #include <linux/cpumask.h> |
12 | #include <linux/pci-aspm.h> | 12 | #include <linux/pci-aspm.h> |
13 | #include <acpi/acpi_hest.h> | ||
14 | #include "pci.h" | 13 | #include "pci.h" |
15 | 14 | ||
16 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ | 15 | #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ |
@@ -904,12 +903,6 @@ void set_pcie_hotplug_bridge(struct pci_dev *pdev) | |||
904 | pdev->is_hotplug_bridge = 1; | 903 | pdev->is_hotplug_bridge = 1; |
905 | } | 904 | } |
906 | 905 | ||
907 | static void set_pci_aer_firmware_first(struct pci_dev *pdev) | ||
908 | { | ||
909 | if (acpi_hest_firmware_first_pci(pdev)) | ||
910 | pdev->aer_firmware_first = 1; | ||
911 | } | ||
912 | |||
913 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) | 906 | #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) |
914 | 907 | ||
915 | /** | 908 | /** |
@@ -939,7 +932,6 @@ int pci_setup_device(struct pci_dev *dev) | |||
939 | dev->multifunction = !!(hdr_type & 0x80); | 932 | dev->multifunction = !!(hdr_type & 0x80); |
940 | dev->error_state = pci_channel_io_normal; | 933 | dev->error_state = pci_channel_io_normal; |
941 | set_pcie_port_type(dev); | 934 | set_pcie_port_type(dev); |
942 | set_pci_aer_firmware_first(dev); | ||
943 | 935 | ||
944 | list_for_each_entry(slot, &dev->bus->slots, list) | 936 | list_for_each_entry(slot, &dev->bus->slots, list) |
945 | if (PCI_SLOT(dev->devfn) == slot->number) | 937 | if (PCI_SLOT(dev->devfn) == slot->number) |
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..8070e074c739 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 | * @rdev: RIO device | ||
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..08fa453af974 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,331 @@ 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 | * @rdev: 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 | * @port: Master port to issue transaction | ||
389 | * @local: Indicate a local master port or remote device access | ||
390 | * @destid: Destination ID of the device | ||
391 | * @hopcount: Number of switch hops to the device | ||
392 | */ | ||
393 | u32 | ||
394 | rio_mport_get_physefb(struct rio_mport *port, int local, | ||
395 | u16 destid, u8 hopcount) | ||
396 | { | ||
397 | u32 ext_ftr_ptr; | ||
398 | u32 ftr_header; | ||
399 | |||
400 | ext_ftr_ptr = rio_mport_get_efb(port, local, destid, hopcount, 0); | ||
401 | |||
402 | while (ext_ftr_ptr) { | ||
403 | if (local) | ||
404 | rio_local_read_config_32(port, ext_ftr_ptr, | ||
405 | &ftr_header); | ||
406 | else | ||
407 | rio_mport_read_config_32(port, destid, hopcount, | ||
408 | ext_ftr_ptr, &ftr_header); | ||
409 | |||
410 | ftr_header = RIO_GET_BLOCK_ID(ftr_header); | ||
411 | switch (ftr_header) { | ||
412 | |||
413 | case RIO_EFB_SER_EP_ID_V13P: | ||
414 | case RIO_EFB_SER_EP_REC_ID_V13P: | ||
415 | case RIO_EFB_SER_EP_FREE_ID_V13P: | ||
416 | case RIO_EFB_SER_EP_ID: | ||
417 | case RIO_EFB_SER_EP_REC_ID: | ||
418 | case RIO_EFB_SER_EP_FREE_ID: | ||
419 | case RIO_EFB_SER_EP_FREC_ID: | ||
420 | |||
421 | return ext_ftr_ptr; | ||
422 | |||
423 | default: | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | ext_ftr_ptr = rio_mport_get_efb(port, local, destid, | ||
428 | hopcount, ext_ftr_ptr); | ||
429 | } | ||
430 | |||
431 | return ext_ftr_ptr; | ||
432 | } | ||
433 | |||
434 | /** | ||
435 | * rio_get_comptag - Begin or continue searching for a RIO device by component tag | ||
436 | * @comp_tag: RIO component tag to match | ||
437 | * @from: Previous RIO device found in search, or %NULL for new search | ||
438 | * | ||
439 | * Iterates through the list of known RIO devices. If a RIO device is | ||
440 | * found with a matching @comp_tag, a pointer to its device | ||
441 | * structure is returned. Otherwise, %NULL is returned. A new search | ||
442 | * is initiated by passing %NULL to the @from argument. Otherwise, if | ||
443 | * @from is not %NULL, searches continue from next device on the global | ||
444 | * list. | ||
445 | */ | ||
446 | static struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from) | ||
447 | { | ||
448 | struct list_head *n; | ||
449 | struct rio_dev *rdev; | ||
450 | |||
451 | spin_lock(&rio_global_list_lock); | ||
452 | n = from ? from->global_list.next : rio_devices.next; | ||
453 | |||
454 | while (n && (n != &rio_devices)) { | ||
455 | rdev = rio_dev_g(n); | ||
456 | if (rdev->comp_tag == comp_tag) | ||
457 | goto exit; | ||
458 | n = n->next; | ||
459 | } | ||
460 | rdev = NULL; | ||
461 | exit: | ||
462 | spin_unlock(&rio_global_list_lock); | ||
463 | return rdev; | ||
464 | } | ||
465 | |||
466 | /** | ||
467 | * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port. | ||
468 | * @rdev: Pointer to RIO device control structure | ||
469 | * @pnum: Switch port number to set LOCKOUT bit | ||
470 | * @lock: Operation : set (=1) or clear (=0) | ||
471 | */ | ||
472 | int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock) | ||
473 | { | ||
474 | u8 hopcount = 0xff; | ||
475 | u16 destid = rdev->destid; | ||
476 | u32 regval; | ||
477 | |||
478 | if (rdev->rswitch) { | ||
479 | destid = rdev->rswitch->destid; | ||
480 | hopcount = rdev->rswitch->hopcount; | ||
481 | } | ||
482 | |||
483 | rio_mport_read_config_32(rdev->net->hport, destid, hopcount, | ||
484 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), | ||
485 | ®val); | ||
486 | if (lock) | ||
487 | regval |= RIO_PORT_N_CTL_LOCKOUT; | ||
488 | else | ||
489 | regval &= ~RIO_PORT_N_CTL_LOCKOUT; | ||
490 | |||
491 | rio_mport_write_config_32(rdev->net->hport, destid, hopcount, | ||
492 | rdev->phys_efptr + RIO_PORT_N_CTL_CSR(pnum), | ||
493 | regval); | ||
494 | return 0; | ||
495 | } | ||
496 | |||
497 | /** | ||
498 | * rio_inb_pwrite_handler - process inbound port-write message | ||
499 | * @pw_msg: pointer to inbound port-write message | ||
500 | * | ||
501 | * Processes an inbound port-write message. Returns 0 if the request | ||
502 | * has been satisfied. | ||
503 | */ | ||
504 | int rio_inb_pwrite_handler(union rio_pw_msg *pw_msg) | ||
505 | { | ||
506 | struct rio_dev *rdev; | ||
507 | struct rio_mport *mport; | ||
508 | u8 hopcount; | ||
509 | u16 destid; | ||
510 | u32 err_status; | ||
511 | int rc, portnum; | ||
512 | |||
513 | rdev = rio_get_comptag(pw_msg->em.comptag, NULL); | ||
514 | if (rdev == NULL) { | ||
515 | /* Someting bad here (probably enumeration error) */ | ||
516 | pr_err("RIO: %s No matching device for CTag 0x%08x\n", | ||
517 | __func__, pw_msg->em.comptag); | ||
518 | return -EIO; | ||
519 | } | ||
520 | |||
521 | pr_debug("RIO: Port-Write message from %s\n", rio_name(rdev)); | ||
522 | |||
523 | #ifdef DEBUG_PW | ||
524 | { | ||
525 | u32 i; | ||
526 | for (i = 0; i < RIO_PW_MSG_SIZE/sizeof(u32);) { | ||
527 | pr_debug("0x%02x: %08x %08x %08x %08x", | ||
528 | i*4, pw_msg->raw[i], pw_msg->raw[i + 1], | ||
529 | pw_msg->raw[i + 2], pw_msg->raw[i + 3]); | ||
530 | i += 4; | ||
531 | } | ||
532 | pr_debug("\n"); | ||
533 | } | ||
534 | #endif | ||
535 | |||
536 | /* Call an external service function (if such is registered | ||
537 | * for this device). This may be the service for endpoints that send | ||
538 | * device-specific port-write messages. End-point messages expected | ||
539 | * to be handled completely by EP specific device driver. | ||
540 | * For switches rc==0 signals that no standard processing required. | ||
541 | */ | ||
542 | if (rdev->pwcback != NULL) { | ||
543 | rc = rdev->pwcback(rdev, pw_msg, 0); | ||
544 | if (rc == 0) | ||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | /* For End-point devices processing stops here */ | ||
549 | if (!(rdev->pef & RIO_PEF_SWITCH)) | ||
550 | return 0; | ||
551 | |||
552 | if (rdev->phys_efptr == 0) { | ||
553 | pr_err("RIO_PW: Bad switch initialization for %s\n", | ||
554 | rio_name(rdev)); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | mport = rdev->net->hport; | ||
559 | destid = rdev->rswitch->destid; | ||
560 | hopcount = rdev->rswitch->hopcount; | ||
561 | |||
562 | /* | ||
563 | * Process the port-write notification from switch | ||
564 | */ | ||
565 | |||
566 | portnum = pw_msg->em.is_port & 0xFF; | ||
567 | |||
568 | if (rdev->rswitch->em_handle) | ||
569 | rdev->rswitch->em_handle(rdev, portnum); | ||
570 | |||
571 | rio_mport_read_config_32(mport, destid, hopcount, | ||
572 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | ||
573 | &err_status); | ||
574 | pr_debug("RIO_PW: SP%d_ERR_STS_CSR=0x%08x\n", portnum, err_status); | ||
575 | |||
576 | if (pw_msg->em.errdetect) { | ||
577 | pr_debug("RIO_PW: RIO_EM_P%d_ERR_DETECT=0x%08x\n", | ||
578 | portnum, pw_msg->em.errdetect); | ||
579 | /* Clear EM Port N Error Detect CSR */ | ||
580 | rio_mport_write_config_32(mport, destid, hopcount, | ||
581 | rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), 0); | ||
582 | } | ||
583 | |||
584 | if (pw_msg->em.ltlerrdet) { | ||
585 | pr_debug("RIO_PW: RIO_EM_LTL_ERR_DETECT=0x%08x\n", | ||
586 | pw_msg->em.ltlerrdet); | ||
587 | /* Clear EM L/T Layer Error Detect CSR */ | ||
588 | rio_mport_write_config_32(mport, destid, hopcount, | ||
589 | rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, 0); | ||
590 | } | ||
591 | |||
592 | /* Clear Port Errors */ | ||
593 | rio_mport_write_config_32(mport, destid, hopcount, | ||
594 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | ||
595 | err_status & RIO_PORT_N_ERR_STS_CLR_MASK); | ||
596 | |||
597 | if (rdev->rswitch->port_ok & (1 << portnum)) { | ||
598 | if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT) { | ||
599 | rdev->rswitch->port_ok &= ~(1 << portnum); | ||
600 | rio_set_port_lockout(rdev, portnum, 1); | ||
601 | |||
602 | rio_mport_write_config_32(mport, destid, hopcount, | ||
603 | rdev->phys_efptr + | ||
604 | RIO_PORT_N_ACK_STS_CSR(portnum), | ||
605 | RIO_PORT_N_ACK_CLEAR); | ||
606 | |||
607 | /* Schedule Extraction Service */ | ||
608 | pr_debug("RIO_PW: Device Extraction on [%s]-P%d\n", | ||
609 | rio_name(rdev), portnum); | ||
610 | } | ||
611 | } else { | ||
612 | if (err_status & RIO_PORT_N_ERR_STS_PORT_OK) { | ||
613 | rdev->rswitch->port_ok |= (1 << portnum); | ||
614 | rio_set_port_lockout(rdev, portnum, 0); | ||
615 | |||
616 | /* Schedule Insertion Service */ | ||
617 | pr_debug("RIO_PW: Device Insertion on [%s]-P%d\n", | ||
618 | rio_name(rdev), portnum); | ||
619 | } | ||
620 | } | ||
621 | |||
622 | /* Clear Port-Write Pending bit */ | ||
623 | rio_mport_write_config_32(mport, destid, hopcount, | ||
624 | rdev->phys_efptr + RIO_PORT_N_ERR_STS_CSR(portnum), | ||
625 | RIO_PORT_N_ERR_STS_PW_PEND); | ||
626 | |||
627 | return 0; | ||
628 | } | ||
629 | EXPORT_SYMBOL_GPL(rio_inb_pwrite_handler); | ||
630 | |||
631 | /** | ||
632 | * rio_mport_get_efb - get pointer to next extended features block | ||
633 | * @port: Master port to issue transaction | ||
634 | * @local: Indicate a local master port or remote device access | ||
635 | * @destid: Destination ID of the device | ||
636 | * @hopcount: Number of switch hops to the device | ||
637 | * @from: Offset of current Extended Feature block header (if 0 starts | ||
638 | * from ExtFeaturePtr) | ||
639 | */ | ||
640 | u32 | ||
641 | rio_mport_get_efb(struct rio_mport *port, int local, u16 destid, | ||
642 | u8 hopcount, u32 from) | ||
643 | { | ||
644 | u32 reg_val; | ||
645 | |||
646 | if (from == 0) { | ||
647 | if (local) | ||
648 | rio_local_read_config_32(port, RIO_ASM_INFO_CAR, | ||
649 | ®_val); | ||
650 | else | ||
651 | rio_mport_read_config_32(port, destid, hopcount, | ||
652 | RIO_ASM_INFO_CAR, ®_val); | ||
653 | return reg_val & RIO_EXT_FTR_PTR_MASK; | ||
654 | } else { | ||
655 | if (local) | ||
656 | rio_local_read_config_32(port, from, ®_val); | ||
657 | else | ||
658 | rio_mport_read_config_32(port, destid, hopcount, | ||
659 | from, ®_val); | ||
660 | return RIO_GET_BLOCK_ID(reg_val); | ||
661 | } | ||
662 | } | ||
663 | |||
664 | /** | ||
336 | * rio_mport_get_feature - query for devices' extended features | 665 | * rio_mport_get_feature - query for devices' extended features |
337 | * @port: Master port to issue transaction | 666 | * @port: Master port to issue transaction |
338 | * @local: Indicate a local master port or remote device access | 667 | * @local: Indicate a local master port or remote device access |
@@ -451,6 +780,110 @@ 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); | 780 | return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); |
452 | } | 781 | } |
453 | 782 | ||
783 | /** | ||
784 | * rio_std_route_add_entry - Add switch route table entry using standard | ||
785 | * registers defined in RIO specification rev.1.3 | ||
786 | * @mport: Master port to issue transaction | ||
787 | * @destid: Destination ID of the device | ||
788 | * @hopcount: Number of switch hops to the device | ||
789 | * @table: routing table ID (global or port-specific) | ||
790 | * @route_destid: destID entry in the RT | ||
791 | * @route_port: destination port for specified destID | ||
792 | */ | ||
793 | int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
794 | u16 table, u16 route_destid, u8 route_port) | ||
795 | { | ||
796 | if (table == RIO_GLOBAL_TABLE) { | ||
797 | rio_mport_write_config_32(mport, destid, hopcount, | ||
798 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, | ||
799 | (u32)route_destid); | ||
800 | rio_mport_write_config_32(mport, destid, hopcount, | ||
801 | RIO_STD_RTE_CONF_PORT_SEL_CSR, | ||
802 | (u32)route_port); | ||
803 | } | ||
804 | |||
805 | udelay(10); | ||
806 | return 0; | ||
807 | } | ||
808 | |||
809 | /** | ||
810 | * rio_std_route_get_entry - Read switch route table entry (port number) | ||
811 | * assosiated with specified destID using standard registers defined in RIO | ||
812 | * specification rev.1.3 | ||
813 | * @mport: Master port to issue transaction | ||
814 | * @destid: Destination ID of the device | ||
815 | * @hopcount: Number of switch hops to the device | ||
816 | * @table: routing table ID (global or port-specific) | ||
817 | * @route_destid: destID entry in the RT | ||
818 | * @route_port: returned destination port for specified destID | ||
819 | */ | ||
820 | int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
821 | u16 table, u16 route_destid, u8 *route_port) | ||
822 | { | ||
823 | u32 result; | ||
824 | |||
825 | if (table == RIO_GLOBAL_TABLE) { | ||
826 | rio_mport_write_config_32(mport, destid, hopcount, | ||
827 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid); | ||
828 | rio_mport_read_config_32(mport, destid, hopcount, | ||
829 | RIO_STD_RTE_CONF_PORT_SEL_CSR, &result); | ||
830 | |||
831 | *route_port = (u8)result; | ||
832 | } | ||
833 | |||
834 | return 0; | ||
835 | } | ||
836 | |||
837 | /** | ||
838 | * rio_std_route_clr_table - Clear swotch route table using standard registers | ||
839 | * defined in RIO specification rev.1.3. | ||
840 | * @mport: Master port to issue transaction | ||
841 | * @destid: Destination ID of the device | ||
842 | * @hopcount: Number of switch hops to the device | ||
843 | * @table: routing table ID (global or port-specific) | ||
844 | */ | ||
845 | int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, | ||
846 | u16 table) | ||
847 | { | ||
848 | u32 max_destid = 0xff; | ||
849 | u32 i, pef, id_inc = 1, ext_cfg = 0; | ||
850 | u32 port_sel = RIO_INVALID_ROUTE; | ||
851 | |||
852 | if (table == RIO_GLOBAL_TABLE) { | ||
853 | rio_mport_read_config_32(mport, destid, hopcount, | ||
854 | RIO_PEF_CAR, &pef); | ||
855 | |||
856 | if (mport->sys_size) { | ||
857 | rio_mport_read_config_32(mport, destid, hopcount, | ||
858 | RIO_SWITCH_RT_LIMIT, | ||
859 | &max_destid); | ||
860 | max_destid &= RIO_RT_MAX_DESTID; | ||
861 | } | ||
862 | |||
863 | if (pef & RIO_PEF_EXT_RT) { | ||
864 | ext_cfg = 0x80000000; | ||
865 | id_inc = 4; | ||
866 | port_sel = (RIO_INVALID_ROUTE << 24) | | ||
867 | (RIO_INVALID_ROUTE << 16) | | ||
868 | (RIO_INVALID_ROUTE << 8) | | ||
869 | RIO_INVALID_ROUTE; | ||
870 | } | ||
871 | |||
872 | for (i = 0; i <= max_destid;) { | ||
873 | rio_mport_write_config_32(mport, destid, hopcount, | ||
874 | RIO_STD_RTE_CONF_DESTID_SEL_CSR, | ||
875 | ext_cfg | i); | ||
876 | rio_mport_write_config_32(mport, destid, hopcount, | ||
877 | RIO_STD_RTE_CONF_PORT_SEL_CSR, | ||
878 | port_sel); | ||
879 | i += id_inc; | ||
880 | } | ||
881 | } | ||
882 | |||
883 | udelay(10); | ||
884 | return 0; | ||
885 | } | ||
886 | |||
454 | static void rio_fixup_device(struct rio_dev *dev) | 887 | static void rio_fixup_device(struct rio_dev *dev) |
455 | { | 888 | { |
456 | } | 889 | } |
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/regulator/ab3100.c b/drivers/regulator/ab3100.c index 1afd008ca957..7b14a67bdca2 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/regulator/driver.h> | 18 | #include <linux/regulator/driver.h> |
19 | #include <linux/mfd/ab3100.h> | 19 | #include <linux/mfd/abx500.h> |
20 | 20 | ||
21 | /* LDO registers and some handy masking definitions for AB3100 */ | 21 | /* LDO registers and some handy masking definitions for AB3100 */ |
22 | #define AB3100_LDO_A 0x40 | 22 | #define AB3100_LDO_A 0x40 |
@@ -41,7 +41,7 @@ | |||
41 | * struct ab3100_regulator | 41 | * struct ab3100_regulator |
42 | * A struct passed around the individual regulator functions | 42 | * A struct passed around the individual regulator functions |
43 | * @platform_device: platform device holding this regulator | 43 | * @platform_device: platform device holding this regulator |
44 | * @ab3100: handle to the AB3100 parent chip | 44 | * @dev: handle to the device |
45 | * @plfdata: AB3100 platform data passed in at probe time | 45 | * @plfdata: AB3100 platform data passed in at probe time |
46 | * @regreg: regulator register number in the AB3100 | 46 | * @regreg: regulator register number in the AB3100 |
47 | * @fixed_voltage: a fixed voltage for this regulator, if this | 47 | * @fixed_voltage: a fixed voltage for this regulator, if this |
@@ -52,7 +52,7 @@ | |||
52 | */ | 52 | */ |
53 | struct ab3100_regulator { | 53 | struct ab3100_regulator { |
54 | struct regulator_dev *rdev; | 54 | struct regulator_dev *rdev; |
55 | struct ab3100 *ab3100; | 55 | struct device *dev; |
56 | struct ab3100_platform_data *plfdata; | 56 | struct ab3100_platform_data *plfdata; |
57 | u8 regreg; | 57 | u8 regreg; |
58 | int fixed_voltage; | 58 | int fixed_voltage; |
@@ -183,7 +183,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg) | |||
183 | int err; | 183 | int err; |
184 | u8 regval; | 184 | u8 regval; |
185 | 185 | ||
186 | err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg, | 186 | err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg, |
187 | ®val); | 187 | ®val); |
188 | if (err) { | 188 | if (err) { |
189 | dev_warn(®->dev, "failed to get regid %d value\n", | 189 | dev_warn(®->dev, "failed to get regid %d value\n", |
@@ -197,7 +197,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg) | |||
197 | 197 | ||
198 | regval |= AB3100_REG_ON_MASK; | 198 | regval |= AB3100_REG_ON_MASK; |
199 | 199 | ||
200 | err = ab3100_set_register_interruptible(abreg->ab3100, abreg->regreg, | 200 | err = abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg, |
201 | regval); | 201 | regval); |
202 | if (err) { | 202 | if (err) { |
203 | dev_warn(®->dev, "failed to set regid %d value\n", | 203 | dev_warn(®->dev, "failed to set regid %d value\n", |
@@ -245,14 +245,14 @@ static int ab3100_disable_regulator(struct regulator_dev *reg) | |||
245 | if (abreg->regreg == AB3100_LDO_D) { | 245 | if (abreg->regreg == AB3100_LDO_D) { |
246 | dev_info(®->dev, "disabling LDO D - shut down system\n"); | 246 | dev_info(®->dev, "disabling LDO D - shut down system\n"); |
247 | /* Setting LDO D to 0x00 cuts the power to the SoC */ | 247 | /* Setting LDO D to 0x00 cuts the power to the SoC */ |
248 | return ab3100_set_register_interruptible(abreg->ab3100, | 248 | return abx500_set_register_interruptible(abreg->dev, 0, |
249 | AB3100_LDO_D, 0x00U); | 249 | AB3100_LDO_D, 0x00U); |
250 | } | 250 | } |
251 | 251 | ||
252 | /* | 252 | /* |
253 | * All other regulators are handled here | 253 | * All other regulators are handled here |
254 | */ | 254 | */ |
255 | err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg, | 255 | err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg, |
256 | ®val); | 256 | ®val); |
257 | if (err) { | 257 | if (err) { |
258 | dev_err(®->dev, "unable to get register 0x%x\n", | 258 | dev_err(®->dev, "unable to get register 0x%x\n", |
@@ -260,7 +260,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg) | |||
260 | return err; | 260 | return err; |
261 | } | 261 | } |
262 | regval &= ~AB3100_REG_ON_MASK; | 262 | regval &= ~AB3100_REG_ON_MASK; |
263 | return ab3100_set_register_interruptible(abreg->ab3100, abreg->regreg, | 263 | return abx500_set_register_interruptible(abreg->dev, 0, abreg->regreg, |
264 | regval); | 264 | regval); |
265 | } | 265 | } |
266 | 266 | ||
@@ -270,7 +270,7 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg) | |||
270 | u8 regval; | 270 | u8 regval; |
271 | int err; | 271 | int err; |
272 | 272 | ||
273 | err = ab3100_get_register_interruptible(abreg->ab3100, abreg->regreg, | 273 | err = abx500_get_register_interruptible(abreg->dev, 0, abreg->regreg, |
274 | ®val); | 274 | ®val); |
275 | if (err) { | 275 | if (err) { |
276 | dev_err(®->dev, "unable to get register 0x%x\n", | 276 | dev_err(®->dev, "unable to get register 0x%x\n", |
@@ -305,7 +305,7 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg) | |||
305 | * For variable types, read out setting and index into | 305 | * For variable types, read out setting and index into |
306 | * supplied voltage list. | 306 | * supplied voltage list. |
307 | */ | 307 | */ |
308 | err = ab3100_get_register_interruptible(abreg->ab3100, | 308 | err = abx500_get_register_interruptible(abreg->dev, 0, |
309 | abreg->regreg, ®val); | 309 | abreg->regreg, ®val); |
310 | if (err) { | 310 | if (err) { |
311 | dev_warn(®->dev, | 311 | dev_warn(®->dev, |
@@ -373,7 +373,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg, | |||
373 | if (bestindex < 0) | 373 | if (bestindex < 0) |
374 | return bestindex; | 374 | return bestindex; |
375 | 375 | ||
376 | err = ab3100_get_register_interruptible(abreg->ab3100, | 376 | err = abx500_get_register_interruptible(abreg->dev, 0, |
377 | abreg->regreg, ®val); | 377 | abreg->regreg, ®val); |
378 | if (err) { | 378 | if (err) { |
379 | dev_warn(®->dev, | 379 | dev_warn(®->dev, |
@@ -386,7 +386,7 @@ static int ab3100_set_voltage_regulator(struct regulator_dev *reg, | |||
386 | regval &= ~0xE0; | 386 | regval &= ~0xE0; |
387 | regval |= (bestindex << 5); | 387 | regval |= (bestindex << 5); |
388 | 388 | ||
389 | err = ab3100_set_register_interruptible(abreg->ab3100, | 389 | err = abx500_set_register_interruptible(abreg->dev, 0, |
390 | abreg->regreg, regval); | 390 | abreg->regreg, regval); |
391 | if (err) | 391 | if (err) |
392 | dev_warn(®->dev, "failed to set regulator register %02x\n", | 392 | dev_warn(®->dev, "failed to set regulator register %02x\n", |
@@ -414,7 +414,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg, | |||
414 | /* LDO E and BUCK have special suspend voltages you can set */ | 414 | /* LDO E and BUCK have special suspend voltages you can set */ |
415 | bestindex = ab3100_get_best_voltage_index(reg, uV, uV); | 415 | bestindex = ab3100_get_best_voltage_index(reg, uV, uV); |
416 | 416 | ||
417 | err = ab3100_get_register_interruptible(abreg->ab3100, | 417 | err = abx500_get_register_interruptible(abreg->dev, 0, |
418 | targetreg, ®val); | 418 | targetreg, ®val); |
419 | if (err) { | 419 | if (err) { |
420 | dev_warn(®->dev, | 420 | dev_warn(®->dev, |
@@ -427,7 +427,7 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg, | |||
427 | regval &= ~0xE0; | 427 | regval &= ~0xE0; |
428 | regval |= (bestindex << 5); | 428 | regval |= (bestindex << 5); |
429 | 429 | ||
430 | err = ab3100_set_register_interruptible(abreg->ab3100, | 430 | err = abx500_set_register_interruptible(abreg->dev, 0, |
431 | targetreg, regval); | 431 | targetreg, regval); |
432 | if (err) | 432 | if (err) |
433 | dev_warn(®->dev, "failed to set regulator register %02x\n", | 433 | dev_warn(®->dev, "failed to set regulator register %02x\n", |
@@ -574,13 +574,12 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = { | |||
574 | static int __devinit ab3100_regulators_probe(struct platform_device *pdev) | 574 | static int __devinit ab3100_regulators_probe(struct platform_device *pdev) |
575 | { | 575 | { |
576 | struct ab3100_platform_data *plfdata = pdev->dev.platform_data; | 576 | struct ab3100_platform_data *plfdata = pdev->dev.platform_data; |
577 | struct ab3100 *ab3100 = platform_get_drvdata(pdev); | ||
578 | int err = 0; | 577 | int err = 0; |
579 | u8 data; | 578 | u8 data; |
580 | int i; | 579 | int i; |
581 | 580 | ||
582 | /* Check chip state */ | 581 | /* Check chip state */ |
583 | err = ab3100_get_register_interruptible(ab3100, | 582 | err = abx500_get_register_interruptible(&pdev->dev, 0, |
584 | AB3100_LDO_D, &data); | 583 | AB3100_LDO_D, &data); |
585 | if (err) { | 584 | if (err) { |
586 | dev_err(&pdev->dev, "could not read initial status of LDO_D\n"); | 585 | dev_err(&pdev->dev, "could not read initial status of LDO_D\n"); |
@@ -595,7 +594,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) | |||
595 | 594 | ||
596 | /* Set up regulators */ | 595 | /* Set up regulators */ |
597 | for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { | 596 | for (i = 0; i < ARRAY_SIZE(ab3100_reg_init_order); i++) { |
598 | err = ab3100_set_register_interruptible(ab3100, | 597 | err = abx500_set_register_interruptible(&pdev->dev, 0, |
599 | ab3100_reg_init_order[i], | 598 | ab3100_reg_init_order[i], |
600 | plfdata->reg_initvals[i]); | 599 | plfdata->reg_initvals[i]); |
601 | if (err) { | 600 | if (err) { |
@@ -617,7 +616,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev) | |||
617 | * see what it looks like for a certain machine, go | 616 | * see what it looks like for a certain machine, go |
618 | * into the machine I2C setup. | 617 | * into the machine I2C setup. |
619 | */ | 618 | */ |
620 | reg->ab3100 = ab3100; | 619 | reg->dev = &pdev->dev; |
621 | reg->plfdata = plfdata; | 620 | reg->plfdata = plfdata; |
622 | 621 | ||
623 | /* | 622 | /* |
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 74841abcc9cc..14b4576281c5 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -22,68 +22,9 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/regulator/driver.h> | 23 | #include <linux/regulator/driver.h> |
24 | #include <linux/regulator/machine.h> | 24 | #include <linux/regulator/machine.h> |
25 | #include <linux/i2c.h> | ||
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
28 | 27 | #include <linux/mfd/tps6507x.h> | |
29 | /* Register definitions */ | ||
30 | #define TPS6507X_REG_PPATH1 0X01 | ||
31 | #define TPS6507X_REG_INT 0X02 | ||
32 | #define TPS6507X_REG_CHGCONFIG0 0X03 | ||
33 | #define TPS6507X_REG_CHGCONFIG1 0X04 | ||
34 | #define TPS6507X_REG_CHGCONFIG2 0X05 | ||
35 | #define TPS6507X_REG_CHGCONFIG3 0X06 | ||
36 | #define TPS6507X_REG_REG_ADCONFIG 0X07 | ||
37 | #define TPS6507X_REG_TSCMODE 0X08 | ||
38 | #define TPS6507X_REG_ADRESULT_1 0X09 | ||
39 | #define TPS6507X_REG_ADRESULT_2 0X0A | ||
40 | #define TPS6507X_REG_PGOOD 0X0B | ||
41 | #define TPS6507X_REG_PGOODMASK 0X0C | ||
42 | #define TPS6507X_REG_CON_CTRL1 0X0D | ||
43 | #define TPS6507X_REG_CON_CTRL2 0X0E | ||
44 | #define TPS6507X_REG_CON_CTRL3 0X0F | ||
45 | #define TPS6507X_REG_DEFDCDC1 0X10 | ||
46 | #define TPS6507X_REG_DEFDCDC2_LOW 0X11 | ||
47 | #define TPS6507X_REG_DEFDCDC2_HIGH 0X12 | ||
48 | #define TPS6507X_REG_DEFDCDC3_LOW 0X13 | ||
49 | #define TPS6507X_REG_DEFDCDC3_HIGH 0X14 | ||
50 | #define TPS6507X_REG_DEFSLEW 0X15 | ||
51 | #define TPS6507X_REG_LDO_CTRL1 0X16 | ||
52 | #define TPS6507X_REG_DEFLDO2 0X17 | ||
53 | #define TPS6507X_REG_WLED_CTRL1 0X18 | ||
54 | #define TPS6507X_REG_WLED_CTRL2 0X19 | ||
55 | |||
56 | /* CON_CTRL1 bitfields */ | ||
57 | #define TPS6507X_CON_CTRL1_DCDC1_ENABLE BIT(4) | ||
58 | #define TPS6507X_CON_CTRL1_DCDC2_ENABLE BIT(3) | ||
59 | #define TPS6507X_CON_CTRL1_DCDC3_ENABLE BIT(2) | ||
60 | #define TPS6507X_CON_CTRL1_LDO1_ENABLE BIT(1) | ||
61 | #define TPS6507X_CON_CTRL1_LDO2_ENABLE BIT(0) | ||
62 | |||
63 | /* DEFDCDC1 bitfields */ | ||
64 | #define TPS6507X_DEFDCDC1_DCDC1_EXT_ADJ_EN BIT(7) | ||
65 | #define TPS6507X_DEFDCDC1_DCDC1_MASK 0X3F | ||
66 | |||
67 | /* DEFDCDC2_LOW bitfields */ | ||
68 | #define TPS6507X_DEFDCDC2_LOW_DCDC2_MASK 0X3F | ||
69 | |||
70 | /* DEFDCDC2_HIGH bitfields */ | ||
71 | #define TPS6507X_DEFDCDC2_HIGH_DCDC2_MASK 0X3F | ||
72 | |||
73 | /* DEFDCDC3_LOW bitfields */ | ||
74 | #define TPS6507X_DEFDCDC3_LOW_DCDC3_MASK 0X3F | ||
75 | |||
76 | /* DEFDCDC3_HIGH bitfields */ | ||
77 | #define TPS6507X_DEFDCDC3_HIGH_DCDC3_MASK 0X3F | ||
78 | |||
79 | /* TPS6507X_REG_LDO_CTRL1 bitfields */ | ||
80 | #define TPS6507X_REG_LDO_CTRL1_LDO1_MASK 0X0F | ||
81 | |||
82 | /* TPS6507X_REG_DEFLDO2 bitfields */ | ||
83 | #define TPS6507X_REG_DEFLDO2_LDO2_MASK 0X3F | ||
84 | |||
85 | /* VDCDC MASK */ | ||
86 | #define TPS6507X_DEFDCDCX_DCDC_MASK 0X3F | ||
87 | 28 | ||
88 | /* DCDC's */ | 29 | /* DCDC's */ |
89 | #define TPS6507X_DCDC_1 0 | 30 | #define TPS6507X_DCDC_1 0 |
@@ -162,101 +103,146 @@ struct tps_info { | |||
162 | const u16 *table; | 103 | const u16 *table; |
163 | }; | 104 | }; |
164 | 105 | ||
165 | struct tps_pmic { | 106 | static const struct tps_info tps6507x_pmic_regs[] = { |
107 | { | ||
108 | .name = "VDCDC1", | ||
109 | .min_uV = 725000, | ||
110 | .max_uV = 3300000, | ||
111 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
112 | .table = VDCDCx_VSEL_table, | ||
113 | }, | ||
114 | { | ||
115 | .name = "VDCDC2", | ||
116 | .min_uV = 725000, | ||
117 | .max_uV = 3300000, | ||
118 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
119 | .table = VDCDCx_VSEL_table, | ||
120 | }, | ||
121 | { | ||
122 | .name = "VDCDC3", | ||
123 | .min_uV = 725000, | ||
124 | .max_uV = 3300000, | ||
125 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
126 | .table = VDCDCx_VSEL_table, | ||
127 | }, | ||
128 | { | ||
129 | .name = "LDO1", | ||
130 | .min_uV = 1000000, | ||
131 | .max_uV = 3300000, | ||
132 | .table_len = ARRAY_SIZE(LDO1_VSEL_table), | ||
133 | .table = LDO1_VSEL_table, | ||
134 | }, | ||
135 | { | ||
136 | .name = "LDO2", | ||
137 | .min_uV = 725000, | ||
138 | .max_uV = 3300000, | ||
139 | .table_len = ARRAY_SIZE(LDO2_VSEL_table), | ||
140 | .table = LDO2_VSEL_table, | ||
141 | }, | ||
142 | }; | ||
143 | |||
144 | struct tps6507x_pmic { | ||
166 | struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; | 145 | struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; |
167 | struct i2c_client *client; | 146 | struct tps6507x_dev *mfd; |
168 | struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; | 147 | struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; |
169 | const struct tps_info *info[TPS6507X_NUM_REGULATOR]; | 148 | const struct tps_info *info[TPS6507X_NUM_REGULATOR]; |
170 | struct mutex io_lock; | 149 | struct mutex io_lock; |
171 | }; | 150 | }; |
172 | 151 | static inline int tps6507x_pmic_read(struct tps6507x_pmic *tps, u8 reg) | |
173 | static inline int tps_6507x_read(struct tps_pmic *tps, u8 reg) | ||
174 | { | 152 | { |
175 | return i2c_smbus_read_byte_data(tps->client, reg); | 153 | u8 val; |
154 | int err; | ||
155 | |||
156 | err = tps->mfd->read_dev(tps->mfd, reg, 1, &val); | ||
157 | |||
158 | if (err) | ||
159 | return err; | ||
160 | |||
161 | return val; | ||
176 | } | 162 | } |
177 | 163 | ||
178 | static inline int tps_6507x_write(struct tps_pmic *tps, u8 reg, u8 val) | 164 | static inline int tps6507x_pmic_write(struct tps6507x_pmic *tps, u8 reg, u8 val) |
179 | { | 165 | { |
180 | return i2c_smbus_write_byte_data(tps->client, reg, val); | 166 | return tps->mfd->write_dev(tps->mfd, reg, 1, &val); |
181 | } | 167 | } |
182 | 168 | ||
183 | static int tps_6507x_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) | 169 | static int tps6507x_pmic_set_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) |
184 | { | 170 | { |
185 | int err, data; | 171 | int err, data; |
186 | 172 | ||
187 | mutex_lock(&tps->io_lock); | 173 | mutex_lock(&tps->io_lock); |
188 | 174 | ||
189 | data = tps_6507x_read(tps, reg); | 175 | data = tps6507x_pmic_read(tps, reg); |
190 | if (data < 0) { | 176 | if (data < 0) { |
191 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | 177 | dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg); |
192 | err = data; | 178 | err = data; |
193 | goto out; | 179 | goto out; |
194 | } | 180 | } |
195 | 181 | ||
196 | data |= mask; | 182 | data |= mask; |
197 | err = tps_6507x_write(tps, reg, data); | 183 | err = tps6507x_pmic_write(tps, reg, data); |
198 | if (err) | 184 | if (err) |
199 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | 185 | dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg); |
200 | 186 | ||
201 | out: | 187 | out: |
202 | mutex_unlock(&tps->io_lock); | 188 | mutex_unlock(&tps->io_lock); |
203 | return err; | 189 | return err; |
204 | } | 190 | } |
205 | 191 | ||
206 | static int tps_6507x_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask) | 192 | static int tps6507x_pmic_clear_bits(struct tps6507x_pmic *tps, u8 reg, u8 mask) |
207 | { | 193 | { |
208 | int err, data; | 194 | int err, data; |
209 | 195 | ||
210 | mutex_lock(&tps->io_lock); | 196 | mutex_lock(&tps->io_lock); |
211 | 197 | ||
212 | data = tps_6507x_read(tps, reg); | 198 | data = tps6507x_pmic_read(tps, reg); |
213 | if (data < 0) { | 199 | if (data < 0) { |
214 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | 200 | dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg); |
215 | err = data; | 201 | err = data; |
216 | goto out; | 202 | goto out; |
217 | } | 203 | } |
218 | 204 | ||
219 | data &= ~mask; | 205 | data &= ~mask; |
220 | err = tps_6507x_write(tps, reg, data); | 206 | err = tps6507x_pmic_write(tps, reg, data); |
221 | if (err) | 207 | if (err) |
222 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | 208 | dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg); |
223 | 209 | ||
224 | out: | 210 | out: |
225 | mutex_unlock(&tps->io_lock); | 211 | mutex_unlock(&tps->io_lock); |
226 | return err; | 212 | return err; |
227 | } | 213 | } |
228 | 214 | ||
229 | static int tps_6507x_reg_read(struct tps_pmic *tps, u8 reg) | 215 | static int tps6507x_pmic_reg_read(struct tps6507x_pmic *tps, u8 reg) |
230 | { | 216 | { |
231 | int data; | 217 | int data; |
232 | 218 | ||
233 | mutex_lock(&tps->io_lock); | 219 | mutex_lock(&tps->io_lock); |
234 | 220 | ||
235 | data = tps_6507x_read(tps, reg); | 221 | data = tps6507x_pmic_read(tps, reg); |
236 | if (data < 0) | 222 | if (data < 0) |
237 | dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); | 223 | dev_err(tps->mfd->dev, "Read from reg 0x%x failed\n", reg); |
238 | 224 | ||
239 | mutex_unlock(&tps->io_lock); | 225 | mutex_unlock(&tps->io_lock); |
240 | return data; | 226 | return data; |
241 | } | 227 | } |
242 | 228 | ||
243 | static int tps_6507x_reg_write(struct tps_pmic *tps, u8 reg, u8 val) | 229 | static int tps6507x_pmic_reg_write(struct tps6507x_pmic *tps, u8 reg, u8 val) |
244 | { | 230 | { |
245 | int err; | 231 | int err; |
246 | 232 | ||
247 | mutex_lock(&tps->io_lock); | 233 | mutex_lock(&tps->io_lock); |
248 | 234 | ||
249 | err = tps_6507x_write(tps, reg, val); | 235 | err = tps6507x_pmic_write(tps, reg, val); |
250 | if (err < 0) | 236 | if (err < 0) |
251 | dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); | 237 | dev_err(tps->mfd->dev, "Write for reg 0x%x failed\n", reg); |
252 | 238 | ||
253 | mutex_unlock(&tps->io_lock); | 239 | mutex_unlock(&tps->io_lock); |
254 | return err; | 240 | return err; |
255 | } | 241 | } |
256 | 242 | ||
257 | static int tps6507x_dcdc_is_enabled(struct regulator_dev *dev) | 243 | static int tps6507x_pmic_dcdc_is_enabled(struct regulator_dev *dev) |
258 | { | 244 | { |
259 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 245 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
260 | int data, dcdc = rdev_get_id(dev); | 246 | int data, dcdc = rdev_get_id(dev); |
261 | u8 shift; | 247 | u8 shift; |
262 | 248 | ||
@@ -264,7 +250,7 @@ static int tps6507x_dcdc_is_enabled(struct regulator_dev *dev) | |||
264 | return -EINVAL; | 250 | return -EINVAL; |
265 | 251 | ||
266 | shift = TPS6507X_MAX_REG_ID - dcdc; | 252 | shift = TPS6507X_MAX_REG_ID - dcdc; |
267 | data = tps_6507x_reg_read(tps, TPS6507X_REG_CON_CTRL1); | 253 | data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1); |
268 | 254 | ||
269 | if (data < 0) | 255 | if (data < 0) |
270 | return data; | 256 | return data; |
@@ -272,9 +258,9 @@ static int tps6507x_dcdc_is_enabled(struct regulator_dev *dev) | |||
272 | return (data & 1<<shift) ? 1 : 0; | 258 | return (data & 1<<shift) ? 1 : 0; |
273 | } | 259 | } |
274 | 260 | ||
275 | static int tps6507x_ldo_is_enabled(struct regulator_dev *dev) | 261 | static int tps6507x_pmic_ldo_is_enabled(struct regulator_dev *dev) |
276 | { | 262 | { |
277 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 263 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
278 | int data, ldo = rdev_get_id(dev); | 264 | int data, ldo = rdev_get_id(dev); |
279 | u8 shift; | 265 | u8 shift; |
280 | 266 | ||
@@ -282,7 +268,7 @@ static int tps6507x_ldo_is_enabled(struct regulator_dev *dev) | |||
282 | return -EINVAL; | 268 | return -EINVAL; |
283 | 269 | ||
284 | shift = TPS6507X_MAX_REG_ID - ldo; | 270 | shift = TPS6507X_MAX_REG_ID - ldo; |
285 | data = tps_6507x_reg_read(tps, TPS6507X_REG_CON_CTRL1); | 271 | data = tps6507x_pmic_reg_read(tps, TPS6507X_REG_CON_CTRL1); |
286 | 272 | ||
287 | if (data < 0) | 273 | if (data < 0) |
288 | return data; | 274 | return data; |
@@ -290,9 +276,9 @@ static int tps6507x_ldo_is_enabled(struct regulator_dev *dev) | |||
290 | return (data & 1<<shift) ? 1 : 0; | 276 | return (data & 1<<shift) ? 1 : 0; |
291 | } | 277 | } |
292 | 278 | ||
293 | static int tps6507x_dcdc_enable(struct regulator_dev *dev) | 279 | static int tps6507x_pmic_dcdc_enable(struct regulator_dev *dev) |
294 | { | 280 | { |
295 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 281 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
296 | int dcdc = rdev_get_id(dev); | 282 | int dcdc = rdev_get_id(dev); |
297 | u8 shift; | 283 | u8 shift; |
298 | 284 | ||
@@ -300,12 +286,12 @@ static int tps6507x_dcdc_enable(struct regulator_dev *dev) | |||
300 | return -EINVAL; | 286 | return -EINVAL; |
301 | 287 | ||
302 | shift = TPS6507X_MAX_REG_ID - dcdc; | 288 | shift = TPS6507X_MAX_REG_ID - dcdc; |
303 | return tps_6507x_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); | 289 | return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); |
304 | } | 290 | } |
305 | 291 | ||
306 | static int tps6507x_dcdc_disable(struct regulator_dev *dev) | 292 | static int tps6507x_pmic_dcdc_disable(struct regulator_dev *dev) |
307 | { | 293 | { |
308 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 294 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
309 | int dcdc = rdev_get_id(dev); | 295 | int dcdc = rdev_get_id(dev); |
310 | u8 shift; | 296 | u8 shift; |
311 | 297 | ||
@@ -313,12 +299,13 @@ static int tps6507x_dcdc_disable(struct regulator_dev *dev) | |||
313 | return -EINVAL; | 299 | return -EINVAL; |
314 | 300 | ||
315 | shift = TPS6507X_MAX_REG_ID - dcdc; | 301 | shift = TPS6507X_MAX_REG_ID - dcdc; |
316 | return tps_6507x_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); | 302 | return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1, |
303 | 1 << shift); | ||
317 | } | 304 | } |
318 | 305 | ||
319 | static int tps6507x_ldo_enable(struct regulator_dev *dev) | 306 | static int tps6507x_pmic_ldo_enable(struct regulator_dev *dev) |
320 | { | 307 | { |
321 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 308 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
322 | int ldo = rdev_get_id(dev); | 309 | int ldo = rdev_get_id(dev); |
323 | u8 shift; | 310 | u8 shift; |
324 | 311 | ||
@@ -326,12 +313,12 @@ static int tps6507x_ldo_enable(struct regulator_dev *dev) | |||
326 | return -EINVAL; | 313 | return -EINVAL; |
327 | 314 | ||
328 | shift = TPS6507X_MAX_REG_ID - ldo; | 315 | shift = TPS6507X_MAX_REG_ID - ldo; |
329 | return tps_6507x_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); | 316 | return tps6507x_pmic_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); |
330 | } | 317 | } |
331 | 318 | ||
332 | static int tps6507x_ldo_disable(struct regulator_dev *dev) | 319 | static int tps6507x_pmic_ldo_disable(struct regulator_dev *dev) |
333 | { | 320 | { |
334 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 321 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
335 | int ldo = rdev_get_id(dev); | 322 | int ldo = rdev_get_id(dev); |
336 | u8 shift; | 323 | u8 shift; |
337 | 324 | ||
@@ -339,12 +326,13 @@ static int tps6507x_ldo_disable(struct regulator_dev *dev) | |||
339 | return -EINVAL; | 326 | return -EINVAL; |
340 | 327 | ||
341 | shift = TPS6507X_MAX_REG_ID - ldo; | 328 | shift = TPS6507X_MAX_REG_ID - ldo; |
342 | return tps_6507x_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); | 329 | return tps6507x_pmic_clear_bits(tps, TPS6507X_REG_CON_CTRL1, |
330 | 1 << shift); | ||
343 | } | 331 | } |
344 | 332 | ||
345 | static int tps6507x_dcdc_get_voltage(struct regulator_dev *dev) | 333 | static int tps6507x_pmic_dcdc_get_voltage(struct regulator_dev *dev) |
346 | { | 334 | { |
347 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 335 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
348 | int data, dcdc = rdev_get_id(dev); | 336 | int data, dcdc = rdev_get_id(dev); |
349 | u8 reg; | 337 | u8 reg; |
350 | 338 | ||
@@ -362,7 +350,7 @@ static int tps6507x_dcdc_get_voltage(struct regulator_dev *dev) | |||
362 | return -EINVAL; | 350 | return -EINVAL; |
363 | } | 351 | } |
364 | 352 | ||
365 | data = tps_6507x_reg_read(tps, reg); | 353 | data = tps6507x_pmic_reg_read(tps, reg); |
366 | if (data < 0) | 354 | if (data < 0) |
367 | return data; | 355 | return data; |
368 | 356 | ||
@@ -370,10 +358,10 @@ static int tps6507x_dcdc_get_voltage(struct regulator_dev *dev) | |||
370 | return tps->info[dcdc]->table[data] * 1000; | 358 | return tps->info[dcdc]->table[data] * 1000; |
371 | } | 359 | } |
372 | 360 | ||
373 | static int tps6507x_dcdc_set_voltage(struct regulator_dev *dev, | 361 | static int tps6507x_pmic_dcdc_set_voltage(struct regulator_dev *dev, |
374 | int min_uV, int max_uV) | 362 | int min_uV, int max_uV) |
375 | { | 363 | { |
376 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 364 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
377 | int data, vsel, dcdc = rdev_get_id(dev); | 365 | int data, vsel, dcdc = rdev_get_id(dev); |
378 | u8 reg; | 366 | u8 reg; |
379 | 367 | ||
@@ -411,19 +399,19 @@ static int tps6507x_dcdc_set_voltage(struct regulator_dev *dev, | |||
411 | if (vsel == tps->info[dcdc]->table_len) | 399 | if (vsel == tps->info[dcdc]->table_len) |
412 | return -EINVAL; | 400 | return -EINVAL; |
413 | 401 | ||
414 | data = tps_6507x_reg_read(tps, reg); | 402 | data = tps6507x_pmic_reg_read(tps, reg); |
415 | if (data < 0) | 403 | if (data < 0) |
416 | return data; | 404 | return data; |
417 | 405 | ||
418 | data &= ~TPS6507X_DEFDCDCX_DCDC_MASK; | 406 | data &= ~TPS6507X_DEFDCDCX_DCDC_MASK; |
419 | data |= vsel; | 407 | data |= vsel; |
420 | 408 | ||
421 | return tps_6507x_reg_write(tps, reg, data); | 409 | return tps6507x_pmic_reg_write(tps, reg, data); |
422 | } | 410 | } |
423 | 411 | ||
424 | static int tps6507x_ldo_get_voltage(struct regulator_dev *dev) | 412 | static int tps6507x_pmic_ldo_get_voltage(struct regulator_dev *dev) |
425 | { | 413 | { |
426 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 414 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
427 | int data, ldo = rdev_get_id(dev); | 415 | int data, ldo = rdev_get_id(dev); |
428 | u8 reg, mask; | 416 | u8 reg, mask; |
429 | 417 | ||
@@ -437,7 +425,7 @@ static int tps6507x_ldo_get_voltage(struct regulator_dev *dev) | |||
437 | TPS6507X_REG_DEFLDO2_LDO2_MASK); | 425 | TPS6507X_REG_DEFLDO2_LDO2_MASK); |
438 | } | 426 | } |
439 | 427 | ||
440 | data = tps_6507x_reg_read(tps, reg); | 428 | data = tps6507x_pmic_reg_read(tps, reg); |
441 | if (data < 0) | 429 | if (data < 0) |
442 | return data; | 430 | return data; |
443 | 431 | ||
@@ -445,10 +433,10 @@ static int tps6507x_ldo_get_voltage(struct regulator_dev *dev) | |||
445 | return tps->info[ldo]->table[data] * 1000; | 433 | return tps->info[ldo]->table[data] * 1000; |
446 | } | 434 | } |
447 | 435 | ||
448 | static int tps6507x_ldo_set_voltage(struct regulator_dev *dev, | 436 | static int tps6507x_pmic_ldo_set_voltage(struct regulator_dev *dev, |
449 | int min_uV, int max_uV) | 437 | int min_uV, int max_uV) |
450 | { | 438 | { |
451 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 439 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
452 | int data, vsel, ldo = rdev_get_id(dev); | 440 | int data, vsel, ldo = rdev_get_id(dev); |
453 | u8 reg, mask; | 441 | u8 reg, mask; |
454 | 442 | ||
@@ -479,20 +467,20 @@ static int tps6507x_ldo_set_voltage(struct regulator_dev *dev, | |||
479 | if (vsel == tps->info[ldo]->table_len) | 467 | if (vsel == tps->info[ldo]->table_len) |
480 | return -EINVAL; | 468 | return -EINVAL; |
481 | 469 | ||
482 | data = tps_6507x_reg_read(tps, reg); | 470 | data = tps6507x_pmic_reg_read(tps, reg); |
483 | if (data < 0) | 471 | if (data < 0) |
484 | return data; | 472 | return data; |
485 | 473 | ||
486 | data &= ~mask; | 474 | data &= ~mask; |
487 | data |= vsel; | 475 | data |= vsel; |
488 | 476 | ||
489 | return tps_6507x_reg_write(tps, reg, data); | 477 | return tps6507x_pmic_reg_write(tps, reg, data); |
490 | } | 478 | } |
491 | 479 | ||
492 | static int tps6507x_dcdc_list_voltage(struct regulator_dev *dev, | 480 | static int tps6507x_pmic_dcdc_list_voltage(struct regulator_dev *dev, |
493 | unsigned selector) | 481 | unsigned selector) |
494 | { | 482 | { |
495 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 483 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
496 | int dcdc = rdev_get_id(dev); | 484 | int dcdc = rdev_get_id(dev); |
497 | 485 | ||
498 | if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) | 486 | if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) |
@@ -504,10 +492,10 @@ static int tps6507x_dcdc_list_voltage(struct regulator_dev *dev, | |||
504 | return tps->info[dcdc]->table[selector] * 1000; | 492 | return tps->info[dcdc]->table[selector] * 1000; |
505 | } | 493 | } |
506 | 494 | ||
507 | static int tps6507x_ldo_list_voltage(struct regulator_dev *dev, | 495 | static int tps6507x_pmic_ldo_list_voltage(struct regulator_dev *dev, |
508 | unsigned selector) | 496 | unsigned selector) |
509 | { | 497 | { |
510 | struct tps_pmic *tps = rdev_get_drvdata(dev); | 498 | struct tps6507x_pmic *tps = rdev_get_drvdata(dev); |
511 | int ldo = rdev_get_id(dev); | 499 | int ldo = rdev_get_id(dev); |
512 | 500 | ||
513 | if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) | 501 | if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) |
@@ -520,47 +508,54 @@ static int tps6507x_ldo_list_voltage(struct regulator_dev *dev, | |||
520 | } | 508 | } |
521 | 509 | ||
522 | /* Operations permitted on VDCDCx */ | 510 | /* Operations permitted on VDCDCx */ |
523 | static struct regulator_ops tps6507x_dcdc_ops = { | 511 | static struct regulator_ops tps6507x_pmic_dcdc_ops = { |
524 | .is_enabled = tps6507x_dcdc_is_enabled, | 512 | .is_enabled = tps6507x_pmic_dcdc_is_enabled, |
525 | .enable = tps6507x_dcdc_enable, | 513 | .enable = tps6507x_pmic_dcdc_enable, |
526 | .disable = tps6507x_dcdc_disable, | 514 | .disable = tps6507x_pmic_dcdc_disable, |
527 | .get_voltage = tps6507x_dcdc_get_voltage, | 515 | .get_voltage = tps6507x_pmic_dcdc_get_voltage, |
528 | .set_voltage = tps6507x_dcdc_set_voltage, | 516 | .set_voltage = tps6507x_pmic_dcdc_set_voltage, |
529 | .list_voltage = tps6507x_dcdc_list_voltage, | 517 | .list_voltage = tps6507x_pmic_dcdc_list_voltage, |
530 | }; | 518 | }; |
531 | 519 | ||
532 | /* Operations permitted on LDOx */ | 520 | /* Operations permitted on LDOx */ |
533 | static struct regulator_ops tps6507x_ldo_ops = { | 521 | static struct regulator_ops tps6507x_pmic_ldo_ops = { |
534 | .is_enabled = tps6507x_ldo_is_enabled, | 522 | .is_enabled = tps6507x_pmic_ldo_is_enabled, |
535 | .enable = tps6507x_ldo_enable, | 523 | .enable = tps6507x_pmic_ldo_enable, |
536 | .disable = tps6507x_ldo_disable, | 524 | .disable = tps6507x_pmic_ldo_disable, |
537 | .get_voltage = tps6507x_ldo_get_voltage, | 525 | .get_voltage = tps6507x_pmic_ldo_get_voltage, |
538 | .set_voltage = tps6507x_ldo_set_voltage, | 526 | .set_voltage = tps6507x_pmic_ldo_set_voltage, |
539 | .list_voltage = tps6507x_ldo_list_voltage, | 527 | .list_voltage = tps6507x_pmic_ldo_list_voltage, |
540 | }; | 528 | }; |
541 | 529 | ||
542 | static int __devinit tps_6507x_probe(struct i2c_client *client, | 530 | static __devinit |
543 | const struct i2c_device_id *id) | 531 | int tps6507x_pmic_probe(struct platform_device *pdev) |
544 | { | 532 | { |
533 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); | ||
545 | static int desc_id; | 534 | static int desc_id; |
546 | const struct tps_info *info = (void *)id->driver_data; | 535 | const struct tps_info *info = &tps6507x_pmic_regs[0]; |
547 | struct regulator_init_data *init_data; | 536 | struct regulator_init_data *init_data; |
548 | struct regulator_dev *rdev; | 537 | struct regulator_dev *rdev; |
549 | struct tps_pmic *tps; | 538 | struct tps6507x_pmic *tps; |
539 | struct tps6507x_board *tps_board; | ||
550 | int i; | 540 | int i; |
551 | int error; | 541 | int error; |
552 | 542 | ||
553 | if (!i2c_check_functionality(client->adapter, | 543 | /** |
554 | I2C_FUNC_SMBUS_BYTE_DATA)) | 544 | * tps_board points to pmic related constants |
555 | return -EIO; | 545 | * coming from the board-evm file. |
546 | */ | ||
547 | |||
548 | tps_board = dev_get_platdata(tps6507x_dev->dev); | ||
549 | if (!tps_board) | ||
550 | return -EINVAL; | ||
556 | 551 | ||
557 | /** | 552 | /** |
558 | * init_data points to array of regulator_init structures | 553 | * init_data points to array of regulator_init structures |
559 | * coming from the board-evm file. | 554 | * coming from the board-evm file. |
560 | */ | 555 | */ |
561 | init_data = client->dev.platform_data; | 556 | init_data = tps_board->tps6507x_pmic_init_data; |
562 | if (!init_data) | 557 | if (!init_data) |
563 | return -EIO; | 558 | return -EINVAL; |
564 | 559 | ||
565 | tps = kzalloc(sizeof(*tps), GFP_KERNEL); | 560 | tps = kzalloc(sizeof(*tps), GFP_KERNEL); |
566 | if (!tps) | 561 | if (!tps) |
@@ -569,7 +564,7 @@ static int __devinit tps_6507x_probe(struct i2c_client *client, | |||
569 | mutex_init(&tps->io_lock); | 564 | mutex_init(&tps->io_lock); |
570 | 565 | ||
571 | /* common for all regulators */ | 566 | /* common for all regulators */ |
572 | tps->client = client; | 567 | tps->mfd = tps6507x_dev; |
573 | 568 | ||
574 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { | 569 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { |
575 | /* Register the regulators */ | 570 | /* Register the regulators */ |
@@ -578,15 +573,16 @@ static int __devinit tps_6507x_probe(struct i2c_client *client, | |||
578 | tps->desc[i].id = desc_id++; | 573 | tps->desc[i].id = desc_id++; |
579 | tps->desc[i].n_voltages = num_voltages[i]; | 574 | tps->desc[i].n_voltages = num_voltages[i]; |
580 | tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? | 575 | tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? |
581 | &tps6507x_ldo_ops : &tps6507x_dcdc_ops); | 576 | &tps6507x_pmic_ldo_ops : &tps6507x_pmic_dcdc_ops); |
582 | tps->desc[i].type = REGULATOR_VOLTAGE; | 577 | tps->desc[i].type = REGULATOR_VOLTAGE; |
583 | tps->desc[i].owner = THIS_MODULE; | 578 | tps->desc[i].owner = THIS_MODULE; |
584 | 579 | ||
585 | rdev = regulator_register(&tps->desc[i], | 580 | rdev = regulator_register(&tps->desc[i], |
586 | &client->dev, init_data, tps); | 581 | tps6507x_dev->dev, init_data, tps); |
587 | if (IS_ERR(rdev)) { | 582 | if (IS_ERR(rdev)) { |
588 | dev_err(&client->dev, "failed to register %s\n", | 583 | dev_err(tps6507x_dev->dev, |
589 | id->name); | 584 | "failed to register %s regulator\n", |
585 | pdev->name); | ||
590 | error = PTR_ERR(rdev); | 586 | error = PTR_ERR(rdev); |
591 | goto fail; | 587 | goto fail; |
592 | } | 588 | } |
@@ -595,7 +591,7 @@ static int __devinit tps_6507x_probe(struct i2c_client *client, | |||
595 | tps->rdev[i] = rdev; | 591 | tps->rdev[i] = rdev; |
596 | } | 592 | } |
597 | 593 | ||
598 | i2c_set_clientdata(client, tps); | 594 | tps6507x_dev->pmic = tps; |
599 | 595 | ||
600 | return 0; | 596 | return 0; |
601 | 597 | ||
@@ -608,19 +604,17 @@ fail: | |||
608 | } | 604 | } |
609 | 605 | ||
610 | /** | 606 | /** |
611 | * tps_6507x_remove - TPS6507x driver i2c remove handler | 607 | * tps6507x_remove - TPS6507x driver i2c remove handler |
612 | * @client: i2c driver client device structure | 608 | * @client: i2c driver client device structure |
613 | * | 609 | * |
614 | * Unregister TPS driver as an i2c client device driver | 610 | * Unregister TPS driver as an i2c client device driver |
615 | */ | 611 | */ |
616 | static int __devexit tps_6507x_remove(struct i2c_client *client) | 612 | static int __devexit tps6507x_pmic_remove(struct platform_device *pdev) |
617 | { | 613 | { |
618 | struct tps_pmic *tps = i2c_get_clientdata(client); | 614 | struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev); |
615 | struct tps6507x_pmic *tps = tps6507x_dev->pmic; | ||
619 | int i; | 616 | int i; |
620 | 617 | ||
621 | /* clear the client data in i2c */ | ||
622 | i2c_set_clientdata(client, NULL); | ||
623 | |||
624 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) | 618 | for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) |
625 | regulator_unregister(tps->rdev[i]); | 619 | regulator_unregister(tps->rdev[i]); |
626 | 620 | ||
@@ -629,83 +623,38 @@ static int __devexit tps_6507x_remove(struct i2c_client *client) | |||
629 | return 0; | 623 | return 0; |
630 | } | 624 | } |
631 | 625 | ||
632 | static const struct tps_info tps6507x_regs[] = { | 626 | static struct platform_driver tps6507x_pmic_driver = { |
633 | { | ||
634 | .name = "VDCDC1", | ||
635 | .min_uV = 725000, | ||
636 | .max_uV = 3300000, | ||
637 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
638 | .table = VDCDCx_VSEL_table, | ||
639 | }, | ||
640 | { | ||
641 | .name = "VDCDC2", | ||
642 | .min_uV = 725000, | ||
643 | .max_uV = 3300000, | ||
644 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
645 | .table = VDCDCx_VSEL_table, | ||
646 | }, | ||
647 | { | ||
648 | .name = "VDCDC3", | ||
649 | .min_uV = 725000, | ||
650 | .max_uV = 3300000, | ||
651 | .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), | ||
652 | .table = VDCDCx_VSEL_table, | ||
653 | }, | ||
654 | { | ||
655 | .name = "LDO1", | ||
656 | .min_uV = 1000000, | ||
657 | .max_uV = 3300000, | ||
658 | .table_len = ARRAY_SIZE(LDO1_VSEL_table), | ||
659 | .table = LDO1_VSEL_table, | ||
660 | }, | ||
661 | { | ||
662 | .name = "LDO2", | ||
663 | .min_uV = 725000, | ||
664 | .max_uV = 3300000, | ||
665 | .table_len = ARRAY_SIZE(LDO2_VSEL_table), | ||
666 | .table = LDO2_VSEL_table, | ||
667 | }, | ||
668 | }; | ||
669 | |||
670 | static const struct i2c_device_id tps_6507x_id[] = { | ||
671 | {.name = "tps6507x", | ||
672 | .driver_data = (unsigned long) tps6507x_regs,}, | ||
673 | { }, | ||
674 | }; | ||
675 | MODULE_DEVICE_TABLE(i2c, tps_6507x_id); | ||
676 | |||
677 | static struct i2c_driver tps_6507x_i2c_driver = { | ||
678 | .driver = { | 627 | .driver = { |
679 | .name = "tps6507x", | 628 | .name = "tps6507x-pmic", |
680 | .owner = THIS_MODULE, | 629 | .owner = THIS_MODULE, |
681 | }, | 630 | }, |
682 | .probe = tps_6507x_probe, | 631 | .probe = tps6507x_pmic_probe, |
683 | .remove = __devexit_p(tps_6507x_remove), | 632 | .remove = __devexit_p(tps6507x_pmic_remove), |
684 | .id_table = tps_6507x_id, | ||
685 | }; | 633 | }; |
686 | 634 | ||
687 | /** | 635 | /** |
688 | * tps_6507x_init | 636 | * tps6507x_pmic_init |
689 | * | 637 | * |
690 | * Module init function | 638 | * Module init function |
691 | */ | 639 | */ |
692 | static int __init tps_6507x_init(void) | 640 | static int __init tps6507x_pmic_init(void) |
693 | { | 641 | { |
694 | return i2c_add_driver(&tps_6507x_i2c_driver); | 642 | return platform_driver_register(&tps6507x_pmic_driver); |
695 | } | 643 | } |
696 | subsys_initcall(tps_6507x_init); | 644 | subsys_initcall(tps6507x_pmic_init); |
697 | 645 | ||
698 | /** | 646 | /** |
699 | * tps_6507x_cleanup | 647 | * tps6507x_pmic_cleanup |
700 | * | 648 | * |
701 | * Module exit function | 649 | * Module exit function |
702 | */ | 650 | */ |
703 | static void __exit tps_6507x_cleanup(void) | 651 | static void __exit tps6507x_pmic_cleanup(void) |
704 | { | 652 | { |
705 | i2c_del_driver(&tps_6507x_i2c_driver); | 653 | platform_driver_unregister(&tps6507x_pmic_driver); |
706 | } | 654 | } |
707 | module_exit(tps_6507x_cleanup); | 655 | module_exit(tps6507x_pmic_cleanup); |
708 | 656 | ||
709 | MODULE_AUTHOR("Texas Instruments"); | 657 | MODULE_AUTHOR("Texas Instruments"); |
710 | MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); | 658 | MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); |
711 | MODULE_LICENSE("GPL v2"); | 659 | MODULE_LICENSE("GPL v2"); |
660 | MODULE_ALIAS("platform:tps6507x-pmic"); | ||
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-ab3100.c b/drivers/rtc/rtc-ab3100.c index 4704aac2b5af..d26780ea254b 100644 --- a/drivers/rtc/rtc-ab3100.c +++ b/drivers/rtc/rtc-ab3100.c | |||
@@ -9,7 +9,7 @@ | |||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/platform_device.h> | 10 | #include <linux/platform_device.h> |
11 | #include <linux/rtc.h> | 11 | #include <linux/rtc.h> |
12 | #include <linux/mfd/ab3100.h> | 12 | #include <linux/mfd/abx500.h> |
13 | 13 | ||
14 | /* Clock rate in Hz */ | 14 | /* Clock rate in Hz */ |
15 | #define AB3100_RTC_CLOCK_RATE 32768 | 15 | #define AB3100_RTC_CLOCK_RATE 32768 |
@@ -45,7 +45,6 @@ | |||
45 | */ | 45 | */ |
46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | 46 | static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) |
47 | { | 47 | { |
48 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
49 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, | 48 | u8 regs[] = {AB3100_TI0, AB3100_TI1, AB3100_TI2, |
50 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; | 49 | AB3100_TI3, AB3100_TI4, AB3100_TI5}; |
51 | unsigned char buf[6]; | 50 | unsigned char buf[6]; |
@@ -61,27 +60,26 @@ static int ab3100_rtc_set_mmss(struct device *dev, unsigned long secs) | |||
61 | buf[5] = (fat_time >> 40) & 0xFF; | 60 | buf[5] = (fat_time >> 40) & 0xFF; |
62 | 61 | ||
63 | for (i = 0; i < 6; i++) { | 62 | for (i = 0; i < 6; i++) { |
64 | err = ab3100_set_register_interruptible(ab3100_data, | 63 | err = abx500_set_register_interruptible(dev, 0, |
65 | regs[i], buf[i]); | 64 | regs[i], buf[i]); |
66 | if (err) | 65 | if (err) |
67 | return err; | 66 | return err; |
68 | } | 67 | } |
69 | 68 | ||
70 | /* Set the flag to mark that the clock is now set */ | 69 | /* Set the flag to mark that the clock is now set */ |
71 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 70 | return abx500_mask_and_set_register_interruptible(dev, 0, |
72 | AB3100_RTC, | 71 | AB3100_RTC, |
73 | 0xFE, 0x01); | 72 | 0x01, 0x01); |
74 | 73 | ||
75 | } | 74 | } |
76 | 75 | ||
77 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | 76 | static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) |
78 | { | 77 | { |
79 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
80 | unsigned long time; | 78 | unsigned long time; |
81 | u8 rtcval; | 79 | u8 rtcval; |
82 | int err; | 80 | int err; |
83 | 81 | ||
84 | err = ab3100_get_register_interruptible(ab3100_data, | 82 | err = abx500_get_register_interruptible(dev, 0, |
85 | AB3100_RTC, &rtcval); | 83 | AB3100_RTC, &rtcval); |
86 | if (err) | 84 | if (err) |
87 | return err; | 85 | return err; |
@@ -94,7 +92,7 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
94 | u8 buf[6]; | 92 | u8 buf[6]; |
95 | 93 | ||
96 | /* Read out time registers */ | 94 | /* Read out time registers */ |
97 | err = ab3100_get_register_page_interruptible(ab3100_data, | 95 | err = abx500_get_register_page_interruptible(dev, 0, |
98 | AB3100_TI0, | 96 | AB3100_TI0, |
99 | buf, 6); | 97 | buf, 6); |
100 | if (err != 0) | 98 | if (err != 0) |
@@ -114,7 +112,6 @@ static int ab3100_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
114 | 112 | ||
115 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 113 | static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
116 | { | 114 | { |
117 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
118 | unsigned long time; | 115 | unsigned long time; |
119 | u64 fat_time; | 116 | u64 fat_time; |
120 | u8 buf[6]; | 117 | u8 buf[6]; |
@@ -122,7 +119,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
122 | int err; | 119 | int err; |
123 | 120 | ||
124 | /* Figure out if alarm is enabled or not */ | 121 | /* Figure out if alarm is enabled or not */ |
125 | err = ab3100_get_register_interruptible(ab3100_data, | 122 | err = abx500_get_register_interruptible(dev, 0, |
126 | AB3100_RTC, &rtcval); | 123 | AB3100_RTC, &rtcval); |
127 | if (err) | 124 | if (err) |
128 | return err; | 125 | return err; |
@@ -133,7 +130,7 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
133 | /* No idea how this could be represented */ | 130 | /* No idea how this could be represented */ |
134 | alarm->pending = 0; | 131 | alarm->pending = 0; |
135 | /* Read out alarm registers, only 4 bytes */ | 132 | /* Read out alarm registers, only 4 bytes */ |
136 | err = ab3100_get_register_page_interruptible(ab3100_data, | 133 | err = abx500_get_register_page_interruptible(dev, 0, |
137 | AB3100_AL0, buf, 4); | 134 | AB3100_AL0, buf, 4); |
138 | if (err) | 135 | if (err) |
139 | return err; | 136 | return err; |
@@ -148,7 +145,6 @@ static int ab3100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
148 | 145 | ||
149 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | 146 | static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) |
150 | { | 147 | { |
151 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
152 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; | 148 | u8 regs[] = {AB3100_AL0, AB3100_AL1, AB3100_AL2, AB3100_AL3}; |
153 | unsigned char buf[4]; | 149 | unsigned char buf[4]; |
154 | unsigned long secs; | 150 | unsigned long secs; |
@@ -165,21 +161,19 @@ static int ab3100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) | |||
165 | 161 | ||
166 | /* Set the alarm */ | 162 | /* Set the alarm */ |
167 | for (i = 0; i < 4; i++) { | 163 | for (i = 0; i < 4; i++) { |
168 | err = ab3100_set_register_interruptible(ab3100_data, | 164 | err = abx500_set_register_interruptible(dev, 0, |
169 | regs[i], buf[i]); | 165 | regs[i], buf[i]); |
170 | if (err) | 166 | if (err) |
171 | return err; | 167 | return err; |
172 | } | 168 | } |
173 | /* Then enable the alarm */ | 169 | /* Then enable the alarm */ |
174 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 170 | return abx500_mask_and_set_register_interruptible(dev, 0, |
175 | AB3100_RTC, ~(1 << 2), | 171 | AB3100_RTC, (1 << 2), |
176 | alarm->enabled << 2); | 172 | alarm->enabled << 2); |
177 | } | 173 | } |
178 | 174 | ||
179 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | 175 | static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) |
180 | { | 176 | { |
181 | struct ab3100 *ab3100_data = dev_get_drvdata(dev); | ||
182 | |||
183 | /* | 177 | /* |
184 | * It's not possible to enable/disable the alarm IRQ for this RTC. | 178 | * It's not possible to enable/disable the alarm IRQ for this RTC. |
185 | * It does not actually trigger any IRQ: instead its only function is | 179 | * It does not actually trigger any IRQ: instead its only function is |
@@ -188,12 +182,12 @@ static int ab3100_rtc_irq_enable(struct device *dev, unsigned int enabled) | |||
188 | * and need to be handled there instead. | 182 | * and need to be handled there instead. |
189 | */ | 183 | */ |
190 | if (enabled) | 184 | if (enabled) |
191 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 185 | return abx500_mask_and_set_register_interruptible(dev, 0, |
192 | AB3100_RTC, ~(1 << 2), | 186 | AB3100_RTC, (1 << 2), |
193 | 1 << 2); | 187 | 1 << 2); |
194 | else | 188 | else |
195 | return ab3100_mask_and_set_register_interruptible(ab3100_data, | 189 | return abx500_mask_and_set_register_interruptible(dev, 0, |
196 | AB3100_RTC, ~(1 << 2), | 190 | AB3100_RTC, (1 << 2), |
197 | 0); | 191 | 0); |
198 | } | 192 | } |
199 | 193 | ||
@@ -210,10 +204,9 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) | |||
210 | int err; | 204 | int err; |
211 | u8 regval; | 205 | u8 regval; |
212 | struct rtc_device *rtc; | 206 | struct rtc_device *rtc; |
213 | struct ab3100 *ab3100_data = platform_get_drvdata(pdev); | ||
214 | 207 | ||
215 | /* The first RTC register needs special treatment */ | 208 | /* The first RTC register needs special treatment */ |
216 | err = ab3100_get_register_interruptible(ab3100_data, | 209 | err = abx500_get_register_interruptible(&pdev->dev, 0, |
217 | AB3100_RTC, ®val); | 210 | AB3100_RTC, ®val); |
218 | if (err) { | 211 | if (err) { |
219 | dev_err(&pdev->dev, "unable to read RTC register\n"); | 212 | dev_err(&pdev->dev, "unable to read RTC register\n"); |
@@ -231,7 +224,7 @@ static int __init ab3100_rtc_probe(struct platform_device *pdev) | |||
231 | * This bit remains until RTC power is lost. | 224 | * This bit remains until RTC power is lost. |
232 | */ | 225 | */ |
233 | regval = 1 | RTC_SETTING; | 226 | regval = 1 | RTC_SETTING; |
234 | err = ab3100_set_register_interruptible(ab3100_data, | 227 | err = abx500_set_register_interruptible(&pdev->dev, 0, |
235 | AB3100_RTC, regval); | 228 | AB3100_RTC, regval); |
236 | /* Ignore any error on this write */ | 229 | /* Ignore any error on this write */ |
237 | } | 230 | } |
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/serial/s5pv210.c b/drivers/serial/s5pv210.c index 8dc03837617b..4a789e5361a4 100644 --- a/drivers/serial/s5pv210.c +++ b/drivers/serial/s5pv210.c | |||
@@ -119,7 +119,7 @@ static int s5p_serial_probe(struct platform_device *pdev) | |||
119 | return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]); | 119 | return s3c24xx_serial_probe(pdev, s5p_uart_inf[pdev->id]); |
120 | } | 120 | } |
121 | 121 | ||
122 | static struct platform_driver s5p_serial_drv = { | 122 | static struct platform_driver s5p_serial_driver = { |
123 | .probe = s5p_serial_probe, | 123 | .probe = s5p_serial_probe, |
124 | .remove = __devexit_p(s3c24xx_serial_remove), | 124 | .remove = __devexit_p(s3c24xx_serial_remove), |
125 | .driver = { | 125 | .driver = { |
@@ -130,19 +130,19 @@ static struct platform_driver s5p_serial_drv = { | |||
130 | 130 | ||
131 | static int __init s5pv210_serial_console_init(void) | 131 | static int __init s5pv210_serial_console_init(void) |
132 | { | 132 | { |
133 | return s3c24xx_serial_initconsole(&s5p_serial_drv, s5p_uart_inf); | 133 | return s3c24xx_serial_initconsole(&s5p_serial_driver, s5p_uart_inf); |
134 | } | 134 | } |
135 | 135 | ||
136 | console_initcall(s5pv210_serial_console_init); | 136 | console_initcall(s5pv210_serial_console_init); |
137 | 137 | ||
138 | static int __init s5p_serial_init(void) | 138 | static int __init s5p_serial_init(void) |
139 | { | 139 | { |
140 | return s3c24xx_serial_init(&s5p_serial_drv, *s5p_uart_inf); | 140 | return s3c24xx_serial_init(&s5p_serial_driver, *s5p_uart_inf); |
141 | } | 141 | } |
142 | 142 | ||
143 | static void __exit s5p_serial_exit(void) | 143 | static void __exit s5p_serial_exit(void) |
144 | { | 144 | { |
145 | platform_driver_unregister(&s5p_serial_drv); | 145 | platform_driver_unregister(&s5p_serial_driver); |
146 | } | 146 | } |
147 | 147 | ||
148 | module_init(s5p_serial_init); | 148 | module_init(s5p_serial_init); |
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/staging/pohmelfs/inode.c b/drivers/staging/pohmelfs/inode.c index 9286e863b0e7..643b413d9f0f 100644 --- a/drivers/staging/pohmelfs/inode.c +++ b/drivers/staging/pohmelfs/inode.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/statfs.h> | 30 | #include <linux/statfs.h> |
31 | #include <linux/writeback.h> | 31 | #include <linux/writeback.h> |
32 | #include <linux/quotaops.h> | ||
33 | 32 | ||
34 | #include "netfs.h" | 33 | #include "netfs.h" |
35 | 34 | ||
@@ -880,7 +879,7 @@ static struct inode *pohmelfs_alloc_inode(struct super_block *sb) | |||
880 | /* | 879 | /* |
881 | * We want fsync() to work on POHMELFS. | 880 | * We want fsync() to work on POHMELFS. |
882 | */ | 881 | */ |
883 | static int pohmelfs_fsync(struct file *file, struct dentry *dentry, int datasync) | 882 | static int pohmelfs_fsync(struct file *file, int datasync) |
884 | { | 883 | { |
885 | struct inode *inode = file->f_mapping->host; | 884 | struct inode *inode = file->f_mapping->host; |
886 | struct writeback_control wbc = { | 885 | struct writeback_control wbc = { |
@@ -969,13 +968,6 @@ int pohmelfs_setattr_raw(struct inode *inode, struct iattr *attr) | |||
969 | goto err_out_exit; | 968 | goto err_out_exit; |
970 | } | 969 | } |
971 | 970 | ||
972 | if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || | ||
973 | (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { | ||
974 | err = dquot_transfer(inode, attr); | ||
975 | if (err) | ||
976 | goto err_out_exit; | ||
977 | } | ||
978 | |||
979 | err = inode_setattr(inode, attr); | 971 | err = inode_setattr(inode, attr); |
980 | if (err) { | 972 | if (err) { |
981 | dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); | 973 | dprintk("%s: ino: %llu, failed to set the attributes.\n", __func__, POHMELFS_I(inode)->ino); |
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/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 6b8bf8c781c4..43abf55d8c60 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c | |||
@@ -794,7 +794,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) | |||
794 | } | 794 | } |
795 | 795 | ||
796 | static int | 796 | static int |
797 | printer_fsync(struct file *fd, struct dentry *dentry, int datasync) | 797 | printer_fsync(struct file *fd, int datasync) |
798 | { | 798 | { |
799 | struct printer_dev *dev = fd->private_data; | 799 | struct printer_dev *dev = fd->private_data; |
800 | unsigned long flags; | 800 | unsigned long flags; |
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index aa88911c9504..0f41c9195e9b 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -593,17 +593,17 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl, | |||
593 | int r; | 593 | int r; |
594 | switch (ioctl) { | 594 | switch (ioctl) { |
595 | case VHOST_NET_SET_BACKEND: | 595 | case VHOST_NET_SET_BACKEND: |
596 | r = copy_from_user(&backend, argp, sizeof backend); | 596 | if (copy_from_user(&backend, argp, sizeof backend)) |
597 | if (r < 0) | 597 | return -EFAULT; |
598 | return r; | ||
599 | return vhost_net_set_backend(n, backend.index, backend.fd); | 598 | return vhost_net_set_backend(n, backend.index, backend.fd); |
600 | case VHOST_GET_FEATURES: | 599 | case VHOST_GET_FEATURES: |
601 | features = VHOST_FEATURES; | 600 | features = VHOST_FEATURES; |
602 | return copy_to_user(featurep, &features, sizeof features); | 601 | if (copy_to_user(featurep, &features, sizeof features)) |
602 | return -EFAULT; | ||
603 | return 0; | ||
603 | case VHOST_SET_FEATURES: | 604 | case VHOST_SET_FEATURES: |
604 | r = copy_from_user(&features, featurep, sizeof features); | 605 | if (copy_from_user(&features, featurep, sizeof features)) |
605 | if (r < 0) | 606 | return -EFAULT; |
606 | return r; | ||
607 | if (features & ~VHOST_FEATURES) | 607 | if (features & ~VHOST_FEATURES) |
608 | return -EOPNOTSUPP; | 608 | return -EOPNOTSUPP; |
609 | return vhost_net_set_features(n, features); | 609 | return vhost_net_set_features(n, features); |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c6fb8e968f21..3b83382e06eb 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -320,10 +320,8 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | |||
320 | { | 320 | { |
321 | struct vhost_memory mem, *newmem, *oldmem; | 321 | struct vhost_memory mem, *newmem, *oldmem; |
322 | unsigned long size = offsetof(struct vhost_memory, regions); | 322 | unsigned long size = offsetof(struct vhost_memory, regions); |
323 | long r; | 323 | if (copy_from_user(&mem, m, size)) |
324 | r = copy_from_user(&mem, m, size); | 324 | return -EFAULT; |
325 | if (r) | ||
326 | return r; | ||
327 | if (mem.padding) | 325 | if (mem.padding) |
328 | return -EOPNOTSUPP; | 326 | return -EOPNOTSUPP; |
329 | if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) | 327 | if (mem.nregions > VHOST_MEMORY_MAX_NREGIONS) |
@@ -333,15 +331,16 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m) | |||
333 | return -ENOMEM; | 331 | return -ENOMEM; |
334 | 332 | ||
335 | memcpy(newmem, &mem, size); | 333 | memcpy(newmem, &mem, size); |
336 | r = copy_from_user(newmem->regions, m->regions, | 334 | if (copy_from_user(newmem->regions, m->regions, |
337 | mem.nregions * sizeof *m->regions); | 335 | mem.nregions * sizeof *m->regions)) { |
338 | if (r) { | ||
339 | kfree(newmem); | 336 | kfree(newmem); |
340 | return r; | 337 | return -EFAULT; |
341 | } | 338 | } |
342 | 339 | ||
343 | if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) | 340 | if (!memory_access_ok(d, newmem, vhost_has_feature(d, VHOST_F_LOG_ALL))) { |
341 | kfree(newmem); | ||
344 | return -EFAULT; | 342 | return -EFAULT; |
343 | } | ||
345 | oldmem = d->memory; | 344 | oldmem = d->memory; |
346 | rcu_assign_pointer(d->memory, newmem); | 345 | rcu_assign_pointer(d->memory, newmem); |
347 | synchronize_rcu(); | 346 | synchronize_rcu(); |
@@ -374,7 +373,7 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
374 | r = get_user(idx, idxp); | 373 | r = get_user(idx, idxp); |
375 | if (r < 0) | 374 | if (r < 0) |
376 | return r; | 375 | return r; |
377 | if (idx > d->nvqs) | 376 | if (idx >= d->nvqs) |
378 | return -ENOBUFS; | 377 | return -ENOBUFS; |
379 | 378 | ||
380 | vq = d->vqs + idx; | 379 | vq = d->vqs + idx; |
@@ -389,9 +388,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
389 | r = -EBUSY; | 388 | r = -EBUSY; |
390 | break; | 389 | break; |
391 | } | 390 | } |
392 | r = copy_from_user(&s, argp, sizeof s); | 391 | if (copy_from_user(&s, argp, sizeof s)) { |
393 | if (r < 0) | 392 | r = -EFAULT; |
394 | break; | 393 | break; |
394 | } | ||
395 | if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) { | 395 | if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) { |
396 | r = -EINVAL; | 396 | r = -EINVAL; |
397 | break; | 397 | break; |
@@ -405,9 +405,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
405 | r = -EBUSY; | 405 | r = -EBUSY; |
406 | break; | 406 | break; |
407 | } | 407 | } |
408 | r = copy_from_user(&s, argp, sizeof s); | 408 | if (copy_from_user(&s, argp, sizeof s)) { |
409 | if (r < 0) | 409 | r = -EFAULT; |
410 | break; | 410 | break; |
411 | } | ||
411 | if (s.num > 0xffff) { | 412 | if (s.num > 0xffff) { |
412 | r = -EINVAL; | 413 | r = -EINVAL; |
413 | break; | 414 | break; |
@@ -419,12 +420,14 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
419 | case VHOST_GET_VRING_BASE: | 420 | case VHOST_GET_VRING_BASE: |
420 | s.index = idx; | 421 | s.index = idx; |
421 | s.num = vq->last_avail_idx; | 422 | s.num = vq->last_avail_idx; |
422 | r = copy_to_user(argp, &s, sizeof s); | 423 | if (copy_to_user(argp, &s, sizeof s)) |
424 | r = -EFAULT; | ||
423 | break; | 425 | break; |
424 | case VHOST_SET_VRING_ADDR: | 426 | case VHOST_SET_VRING_ADDR: |
425 | r = copy_from_user(&a, argp, sizeof a); | 427 | if (copy_from_user(&a, argp, sizeof a)) { |
426 | if (r < 0) | 428 | r = -EFAULT; |
427 | break; | 429 | break; |
430 | } | ||
428 | if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) { | 431 | if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) { |
429 | r = -EOPNOTSUPP; | 432 | r = -EOPNOTSUPP; |
430 | break; | 433 | break; |
@@ -477,9 +480,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
477 | vq->used = (void __user *)(unsigned long)a.used_user_addr; | 480 | vq->used = (void __user *)(unsigned long)a.used_user_addr; |
478 | break; | 481 | break; |
479 | case VHOST_SET_VRING_KICK: | 482 | case VHOST_SET_VRING_KICK: |
480 | r = copy_from_user(&f, argp, sizeof f); | 483 | if (copy_from_user(&f, argp, sizeof f)) { |
481 | if (r < 0) | 484 | r = -EFAULT; |
482 | break; | 485 | break; |
486 | } | ||
483 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 487 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
484 | if (IS_ERR(eventfp)) { | 488 | if (IS_ERR(eventfp)) { |
485 | r = PTR_ERR(eventfp); | 489 | r = PTR_ERR(eventfp); |
@@ -492,9 +496,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
492 | filep = eventfp; | 496 | filep = eventfp; |
493 | break; | 497 | break; |
494 | case VHOST_SET_VRING_CALL: | 498 | case VHOST_SET_VRING_CALL: |
495 | r = copy_from_user(&f, argp, sizeof f); | 499 | if (copy_from_user(&f, argp, sizeof f)) { |
496 | if (r < 0) | 500 | r = -EFAULT; |
497 | break; | 501 | break; |
502 | } | ||
498 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 503 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
499 | if (IS_ERR(eventfp)) { | 504 | if (IS_ERR(eventfp)) { |
500 | r = PTR_ERR(eventfp); | 505 | r = PTR_ERR(eventfp); |
@@ -510,9 +515,10 @@ static long vhost_set_vring(struct vhost_dev *d, int ioctl, void __user *argp) | |||
510 | filep = eventfp; | 515 | filep = eventfp; |
511 | break; | 516 | break; |
512 | case VHOST_SET_VRING_ERR: | 517 | case VHOST_SET_VRING_ERR: |
513 | r = copy_from_user(&f, argp, sizeof f); | 518 | if (copy_from_user(&f, argp, sizeof f)) { |
514 | if (r < 0) | 519 | r = -EFAULT; |
515 | break; | 520 | break; |
521 | } | ||
516 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); | 522 | eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); |
517 | if (IS_ERR(eventfp)) { | 523 | if (IS_ERR(eventfp)) { |
518 | r = PTR_ERR(eventfp); | 524 | r = PTR_ERR(eventfp); |
@@ -575,9 +581,10 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, unsigned long arg) | |||
575 | r = vhost_set_memory(d, argp); | 581 | r = vhost_set_memory(d, argp); |
576 | break; | 582 | break; |
577 | case VHOST_SET_LOG_BASE: | 583 | case VHOST_SET_LOG_BASE: |
578 | r = copy_from_user(&p, argp, sizeof p); | 584 | if (copy_from_user(&p, argp, sizeof p)) { |
579 | if (r < 0) | 585 | r = -EFAULT; |
580 | break; | 586 | break; |
587 | } | ||
581 | if ((u64)(unsigned long)p != p) { | 588 | if ((u64)(unsigned long)p != p) { |
582 | r = -EFAULT; | 589 | r = -EFAULT; |
583 | break; | 590 | break; |
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/fb_defio.c b/drivers/video/fb_defio.c index 1105a591dcc1..073c9b408cf7 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c | |||
@@ -66,7 +66,7 @@ static int fb_deferred_io_fault(struct vm_area_struct *vma, | |||
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | 68 | ||
69 | int fb_deferred_io_fsync(struct file *file, struct dentry *dentry, int datasync) | 69 | int fb_deferred_io_fsync(struct file *file, int datasync) |
70 | { | 70 | { |
71 | struct fb_info *info = file->private_data; | 71 | struct fb_info *info = file->private_data; |
72 | 72 | ||
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; |
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c index 69c6adbd8205..428f8a1583e8 100644 --- a/drivers/watchdog/rdc321x_wdt.c +++ b/drivers/watchdog/rdc321x_wdt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * RDC321x watchdog driver | 2 | * RDC321x watchdog driver |
3 | * | 3 | * |
4 | * Copyright (C) 2007 Florian Fainelli <florian@openwrt.org> | 4 | * Copyright (C) 2007-2010 Florian Fainelli <florian@openwrt.org> |
5 | * | 5 | * |
6 | * This driver is highly inspired from the cpu5_wdt driver | 6 | * This driver is highly inspired from the cpu5_wdt driver |
7 | * | 7 | * |
@@ -36,8 +36,7 @@ | |||
36 | #include <linux/watchdog.h> | 36 | #include <linux/watchdog.h> |
37 | #include <linux/io.h> | 37 | #include <linux/io.h> |
38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
39 | 39 | #include <linux/mfd/rdc321x.h> | |
40 | #include <asm/rdc321x_defs.h> | ||
41 | 40 | ||
42 | #define RDC_WDT_MASK 0x80000000 /* Mask */ | 41 | #define RDC_WDT_MASK 0x80000000 /* Mask */ |
43 | #define RDC_WDT_EN 0x00800000 /* Enable bit */ | 42 | #define RDC_WDT_EN 0x00800000 /* Enable bit */ |
@@ -63,6 +62,8 @@ static struct { | |||
63 | int default_ticks; | 62 | int default_ticks; |
64 | unsigned long inuse; | 63 | unsigned long inuse; |
65 | spinlock_t lock; | 64 | spinlock_t lock; |
65 | struct pci_dev *sb_pdev; | ||
66 | int base_reg; | ||
66 | } rdc321x_wdt_device; | 67 | } rdc321x_wdt_device; |
67 | 68 | ||
68 | /* generic helper functions */ | 69 | /* generic helper functions */ |
@@ -70,14 +71,18 @@ static struct { | |||
70 | static void rdc321x_wdt_trigger(unsigned long unused) | 71 | static void rdc321x_wdt_trigger(unsigned long unused) |
71 | { | 72 | { |
72 | unsigned long flags; | 73 | unsigned long flags; |
74 | u32 val; | ||
73 | 75 | ||
74 | if (rdc321x_wdt_device.running) | 76 | if (rdc321x_wdt_device.running) |
75 | ticks--; | 77 | ticks--; |
76 | 78 | ||
77 | /* keep watchdog alive */ | 79 | /* keep watchdog alive */ |
78 | spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); | 80 | spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); |
79 | outl(RDC_WDT_EN | inl(RDC3210_CFGREG_DATA), | 81 | pci_read_config_dword(rdc321x_wdt_device.sb_pdev, |
80 | RDC3210_CFGREG_DATA); | 82 | rdc321x_wdt_device.base_reg, &val); |
83 | val |= RDC_WDT_EN; | ||
84 | pci_write_config_dword(rdc321x_wdt_device.sb_pdev, | ||
85 | rdc321x_wdt_device.base_reg, val); | ||
81 | spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); | 86 | spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); |
82 | 87 | ||
83 | /* requeue?? */ | 88 | /* requeue?? */ |
@@ -105,10 +110,13 @@ static void rdc321x_wdt_start(void) | |||
105 | 110 | ||
106 | /* Clear the timer */ | 111 | /* Clear the timer */ |
107 | spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); | 112 | spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); |
108 | outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR); | 113 | pci_write_config_dword(rdc321x_wdt_device.sb_pdev, |
114 | rdc321x_wdt_device.base_reg, RDC_CLS_TMR); | ||
109 | 115 | ||
110 | /* Enable watchdog and set the timeout to 81.92 us */ | 116 | /* Enable watchdog and set the timeout to 81.92 us */ |
111 | outl(RDC_WDT_EN | RDC_WDT_CNT, RDC3210_CFGREG_DATA); | 117 | pci_write_config_dword(rdc321x_wdt_device.sb_pdev, |
118 | rdc321x_wdt_device.base_reg, | ||
119 | RDC_WDT_EN | RDC_WDT_CNT); | ||
112 | spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); | 120 | spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); |
113 | 121 | ||
114 | mod_timer(&rdc321x_wdt_device.timer, | 122 | mod_timer(&rdc321x_wdt_device.timer, |
@@ -148,7 +156,7 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
148 | unsigned long arg) | 156 | unsigned long arg) |
149 | { | 157 | { |
150 | void __user *argp = (void __user *)arg; | 158 | void __user *argp = (void __user *)arg; |
151 | unsigned int value; | 159 | u32 value; |
152 | static const struct watchdog_info ident = { | 160 | static const struct watchdog_info ident = { |
153 | .options = WDIOF_CARDRESET, | 161 | .options = WDIOF_CARDRESET, |
154 | .identity = "RDC321x WDT", | 162 | .identity = "RDC321x WDT", |
@@ -162,9 +170,10 @@ static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd, | |||
162 | case WDIOC_GETSTATUS: | 170 | case WDIOC_GETSTATUS: |
163 | /* Read the value from the DATA register */ | 171 | /* Read the value from the DATA register */ |
164 | spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); | 172 | spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); |
165 | value = inl(RDC3210_CFGREG_DATA); | 173 | pci_read_config_dword(rdc321x_wdt_device.sb_pdev, |
174 | rdc321x_wdt_device.base_reg, &value); | ||
166 | spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); | 175 | spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); |
167 | if (copy_to_user(argp, &value, sizeof(int))) | 176 | if (copy_to_user(argp, &value, sizeof(u32))) |
168 | return -EFAULT; | 177 | return -EFAULT; |
169 | break; | 178 | break; |
170 | case WDIOC_GETSUPPORT: | 179 | case WDIOC_GETSUPPORT: |
@@ -219,17 +228,35 @@ static struct miscdevice rdc321x_wdt_misc = { | |||
219 | static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) | 228 | static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) |
220 | { | 229 | { |
221 | int err; | 230 | int err; |
231 | struct resource *r; | ||
232 | struct rdc321x_wdt_pdata *pdata; | ||
233 | |||
234 | pdata = pdev->dev.platform_data; | ||
235 | if (!pdata) { | ||
236 | dev_err(&pdev->dev, "no platform data supplied\n"); | ||
237 | return -ENODEV; | ||
238 | } | ||
239 | |||
240 | r = platform_get_resource_byname(pdev, IORESOURCE_IO, "wdt-reg"); | ||
241 | if (!r) { | ||
242 | dev_err(&pdev->dev, "failed to get wdt-reg resource\n"); | ||
243 | return -ENODEV; | ||
244 | } | ||
245 | |||
246 | rdc321x_wdt_device.sb_pdev = pdata->sb_pdev; | ||
247 | rdc321x_wdt_device.base_reg = r->start; | ||
222 | 248 | ||
223 | err = misc_register(&rdc321x_wdt_misc); | 249 | err = misc_register(&rdc321x_wdt_misc); |
224 | if (err < 0) { | 250 | if (err < 0) { |
225 | printk(KERN_ERR PFX "watchdog misc_register failed\n"); | 251 | dev_err(&pdev->dev, "misc_register failed\n"); |
226 | return err; | 252 | return err; |
227 | } | 253 | } |
228 | 254 | ||
229 | spin_lock_init(&rdc321x_wdt_device.lock); | 255 | spin_lock_init(&rdc321x_wdt_device.lock); |
230 | 256 | ||
231 | /* Reset the watchdog */ | 257 | /* Reset the watchdog */ |
232 | outl(RDC_WDT_RST, RDC3210_CFGREG_DATA); | 258 | pci_write_config_dword(rdc321x_wdt_device.sb_pdev, |
259 | rdc321x_wdt_device.base_reg, RDC_WDT_RST); | ||
233 | 260 | ||
234 | init_completion(&rdc321x_wdt_device.stop); | 261 | init_completion(&rdc321x_wdt_device.stop); |
235 | rdc321x_wdt_device.queue = 0; | 262 | rdc321x_wdt_device.queue = 0; |
@@ -240,7 +267,7 @@ static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) | |||
240 | 267 | ||
241 | rdc321x_wdt_device.default_ticks = ticks; | 268 | rdc321x_wdt_device.default_ticks = ticks; |
242 | 269 | ||
243 | printk(KERN_INFO PFX "watchdog init success\n"); | 270 | dev_info(&pdev->dev, "watchdog init success\n"); |
244 | 271 | ||
245 | return 0; | 272 | return 0; |
246 | } | 273 | } |